fix(edit-history): remote lookup finds tmux, a timeout reaches ssh, docs follow

Applies the review of #766.

The live lookup ran tmux on the bare PATH of the ssh command. On a host
where tmux sits in ~/.local/bin or /opt/homebrew/bin it found no pane, the
2>/dev/null hid that, and the panel stayed on the launch conversation after
a /clear. It now goes through withRemoteTmuxPath(), inside the sh script and
scoped to the $(...), so the other tools keep the PATH they had. The fake
tmux of the test block moved to $HOME/.local/bin for the same reason: that
directory is first on the new PATH, so a real tmux is never asked.

The two ssh commands get exec. Node signals the local sh -c, and dash stays
the parent of a plain command, so ssh survived the timeout. A test with a
fake ssh shows the process dies now and survives without exec.

The comment at the meta budget claimed a meta past it comes with a later
read. A meta comes only with a subagent's first read, so it is never sent.

Docs: the store is named as the exception to "never copied to local disk",
remoteProbePaths and the remote transcript lookup are described, and the
line saying a remote session loads no store is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-11-06 02:57:58 +01:00
1 parent cce28c24f9
commit 26b63aea2d
7 files changed
+90 -17

No files matched your search

+1 -1
View File
@@ -1398,7 +1398,7 @@ The interval is two **synced** settings in `PUT /api/settings` (`src/git-fetch-s
What the Edit history panel reads (Settings → Header & Panels → Header, per-device, default off): the edits a **claude session** made (local or remote SSH), main agent and subagents, read from its transcripts. Read-only. Every route resolves the session through `findSessionOrFail` (another user's session is `404`). A remote session is read over ssh and never woken: a sleeping host answers `unavailable`. Docker and non-claude sessions answer `state: 'unsupported'` and are never read.
`GET /api/sessions/:id/edits[?sync=1]` lists the stored edits, newest first, without diffs: `{ state, reason?, backfillTruncated, agents, entries }`. With `sync=1` it first reads what the transcripts gained since the last read (after `/clear` or a resume, the previous conversation's transcripts to their end first); without it the server reads nothing. `state` is `ok`, `unavailable` (stored entries only; `reason` is `no-transcript` before the session has a transcript Codeman can find, `removed` while the session's history is being deleted, or the read error; the transcript is the one the session's hooks report, else the newest `<id>.jsonl` under the session's `CLAUDE_CONFIG_DIR` override or the server's config dir) or `unsupported` (`reason`: `docker`, `mode`). Each entry is `{ id, ts, path, relPath, kind: 'code'|'image', tool, created, added, removed, truncated, agentId? }`, where `tool` is the edit tool, `bash` for an image a Bash call produced or `sent` for one the agent sent; `relPath` is relative to the workspace (a subagent's worktree for its edits). `agents` maps a subagent id to `{ description, agentType, worktreeBranch? }`. `backfillTruncated: true` means older edits can still be loaded.
`GET /api/sessions/:id/edits[?sync=1]` lists the stored edits, newest first, without diffs: `{ state, reason?, backfillTruncated, agents, entries }`. With `sync=1` it first reads what the transcripts gained since the last read (after `/clear` or a resume, the previous conversation's transcripts to their end first); without it the server reads nothing. `state` is `ok`, `unavailable` (stored entries only; `reason` is `no-transcript` before the session has a transcript Codeman can find, `removed` while the session's history is being deleted, or the read error; the transcript is the one the session's hooks report, else the newest `<id>.jsonl` under the session's `CLAUDE_CONFIG_DIR` override or the server's config dir; a remote session sends no hooks, so its host is asked over ssh for the conversation the pane's claude writes now, else the most recently written of the stored conversation, the session's `claudeSessionId` and its id, under the host's `CLAUDE_CONFIG_DIR` or `~/.claude`) or `unsupported` (`reason`: `docker`, `mode`). Each entry is `{ id, ts, path, relPath, kind: 'code'|'image', tool, created, added, removed, truncated, agentId? }`, where `tool` is the edit tool, `bash` for an image a Bash call produced or `sent` for one the agent sent; `relPath` is relative to the workspace (a subagent's worktree for its edits). `agents` maps a subagent id to `{ description, agentType, worktreeBranch? }`. `backfillTruncated: true` means older edits can still be loaded.
`GET /api/sessions/:id/edits/:entryId` returns one edit's diff as unified text: `{ diff, truncated }` (each edit's diff is capped at 64 KiB). `404` for an edit the session does not have.