Skip to content

Claude/improve cli output b8 gp r#28

Merged
chinmaymk merged 14 commits intomainfrom
claude/improve-cli-output-B8GpR
Mar 12, 2026
Merged

Claude/improve cli output b8 gp r#28
chinmaymk merged 14 commits intomainfrom
claude/improve-cli-output-B8GpR

Conversation

@chinmaymk
Copy link
Copy Markdown
Owner

No description provided.

claude added 14 commits March 11, 2026 22:40
…ppearance

- `stopSpinner(false)` now always outputs a blank line before the `›` response
  prefix, creating clear visual separation between tool calls and model responses.
  Also fixes a bug where `›` was missing after extended thinking blocks.
- `printToolCall` removes the leading `\n` so tool calls render directly on the
  cleared spinner line, eliminating wasted blank lines before the first tool.
- `closeAssistantBox` reduced from `\n\n` to `\n` to avoid excess trailing space
  now that indentation adds an implicit blank line at response end.
- Streaming text in the REPL gets 2-space indentation (`\n` → `\n  `) so multi-
  line responses are visually distinct from tool calls and the input prompt.
- Remove the pre-spinner `\n` from `processInput` since the blank separator is
  now provided by `stopSpinner(false)` at the start of each response.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
Model responses now start with bold bright-cyan 'ra' followed by a dim '›',
making it immediately clear who is speaking. The user's readline input prompt
remains the plain bright-cyan '›', so the two are visually distinct at a glance.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
User input keeps the bright-cyan › from readline. Model response now flows
without any prefix — clean and unindented, differentiated by the blank line
separator and the presence/absence of the › prompt.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
Model text is indented 2 spaces (initial indent from stopSpinner, newlines
replaced with newline+2spaces), keeping responses visually distinct from the
user's flush-left › prompt without any prefix character.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
stopSpinner was writing \n before the 2-space indent, but readline already
advances a line on Enter — resulting in a blank line between user and model.
Drop the \n so the response starts on the very next line.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
- closeAssistantBox now writes \n\n instead of \n
- fallback path in repl also writes \n\n
- stream handler buffers trailing newlines and discards them at
  response end, so the model's trailing whitespace doesn't add
  extra blank lines before the separator

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
LLM text is now wrapped at terminalWidth-2 columns so wrapped lines
stay aligned with the 2-space indent. A lineCol cursor tracks position
across streaming chunks so wrapping is accurate even when chunks split
mid-word. lineCol resets to 0 around tool calls.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
The previous approach wrote the space immediately on seeing it, then wrapped
before the next word — leaving a trailing space at the end of the line.

Replace _flushWord with _emitWord(withLeadingSpace): the space is deferred
as pendingSpace until we know the next word's length. If the word wraps, the
newline+indent replaces the space; if it fits, the space is written normally.
This correctly handles words split across streaming chunks too.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
Previously, words longer than the available line width (URLs, file paths,
code snippets) were written as-is, causing the terminal to wrap them at
column 0 — breaking out of the indented bounding box.

Now _emitWord has three paths:
1. Word fits on current line → write normally
2. Word fits on a fresh line → soft-wrap before it
3. Word too long for any line → hard-break char by char at column limit

Every continuation line starts with the 2-space indent so text never
escapes the bounding box.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
The hand-rolled LineWrapper had two classes of bugs:
1. Post-tool-call indent: text resuming after a tool call wrote at col 0
   (wrapper.col=0 but no prefix was emitted before the content)
2. Column tracking: char-level counting was fragile — off for wide chars,
   ANSI codes, and edge cases across streaming chunks

New approach:
- StreamBuffer buffers text until '\n', then wraps each complete logical
  line with wrap-ansi (handles ANSI codes, wide chars, hard-breaks long
  words like URLs). Zero manual column tracking.
- boxOpened is reset to false after each tool call so text resuming after
  tools goes through the normal stopSpinner() path, which writes the
  prefix and creates a fresh StreamBuffer. No special-case needed.
- startSpinner() is called unconditionally in afterToolExecution so the
  model computing phase always shows a spinner.

Visual improvement: response lines are prefixed with "  │ " (dim left
border) making the response area visually distinct from tool call output.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
The │ box-drawing character only fills the centre of the character cell,
creating a floating-bar artefact that looks wrong next to normal text.
Plain whitespace indent is cleaner and avoids any font rendering issues.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
TypeScript's control-flow analysis does not track assignments to `let`
variables made inside async closures. It sees `streamBuf` initialized
to `null` and keeps that narrow type at the post-loop read sites, making
`if (streamBuf)` narrow to `never`.

Cast `(streamBuf as tui.StreamBuffer | null)?.end()` to explicitly widen
back to the declared union type and bypass the spurious narrowing.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
printToolCall now accepts the raw JSON arguments string, collapses it
to a single line (stripping outer braces for readability), and truncates
with '…' when it would exceed the terminal width.

https://claude.ai/code/session_01TpMwMFqNRqfoB7FfkA8j7Y
@chinmaymk chinmaymk merged commit 70bec82 into main Mar 12, 2026
1 check 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.

2 participants