Skip to content

feat(status): informative tmux bar (#42) + Claude Code model·effort·context statusLine (#67) - #68

Merged
rappdw merged 1 commit into
mainfrom
feat/42-67-status-lines
Jul 23, 2026
Merged

feat(status): informative tmux bar (#42) + Claude Code model·effort·context statusLine (#67)#68
rappdw merged 1 commit into
mainfrom
feat/42-67-status-lines

Conversation

@rappdw

@rappdw rappdw commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Closes #42, closes #67.

Two complementary status lines, each showing what it actually has live access to.

#42 — outer tmux bar (sandbox state)

Replaces the uninformative default-tmux window-list furniture with:

 sandy · permissive · claude          myproj · 1 client · session · 14:32   (interactive)
 sandy · strict · claude,codex        myproj · 2 clients · daemon · 09:07    (daemon)
 sandy · no-net-iso · claude          myproj · 1 client · session · 22:15    (proxy off — orange warning)
  • Isolation posture is the star, color-coded: green ★ strict / cyan ★ permissive / orange ★ no-net-iso (a warning).
  • Reads at tmux runtime from env forwarded by docker run -e (#{E:SANDY_EGRESS_MODE}/SANDY_AGENT/SANDY_PROJECT_NAME/SANDY_DAEMON) + native #{session_attached}.
  • Window list blanked — every sandy session is single-window (multi-agent splits into panes).

#67 — inner Claude Code native statusLine (live model · effort · context)

The tmux bar structurally can't show the model (it'd be the stale launch-time value) or the reasoning effort (no env surface). Claude Code's own statusLine gets both live on stdin, so sandy now:

  • bakes /usr/local/bin/sandy-claude-statusline (jq → Opus 4.8 · effort: high · 42% ctx; effort omitted when the model doesn't support it; graceful sandy fallback on empty/malformed input),
  • points the generated settings.json statusLine at it — only if the user hasn't set their own (preserved via node's !(k in s) / jq's //= across all three seed branches; claude-gated).

Verification

  • Plan (fable) → implement (Sonnet 5) → adversarial verify (Opus 4.8): SHIP, no blockers. Both tmux format strings brace-balanced (7/7); the only comma-bearing style spec is top-level, not inside a conditional (escaping hazard avoided); all three settings.json branches preserve a user's own statusLine and produce valid JSON; the jq script fails safe on every malformed/empty/wrong-shape input.
  • bash -n clean; regen --check clean (no new config key; changed regions outside the user-setup mirror); §81 (20 assertions) green standalone.
  • Maintainer host-confirm (both fail-open cosmetic, flagged): the egress-color segments render as intended, and the blanked window-status leaves no stray colored artifact. Not runnable in CI (visual/live-render).
  • The power glyph was dropped for plain color-differentiated daemon/session text (U+23FB font-coverage risk); ·/ kept.

Additive-only (1.3.0); schema_version stays 1; no new config key.

🤖 Generated with Claude Code

…ontext statusLine (#67)

Two complementary status lines, each showing what it actually has live access to.

#42 — outer tmux bar. Replace the uninformative default-tmux window-list
furniture with sandbox state: brand · isolation posture (color-coded: green
strict / cyan permissive / orange no-net-iso warning) · agent(s) on the left;
workspace · client count · daemon|session marker · clock on the right. All read
at tmux runtime from env forwarded by `docker run -e`
(SANDY_EGRESS_MODE/SANDY_AGENT/SANDY_PROJECT_NAME/SANDY_DAEMON via #{E:}) plus
native #{session_attached}. The window list is blanked — every sandy session is
single-window (multi-agent splits into panes, not windows).

#67 — inner Claude Code native statusLine. The tmux bar structurally can't show
the model (it'd be the stale launch-time value) or the reasoning effort (no env
surface for it). Claude Code's own statusLine gets both live on stdin, so sandy
now bakes /usr/local/bin/sandy-claude-statusline (a jq one-liner → "<model> ·
effort: <level> · <pct>% ctx", effort omitted when the model doesn't support it,
graceful `sandy` fallback on empty/malformed input) and points the generated
settings.json `statusLine` at it — only if the user hasn't set their own
(preserved via node's `!(k in s)` guard / jq's `//=` across all three seed
branches; claude-gated, so other agents are untouched).

- generate_tmux_conf(): new status-left/right + window-status blanking.
- generate_dockerfile_base(): bake sandy-claude-statusline (jq present in base).
- settings.json seed (node/jq/last-resort branches): statusLine, only-if-absent.
- run-tests.sh §81 (20 structural + live-jq checks); SPEC Appendix A/C, CLAUDE.md
  "Status Lines", RELEASE_NOTES.

Plan(fable)/implement(sonnet)/verify(opus 4.8) loop. The `⏻` glyph was dropped
for plain color-differentiated daemon/session text (U+23FB font-coverage risk);
`·`/`★` kept. Live tmux/Claude render is a maintainer host-confirm (both flagged
items are fail-open cosmetic) — not runnable in CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rappdw
rappdw merged commit b545756 into main Jul 23, 2026
2 checks passed
@rappdw
rappdw deleted the feat/42-67-status-lines branch July 23, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant