diff --git a/deny.toml b/deny.toml index ddd9601..937b468 100644 --- a/deny.toml +++ b/deny.toml @@ -14,6 +14,15 @@ ignore = [ # Revisit when zellij-tile moves off clap 3. "RUSTSEC-2024-0370", # proc-macro-error "RUSTSEC-2024-0375", # atty + # Transitive through notify-rust -> tauri-winrt-notification -> quick-xml. + # tauri-winrt-notification is a Windows-only (WinRT toast) dependency, so + # quick-xml is not compiled into muxa on the Unix targets we ship. Both are + # DoS-on-untrusted-XML issues; muxa never feeds attacker-controlled XML to + # this crate (Windows notification templates only), and tauri-winrt-notification + # 0.7.2 pins quick-xml ^0.37 so the fixed 0.41 can't be selected yet. + # Revisit when notify-rust ships a tauri-winrt-notification that allows quick-xml >=0.41. + "RUSTSEC-2026-0194", # quick-xml: quadratic runtime on duplicate attribute names + "RUSTSEC-2026-0195", # quick-xml: unbounded namespace-declaration allocation (NsReader) ] [licenses] diff --git a/docs/demo-README.md b/docs/demo-README.md index 6db4dec..7755c37 100644 --- a/docs/demo-README.md +++ b/docs/demo-README.md @@ -11,8 +11,24 @@ to re-record it. | ---------------------- | ------------------------------------------------------------------------------------- | | `docs/demo.tape` | [VHS](https://github.com/charmbracelet/vhs) script — the recording itself. | | `docs/demo-setup.sh` | Bootstraps an isolated `tmux -L muxa-demo` server with a few seeded panes + windows. | +| `docs/demo-paint.sh` | Paints believable static agent frames (claude/codex/gemini) into the demo panes so `muxa attend` / attach land on real-looking content instead of an empty `cat`. | | `docs/demo-seed.sh` | Older pane-seed script (kept for reference; the live setup script does this inline). | -| `docs/demo.gif` | The output. 1200 × 720; includes status, stats, activity, and the session watch view. | +| `docs/demo.gif` | The output. 1200 × 720; the status → stats → watch → attend story arc. | + +## Story arc + +The recording is a four-beat narrative, not a feature tour — the point is +to make "which of my agents needs me?" felt, then answered: + +1. **Overwhelm** — `muxa status`: claude working, codex blocked on an + approval, gemini waiting. +2. **The accountant** — `muxa stats`: where the day actually went + (WORK / WAIT / TMUX / ACT / THINK). +3. **The god view** — `prefix + s` → `muxa watch`, every agent on one + screen, with the real prompt + response in the preview popup. +4. **The finale** — `muxa attend` teleports the tmux client straight to + the longest-blocked agent (codex, mid shell-approval). Strongest note + to end on, so it comes last: attend moves us off the shell pane. The tape's prelude (`Hide` block) does the boring setup so the visible recording stays focused on the muxa UI: @@ -74,9 +90,10 @@ docker cp ~/.cargo/bin/muxa "$CID":/usr/local/bin/muxa docker cp ~/.cargo/bin/muxad "$CID":/usr/local/bin/muxad docker cp docs/demo.tape "$CID":/work/docs/demo.tape docker cp docs/demo-setup.sh "$CID":/work/docs/demo-setup.sh +docker cp docs/demo-paint.sh "$CID":/work/docs/demo-paint.sh docker cp docs/demo-seed.sh "$CID":/work/docs/demo-seed.sh -# 4) Record. The visible flow shows status, stats, activity, and watch. +# 4) Record. The visible flow shows status, stats, watch, and attend. docker exec -w /work "$CID" vhs docs/demo.tape # 5) Pull the resulting GIF out and tear the container down. @@ -105,7 +122,7 @@ docker exec -w /src "$CID" sh -c \ A few patterns that come up: -* **Pacing**: the visible flow targets ~17 s. `Sleep` durations are in +* **Pacing**: the visible flow targets ~19 s. `Sleep` durations are in milliseconds; ~1500 ms after a key gives the viewer time to read, ~500 ms is right between consecutive keystrokes. * **New key in muxa watch**: add the keystroke after `Type "p"` / diff --git a/docs/demo-paint.sh b/docs/demo-paint.sh new file mode 100755 index 0000000..e242ccc --- /dev/null +++ b/docs/demo-paint.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Paint a believable, static agent frame into a demo pane, then hold on +# `cat` so the pane stays put (and keeps clean scrollback) for the +# recording. Replaces the bare `cat` panes in docs/demo-setup.sh so that +# `muxa attend` / Enter actually land the viewer on something that looks +# like a real agent session instead of an empty shell. +# +# Usage (from a tmux pane command): +# bash docs/demo-paint.sh claude +# bash docs/demo-paint.sh codex +# bash docs/demo-paint.sh gemini +# +# Colors are raw ANSI so this has no dependency on the agent binaries — +# the frames are fixtures, matched closely enough to each CLI's look to +# read as genuine at GIF resolution. + +set -euo pipefail + +C_RESET=$'\033[0m' +C_DIM=$'\033[2m' +C_BOLD=$'\033[1m' +C_GREEN=$'\033[1;32m' +C_YELLOW=$'\033[1;33m' +C_BLUE=$'\033[1;34m' +C_CYAN=$'\033[1;36m' +C_MAG=$'\033[1;35m' + +clear + +case "${1:-}" in + claude) + printf '%s● claude%s %s· muxa%s\n' "$C_MAG" "$C_RESET" "$C_DIM" "$C_RESET" + printf '%s~/src/muxa on ipc-frames%s\n\n' "$C_DIM" "$C_RESET" + printf '%s›%s refactor the ipc module to use length-prefixed frames\n\n' "$C_GREEN" "$C_RESET" + printf ' %s⚙%s editing crates/muxa/src/ipc.rs\n' "$C_DIM" "$C_RESET" + printf ' %s⚙%s running cargo test --lib ipc\n\n' "$C_DIM" "$C_RESET" + printf ' %s▶ working…%s\n' "$C_BLUE" "$C_RESET" + ;; + codex) + printf '%s● codex%s %s· legacy-auth%s\n' "$C_CYAN" "$C_RESET" "$C_DIM" "$C_RESET" + printf '%s~/src/legacy on main%s\n\n' "$C_DIM" "$C_RESET" + printf '%s›%s audit the legacy auth middleware for raw bearer tokens\n\n' "$C_GREEN" "$C_RESET" + printf ' %s⚙%s ran rg -n "bearer" src/ %s18 matches%s\n' "$C_DIM" "$C_RESET" "$C_DIM" "$C_RESET" + printf ' %s⚙%s ran cat src/auth/middleware.rs\n\n' "$C_DIM" "$C_RESET" + printf ' %s⏸ Approval required%s\n' "$C_YELLOW" "$C_RESET" + printf ' %s$ rg -n "token" --type rust -g '\''!tests/'\''%s\n\n' "$C_BOLD" "$C_RESET" + printf ' %s[y]%s yes %s[n]%s no %s[a]%s yes, and don'\''t ask again\n' \ + "$C_GREEN" "$C_RESET" "$C_YELLOW" "$C_RESET" "$C_DIM" "$C_RESET" + ;; + gemini) + printf '%s● gemini%s %s· review%s\n' "$C_BLUE" "$C_RESET" "$C_DIM" "$C_RESET" + printf '%s~/src/review on main%s\n\n' "$C_DIM" "$C_RESET" + printf '%s›%s review PR #482 — new sorting knob in muxa watch\n\n' "$C_GREEN" "$C_RESET" + printf ' %s?%s Which default ordering should I evaluate against —\n' "$C_YELLOW" "$C_RESET" + printf ' [Session, Activity] or [Activity, Session]?\n\n' + printf ' %s▶ waiting for your reply%s\n' "$C_BLUE" "$C_RESET" + ;; + *) + printf 'usage: demo-paint.sh {claude|codex|gemini}\n' >&2 + exit 2 + ;; +esac + +# Hold the pane. `cat` keeps the frame on screen and the pane alive with a +# quiet stdin, exactly like the old bare-`cat` panes. +exec cat diff --git a/docs/demo-setup.sh b/docs/demo-setup.sh index 53be628..99d3ec5 100755 --- a/docs/demo-setup.sh +++ b/docs/demo-setup.sh @@ -20,6 +20,8 @@ set -euo pipefail : "${MUXA_SOCKET:=/tmp/muxa-demo.sock}" TMUX_LBL=muxa-demo SHIM_DIR=/tmp/muxa-demo-shim +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PAINT="$SCRIPT_DIR/demo-paint.sh" # believable agent frames instead of bare `cat` rfc3339_ago() { local seconds="$1" @@ -32,15 +34,18 @@ rfc3339_ago() { # 1) PATH shim — every later `tmux` call (ours and muxa's children) routes # through `tmux -L muxa-demo`. +# Real tmux binary, resolved absolutely so it bypasses the PATH shim below. +# Docker/CI has it at /usr/bin/tmux; a Homebrew mac has it elsewhere, so the +# tape passes MUXA_DEMO_TMUX after resolving `command -v tmux` pre-shim. +TM="${MUXA_DEMO_TMUX:-/usr/bin/tmux}" + mkdir -p "$SHIM_DIR" cat > "$SHIM_DIR/tmux" </dev/null" +Type "$MUXA_DEMO_TMUX -u -L muxa-demo kill-server 2>/dev/null" Enter Type "kill %1 2>/dev/null" Enter