Skip to content

fix(chat): tab status edge cases - #17

Merged
dartpain merged 6 commits into
mainfrom
fix/tab-status-states
Oct 16, 2026
Merged

dartpain merged 6 commits into
mainfrom
fix/tab-status-states

Conversation

@dartpain

Copy link
Copy Markdown
Contributor

Fixes for the iTerm2 tab status (OSC 21337) added in v1.10.0.

  • GNU screen (docs): tab_status on only gets through tmux's passthrough; screen drops the sequence either way. docs/configuration.md, docs/chat.md and CLAUDE.md now say so.
  • Failing !cmd: showed done. tools.RunShell now also returns whether the command exited 0, and a failing one shows failed.
  • Message not sent (its files could not be attached, put back into the input): kept the previous answer's status. It now shows failed and notifies (only fires when the terminal is unfocused). It is not cleared because a queued message can fail while the user is away, and it waits in the input for them.
  • Changing tab_status in /settings: only off was handled, so going from on to auto inside tmux left the forced status on the tab. The chat now remembers the current status and re-applies it under the new mode whenever the mode changes (auto in tmux clears it, off clears it, on sends it again).
  • Approval with Edit: the status flipped waiting → working → waiting… on each Choose/Edit, and Notify on Status Change alerted each time. screenTools now goes to waiting at the first question and back to working once, when the call's output starts or its block closes (approved, denied, cancelled). A cancelled approval still ends cleared, since the send clears on interruption. Auto-approved calls never touch it.
  • Hard kill: a chat killed with SIGKILL/OOM left working forever. The chat now writes one clear at startup while the screen is up, only where a status would be sent (not with off, nor in tmux under auto). The limitation is documented in docs/chat.md.

Supporting changes: a headless ui.Screen can take an Output file (for tests), untab writes through the screen's output, and the Ctrl+Z handoff body is now screenModel.stop.

Testing

  • New tests: TestTabStatusControls (ESC/BEL/C1/newlines stripped from the text), TestTabStatusSuspend (cleared on Ctrl+Z, shown again on resume), TestClearTabStatus, TestRunShellStatus, and chat-level TestTabStatusShell, TestTabStatusNotSent, TestTabStatusApproval, TestTabStatusSettings and TestTabStatusStartup, which read the statuses a headless chat writes.
  • gofmt -l . is clean. go build ./... && go vet ./... && go test ./... pass, and so does GOOS=windows go vet ./....

A chat killed with SIGKILL, by the OOM killer or a fatal error cannot
clear its tab status, so the tab showed "working" for good. The chat now
clears it once when it starts, where a status would be sent (not with
tab_status off, nor inside tmux unless it is on).

untab writes through the screen's output, and a headless screen can take
one, so the tab status is tested: control characters in the text, and
Ctrl+Z clearing it until the chat resumes.
A !cmd that exited non-zero showed "done" on the tab: RunShell now also
reports whether the command succeeded. A message put back into the input
because its files could not go left the status of the answer before; it
shows "failed" now, and notifies, since a queued message can fail while
the user is away.
Only "off" cleared the tab from /settings: turning "on" back to "auto"
inside tmux left the status it had forced through, and "on" showed
nothing until the next message. The chat keeps the status it shows and,
whenever the mode changes, shows it again as the new mode has it.
Choosing Edit at an approval flipped the tab from waiting to working and
back several times (Choose and Edit each set and reset it), and iTerm2's
Notify on Status Change alerted on each flip. The status now turns to
waiting at the first question and back to working once, when the call
runs or closes: approved, denied or cancelled.
GNU screen drops the tab status even with tab_status on (only tmux gets
the passthrough). Document the statuses a failing !cmd and an unsent
message show, that an approval stays one wait through Edit, that a
settings change applies at once, and that a killed chat leaves its status
until the next chat clears it.
- An approved read, write or edit turns the tab back to working as soon
  as it is approved, not when its block closes: the approval's answer
  ends the wait (Output no longer does).
- A cancelled approval no longer shows working for a moment before the
  stopped run clears the tab.
- untab checks for an output like the other writers.
- docs: a leftover status is not cleared under auto inside tmux or screen
  either.
@dartpain
dartpain merged commit 0bf9e87 into main Oct 16, 2026
1 check passed
@dartpain
dartpain deleted the fix/tab-status-states branch October 16, 2026 14:22
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