Specimen Report · Rust

claude-esp-rs

phiat/claude-esp-rs

Stream Claude Code's hidden output (thinking, tool calls, subagents) to a separate terminal in real-time (Rust port)

Stars
★ 20
Forks
⑂ 1
Language
Rust
Size
550 kB
Last Push
20d ago
Forged
4mo ago
agentsclauderusttui
# claude-esp-rs [![Crates.io](https://img.shields.io/crates/v/claude-esp)](https://crates.io/crates/claude-esp) Stream Claude Code's hidden output (thinking, tool calls, subagents) to a separate terminal in real-time. ![claude-esp-rs screenshot](docs/screenshot.png) > **Note:** This is a Rust port of the [Go version](https://github.com/phiat/claude-esp). The binary is named `claude-esp-rs` to allow running both versions side-by-side. ## The Problem When using Claude Code interactively, tool outputs and thinking are collapsed by default and require pressing `Ctrl+O` to toggle visibility. This tool lets you watch all that output in a **separate terminal** with a nice TUI, without interrupting your main Claude Code session. ## Features - **Multi-session support** - Watch all active Claude sessions simultaneously - **Hierarchical tree view** - Sessions with nested Main/Agent nodes - **Real-time streaming** - See thinking, tool calls, and outputs as they happen - **Subagent tracking** - Automatically discovers and displays subagent activity - **Session events** - Compaction boundaries, hook output, post-edit LSP diagnostics, and PR-link events surfaced inline - **Agent type labels** - Shows agent types (Explore, code-reviewer, etc.) from `.meta.json` - **Token usage tracking** - Cumulative input/output token counts in the header bar - **Per-agent context size** - Each Main/subagent row shows current context as a percentage of the model's max context window (`Main 18%`, `Explore 9%`). Denominator is the model's *max window* (1M for opus-4-7 / sonnet-4-6, 200k for haiku-4-5), **not** the auto-compact threshold - **Tool execution duration** - Shows how long each tool call took - **Background task visibility** - See background tasks (⏳/✓) under spawning agent - **Filtering** - Toggle visibility of thinking, tools, outputs per session/agent - **Auto-scroll** - Follows new output, or scroll freely through history ## Requirements - Rust 1.86 or later ## Installation ```bash # Install from crates.io cargo install claude-esp # Or clone and build from source git clone https://github.com/phiat/claude-esp-rs.git cd claude-esp-rs cargo build --release # Optional: install to PATH cp target/release/claude-esp-rs ~/.local/bin/ ``` ### Pre-built binaries Download pre-built binaries from the [Releases](https://github.com/phiat/claude-esp-rs/releases) page. Available for Linux (amd64, arm64), macOS (amd64, arm64), and Windows (amd64). ## Usage ```bash # In your main terminal: run Claude Code as normal claude # In a second terminal/tmux pane: run the watcher claude-esp-rs ``` ### Options | Option | Description | | ------------ | --------------------------------------------- | | `-s <ID>` | Watch a specific session by ID | | `-n` | Start from newest (skip history, live only) | | `-l` | List recent sessions | | `-a` | List active sessions | | `-p <ms>` | Poll interval in ms (fallback mode only, default 500) | | `-w <secs>` | Active window in seconds (default `300` = 5 min) | | `-m <N>` | Max sessions to show in tree (default 0 = unlimited) | | `-c <secs>` | Auto-collapse sessions inactive ≥ secs (default 0 = disabled, e.g. `120` for 2 min) | | `-D` | Debug: surface raw `type:subtype` for every JSONL line type the parser would otherwise drop | | `-V` | Show version | | `-h` | Show help | ### Environment Variables | Variable | Description | | ------------- | --------------------------------------------------- | | `CLAUDE_HOME` | Override Claude config directory (default: `~/.claude`) | ### Examples ```bash # Watch all active sessions claude-esp-rs # Skip history, only show new output claude-esp-rs -n # List active sessions claude-esp-rs -a # Watch a specific session claude-esp-rs -s 0b773376 # Faster poll interval (200ms) claude-esp-rs -p 200 # List recent sessions claude-esp-rs -l ``` ## Keybindings | Key | Action | | --------- | ----------------------------------------- | | `t` | Toggle thinking visibility | | `i` | Toggle tool input visibility | | `o` | Toggle tool output visibility | | `x` | Toggle text/response visibility | | `a` | Toggle auto-scroll | | `h` | Hide/show tree pane | | `A` | Toggle auto-discovery of new sessions | | `tab` | Switch focus between tree and stream | | `j/k/↑/↓` | Navigate tree or scroll stream | | `space/enter` | On session: collapse/expand (pins on manual expand) · On agent: toggle visibility · On bg task: load output | | `s` | Solo selected session/agent (toggle) | | `g/G` | Go to top/bottom of stream | | `q/Ctrl+c`| Quit | ## Auto-Collapse Run with `-c 120` to automatically collapse sessions that have been idle for 2 minutes. Collapsed sessions show `▸` instead of `▾` in the tree and display the count of hidden subagents (e.g. `📂▸ my-session (+2)`). Children of collapsed sessions are also filtered out of the stream pane — the whole point is to stop sleeping sessions from dominating your view. Press `space` on a collapsed session to expand it manually. Manual expansion **pins** the session — it won't auto-collapse again until it wakes up (receives new activity) and then goes idle once more. Press `s` to solo a session; if it's collapsed, Solo force-expands and pins it so you can see its output. ## How It Works Claude Code stores conversation transcripts as JSONL files in: ``` ~/.claude/projects/<project-path>/<session-id>.jsonl ``` Subagents are stored in: ``` ~/.claude/projects/<project-path>/<session-id>/subagents/agent-<id>.jsonl ``` Background task outputs are stored in: ``` ~/.claude/projects/<project-path>/<session-id>/tool-results/toolu_*.txt ``` The watcher: 1. Discovers active sessions (modified in last 5 minutes) 2. Uses OS-native filesystem notifications ([notify](https://docs.rs/notify)) to detect file changes in real-time (inotify on Linux, kqueue/FSEvents on macOS) 3. Falls back to polling (configurable with `-p`) on filesystems that don't support notifications (NFS, some cross-FS WSL2 setups) 4. Debounces rapid writes (50ms window) to efficiently handle burst output 5. Parses JSON lines and extracts thinking/tool_use/tool_result 6. Discovers background tasks and correlates them with spawning agents 7. Renders them in a TUI with tree navigation and filtering ## tmux Setup Recommended tmux layout: ```bash # Create a new tmux session with two panes tmux new-session -s claude \; \ split-window -h \; \ send-keys 'claude-esp-rs' C-m \; \ select-pane -L \; \ send-keys 'claude' C-m ``` Or add to your `.tmux.conf`: ``` bind-key C-c new-window -n claude \; \ send-keys 'claude' C-m \; \ split-window -h \; \ send-keys 'claude-esp-rs' C-m \; \ select-pane -L ``` Then press `prefix + Ctrl+C` to open a Claude Code workspace. ## Project Structure ``` claude-esp-rs/ ├── Cargo.toml ├── src/ │ ├── main.rs # CLI entry point │ ├── lib.rs # Library exports │ ├── types.rs # Data structures │ ├── parser.rs # JSONL parsing │ ├── watcher.rs # File monitoring │ └── tui/ │ ├── mod.rs # Ratatui main app │ ├── tree.rs # Session/agent tree view │ ├── stream.rs # Scrollable output stream │ └── styles.rs # Colors and styling └── tests/ └── integration_test.rs ``` ## Development Built with [Ratatui](https://github.com/ratatui/ratatui) and [Tokio](https://tokio.rs/). Issue tracking was done with [beads](https://github.com/steveyegge/beads). ```bash # Run tests cargo test # Build release cargo build --release # Check formatting cargo fmt --check # Lint cargo clippy ``` ## License MIT
↗ GitHub