agents: synthesize shell_output_delta for claude-code via container log stream #957
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Depends on
Reference
charles/claude-hooks#957
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As an operator watching a long-running shell command (e.g.
bun test,just qa) inside a claude-code agent, I want to see live stdout/stderr just like I would for cursor'sShellToolCall, so the dashboard doesn't pretend the agent is idle while a 5-minute test suite is actually running.Context
The Claude Code SDK does not expose stdout deltas for
Bashinvocations — the dashboard sees one event at start and one at completion. Cursor's SDK exposesShellOutputDeltaUpdatefor the same situation. We own the docker container the agent runs in, so we can synthesize equivalent delta events for claude-code by tailing the container's process tree or piping the shell wrapper's output through a sidecar.This is invasive and should land after the cursor delta + tool-kind-taxonomy work — render path needs to exist first.
Acceptance criteria
Approach (decide during design phase, document the choice in the PR)
Bashinvocation, replaces the command withbash -c '<cmd>' 2> >(tee /dev/stderr | logger -t claude-hooks-shell-${call_id}) | tee /dev/stdout | logger -t claude-hooks-shell-${call_id}(or simpler: redirect to a per-call FIFO). Server tailsjournalctl --user -t claude-hooks-shell-${call_id}(or the FIFO) and emitsshell_output_deltaevents with the rightcallId.docker exec -it claude-hooks-${agent} sh -c 'tail -f /tmp/shell-${call_id}.log', tailed by the runner.The PR proposes one, motivates the choice on simplicity / robustness / hook compatibility, and benchmarks at least one realistic workload (e.g.
bun test --watchfor 30 s).Wire format
ShellOutputDeltaEventshape from the cursor delta-streaming issue. UI doesn't know which provider produced it.Edge cases
Tests
Out of scope
Bashbenefits from live output.extractProgressshort text — that stays as the "single line of progress" complement to the live pane.References
ShellOutputDeltaUpdateindelta-types.d.tsdocs/plugins.md+apps/server/src/...(search for "rtk" and "PreToolUse").🤖 Auto-assigned to code-lead (heuristic: area:agents → code-lead (architecture-touching)). Reply
/unassignto reroute.🧹 janitor: this ticket has been idle-assigned since 2026-05-08T15:36:12.000Z. Re-dispatching.
🦵 @charles kicked the queue — re-running implement on @code-lead.
🦵 @charles kicked the queue — re-running implement on @code-lead.
🦵 @charles kicked the queue — re-running implement on @code-lead.
⚠️ duplicate dispatch — issue was closed by PR #994 (merged at 2026-05-08T19:39:01Z) while a parallel
code-lead/957implementation was in progress.A fully tested implementation landed locally on branch
code-lead/957(b904196 feat(agents): synthesise shell_output_delta for claude-code via container tail) covering all acceptance criteria — Option A bash wrapper via PreToolUse,ShellDeltaSourceabstraction withMemoryShellDeltaSourcetest double +DockerExecShellDeltaSourceproduction, per-agentshell-tee-hook.pyrendered byagent-env-sync/render-for-instance.ts, integration intoSdkClaudeAgent.runTask, 50 passing tests covering 1k-line ordering, abort cleanup, multi-call isolation, and the python hook's safety guards.Not pushing the branch — PR #994 already shipped the same surface (different layout: single
/tmp/shell-stream/stream.log+ base64 frames +ShellStreamTailervs. per-call/state/shell-deltas/<callId>.{stdout,stderr}+ python hook +ShellDeltaSource). Leaving the local commit intact for reference; operator cangit diffbetween branches if a comparative review of the two designs is useful.Reporting and stopping.