Skip to content

Troubleshooting ​

Installation ​

/plugin isn't available in this environment in VS Code ​

/plugin is the plugin panel of the Claude Code CLI. In the VS Code extension, type /plugins to open Manage plugins, or run the claude plugin commands in a terminal (Installation). A plugin installed one way shows up in the other.

Host key verification failed when adding the marketplace ​

Claude Code clones the short form owner/repo over SSH, and your machine does not trust GitHub's SSH host key yet. Use the HTTPS URL:

bash
claude plugin marketplace add https://github.com/pssah4/pulse.git

claude: command not found ​

Install the CLI (curl -fsSL https://claude.ai/install.sh | bash, or Homebrew), open a new shell, and check claude --version. The VS Code extension brings its own copy for its chat panel but puts no claude on your PATH.

pulse: command not found ​

Run pulse setup --cli from the installed plugin (the command for your agent is in Installation); in VS Code, run it in the integrated terminal. Then check that ~/.local/bin is on your PATH: add export PATH="$HOME/.local/bin:$PATH" to ~/.zshrc (zsh) or to ~/.bash_profile (bash; ~/.bashrc on Linux) and open a new terminal. If pulse says "no installed Pulse found", the plugin is gone: install it again, or take the command out with rm ~/.local/bin/pulse. A terminal panel "Pulse map" that says command not found: pulse each time VS Code opens the folder comes from the task that pulse setup wrote to .vscode/tasks.json: put the command on your PATH, or delete the task.

Installed from a clone (Codex without the plugin): ~/.local/bin/pulse is a link into the clone, and pulse setup --cli keeps it and reports kept: not written by pulse setup. Check the link with ls -l ~/.local/bin/pulse, which must point to ~/.codex/pulse/bin/pulse, and that ~/.local/bin is on your PATH.

The /pulse commands do not show up ​

  1. claude plugin list in a terminal, or Manage plugins (/plugins) in the VS Code extension, shows pulse@pssah4-skills?
  2. Start a new session; skills load at session start.
  3. Still the old commands (/dia-guide, /coding)? The predecessor plugin is still installed: see Coming from the Digital Innovation Agents plugin.

An update does not arrive ​

Claude Code does not update the pssah4-skills marketplace on its own. Run claude plugin marketplace update pssah4-skills, then claude plugin update pulse@pssah4-skills, and restart. In Codex, codex plugin marketplace upgrade pssah4-skills and then codex plugin add pulse@pssah4-skills again, and restart Codex or start a new chat in the extension.

Codex does not find the skills ​

With the plugin, in the CLI and the IDE extension alike: codex plugin list shows pulse@pssah4-skills (without the CLI, first run the codex() line from Installation, which runs the extension's newest binary), then restart Codex or start a new chat in the extension. Installed from a clone, the fallback without the plugin: ls ~/.agents/skills/pulse must list the skill folders. With both, every skill shows up twice: remove one. Codex names the skills pulse:pulse-ba and so on: type $pulse:pulse-ba for /pulse-ba, in the CLI and the IDE extension alike. The Codex CLI also lists them under /skills > List skills, or as soon as you type $, by the names pulse-ba (pulse) and so on; in the IDE extension, type / in the prompt box and pick one from the Skills group.

Running Pulse ​

GitHub API rate limit ​

This is GitHub's request budget, not the agent's token allowance. Pulse pauses requests until GitHub's reset or Retry-After deadline, and uses bounded backoff when no deadline is available. The map names the limit and marks its cached board as stale. Its counts may no longer match GitHub. It clears the warning after a successful fresh read; restarting the map does not bypass the shared cooldown.

Do not rotate credentials or remove the cooldown to force retries. Keep only the maps and runners you need open. Requests from other tools can consume the same account's budget. A cached revision can support a local queued intent, but only shared confirmation grants authority. A stale revision conflicts; refresh the item before confirming a new intent.

A deferred item does not resume automatically ​

That is intentional. In your own terminal, pulse resume <n> resumes work explicitly. Defer preserves its branch, worktree, notes and evidence; normal content and commit checks still apply. A stop request with an unreachable holder remains pending. If uncommitted work needs its original worktree, use that clone for the handover instead of deleting the worktree or taking its claim blindly.

pulse says "not inside a git repository" or names several remotes ​

Pulse needs to know which GitHub repository holds the item records. It takes, in this order, repo from .pulse/config.toml, the repository set with gh repo set-default, or the only GitHub remote. With several remotes it does not guess:

bash
gh repo set-default owner/name

pulse setup complains about gh ​

Pulse needs gh 2.94 or newer for parent links and "blocked by" links. Update it (brew upgrade gh, or see cli.github.com) and run gh auth status.

pulse new refuses: push the spec first ​

A spec must be committed and published so other clones can plan it. pulse new --spec validates its structure and reports R2-R6 findings; fix them before attaching it. Reserve a draft first to obtain the number, create <type>/<n>-<slug>, commit and push its spec, then attach it with pulse new <type> "<title>" --spec <path> --issue <n>. Commit and push its metadata changes on the same branch. No docs PR is created.

If the spec changed after publication, commit and push again. A missing path means the spec is absent or the path is wrong. A missing or unpublished spec exits with exit 2; correct the path or publish it, then retry. A missing priority label needs pulse setup --labels in the person's terminal. Reuse the existing draft number rather than creating another item.

pulse new, pulse number, or pulse claim says git fetch said ​

pulse new --spec, pulse number --apply, and pulse claim fetch every branch from origin, then ask origin which commit each branch is on (git ls-remote) and hold that against the refs git lists here. After a fetch that failed while origin answered, they print git's error; after one that went through but left a listed ref on another commit than origin names, they print the fetch went through, but refs here differ from origin: and the refs. Only when something they need is not as origin has it do pulse new and pulse number refuse (exit 2) and pulse claim name no start point (it still exits 0, the claim made):

text
pulse number: git fetch said: error: cannot lock ref 'refs/remotes/origin/docs/login': Unable to create '/home/ana/shop/.git/refs/remotes/origin/docs/login.lock': File exists. Another git process seems to be running in this repository, or the lock file may be stale
  • pulse new --spec on the base branch or a build branch needs the branch you are on as origin has it, and refuses when origin no longer has that branch; on a docs branch it pushes and fetches nothing.
  • pulse number --apply needs the history of every branch on origin. A branch whose ref git could not update, or wrote on another commit, counts through the commit origin names; when that commit or its history did not arrive (a fetch cut short), the refusal names the branch. Of two specs with the same ID, the one on the base branch as origin has it keeps the ID.
  • pulse claim names no start point while the ref it lists for the base branch or a branch of the item is not as origin has it (start point not checked: ...); otherwise it names the start point.

When they go on, the line goes to stderr. pulse status, also for one item, prints the same git fetch said: ... until a fetch goes through. A timeout says no answer within 60 s; Pulse ends Git and its transport processes, keeps that cause, and skips the second remote query. offline: origin did not answer means no more specific cause was available. Two common causes:

  • A lock file that a git process left when it stopped (File exists): when no other git runs in the clone, delete the .lock file the message names.
  • Two branches whose names differ only in case (on origin, or a local branch beside one on origin), on a file system that ignores case (macOS, Windows, where git sets core.ignorecase): the clone keeps one ref file for both, loose or in packed-refs, and a fetch may even exit without an error. Pulse then says branch names that differ only in case share one ref file here: and the names. pulse new registers nothing, pulse claim names no start point, pulse number counts through the commits origin names, pulse go starts nothing from the base or the item's branch, and the hint of pulse claim and pulse release on where another holder's work is says where the work is stays unnamed. With core.ignorecase set and origin not answering, pulse go starts nothing either. Delete or rename one of the two branches on origin, or move the clone to the reftable format with git refs migrate --ref-format=reftable (git 2.46 or newer).

git fetch --prune origin shows git's whole message. When origin does not answer at all, pulse new and pulse number refuse with origin did not answer and hand out nothing; pulse claim makes the claim and says start point not checked: origin did not answer.

Pulse's Git network calls also disable terminal, SSH Askpass and Git Credential Manager prompts, including during checks of preserved work and feature removal. Existing credentials and SSH configuration still apply. If authentication needs your attention, run git fetch origin in your own terminal, resolve the reported login or host-key issue there, then retry Pulse. A transport that does not respond stops after 60 seconds. A push may take up to 30 minutes, because it runs your project's pre-push hook; settings changes from the Map stop after 5 minutes.

pulse approve says to open or refresh the Map ​

The CLI has no cached shared revision for that item. Open or refresh pulse map, inspect its result, and confirm approval there or retry the command in your terminal. Acceptance saves a local action; it is not a synchronous whole-board read or an integration decision by itself.

A result cannot be approved ​

Final approval requires a published, verified result whose head and base are still current. A hold, failed gate, changed branch or moved base keeps it unavailable. Read the item findings and current runner report. Resolve the named finding or revalidate the result before approving its new exact head/base pair. A valid spec or Plan alone is not a final result.

An action stays queued, syncing, conflict or error ​

The request was saved locally before network work. Its synchronization worker can continue after the Map closes. Check the displayed reason: network errors retain the request for retry, while a changed shared revision produces a conflict. Refresh before proposing a new intent; Pulse never silently binds an old approval to newer code. Only confirmed approval authorizes integration. Defer and revoke already block locally while their shared updates are pending.

A published spec or Plan is not ready ​

Check its R1-R6 or P1-P6 findings and the named publication branch. Specs, Plans and implementation use the same item branch. Fix and publish the document; no separate spec merge or early approval is needed. If several eligible branches make the source ambiguous, resolve that ambiguity before planning rather than choosing one arbitrarily.

The item branch conflicts with the current base ​

Fetch origin, then merge refs/remotes/origin/<base> into the item's branch with the project's normal hooks enabled. If both branches added items to the same epic, keep both entries and their links. Resolve the conflict, run the affected checks, commit and push the item branch. The changed head or base needs revalidation before final approval; never force the base update or delete another item's work.

Plan-only commits fail project validation ​

Run pulse setup --check-plan and read the base SHA, step, result and log. The isolated probe uses a valid Plan naming future files with the real project commit gates enabled. Missing setup, incompatible checks or a timeout leave concrete findings. Correct the tracked rule and recheck; never create placeholder code or disable hooks to obtain a passing probe.

The map does not start pulse go ​

It never does. Start pulse go in your terminal or explicitly ask the Pulse skill to execute it. Without a TTY Pulse starts or reuses its managed process, confirms its report and returns the log path. Ctrl-C stops a foreground run; pulse go --stop requests a controlled stop of the current run (pulse go).

The map shows "no agent active" although an agent works ​

The Map reads runner phases and supported local hook activity separately from claims. A claim alone proves ownership, not that an agent is active. Check hook trust and PULSE_PRESENCE; without trusted activity hooks, interactive work may be unknown while runner phases remain visible. Preparation appears as Pulse runner before any coding agent starts. See activity.

pulse map prints one frame and ends ​

It does that without a terminal: in a pipe, a file, or an agent's shell tool. Run it in a terminal of its own; pulse map says where for each chat. A working light that does not breathe is no fault: terminals with 16 colors show steady lights.

The agent ignores the rules ​

Check .pulse/config.toml: mode = "off" silences every hook. In Claude Code, claude plugin list in a terminal, or Manage plugins (/plugins) in the VS Code extension, should show pulse as enabled. In Codex, the plugin's hooks bring the rules once you trusted them; Codex installed from a clone reads them from its global AGENTS.md, in $CODEX_HOME when you set it, else in ~/.codex (see Codex without the plugin).

pulse check reports findings ​

Each finding names the file, the line, and the rule (C1 to C10, or R1 to R6 for a published spec, see Commands). Fix the document, or for a cap, add a ## Reasoned exception section (the heading in any case). An epic's ## Items list, which pulse new writes, does not count toward its cap.

A C10 finding names a spec whose file name lacks the ID of its place in the tree: it has none yet, it moved to another parent, or another branch took the same ID. pulse number --apply renames it, rewrites the paths to it, and moves its record along; commit the result. An open record keeps its old path until the rename is on the base branch: after the merge, run pulse number --apply once more.

An R finding names the selected published spec. Fix and publish it on the item's branch, then refresh and recheck. Use pulse defer <n> when you need a deliberate pause while resolving a requirement; only a confirmed resume removes that pause. Old approval labels do not control readiness or authorize final integration.

pulse claim says an item is held ​

Every claim leaves a mark on the item's record that names the session holding it: a Claude Code session, a Codex thread, a pulse go run, or a terminal. Another session is refused, even under your login, so two agents never build the same item. The refusal names the holder, since when, and the command that frees the item:

text
#12 is held by alice since 2026-09-24 09:12 UTC; to hand it over: pulse release --take 12
  • Another person or session holds it: inspect its work and request pulse release --take <n> in your own terminal. Repository write permission can authorize this across accounts. The handoff waits for the writer to stop and preserve work before ownership changes. An agent cannot perform this person-only action or bypass it with keys.
  • An ended session of your own: use the person-only recovery path pulse claim --take <n> and follow its preserved-work checks.

Continue only after shared confirmation, from the published branch or recorded original worktree. Never discard unpublished work to clear a claim.

release refuses a claim that is not yours in the same way.

The map says spec in progress by <login> ​

The item is a draft: a /pulse-ba, /pulse-re, or /pulse-realign session of that person registered it with pulse new ... --draft and holds it while it writes. A draft has no spec on the board yet, cannot be approved, and no agent builds it. Talk to that person before you write about the same topic. The draft ends when its spec is pushed and attached with pulse new <type> "<title>" --spec <path> --issue <n>. For a draft held by an ended session, use the person-only handoff or recovery path in your own terminal.

pulse new --draft says is the draft ... already ​

An open draft of the same type carries the same title, for example a realign (Realign: <owner/repo>) or a Project-BA that another session started. The line names its number and who holds it, and nothing new is created. A draft another person holds stays theirs: talk to them. One nobody holds, or one of yours, goes on with the same command plus --issue <n>; a session of your own that has ended hands it over with pulse claim --take <n>.

The map says no sign of life ​

A teammate's pulse go run holds the item and has not reported for 30 minutes or more. pulse go reports each phase it starts and every 10 minutes while one runs, so silence means the run was stopped, or its machine is off the network. pulse status <n> prints claimed_phase and claimed_beat, the time of the last report in UTC. A session's claim never says this: nothing renews its time, so the map shows how long it is held (held 2 h), which says nothing about whether the session still works.

Inspect the holder and preserved work, then request a handoff with pulse release --take <n> in your own terminal. Pulse requires the writer's stop and recorded work before releasing the claim. Until it is confirmed, do not begin a second writer. Continue its published branch or its original retained worktree; unpushed changes remain in that clone.

The item says stop not confirmed ​

The previous writer has not acknowledged the stop request. No new claim can start while this remains open. Confirm that the named writer has ended, then run pulse release --take <n> --stopped in your own terminal, in the clone that holds its recorded worktree. This also works for an ended interactive session or another account's writer. Pulse checks your current write permission, the observed item revision, the stop generation and the preserved checkout. It reads the current worktree without changing files. A changed head, missing worktree or multiple checkouts of the branch requires inspection first.

The action is queued locally and completed through background synchronization. Wait for confirmed. Existing holds and failed results still need pulse resume <n>; otherwise a regular claim can continue the preserved work. The confirmation starts no agent and adds no hold. Never use --stopped while the writer is still running. Pulse does not detect process termination on another computer.

The backlog says last run: ... ​

A pulse go run gave the item back and left a note on it: why it stopped (a failure or a stop) and which branch holds its work. The map shows the first line; pulse status <n> prints the whole note. Nobody holds the item, so claim it as usual. pulse go starts its worktree from the pushed item branch; in a session, /pulse-build <n> continues on that branch. Changes of a phase the run stopped halfway stay in that run's worktree, under .worktrees/ in the repository of the machine that ran it.

A command says "only a person does this" ​

approve, revoke, lifecycle actions, claim --take, and release --take refuse to run in an agent session, which carries PULSE_HOLDER, CLAUDE_CODE_SESSION_ID, CLAUDE_CODE_CHILD_SESSION, or CODEX_THREAD_ID, and when stdin is not a terminal. These decisions belong to a person: run the command in your own terminal. An explicit pulse go request can run through the interactive Pulse skill; without a TTY Pulse owns its managed process. Nested runner agents remain refused. So do setup --remove and setup --mode off, which would switch the guard off. CLAUDECODE alone does not count, since IDE extensions set it in their terminals too. Such an agent also claims and gives back only the item it was started for (PULSE_ITEM); pulse claim or pulse release of another item ends with "claims and releases only its own item".

An agent's command is denied: "Gate levers belong to a person" ​

The Pulse guard denied a command that pulls a person's lever, or that sends one into another terminal. The agent should name the gate that waits; run the command in your own terminal when you want it. The guard also denies a search for such a phrase, such as grep -r "pulse approve" docs/: it reads quoted text too. Search for pulse.approve instead, or run the search yourself.

The map names another account ​

Pulse acts as the account gh uses in that terminal: gh auth status shows it, and a GH_TOKEN in the environment wins over the login. Switch with gh auth switch, or unset GH_TOKEN; the map shows the new account at once, since Pulse keeps the login per gh config and token. A map that another program started, such as a Herdr pane or a VS Code task, has that program's environment. The final approval proof binds its operation, result and base to the actual comment author. Pulse verifies that account's repository write permission when synchronizing and integrating.

Codex hooks not trusted: run /hooks in Codex ​

The agents of this project include Codex (agent in .pulse/config.toml), and Codex has not trusted the Pulse hooks yet: its sessions get no rules, and the lever guard does not run there. Start codex in the project and trust them with /hooks in the CLI, or click Trust on each Pulse hook on the Hooks page of the IDE extension's settings. Pulse reads the trust from $CODEX_HOME/config.toml (else ~/.codex/config.toml), where Codex keeps it as tables named [hooks.state."pulse@pssah4-skills:..."].

pulse go skips an item: on hold (pulse:hold) ​

A shared or pending local hold pauses the item. Inspect its reason; deferred work needs pulse resume <n> in your terminal or the Map and shared confirmation. Removing a legacy label alone does not clear canonical state.

CI is pending or red ​

CI status does not hold Pulse planning, building or integration. The runner needs a fetched base and valid configuration; it verifies the completed result itself before integration. Agents run targeted checks, and the supervisor owns the full verify of that result. Read the current report for the actual blocker, such as a failed fetch, missing configuration, a hold or failing result gates. An old base red: <check> report describes a previous runner version, not current start authority.

pulse go pauses: hook rejected: <hook> at #n ​

A project hook refused a commit or push of pulse go for item #n. The run starts nothing new until the base branch moves or you start it again, and the item gives its claim back without failing; its worktree keeps the work. pulse go never skips a hook: run the hook's check in the worktree, fix the cause, then start pulse go again.

pulse go does not start: no [spec_tests] ​

pulse go runs each spec test with its own runner and reads the runners from [spec_tests] in .pulse/config.toml on the base branch as origin has it, like verify, setup, and [agents]. Add the section (Configuration), commit it, and merge it into the base branch; a change only in your working tree counts for nothing.

A worker cannot reach a localhost test server ​

localhost = true no longer changes agent selection. Pulse uses the configured worker slots, and the native harness decides whether a worker can reach the server. Read the actual failure in .git/pulse/go/<n>.log and check that harness's native settings in the item's worktree. An older run may still show needs a Claude agent (localhost spec tests) in its retained report.

pulse go skips an item: failed (pulse:failed) ​

Read the preserved finding and .git/pulse/go/<n>.log, repair what it names test-first and publish the item branch. Use pulse resume <n> in your own terminal, or resume in the Map, to request a retry through the local outbox. Wait for shared confirmation; the next run reuses preserved work and applies the normal checks. Final approval does not clear a failure or authorize unverified integration.

An item was approved by mistake ​

Use pulse revoke <n> in your terminal or revoke in the Map. It blocks locally immediately and synchronizes the withdrawal. Read its status until confirmed; an old approval comment remains historical evidence and cannot override the withdrawal.

An agent of pulse go is refused a command ​

Workers use a new native CLI in the item's worktree, or a separate directory for review and audit. The CLI reads its own settings there; Pulse does not copy the original clone's local settings or the calling chat's temporary permissions. It starts with closed stdin, so that chat cannot answer its permission prompts.

For an explicit native permission, authentication or required-hook failure, read the report's phase, concrete cause, preserved branch and worktree, and next action. Resolve that prerequisite through the native harness's configuration or login. Pulse keeps the work and does not repeat the same failure automatically. If the item is recorded as failed, request pulse resume <n> in your terminal or the Map and wait for confirmation before running it again. Usage-limit waits keep their existing recovery path.

An unavailable executable needs installation or a corrected [agents] path. A missing Pulse hook needs the Pulse installation repaired; a native policy that refuses a required hook needs its own authorized configuration change. Pulse neither overrides that policy nor starts another sandbox. For worker_permissions or an old permission placeholder, follow the migration steps before restarting the run.

pulse go leaves an item as failed ​

Its claim goes back to the backlog and its worktree stays for a look; the log is in .git/pulse/go/<n>.log. Fix the cause, then run pulse go again.

pulse go refuses a branch with a foreign upstream ​

A local branch left by gh pr checkout may follow a fork or an origin refs/pull/... ref. Pulse skips it when finding an item's branch and, if its generated branch name would reuse it, stops before setup with has a foreign upstream. Keep the reviewed fork on a different branch name, then retry. An own branch without an upstream, or one tracking a branch on origin or in this clone, still works. Change its tracking configuration only after checking that the commits belong to your work.

Known limits ​

  • The guard reads commands, not files. It checks shell, Monitor, and MCP calls. An agent that writes .pulse/config.toml or .claude/settings.json with its own file tools, or runs a script file, passes it (Levers belong to a person). While a map runs, it refuses more tmux commands than it needs to.
  • The guard reads quoted text too. A commit message or a search that contains a lever, such as pulse auto build on, is denied.
  • Approval policy. Final approval is automatic by default; a person may choose manual approval for regular integration. The same result, base and evidence checks apply, and destructive removal stays explicit. Historical auto comments and labels grant no authority.
  • Spec tests. A runner that waits for the lock of another item's spec tests spends that time from agent_timeout. The Plan rule P6 looks only at files whose names read as tests.
  • Herdr. The pane beside the chat and the notifications are tested against a stand-in for Herdr; tell us when yours behaves differently.

Versions ​

claude plugin list and codex plugin list show the installed version; the changelog says what each version brought. After an update, restart the agent: a running Claude Code session keeps the version it started with, while the Codex update deletes the old version folder that a running Codex session still points at.

Still stuck? ​

Open an issue on GitHub with your platform, pulse --help output, and what you tried.