10 KiB
Roadmap
Status (2026-07-13): Wave 1-4 (all 8 items) implemented + committed on
develop— see docs/PROGRESS_LOG.md for the per-feature commits. Remaining: Wave 5 (fan-out board, access token, Android parity) + the deferred backlog.
Prioritized backlog of features to build next, derived from a grounded analysis of the codebase + the existing planning docs (5 exploration lenses → 24 candidates → this synthesis). Each item keeps what it touches (real files/subsystems) and a rough effort so it's actionable, not aspirational.
The throughline: the product already captures everything — Claude Code hooks, statusLine telemetry, the activity timeline, git diff, live-sessions — but under-acts on it. The highest-leverage work turns passive capture into a trustworthy remote review-and-drive surface, without touching the byte-shuttle. Two small primitives unlock a whole family of features: a server-side PTY-inject call and a preview on the approval bar.
Effort key: S ≈ 1–2 days · M ≈ 3–4 days · L ≈ 1–2 weeks. Order = suggested build sequence (dependencies noted).
Recently shipped (context)
- Split-grid watch board (v0.8, desktop) — 1×2/1×3/2×2/2×3 layouts, click-to-focus,
per-quadrant inline approve / maximize / read-only monitor, drag-to-quadrant,
resizable splitters, saved presets. (
public/grid-layout.ts,grid-presets.ts,cell-monitor.ts,tabs.ts.) - Fixed: browser worktree-create was 400ing (frontend sent
repoPath, server readspath); now aligned + regression-tested (public/projects.ts,test/worktree-form.test.ts).
Wave 1 — ship first (high-trust / high-delight, independent)
-
Approval preview — see-what-you-approve ⭐ (strongest) Show the pending
Bashcommand orEdit/Writediff above Approve/Reject, so remote one-tap approval stops being blind (today you could tap Approve onrm -rf build). The core walk-away trust gap. Touches:src/http/hook.ts(tool_inputis already parsed at:104— derive a bounded preview for Bash/Edit/Write/MultiEdit) →/hook/permission+pendingApprovalsinsrc/server.ts:423(attach + re-send to late joiners, likegatealready does) → optional boundedpreviewon thestatusServerMessage insrc/types.ts→manager→ approval bar inpublic/tabs.ts(reusepublic/diff.tsrenderer +sanitizeField). Pure side-channel. Effort: M. Risk: truncate + strip control chars + cap bytes,textContent/diff-render only, unknown tools fall back to today's name-only bar. -
Clickable URLs & file paths in the terminal Tap the dev-server URL or file path Claude prints instead of soft-keyboard copy gymnastics (paths reuse
POST /open-in-editor). TECH_DOC named@xterm/addon-web-linksin v0.2; never built. Touches: frontend only —public/terminal-session.ts(add the addon + a path-matcher regex →/open-in-editor). Zero server change. Effort: S.
Wave 2 — the unlocking primitive
- Server-side PTY-inject + queued follow-up prompt (unlocks a family)
A thin Origin/loopback-guarded route that writes text into a session's PTY, plus a
per-session queue that fires one entry when Claude goes idle ("now run the tests", then
"now open a PR"). Walk-away = give a task and leave; queuing lets the session advance itself.
Touches: new
POST /live-sessions/:id/queuecalling the existingwriteInput(src/session/session.ts:201); a small queue inmanager.ts; dequeue in the existing Stop/SessionEnd hook branch (src/server.ts:414); FE nearpublic/quick-reply.ts. Injection is identical to a keystroke → byte-shuttle preserved, broadcasts to mirrors. Effort: M. Risk: gate firing onclaudeStatus==='idle'+ settle delay; surface the queue in UI. Foundation for templated launches, auto-continue, issue-intake (backlog).
Wave 3 — read-only side-channel batch (review from the phone)
-
Diff against a base branch (
?base=<rev>) Review a whole agent branch vsmainbefore landing, not just uncommitted changes.src/http/diff.tsalready deferred this (FR-B1.9) and named its mitigation:git rev-parse --verifyallow-list before any revision reaches the CLI. Touches: optionalbaseongetDiff()(guardedgit rev-parse --verify <base>+ trailing--, thengit diff <base>...); branch-picker inpublic/diff.ts. Effort: S/M. -
PR + CI/checks status via
gh(read-only) Per-project/session chip: PR state · checks passing · mergeable — glance from the phone, re-engage only when red. Noghusage exists insrc/yet;ghemits JSON (no parsing pain). Touches: newsrc/http/gh.ts(mirrordiff.ts'srunGit);GET /projects/pr?path=guarded byisValidGitDir;PrStatusinsrc/types.ts; FE chip in project detail. Capability-probe + empty-degrade whenghabsent/unauthed. Effort: M. -
Quick wins (small, cheap, high-delight)
- Sync chip on project cards — ahead/behind + last-commit, folded into the existing
per-repo metadata pass in
src/http/projects.ts(no new route). S. - Cost budget guard + push alert —
costUsdalready flows via statusLine (handleStatusLine); addCOST_BUDGET_USD+ a one-shot latch (likestuckNotified) + warn styling inpublic/preview-grid.ts. The rail that makes unattended auto-continue safe. S–M. - "While you were away" reconnect digest — read-side aggregate over
manager.list()- telemetry/timeline/status → "3 done, 1 waiting, $6, 2 PRs" on reconnect. S–M.
- Recent-commits log per project —
git log --oneline -n N(NUL-delimited) via a guardedGET /projects/log; inert-text render. S–M.
- Sync chip on project cards — ahead/behind + last-commit, folded into the existing
per-repo metadata pass in
Wave 4 — close the git loop
-
Worktree lifecycle: remove / prune (create is now fixed) Delete losing worktrees + land the winner from any device — closes the create-only loop. Touches:
removeWorktree/pruneWorktreesinsrc/http/worktrees.ts(same execFile no-shell + timeout, validate target ingit worktree list& not main, reuse realpath containment);DELETE /projects/worktree+POST /projects/worktree/prune(Origin-guarded); make the existinglocked/prunabletags actionable. Effort: S–M. Risk: destructive — require--force+ confirm for dirty trees, reject the main worktree, safe error messages. -
Stage / commit / push from the diff viewer Claude's done, you reviewed on the phone — now commit + push without typing git into a mobile terminal. Highest-risk git write; bound the MVP to per-file stage-toggle + commit + push-current-branch only; defer discard/checkout; realpath-contain paths, cap msg length, push only to existing upstream or
-u, CSRF-guarded. Effort: M–L.
Wave 5 — bigger bets
-
Worktree fan-out board (the north star: 真并行不互踩) Fan one task across N branch/agent lanes of one repo, watch them race, approve/kill per lane, keep the winner. Mostly composition of shipped parts —
createWorktree+ live-sessions + the split-grid watch board + statusLine gauges + per-quadrant inline approve; server side is a thin "sessions grouped by repo/worktree" endpoint. Cost is UI. Effort: L. Depends on Wave 4. -
App-level access token (leave-the-LAN bar-raiser) Smallest step to safely use the new relay/tunnel off-LAN: a constant-time-compared
WEBTERM_TOKENchecked on the WS handshake (alongside Origin) + on state-changing routes, set as an httpOnly cookie after one-time?token=, disabled when unset (keeps LAN zero-config). Honest tradeoff: a bar-raiser, not a TLS/Tailscale substitute; needs constant-time compare + cookie flags + rate-limiting or it's security theater. Effort: M. -
Android Projects / Diff / Worktree screens (client parity) Android's whole v0.6/v0.7 projects-git UI is SDK-gated/off in
settings.gradle.kts. Zero server change (the:api-clientmodule already speaks the endpoints), but the largest scope. Sequence after the server-side git features so it's one parity pass. Effort: L.
Deferred backlog (your own recorded intent, surfaced from the docs)
Consciously punted in the planning docs; several become cheap once the two unlocking primitives (PTY-inject, approval-preview) land.
| Feature | Deferred in | Note |
|---|---|---|
| Line-level review comments → agent | FEATURE_WALKAWAY_WORKBENCH.md §B1.6 / US-B1.4 |
Tap a diff line, type feedback, composed with file:line and sent via TerminalSession.send. No new route. Pairs with diff-vs-base. M. |
| GitHub issue → new session/worktree | FEATURE_PROJECT_MANAGER.md §9 |
Pick an issue → spawn a session (optionally fresh worktree) with title+body as the prompt. Rides PTY-inject + host gh. Treat issue text as untrusted bytes. M. |
| Templated one-tap launches (repo + prompt + mode) | implied by attach.cwd + Projects launchers |
"Triage repo X in plan mode" as one tap. Rides PTY-inject + a template store. M. |
| Auto-continue on idle (bounded) | no idle automation today | Opt-in auto-inject "continue" up to N times under a cost ceiling. Rides PTY-inject + budget guard. Build last, low default cap, never auto-approve. S–M. |
| Cross-session cost rollup / trends | FEATURE_WALKAWAY_WORKBENCH.md §B2.6 |
Bounded ring beside the latest-only field + GET /telemetry/summary + dashboard panel. Overlaps the budget-guard quick win. M. |
| Mission Control: cross-session feed + durable run log | (no cockpit persistence today) | Merged reverse-chron feed + append-only on-disk tail (reuse subscription-store.ts JSONL/atomic write, byte-capped) so overnight runs survive restart. The "while you were away" digest is its first slice. M–L. |
| Per-project task backlog | task tracking unbuilt | Per-repo TODO store mirroring prefs-store.ts; one tap spawns Claude pre-filled. Local state, not a GitHub Issues sync (YAGNI). M. |
| Host tmux session discovery + attach | user request (this is not raw-iTerm; needs tmux) | We already run as a tmux client on the user's default tmux server (sessions web_<id>), so tmux ls already sees manual/iTerm tmux sessions. Add a discovery list + "attach external tmux session" entry in the launcher → spawn a client PTY tmux attach -t <name>, wrapped in the session model. S–M. |
Kept in sync by the maintainer. Ideas are grounded against the code as of develop — verify
file/line references before starting (they drift).