Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
b0011e7
docs(superpowers): add interactive-claude tmux/sidecar design spec
codefriar May 16, 2026
964f8b7
docs(superpowers): add interactive-claude tmux/sidecar implementation…
codefriar May 16, 2026
572127a
feat(settings): add claudeInteractiveEnabled experimental flag
codefriar May 17, 2026
00b4699
test(settings): reset claudeInteractiveEnabled before each test
codefriar May 17, 2026
0fe7e69
feat(settings): persist claudeInteractiveEnabled via app_settings
codefriar May 17, 2026
de94116
feat(db): add interactive_sessions table migration
codefriar May 17, 2026
e4c4785
feat(db): add interactive_sessions CRUD helpers
codefriar May 17, 2026
7653c1c
fix(db): error on missing-sid interactive_sessions updates + cover li…
codefriar May 17, 2026
cc49aea
feat(agent): add interactive_protocol wire types
codefriar May 17, 2026
1be1cb4
feat(agent): add length-prefixed JSON-line framing
codefriar May 17, 2026
d49b50a
test(agent): add stub-tui fixture for interactive host tests
codefriar May 17, 2026
b3c01c2
feat(agent): define InteractiveHost trait and shared types
codefriar May 17, 2026
5676468
fix(agent): re-export HostSessionSummary; clean up interactive_host p…
codefriar May 17, 2026
0d9e798
test(agent): add InteractiveHost conformance suite skeleton
codefriar May 17, 2026
120ddf3
fix(agent): make conformance status subtest self-contained; drop dupe…
codefriar May 17, 2026
052e5a4
feat(agent): add tmux availability check with TTL cache
codefriar May 17, 2026
df1c97f
fix(agent): robust tmux version parsing for pre-release suffixes
codefriar May 17, 2026
ed918f0
feat(session-host): scaffold claudette-session-host crate
codefriar May 17, 2026
3d69f0f
fix(session-host): honor RUST_LOG env var for tracing
codefriar May 17, 2026
1e5e9c5
feat(session-host): accept connections and answer Hello handshake
codefriar May 17, 2026
abbc595
fix(session-host): propagate serde errors in handshake; gate test cfg…
codefriar May 17, 2026
21f4e3d
feat(session-host): EnsureSession + Status + SendInput + Stop
codefriar May 17, 2026
da580c8
fix(session-host): drop map lock before inner-field await; document S…
codefriar May 17, 2026
9ef0a78
feat(session-host): Attach streaming, Detach (via close), Resize, Cap…
codefriar May 17, 2026
f88a86b
fix(session-host): warn on attach subscriber lag; document capture_sc…
codefriar May 17, 2026
9ad3a1a
feat(session-host): idle-exit when no sessions and no clients
codefriar May 17, 2026
fc1471d
feat(agent): SidecarHost client passes InteractiveHost conformance
codefriar May 17, 2026
68ec88a
feat(agent): TmuxHost passes InteractiveHost conformance
codefriar May 17, 2026
34e4da9
fix(agent): propagate tmux kill-session errors; add tracing to TmuxHost
codefriar May 17, 2026
3fcd56a
feat(agent): TmuxHost::reconcile returns sessions killed externally
codefriar May 17, 2026
bee2227
feat(cli): add 'chat hook' subcommand for Claude Code hook events
codefriar May 17, 2026
7f5e968
feat(tauri): route 'chat hook' IPC into per-session interactive channels
codefriar May 17, 2026
37bbb3c
feat(agent): settings overlay materializes Claude Code hooks
codefriar May 17, 2026
2b29b29
feat(agent): add ClaudeInteractive harness variant and backend resolv…
codefriar May 17, 2026
e6d8a7a
feat(agent): InteractiveSession::start with host selection
codefriar May 17, 2026
b4737e7
fix(agent): use platform-correct shell quoting for hook commands
codefriar May 17, 2026
390130b
feat(tauri): interactive_start/send_input/attach/capture_screen/stop …
codefriar May 17, 2026
5ff4d05
fix(tauri): wire interactive hook channel in start/stop; surface capt…
codefriar May 17, 2026
9578046
build(tauri): bundle claudette-session-host as externalBin sidecar
codefriar May 17, 2026
57af970
fix(tauri): forward --release-built to session-host stage; add CLAUDE…
codefriar May 17, 2026
c80095b
feat(ui): add Claude (Interactive) toggle to Experimental settings
codefriar May 17, 2026
aa1cb4f
feat(ui): expose Claude (Interactive) runtime card gated by experimen…
codefriar May 17, 2026
2dd197a
fix(ui): honor claude_interactive harness override in effectiveHarnes…
codefriar May 17, 2026
108d958
feat(ui): add interactive Tauri bridge service
codefriar May 17, 2026
2cd37e4
fix(ui): preserve unknown-kind label on flat hook path; export RawHoo…
codefriar May 17, 2026
f61cece
feat(ui): hook-delimited turn assembler for interactive sessions
codefriar May 17, 2026
7b2ebeb
fix(ui): reset turn assembler state on sid change; pin turn-id numbering
codefriar May 17, 2026
18cf34f
feat(ui): InteractiveTurnView renders per-turn xterm.js
codefriar May 17, 2026
5ccd780
fix(ui): retain InteractiveTurnView bytes across resize; assert dispose
codefriar May 17, 2026
234aa9a
feat(ui): wire ChatPanel to interactive backend (embedded + full-term…
codefriar May 17, 2026
2cf4ddd
feat(ui): sidebar badges for interactive session state
codefriar May 17, 2026
1d5ec6b
fix(ui): tighten InteractiveSessionRow.state to a typed union
codefriar May 17, 2026
2194be5
feat(ui): copy tmux attach command for interactive sessions on Unix
codefriar May 17, 2026
2413c9c
fix(ui): use Tauri clipboard plugin for tmux attach copy
codefriar May 17, 2026
22e0dae
feat(tauri): reattach surviving interactive sessions on startup
codefriar May 17, 2026
b3d3274
fix(tauri): single DB open in boot reconciler
codefriar May 17, 2026
3e2c9e1
feat(tauri): stop interactive sessions when workspaces are deleted
codefriar May 17, 2026
d45f43b
fix(agent): skip stopped sessions on teardown; align sid-cleanup comment
codefriar May 17, 2026
647043a
feat(interactive): detect and clean up orphaned interactive sessions
codefriar May 17, 2026
03d5724
fix(interactive): exclude non-running host sessions from orphan detec…
codefriar May 17, 2026
21157d4
docs(site): describe interactive-claude experimental backend
codefriar May 17, 2026
cdf1b9a
docs: document interactive-claude backend in CLAUDE.md + copilot inst…
codefriar May 17, 2026
d7b983b
fix(interactive): final review pass — state vocabulary, screen blob, …
codefriar May 17, 2026
8ff78fd
docs(superpowers): coverage plan for interactive-claude patch set (>=…
codefriar May 18, 2026
63d9f73
chore(ci): add interactive-claude coverage gate (vitest)
codefriar May 18, 2026
01d99d1
fix(ci): align @vitest/coverage-istanbul to caret range with vitest
codefriar May 18, 2026
c147631
chore(ci): gate Claude Interactive patch at >=85% via cargo llvm-cov
codefriar May 18, 2026
ce08eb0
test(agent): cover SidecarHost ConnHandle fault paths
codefriar May 18, 2026
908bb49
test(agent): cover frame truncation and zero-length payloads
codefriar May 18, 2026
7cb9573
test(agent): cover SettingsOverlay I/O failures and idempotent cleanup
codefriar May 18, 2026
67087ac
test(interactive): cover reattach_rows DB-write isolation
codefriar May 18, 2026
2bcda8e
test(interactive): empty-input fast paths skip host.status
codefriar May 18, 2026
c6c3135
test(session-host): document reader Ok(0) and waiter Err paths as unr…
codefriar May 18, 2026
7dd51fa
test(session-host): cover lagged broadcast subscriber path
codefriar May 18, 2026
3eca7c2
test(session-host): cover Hello version mismatch returning HelloNack
codefriar May 18, 2026
50771f4
test(tauri): cover boot reconciler branches
codefriar May 18, 2026
c3dc02d
test(tauri): cover interactive_* command handlers
codefriar May 18, 2026
d3f09d9
test(tauri): interactive session teardown fires on workspace archive …
codefriar May 18, 2026
b845b8c
test(cli): cover chat hook IPC failure paths
codefriar May 18, 2026
0a4b975
test(ui): cover xterm onData → sendInput keystroke path
codefriar May 18, 2026
bc1e421
test(ui): cover services/interactive rejection paths
codefriar May 18, 2026
0e73580
test(ui): cover App.tsx orphan-detected listener wiring
codefriar May 18, 2026
d986944
test(ui): cover turn-assembler buffering and post-stop Exit
codefriar May 18, 2026
55d5e26
test(ui): cover InteractiveTerminalMode promise-rejection and race paths
codefriar May 18, 2026
d2cffaa
test(ui): cover InteractiveBadge mixed-state precedence + state exhau…
codefriar May 18, 2026
c88a12f
chore(ci): enforce Claude Interactive patch coverage at >=85%
codefriar May 18, 2026
407718d
fix(interactive): final coverage cleanup — orphan listener catch, tig…
codefriar May 18, 2026
3371659
fix(rebase): align interactive backend with post-rebase main
jamesbrink May 22, 2026
8d9720b
fix(stub-tui): bump fixture crate to 0.25.0 for workspace version sync
jamesbrink May 22, 2026
0bffca1
test(session-host): widen attach READY timeouts for slow CI/llvm-cov
jamesbrink May 22, 2026
1e90d4c
fix(tauri): supply missing input_values / required_inputs in test fix…
jamesbrink May 22, 2026
7eace38
feat(ui): expose Claude (Interactive) runtime selection behind experi…
codefriar May 22, 2026
7203c0d
fix(ui): mock effectiveHarness with flag guard; fix doc comment typos
codefriar May 22, 2026
ecc1baf
chore: document stub-tui fixture; add src-session-host to version-syn…
codefriar May 22, 2026
e8efaa9
test(session-host): gate stub-tui READY behind STUB_TUI_DELAY_MS to d…
codefriar May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Claudette Repository Instructions

Claudette is a cross-platform desktop orchestrator for parallel Claude Code agents. It uses a Tauri 2 Rust backend, a React/TypeScript frontend, SQLite via rusqlite, Tokio process management, git worktrees, xterm.js terminals, Lua plugins, and a local CLI that talks to the running GUI over IPC.
Claudette is a cross-platform desktop orchestrator for parallel Claude Code agents. It uses a Tauri 2 Rust backend, a React/TypeScript frontend, SQLite via rusqlite, Tokio process management, git worktrees, xterm.js terminals, Lua plugins, and a local CLI that talks to the running GUI over IPC. A fifth workspace crate, `claudette-session-host` (`src-session-host/`), is a bundled sidecar that owns interactive Claude PTYs via `portable-pty` — required on Windows and an opt-in Unix fallback when tmux is unavailable.

Follow the existing architecture. Core behavior belongs in the `claudette` crate under `src/`. `src-tauri/src/commands/` should stay thin Tauri wrappers. Shared data types belong in `src/model/` and must derive `Serialize`. Frontend state lives in Zustand slices under `src/ui/src/stores/slices/`, not ad hoc globals.

The chat-send resolver dispatches on a per-backend `runtime_harness` (`AgentBackendConfig::effective_harness` in `src/agent_backend.rs`), not on `AgentBackendKind` directly. A second Anthropic harness, `AgentHarnessKind::ClaudeInteractive` (`src/agent/claude_interactive.rs`), runs the real `claude` TUI inside a long-lived PTY — gated behind the `claudeInteractiveEnabled` experimental flag and surfaced as the "Claude (Interactive)" card in Settings > Models > Runtime. Two hosts back it: `TmuxHost` (Unix, when `tmux >= 3.4` is available and the flag is on) and `SidecarHost` (Windows + opt-in Unix), both implementing `InteractiveHost` in `src/agent/interactive_host/`. The framed JSON wire protocol with the sidecar lives in `src/agent/interactive_protocol.rs`. Turn boundaries flow over Claude Code hooks: the `claudette chat hook` CLI subcommand sends a `chat_hook` IPC request that `AppState::dispatch_interactive_hook` routes into per-session channels, which the frontend assembler (`useInteractiveTurnAssembler`) turns into per-turn xterm.js views (`InteractiveTurnView` and friends in `src/ui/src/components/chat/`, with `services/interactive.ts` as the Tauri bridge). The interactive surface lives in sibling files next to `ChatPanel.tsx` (a god file) — keep new runtime-specific UI in dedicated components, not inside ChatPanel. **Known limitation:** `SidecarHost` does not yet recover from a dropped sidecar connection — the cached `ConnHandle` in `OnceCell` is never reset, so if `claudette-session-host` exits (e.g., its 600s idle timer fires) while Claudette is still running, subsequent `interactive_*` commands fail with "conn closed" errors until Claudette is restarted. Tracked as follow-up work.

Treat regressions as the main risk. Before changing behavior, identify the current contract: persisted DB fields, Tauri command payloads, CLI output, plugin manifests, settings keys, localized strings, terminal/session semantics, worktree behavior, and visible UI workflows. Do not remove, rename, or silently reinterpret any of these unless the task explicitly asks for that change.

If a behavior change is intentional, call it out plainly in the PR summary or review response and add/update tests that pin the new behavior. If the change was incidental, preserve compatibility instead.
Expand All @@ -14,7 +16,7 @@ Control god files. Do not make already-large files the default destination for n

When touching a god file, keep the diff surgical or extract cohesive behavior first. New code should reduce or isolate complexity, not add another unrelated responsibility.

Use the repo's tools. Rust CI expects `cargo fmt --all --check`, `cargo clippy -p claudette -p claudette-server -p claudette-cli --all-targets --all-features` with `RUSTFLAGS=-Dwarnings`, tests for the same three crates on Linux (run via `cargo llvm-cov -p claudette -p claudette-server -p claudette-cli --all-features` for coverage), and `scripts/stage-cli-sidecar.sh --profile debug` followed by `cargo test -p claudette-tauri --no-default-features --features devtools,server,voice,alternative-backends,pi-sdk --no-run` with Linux Tauri system libraries installed (`--no-run` compiles the binary crate's test targets so a broken `claudette-tauri` test fixture is caught — the coverage `test` job only builds `claudette` / `-server` / `-cli`). The Tauri check should stay cache-friendly: use the shared Rust cache and Bun package cache for Pi harness sidecar staging instead of release-building extra artifacts. A separate macOS job also runs `cargo clippy -p claudette-mobile --target aarch64-apple-darwin --all-targets --locked` and `cargo test -p claudette-mobile --locked`. Frontend CI expects `cd src/ui && bun install --frozen-lockfile`, `bunx tsc --noEmit`, `bun run lint:css`, `bun run build`, and `bun run test` (ESLint via `bun run lint` is available locally but not run in CI).
Use the repo's tools. Rust CI expects `cargo fmt --all --check`, `cargo clippy -p claudette -p claudette-server -p claudette-cli --all-targets --all-features` with `RUSTFLAGS=-Dwarnings`, tests for the same three crates on Linux (run via `cargo llvm-cov -p claudette -p claudette-server -p claudette-cli --all-features` for coverage), and `scripts/stage-cli-sidecar.sh --profile debug` followed by `cargo test -p claudette-tauri --no-default-features --features devtools,server,voice,alternative-backends,pi-sdk --no-run` with Linux Tauri system libraries installed (`--no-run` compiles the binary crate's test targets so a broken `claudette-tauri` test fixture is caught — the coverage `test` job only builds `claudette` / `-server` / `-cli`). The Tauri check should stay cache-friendly: use the shared Rust cache and Bun package cache for Pi harness sidecar staging instead of release-building extra artifacts. A separate macOS job also runs `cargo clippy -p claudette-mobile --target aarch64-apple-darwin --all-targets --locked` and `cargo test -p claudette-mobile --locked`. CI also runs the Claude Interactive patch-coverage gate via `scripts/coverage-interactive.sh` + `scripts/check-coverage-interactive.sh` — informational until Task G1 flips it blocking at >=85% line coverage. Frontend CI expects `cd src/ui && bun install --frozen-lockfile`, `bunx tsc --noEmit`, `bun run lint:css`, `bun run build`, and `bun run test` (ESLint via `bun run lint` is available locally but not run in CI).

Always run `cd src/ui && bunx tsc -b` after TypeScript changes. Vitest uses esbuild and does not type-check the project.

Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ jobs:
slug: utensils/claudette
files: lcov.info
fail_ci_if_error: false
# Claude Interactive patch-coverage gate (blocking — Task G1).
# See scripts/check-coverage-interactive.sh and CLAUDE.md. Files
# excluded from the gate (e.g. tmux.rs, sidecar.rs) are documented
# inline in the check script with their structural rationale.
- name: Run llvm-cov (interactive patch JSON)
run: ./scripts/coverage-interactive.sh
- name: Check interactive patch coverage
env:
COVERAGE_GATE_BLOCKING: "1"
run: ./scripts/check-coverage-interactive.sh

frontend:
name: Frontend
Expand All @@ -165,6 +175,10 @@ jobs:
- run: bun run lint:css
- run: bun run build
- run: bun run test
# Claude Interactive patch-coverage gate for the frontend (blocking —
# Task G1). Per-file thresholds live in `vitest.config.ts` and vitest
# exits non-zero if any of them regresses.
- run: bun run test:coverage:interactive

frontend-smoke:
name: Frontend Bundle Smoke
Expand Down
Loading
Loading