Skip to content

feat(cli): show the change, the reasoning, and the whole error - #218

Merged
oratis merged 1 commit into
mainfrom
feat/cli-rendering
Aug 3, 2026
Merged

feat(cli): show the change, the reasoning, and the whole error#218
oratis merged 1 commit into
mainfrom
feat/cli-rendering

Conversation

@oratis

@oratis oratis commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Finding A from docs/THREE_WAY_REVIEW.md — the CLI presentation layer. The REPL printed a tool call as one line, its result cut at 200 characters, no colour anywhere, and dropped every reasoning token the model produced. Approving an Edit meant answering y/n to a tool name.

What changes

Diffs. Edit and Write render a hunked, capped unified diff — at the approval prompt, and again when the call runs, so acceptEdits (which has no prompt) still shows the change. Write is diffed against the file on disk when one exists, so an overwrite doesn't read as a creation. Bash prints its command in full, every line.

  ● Edit  src/auth.ts
       1   function login(user) {
       2 +   if (!user) throw new Error("no user");
       3     return db.find(user);
       4   }

Long files collapse: a two-line change in a 900-line file prints as ~6 rows with markers, and a whole-file rewrite caps with ⋯ N more changed lines.

Reasoning. thinking_delta went straight to return. It now streams into a dim gutter that closes before anything else prints. DeepSeek's reasoner is the premise of this product and its reasoning was the one thing the terminal threw away. --no-thinking opts out.

Output. Tool results elide the middle instead of cutting at 200 bytes — the tail of a failing command is usually the part that matters. Single pathological lines (minified JSON, base64) are clipped so they can't flood the terminal.

Colour. Resolved once at startup from --no-color, NO_COLOR, FORCE_COLOR, TERM=dumb, and whether stdout is a TTY, then threaded through as a palette — piped output is byte-identical minus the escapes.

Shared differ

apps/desktop/src/lib/diff.ts moves into packages/core/src/util/diff.ts; the desktop module re-exports it. The file panel and the terminal now render diffs from one implementation instead of two.

Review notes

Two bugs came out of rendering real output rather than trusting green tests, both now covered:

  • reasoning was painted per characterESC[2mT ESC[0m ESC[2mh ESC[0m …, kilobytes of escape soup for one paragraph
  • a failing command's elision marker was painted twice (ESC[31m ESC[2m … ESC[0m ESC[0m)

render.ts is pure string → string, so all of it is tested without a TTY: 29 new cases covering colour precedence, diff hunking/capping, elision, approval previews per tool, and the reasoning stream's line-state machine.

Verification

pnpm typecheck · lint · format:check clean. core 718/16 skipped · cli 204 · desktop 54 · server 41 · protocol 24 · vscode 12 · lsp 13 · scripts 21. Rendered sample output through the built module and read the raw bytes with cat -v — that is how both colour bugs surfaced.

🤖 Generated with Claude Code

The REPL printed a tool call as one line, its result truncated at 200
characters, no colour anywhere, and threw away every reasoning token the
model produced. Approving an Edit meant answering y/n to a tool name with no
way to see what it would do. Finding A in docs/THREE_WAY_REVIEW.md.

Diffs. Edit and Write now render a hunked, capped unified diff — at the
approval prompt, and again when the call runs, so acceptEdits mode (no
prompt) still shows the change. Write is diffed against the file on disk when
one exists, so an overwrite doesn't read as a creation. Bash prints its
command in full, every line, rather than the first 80 characters.

Reasoning. thinking_delta went to `return`. It now streams into a dim
gutter that closes before anything else prints. DeepSeek's reasoner is the
premise of this product and its reasoning was the one thing the CLI dropped.
`--no-thinking` opts out.

Output. Tool results elide the middle rather than cutting at 200 bytes — the
tail of a failing command is usually the part that matters. Single
pathological lines (minified JSON, base64) are clipped so they can't flood
the terminal.

Colour. Resolved once at startup from --no-color, NO_COLOR, FORCE_COLOR,
TERM=dumb and whether stdout is a TTY, then threaded through as a palette,
so piped output is byte-identical minus the escapes.

The line differ moves from apps/desktop/src/lib/diff.ts into core, where the
CLI can reach it; the desktop module re-exports it, so the file panel and the
terminal now show the same diffs from the same code.

Two bugs caught by rendering real output rather than trusting the tests:
reasoning was painted per character (kilobytes of escape soup for a
paragraph), and a failing command's elision marker was painted twice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oratis
oratis merged commit 79c67e7 into main Aug 3, 2026
5 checks passed
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