fix(launch): stop the --print helper from clearing the pane badge - #120
Merged
Conversation
announceTmuxProfile() gated only on being inside tmux, so every cue launch
reached it — including the short-lived `--print` skill-selector cue spawns on
each session start. That helper inherits TMUX_PANE from the session it is
helping, so it set @cue_* on that pane and then, seconds later, its exit
handler unset all eight. The interactive session kept running with its badge
wiped from the pane border: the profile name and icon simply vanished.
Measured on this machine: 1 of 12 live panes still had @cue_profile_name set.
Two guards, because they cover different cases:
- ownsPaneBadge() adds a TTY requirement. Verified against live processes:
all seven interactive launchers write to /dev/pts/N, while the classifier
is spawned with stdio ["ignore", "pipe", "ignore"], so a pipe is exactly
what distinguishes a helper from the session the user is looking at.
- The exit sweep now reads the options back and unsets only those still
holding the values it wrote. A nested launch — supported since #119 — has
a TTY too, so the TTY guard alone would not stop it from clearing an outer
session's badge on exit. One extra spawn, batched like the set path.
A failed read-back leaves the options in place: leaking a stale badge is
recoverable on the next launch, clearing a live one is not.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
NagyVikt
pushed a commit
that referenced
this pull request
Aug 7, 2026
Brings 36 commits of main onto the branch, including the pane-badge fixes (#111, #120) the branch predates. Six conflicts, all resolved to main's side: main's SkillSpector (#108) is a strict superset of the branch's earlier take — same exports plus baselineDirs/resolveBaselineFor and a --baseline runner arg — and its security.ts keeps both `security scan` and `security baseline`. README and the smart-loader perf test take main's wording likewise. Full suite vs both parents, same conditions: 29 failures on the merge, 28 on main, 34 on the branch, and zero that fail on the merge but on neither parent. Nine smart-loader tests that were red on the branch go green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
announceTmuxProfile()gated only onprocess.env.TMUX, so every cue launch reached it — including the short-lived--printskill-selector cue spawns on each session start. That helper inheritsTMUX_PANEfrom the session it is helping, so it wrote@cue_*onto that pane and then, seconds later, itsprocess.on("exit")handler unset all eight.The interactive session kept running with its badge wiped off the pane border: the profile name and icon simply vanished mid-session.
Evidence
Measured on a live machine: 1 of 12 panes still had
@cue_profile_nameset.The helper is the one cue spawns itself — observed live as
bun cue/src/index.ts launch claude --print --strict-mcp-config --model haiku -p "You are choosing which skills to load…",matching
classifierSpawnArgs()exactly.Fix — two guards, for two different cases
ownsPaneBadge()adds a TTY requirement. Verified against live processes: all seven interactive launchers write to/dev/pts/N, whileclaude-classifier.tsspawns withstdio: ["ignore", "pipe", "ignore"]. A pipe is precisely what separates a helper run from the session the user is looking at.The exit sweep now checks ownership. It reads the eight options back and unsets only those still holding the values it wrote. This is not redundant with the TTY guard: a nested launch — supported since #119 — has a TTY too, so the guard alone would not stop it from clearing an outer session's badge when it exits.
The read-back is one extra spawn, batched through
display-message -pwith a\x1fseparator, in keeping with the existing set/unset batching. A failed read-back leaves the options in place — leaking a stale badge is recoverable on the next launch, clearing a live one is not.Tests
ownsPaneBadgeis extracted as a pure predicate so the rule is explicit and covered: interactive-in-tmux owns it; piped does not; outside tmux nobody does;CUE_TMUX_TITLE=0still opts out.Verification
tsc --noEmitbiome lintmain— zero new failuresThe suite is red at baseline on
main; the failing set was captured on both sides and diffed after stripping bun's per-test timing annotations.🤖 Generated with Claude Code