DESIGN-REVIEW.md is Fable's review of the v0.3.0 UI: token gaps and three WCAG AA contrast failures, the modal/accessibility audit, and an IA proposal that promotes the project from a sidebar card to a tabbed main-area view. ROADMAP.md covers Claude Code feature coverage — the five settings.json keys currently surfaced, the gaps worth closing, the ones deliberately skipped, the authentication handoff design, and phase sequencing. Also published as an artifact for easier reading. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
9.8 KiB
Triple-C Roadmap — Claude Code Feature Parity
Date: 2026-08-09 · Baseline: v0.3.0 · Claude Code reference: 2.1.226
Companion to DESIGN-REVIEW.md, which covers visual design and information architecture. This document covers which Claude Code capabilities Triple-C should surface, and why.
Guiding principle
Triple-C shows state and launches things. Claude Code edits its own config.
Triple-C's built-in MCP server management was removed in this cycle because Claude Code
absorbed the capability natively (claude mcp add/list/remove, .mcp.json, /mcp).
Hooks, skills, agents, plugins, output styles, and statusline are the same species: files
under .claude/ with first-class Claude Code TUIs. Building GUI form editors for them
means losing the same race again.
What Claude Code cannot do is what Triple-C uniquely owns: the container boundary and what persists behind it — the config volume, workspace mounts, lifecycle, the bundled scheduler, and the fleet view across many projects.
Current coverage (v0.3.0)
Triple-C sets exactly five settings.json keys, plus a sandbox block:
| Key | Surfaced as |
|---|---|
tui |
TUI Mode select (fullscreen) |
effort |
Effort Level select (low/medium/high) |
autoScrollEnabled |
Auto-Scroll Disabled toggle |
focusMode |
Focus Mode toggle |
showThinkingSummaries |
Thinking Summaries toggle |
sandbox.* |
Sandbox toggle (enabled, enableWeakerNestedSandbox, allowUnsandboxedCommands) |
Plus four env feature flags — CLAUDE_CODE_NO_FLICKER, CLAUDE_CODE_ENABLE_AWAY_SUMMARY,
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB, ENABLE_PROMPT_CACHING_1H — and arbitrary user-set
CLAUDE_CODE_* vars via the Env Vars modal.
Also covered: per-project auth backends (Anthropic OAuth, Bedrock incl. SSO refresh,
Ollama, OpenAI-compatible), user-level CLAUDE.md composition, claude update on every
container start, terminal ergonomics (OAuth URL detection, OSC 52 clipboard, image paste,
file drag-drop, STT), the web terminal, and workspace backup.
Gap analysis
Committed for this cycle
| # | Gap | Today | Plan |
|---|---|---|---|
| 1 | Permission modes | one boolean → --dangerously-skip-permissions |
Four-state control (Plan / Default / Accept Edits / Bypass) → --permission-mode. Verified choices on 2.1.226: acceptEdits, auto, bypassPermissions, manual, dontAsk, plan. |
| 2 | Session resume | none | List sessions from the config volume; [Resume] opens a terminal on claude --resume <id>. |
| 3 | Capability inventory | none | Read-only counts + names for skills / agents / hooks / plugins / commands / native MCP servers. Deep-link to the terminal to manage. |
| 4 | Automation | triple-c-scheduler ships in every container with zero UI |
Task list, cron editor, run-now, logs, notification badges. |
| 5 | Container auth handoff | manual code paste | See "Authentication handoff" below — design decision pending. |
Deliberately skipped
Status line builder · output-styles editor · hook editors · checkpoint/rewind browser · plugin marketplace browser. Each is niche, natively handled by Claude Code's own TUI, or a settings-editor trap. Surface counts and deep-link instead.
Not yet scheduled
- Granular
permissions.allow/ask/denyrules andadditionalDirectories - Sandbox detail settings (
filesystem.allowRead/allowWrite,allowedDomains,excludedCommands) — currently documented for hand-editing viaSANDBOX_INSTRUCTIONS - Project-level
.claude/settings.jsonvs user-level settings hierarchy - A model picker. Note: the only model strings in the app today are stale placeholders
(
anthropic.claude-sonnet-4-20250514-v1:0inAwsSettings.tsxandProjectCard.tsx,qwen3.5:27b,gpt-4o / gemini-pro / etc.). These are free-text placeholders, not dropdowns, but they should be refreshed to current model identifiers regardless. - The container's settings.json merge is shallow (
jq -s '.[0] * .[1]'), so a user-authored nested block such assandbox.filesystem.allowWriteis replaced wholesale on every container start. Worth deepening to*recursive merge.
Authentication handoff
Goal: stop making users hand-copy an auth code into every container.
Constraint discovered during research: claude login's callback server uses an
ephemeral port and its redirect URI is not configurable for the main login flow
(--callback-port and oauth.callbackPort apply to MCP server OAuth only). So a design
that pre-assigns each container a fixed callback port and routes to it cannot work as
stated — there is no fixed port to route.
There is also a known container gotcha: on Linux, Node resolves localhost to IPv6 first,
so the callback server may bind [::1]:PORT only and be unreachable over IPv4
(anthropics/claude-code#44844).
Two viable options:
Option A — long-lived token injection (simple)
claude setup-token (verified present on 2.1.226: "Set up a long-lived authentication
token (requires Claude subscription)") returns a ~1-year OAuth token. Triple-C runs it
once on the host, stores the token in the OS keychain via the existing secure.rs, and
injects CLAUDE_CODE_OAUTH_TOKEN into every container that uses the Anthropic backend.
- No routing, no ports, no proxy.
- One auth event covers every project.
- Cost: small. Reuses existing keychain and env-injection plumbing.
- Limits: token is subscription-scoped and expires annually; per the docs a
setup-tokentoken cannot drive Remote Control sessions or claude.ai connector fetches.
Option B — the Auth Bridge (general loopback-callback bridge)
Option A only solves Claude Code. The same problem affects every CLI that authenticates by
starting a temporary loopback listener and opening a browser at a URL that redirects back
to it — Concourse fly login (random loopback port serving /auth/callback),
aws sso login, and many others. Inside a container the host browser cannot reach that
listener, so login stalls.
Because the ports are ephemeral and unconfigurable, nothing can be pre-assigned. The bridge discovers listeners instead:
- While enabled for a running project, poll the container for loopback TCP listeners by
reading
/proc/net/tcpand/proc/net/tcp6overdocker exec— no dependency onss/netstat/lsof, which aren't guaranteed in the image. - For each newly-appeared loopback listener, bind the same port on the host's
127.0.0.1(never0.0.0.0— that would expose container internals to the LAN). - Proxy each accepted connection into the container over the Docker API via
socat - TCP:127.0.0.1:<port>(socat already ships in the image), reusing the existing attached-exec streaming indocker/exec.rs. Going through the Docker API rather than a container IP keeps this working on Docker Desktop, where container IPs are not routable from the host. - Fall back to
TCP6:[::1]:<port>when the listener appeared only on IPv6 — on Linux, Node resolveslocalhostto IPv6 first, soclaude loginfrequently binds::1only (anthropics/claude-code#44844). - Tear down when the listener vanishes, the container stops, the bridge is disabled, or the app exits. Ports already covered by the project's explicit port mappings are skipped; host-side conflicts are reported rather than silently swallowed.
Opt-in per project (auth_bridge_enabled, default off), since it makes container-internal
loopback services reachable from the host.
Plan: ship A for Claude Code specifically — it removes the pain for the common case at a fraction of the cost — and B as the general mechanism covering every other CLI. They compose: A means most users never trigger a browser login at all; B catches AWS SSO, Concourse, and anything else that needs a real callback.
Sequencing
Phase 0 — done. Remove MCP (frontend, backend, entrypoint, docs) with a self-healing migration for containers created against the old per-project Docker network.
Phase 1 — foundations. Permission modes end-to-end (including the scheduler bug fix below). Read-only introspection backend: sessions, capabilities, scheduler.
Phase 2 — Tier-1 polish. Focus rings, contrast fixes, real buttons, inline start/stop
progress, status labels, onboarding welcome screen, shared accessible <Modal>.
Phase 3 — Project Home. Move project config out of the sidebar card into a tabbed
main-area view (Overview / Sessions / Automation / Config), dissolving the modal pile and
splitting the 1,257-line ProjectCard.
Phase 4 — authentication handoff. Option A, then evaluate B.
Phase 5 — Library. Global skills/agents/commands with per-project enable, synced into the config volume by the entrypoint. Generalizes the pattern the MCP tab was reaching for.
Bugs found during this review
-
Scheduled tasks ignore the project's permission setting.
container/triple-c-task-runner:69runsclaude -p "$PROMPT" --dangerously-skip-permissionsunconditionally, regardless of the project's Full Permissions toggle. Being fixed as part of Phase 1. -
Docs claim Reset preserves credentials; it does not.
rebuild_project_containercallsremove_project_volumes, which deletes bothtriple-c-home-{id}(holding~/.claude.json) andtriple-c-claude-config-{id}(holding~/.claude). README.md, HOW-TO-USE.md, and CLAUDE.md all still state that OAuth tokens survive a Reset. Pre-existing; not yet corrected. -
Stale model placeholders — see "Not yet scheduled" above.
-
Silent save failures. Project config saves on blur; failures go only to
console.error. No user-visible indication. Addressed in Phase 3.