cmux-tui: status indicators (loading fields, owned auto-clear, terminal busy, cmux status)

Closed
LA
1mo ago
+2365-114

Status indicators, daemon and CLI side (plans/cmux-next/status-indicators.md section 5; spec decisions U5-U9). The app only renders; these are the facts it renders.

What changes

  • workspace_status.set takes optional state (busy|success|error|waiting|info), progress, style, ttl_ms, owner {pid, terminal, agent_session}, target_terminal, exit_code, duration_ms. Stored in the additive table workspace_status_meta (state/status_meta.rs). Callers that send only text, icon and color are unchanged, and their request fingerprint is the same as before.

  • The daemon removes an owned entry in its own commit (workspace_status.auto_clear, a state_upsert of the workspace status) when:

    • its TTL passes: one expiry thread sleeps until the earliest deadline, with backoff after a failed commit;
    • its owner terminal exits: the session host's exit subscription;
    • its owner process exits: kqueue NOTE_EXIT or pidfd.

    A process owner must be running, is accepted only from a trusted local connection (server.rs), and is recorded with the machine id and the kernel start time, so a reused pid never stands in for it. Watches resume at daemon start (state/status_owners.rs).

  • terminal-activity-v1: terminal records carry extra.busy {since_ms} while a shell command runs between OSC 133 C and D. A new prompt clears stale OSC 9;4 progress. An exited terminal publishes neither (terminal_activity.rs). The client applies the "show after N s" setting.

  • CLI (cli/status.rs, cli/command/state/status_flags.rs):

    • workspace status set takes --state, --progress 0.4|40%, --style, --ttl 30s, --pid, --owner terminal|none, --target-terminal, --exit-code and --duration-ms.
    • New shorthand cmux status set [KEY] --label T | clear [KEY] [--all] | list | run [--label] [--badge-ttl 8s] -- CMD.
    • run marks the entry busy, owned by its own pid, and runs CMD with the terminal's stdio. It forwards signals that another process sent, then records success or error with the exit code and duration. It exits with CMD's status, and re-raises CMD's terminating signal so a shell loop around it stops too.
    • The CLI never sends a notification. The app decides, from the duration and the terminal's visibility.
  • Catalog fields and binding descriptors are updated. The transport coverage test exercises every new field.

The owner's three changes from #16174 are applied:

  • the daemon validates owners;
  • the owner decides auto-clear in the same commit, with its own transaction;
  • terminal facts sit on the terminal record, and waits go under the terminal noun.

Not in this PR

  • cmux status wait KEY, and cmux terminal <term> wait --until idle|prompt. Both need a new connection-owned wait op. exit and output already exist as terminal <t> process wait and terminal <t> screen wait --pattern.
  • Agent-session-end auto-clear.
  • busy is not restored after a daemon restart: it shows idle until the next OSC 133 mark.
  • A terminal-owner watch holds the daemon while it blocks.

Verification (Blacksmith Testbox, Linux)

  • cargo test --locked for the whole workspace: all pass except session_shutdown_exits_an_interactive_detached_owner_client. That test flakes on the base commit too (1 of 6 failed there).
  • cargo clippy -p cmux-tui-core -p cmux-tui --all-targets -D warnings is clean.
  • cargo fmt --check is clean for this diff. The remaining diffs are in cmux-tasks from the base branch.
  • End to end with a built daemon:
    • cmux status run --label Tests --badge-ttl 2s -- sh -c 'sleep 2; exit 3' shows busy with a pid owner while it runs, then error with exit code 3 and duration 2001 ms. The CLI exits 3, and the entry is gone after 2 s.
    • printf '\e]9;4;1;40\a\e]133;C\a' in a terminal shows extra {busy: {since_ms}, progress: {state: normal, value: 40}}.
  • A review subagent checked correctness against OWNERSHIP-PRINCIPLES. Its findings are fixed in 152e55e0161.
  • macOS kqueue code is not run on the box (UNVERIFIED there).

๐Ÿค– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Adds loading-indicator metadata to workspace status entries with daemon-side auto-clear, plus a cmux status CLI and terminal busy facts from OSC 133 marks. Entries written by older clients (text/icon/color only) are unaffected, and the new data is stored in an additive table that older binaries ignore.

Status entries and auto-clear

  • workspace_status.set accepts optional state, progress, style, ttl_ms, owner (pid, terminal, agent session), target_terminal, exit_code, and duration_ms, persisted in a new workspace_status_meta table.
  • The daemon removes owned entries itself when the TTL passes (one expiry thread), the owner terminal exits, or the owner process exits, using kqueue/pidfd; process owners are recorded with their kernel start time and accepted only from trusted local connections.
  • Busy state is not restored after a daemon restart โ€“ the terminal shows idle until the next OSC 133 mark.

CLI and terminal facts

  • New cmux status set | clear | list | run: run marks the entry busy and owned by its own pid, runs the command with the terminal's stdio, records success or error with exit code and duration, propagates the child's exit status and signals, and keeps the entry for a configurable badge TTL (default 8s).
  • workspace status set gains matching flags (--state, --progress, --style, --ttl, --pid, --owner, --target-terminal, --exit-code, --duration-ms).
  • Terminal records publish extra.busy {since_ms} between OSC 133 C and D; exited terminals publish neither busy nor progress. A new prompt clears stale OSC 9;4 progress.