Skip to content

feat(cli): claw run tails the server-side run in the terminal - #93

Merged
EdmondDantes merged 1 commit into
mainfrom
feat/cli-run-tail
Jul 27, 2026
Merged

feat(cli): claw run tails the server-side run in the terminal#93
EdmondDantes merged 1 commit into
mainfrom
feat/cli-run-tail

Conversation

@EdmondDantes

Copy link
Copy Markdown
Contributor

What

The third slice of TODO item 2. #92 made claw run hand the run to the server and return; this brings the live view back to the terminal. After starting the run, the CLI follows it and prints the trace as it arrives, ending when the run does.

  • Server: GET /api/projects/{key}/issues/{id}/runs — the runs for an issue (needed because the run id is minted inside the run, so a start cannot return it).
  • ServerClient: runs(), trace(), latestRunId(), awaitRun() — find the run a start produced (the first id past the pre-start high-water mark) and poll its trace.
  • WorkflowMode::tailRun() — renders each trace row exactly as an in-process run does (same TraceFormat, same depth indentation and ▶ ◀ · glyphs, same level threshold from -q/-v), and stops on done/failed.

Behaviour

  • claw run prints the run's trace live again, then Run #N finished issue #M. (or a failure pointer to claw log).
  • A human gate shows ⏸ waiting for a human — answer it in the dashboard; Ctrl-C detaches (the run continues). Detaching loses only the view — the run keeps going on the server and claw log shows the rest. Answering the gate from the terminal is the next slice (3b).
  • If the CLI can't attach a tail (no run appears in time), it falls back to watch it with: claw log and exits 0.

Verified live

Against the real server extension: claw run 6 autospawned a server, started the run, discovered its id, and rendered the trace as it worked —

▶ workflow Issue6Solver
  ▶ step implementStatsClass
  ◀ end
  ▶ workflow supervise-run
    ▶ step repair
          · tool recall
          · tool-result recall  Title: Statistics module with tests…
          · tool list_files
          · tool read_file

Design notes

  • Polling, not SSE. The trace poll (?since=<seq>) is the SSE fallback endpoint and returns the same rows; CurlHttpClient buffers the whole body, so it cannot stream an SSE response anyway. 500 ms cadence.
  • List endpoints (runs, trace) are decoded directly in ServerClient, not via HttpResponse::json() — that method refuses a top-level JSON array by contract (it is for string-keyed objects). This surfaced as three tests throwing HttpException; Testo's parallel runner misattributed them to unrelated files at first.

Not in this PR

  • 3b: answering the gate from the terminal (POST …/answer), which turns the read-only tail interactive.
  • /start returning the run id (would remove the awaitRun discovery poll; deferred because the id is created mid-run).

Checks

composer qa green — cs, PHPStan level 8, Testo (457 tests). New ServerClient tests cover the run-list parsing, latestRunId, awaitRun, and trace decoding (incl. the top-level-array case).

After starting a run, the CLI discovers its id (GET issues/{id}/runs, since the id is minted inside the run and not returned by the start) and polls the trace, rendering each row exactly as an in-process run does. A human gate is shown with a hint to answer it in the dashboard; Ctrl-C detaches without stopping the run. Restores the live progress the server cutover removed. Verified live: the trace renders as the run works. Reads list endpoints directly — HttpResponse::json() refuses a top-level array by contract.
@EdmondDantes
EdmondDantes merged commit fcc2758 into main Jul 27, 2026
2 checks passed
@EdmondDantes
EdmondDantes deleted the feat/cli-run-tail branch July 27, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant