Launch Progress TUI
Status: Open — design proposal (operator launch surface)
Problem
Section titled “Problem”jackin load and the launch path entered from jackin console should feel like the same product surface, but today the launch path still reads as a sequence of terminal printouts. The current implementation in src/runtime/launch.rs uses direct status lines, config tables, animated step shimmer, and full-screen rain hooks that are tied to a single launch rather than to the larger “operator has entered or left jackin’” lifecycle. That makes repeated sequential launches slower and visually noisy, and it makes debug mode worse for normal users because troubleshooting detail competes with the product-level progress story.
The missing product model is a launch cockpit: a compact, recognizable, cyberpunk-styled TUI that explains what jackin’ is doing now, what is waiting next, where failures are recorded, and when the operator has crossed a session boundary. Full digital rain should mark entering or leaving jackin’ work, not every container start. The stage names should use jackin’ vocabulary: the construct is the base world, the derived image is the role-specific layer, the Capsule is the persistent in-container control plane, and the hardline is the direct line into a running agent session.
Product principles
Section titled “Product principles”- Digital rain is a boundary ritual. It appears when the operator starts the first active container owned by jackin’, and when the last active container owned by jackin’ exits. It does not appear between sequential launches while any container owned by jackin’ is still running.
jackin loadand console-triggered launches use the same launch visualization when the terminal supports it.- The default operator surface stays compact: lifecycle status, current stage, next stage, short failure diagnosis, and a diagnostics reference.
- Debug output becomes more detailed in diagnostics, not on screen.
--debugmust not turn the launch TUI into raw command output. - No launch command should ever show log streams, command output dumps, Docker build logs, stack traces, or debug traces in the operator-facing progress surface. The launch surface is a product UI, not a terminal log viewer.
- The launch UI is product-facing, but its internal event stream is contributor-facing and testable.
- Startup speed matters. Work that is independent should run in parallel after prompts and trust barriers are satisfied.
- All host-side writes remain explicit state owned by jackin’. The launch UI must not “fix” host Git, shell, Docker,
gh, or agent configs behind the operator’s back.
Target experience
Section titled “Target experience”When the terminal supports a rich TUI, jackin load and console launches should enter a full-screen progress surface after any required prompts. The screen should be operationally dense but quiet. Saved workspaces and ad-hoc directory launches should render as different target identities because they mean different things: a workspace is a configured project boundary, while a directory launch is a one-off target.
Saved workspace example:
jackin' / loading agent-smith into workspace
workspace big-monorepoworkdir ~/Projects/appmounts 3 configuredcontainer jk-k7p9m2xq-bigmonorepo-agentsmithagent claudeimage jackin/agent-smith:latest
● identity resolved role + operator● role trusted source◐ construct pulling base world○ derived image queued○ workspace queued○ network queued○ sidecar queued○ capsule queued○ hardline queued
status: pulling projectjackin/construct:trixiediagnostics: launch jk-lch-42f9Ad-hoc directory example:
jackin' / loading agent-smith in directory
directory ~/Projects/appmount same pathcontainer jk-k7p9m2xq-agentsmithagent claudeimage jackin/agent-smith:latest
● identity resolved role + operator● role trusted source◐ construct pulling base world○ derived image queued○ workspace queued○ network queued○ sidecar queued○ capsule queued○ hardline queued
status: pulling projectjackin/construct:trixiediagnostics: launch jk-lch-42f9The identity panel should never label an ad-hoc directory as a workspace. For a saved workspace, show the workspace name first and then the configured workdir/mount summary. For a directory launch, show directory first and describe the direct mount shape. This keeps the TUI honest about whether jackin’ is applying a saved workspace configuration or simply launching in the target directory the operator chose.
The main panel should use the same phosphor-green vocabulary as the console and landing page. A bounded rain strip or subtle background panel can provide motion without forcing the full intro animation. The visual language should remain terminal-native: thin lines, strong monospace rhythm, compact labels, and bright state changes. It should avoid marketing copy, large empty hero layouts, or a wall of command output.
The renderer should start from jackin’ console conventions: modal sizing, red-border error surfaces, footer-only key hints, phosphor palette, tight chrome, and one clear focused action at a time. It should still leave room for product experiments that make launch feel more distinctive, such as a stronger construct/derived-image visual split, a live rain strip that reacts to stage transitions, or a more cinematic hardline-opening moment, as long as those experiments keep the console’s interaction rules intact.
When the terminal is not interactive or cannot support the TUI, launch falls back to compact line output with the same event vocabulary. Scripts should still get deterministic stderr/stdout behavior and useful failure text, but the fallback must remain product-level: no raw logs, no streamed Docker output, and no debug firehose.
Visual language
Section titled “Visual language”The launch surface should be colorful enough to feel recognizable, but disciplined enough to stay readable during a real failure. Phosphor green remains the base identity color; secondary accents should be sparse and stage-specific:
| Stage family | Accent direction | Why |
|---|---|---|
identity, role, credentials | phosphor green / dim green | Resolution and trust are jackin’ control-plane work. |
construct | cyan-green | The shared base world is coming online. |
derived image | amber | Image builds are the slow transformation stage; amber signals active work without implying failure. |
network, sidecar | blue-cyan | Infrastructure wiring and private daemon startup should read as system-level connectivity. |
capsule | white + green | The control plane is awake and ready. |
hardline | bright white pulse into green | The final connection should feel like the direct line opening, then settle back into normal jackin’ chrome. |
Motion should communicate state rather than decorate the screen. Good candidates:
- A narrow rain strip or side column that brightens when a stage starts, dims when queued, and briefly pulses when a stage completes.
- A signal-strength motif for hardline opening, for example
hardline ▂▄▆█ opening primary session. - A compact progress bar only for stages with meaningful progress signals; otherwise prefer stage status words over fake percentages.
- Micro-completion labels that are more product-native than
done:online,ready,isolated,awake,open.
The construct and derived image stages should have a visible layer split. This can be a small stack panel:
construct projectjackin/construct:trixie onlinederived image agent-smith + claude runtime buildingcapsule jackin-capsule stagedThis teaches the launch model while work is running: jackin’ pulls or verifies the base world, layers the role and runtime on top, starts Capsule, then opens the hardline. The TUI should not expose raw Docker command streams as the primary visual model.
Use stronger verbs where they clarify the product story, but avoid theatrical wording that hides what is happening. Good candidate status lines:
| Stage | Candidate wording |
|---|---|
identity | resolving operator, claiming instance identity |
role | trusting role, validating role contract |
construct | pulling construct, construct already online |
derived image | building derived image, refreshing agent runtime layer |
workspace | materializing workspace, mounting directory |
network | wiring private network |
sidecar | waking sidecar |
capsule | starting Capsule, seeding agent home |
hardline | opening hardline, focusing Claude tab |
The footer acts as the stable status/control strip. During normal launch it can show a short diagnostics reference and any active non-destructive key. During fatal failure it shows only Enter Close plus the diagnostics reference. Do not put key hints inside the main panel or inside error dialogs.
Reduced-motion and low-capability terminals must keep the same information architecture. When motion is unavailable or disabled, render a static phosphor layout with stage accents and status text, no shimmer, no animated rain, and no cursor-control assumptions beyond the selected renderer’s capability level. The visual identity should survive without animation.
Digital rain lifecycle
Section titled “Digital rain lifecycle”The current launch code calls the intro animation before the launch and the outro renderer after the foreground session exits. The new rule should be keyed to the active count of containers owned by jackin’:
| Moment | Desired behavior |
|---|---|
| Before launch, zero active containers owned by jackin’ | Show full intro rain, then enter the launch progress TUI. |
| Before launch, one or more active containers owned by jackin’ | Skip full intro rain and enter the launch progress TUI immediately. |
| After foreground session exit, one or more active containers owned by jackin’ remain | Skip full outro rain and show a compact return/remaining-sessions notice if needed. |
| After foreground session exit, zero active containers owned by jackin’ remain | Show full outro rain. |
The count must use runtime discovery managed by jackin’ rather than raw Docker process guesses. It should include containers preserved because active Capsule sessions remain, and it should exclude stale records that are not actually running. If discovery fails, the safe default is to skip the boundary animation and record the reason in diagnostics; a failed count should not block launch or exit.
Stage vocabulary
Section titled “Stage vocabulary”The TUI should show a small stable list of public stages. Substatus text can be more specific, but the top-level stages should not mirror every implementation detail. The labels should make the launch feel like jackin’ is assembling an isolated world and then opening a hardline into it, not like Docker is dumping raw plumbing into the terminal.
| Stage | Meaning |
|---|---|
identity | Resolve the operator, workspace, selected runtime agent, and instance identity. |
role | Fetch/update the role repository, validate its contract, and complete source trust or branch confirmation. |
credentials | Resolve manifest env, operator env, agent auth mode, GitHub auth mode, and credential preflight checks. |
construct | Pull or verify the shared construct image and prepare the matching Capsule binary for the derived build. This is the base world every role extends. |
derived image | Build, refresh, or reuse the role-specific image layered on top of the construct, including the role tools and selected agent runtime layers. |
workspace | Materialize workspace mounts, isolated worktrees/clones, and launch-time filesystem state. |
network | Create the private per-instance network and launch-scoped Docker resources. |
sidecar | Start Docker-in-Docker and wait until the private daemon is reachable. |
capsule | Create and start the role container with resolved mounts, env, terminfo, state, Capsule config, setup hooks, and container-local runtime integration artifacts. |
hardline | Open the direct line through Capsule to the focused agent session and hand the terminal to that session. |
Statuses should be explicit: queued, running, done, skipped, failed, and optionally blocked when a prompt is open. The UI should distinguish “skipped because cached/reused” from “not reached yet”.
The construct and derived image stages should expose precise substatus because they are the most visible slow path on first launch:
| Stage | Example substatus |
|---|---|
construct | pulling projectjackin/construct:trixie, construct already current, using JACKIN_CONSTRUCT_IMAGE override, preparing Capsule binary |
derived image | checking role image cache, building role tools, refreshing Claude layer, reusing image built from current role SHA |
capsule | creating role container, seeding agent home, running setup hooks, starting Capsule |
hardline | opening primary session, focusing Claude tab, ready for operator |
Failure model
Section titled “Failure model”Fatal launch failures should open a compact error dialog in the TUI:
Docker unavailable
jackin' could not reach the Docker daemon.
docker daemon is not respondingdiagnostics: launch jk-lch-42f9The dialog should show:
- a short human diagnosis;
- the failed public stage;
- one actionable next move when obvious;
- the diagnostics reference for the failed launch/session;
- no stack trace or raw log excerpt.
The footer for a fatal launch failure should expose exactly one action: Enter Close. There should be no Retry, Continue, Back, secondary close button, or multi-button confirmation state unless a future failure class is explicitly recoverable without leaving the launch. Pressing Enter closes the dialog and exits the launch path immediately.
The detailed error, command trace, Docker API trace, captured docker logs, build output, and debug evidence belong outside the launch UI. The operator-facing surface shows the short diagnosis and a stable diagnostics reference only. After the UI exits, an operator or agent can use that reference with the dedicated diagnostics/log command to inspect the detailed evidence for the specific launch/session. The exact shape of that reference still needs design — likely a launch ID or session ID that maps cleanly to the container/instance that failed.
Diagnostics model
Section titled “Diagnostics model”The current debug_log! channel in src/tui/mod.rs writes debug lines to stderr or a temporary buffer while the console TUI is active. Launch progress needs the same split but with a durable diagnostics destination and a hard product boundary: detailed logs are never rendered in the launch UI.
- Compact UI events go to the renderer.
- Compact launch breadcrumbs go to the diagnostics artifact even without
--debug. --debugenables detailed command, Docker, resolver, auth, cache, materialization, cleanup, and build traces in the diagnostics artifact.- The TUI never streams the debug firehose, Docker build output, captured
docker logs, or command stdout/stderr directly. - Secrets and token values remain redacted; source references are allowed only where existing auth diagnostics already permit them.
- On launch failure before a container exists, the host-side diagnostics artifact is the primary artifact. Once the Capsule multiplexer is running, diagnostics should point to the relevant in-container artifact for that instance/session instead of making the operator guess which container to inspect.
- The progress surface should display only a compact diagnostics handle such as a launch ID, session ID, or future
jackin logs ...selector. Designing that ID shape is follow-up work, but the UX requirement is fixed: one reference, no inline logs.
The implementation should introduce one launch-scoped diagnostics handle rather than sprinkling new eprintln! calls through launch code. Existing debug_log! sites should be routed into that handle while launch TUI buffering is active, then flushed to the durable diagnostics artifact. This keeps --debug useful without making the user’s terminal noisy.
Event model
Section titled “Event model”The launch path should stop rendering directly from deep implementation code. Instead, launch should emit structured events to a progress sink:
enum LaunchEvent { Started { role, workspace, agent }, StageStarted { stage, label }, StageProgress { stage, detail }, StageSkipped { stage, reason }, StageDone { stage, detail }, StageFailed { stage, summary, detail }, DiagnosticsHint { launch_or_session_ref }, OpeningHardline,}The exact Rust shape can differ, but the boundary should exist. Renderers then become replaceable:
| Renderer | Used when | Behavior |
|---|---|---|
| Rich TUI renderer | Interactive terminal with required capabilities | Full-screen ratatui launch surface with bounded rain, stage list, identity panel, footer, and error dialog. |
| Compact renderer | TTY without rich support or explicit no-TUI mode | Same events as short line output. |
| Non-interactive renderer | Script/CI/no TTY | Deterministic compact text, no cursor control, no animation. |
| Test renderer | Unit/integration tests | Captures events for assertions without terminal I/O. |
This also gives future console integration a clean transition: jackin console can tear down the manager, run the shared launch progress renderer, then open the Capsule hardline without duplicating the launch UI.
Parallelization plan
Section titled “Parallelization plan”Parallelization should come after the event/diagnostics boundary, because concurrent tasks must report progress without interleaving terminal output. The dependency graph should be explicit:
- Safe early parallel work: orphan cleanup, Docker connectivity probe, Git identity lookup, host identity lookup, terminal capability detection, and cached role metadata reads.
- Prompt barriers: source trust, branch confirmation, sensitive mount confirmation, and interactive manifest env prompts remain sequential and must finish before irreversible work.
- Credential preflights should run before expensive image/network work where possible so missing secrets fail early.
- Construct verification, Capsule-binary preparation, derived-image cache checks, and workspace materialization can run in parallel only when all host-side preflight prompts have completed and the dependency edge is explicit.
- Network and DinD sidecar setup can begin after names/resources are claimed and before the role image is ready if the Docker API path confirms no image dependency.
- Hardline remains last because the foreground terminal is handed to the selected agent session.
The first implementation should prioritize correctness and clean progress events. Parallel work should be added one dependency edge at a time with tests or trace assertions showing that failures still clean up claimed resources.
Implementation phases
Section titled “Implementation phases”Phase 0 — Roadmap and acceptance criteria
Section titled “Phase 0 — Roadmap and acceptance criteria”Capture the product model, UX rules, event vocabulary, diagnostics split, intro/outro lifecycle, and staged implementation plan. This page is that artifact.
Phase 1 — Boundary animation gating
Section titled “Phase 1 — Boundary animation gating”Replace launch-local intro/outro decisions with active container counting managed by jackin’. Ensure both jackin load and console-triggered launches use the same rule. Keep existing animations for now, but call them only at first-container start and last-container exit.
Phase 2 — Launch progress event sink
Section titled “Phase 2 — Launch progress event sink”Add a launch-scoped progress sink and route current StepCounter, config-table, auth notices, Docker launch milestones, restore decisions, cleanup notices, and failure paths through structured events. Keep the compact renderer initially so behavior changes are small and testable. This phase should establish the public stage names (identity, role, credentials, construct, derived image, workspace, network, sidecar, capsule, hardline) even before the rich TUI exists.
Phase 3 — Durable launch diagnostics
Section titled “Phase 3 — Durable launch diagnostics”Introduce a launch diagnostics artifact for pre-Capsule work and route debug traces into it while the launch progress renderer is active. Update failure messages to include a compact diagnostics reference. Ensure secrets stay redacted and --debug changes diagnostics verbosity, not TUI noise level.
Phase 4 — Rich TUI renderer
Section titled “Phase 4 — Rich TUI renderer”Build the ratatui launch renderer using console-compatible palette, layout, footer, fatal error dialog, and bounded rain. Reuse the existing rain engine where practical instead of creating a parallel animation implementation. Prototype more distinctive launch visuals only inside those constraints: footer-only hints, tight modal geometry, one focused action, no hidden shortcuts, no noisy debug stream, and no inline log output. Add snapshot-style tests once the Snapshot tests for TUI render roadmap item or an equivalent minimal harness is in place.
Phase 5 — Console integration
Section titled “Phase 5 — Console integration”Make console-triggered launches use the same renderer as jackin load. The console should select workspace/role/agent, then the shared launch progress surface owns terminal feedback until the Capsule hardline opens.
Phase 6 — Parallel launch execution
Section titled “Phase 6 — Parallel launch execution”Refactor launch execution around explicit dependencies and add parallelism where it reduces wall-clock startup without moving prompts later or weakening cleanup. Add debug trace spans so startup regressions and race failures can be reconstructed from diagnostics.
Documentation impact
Section titled “Documentation impact”When implementation lands, update the operator-facing command docs for jackin load and jackin console to describe the visible behavior without internal paths or Rust names. Contributor-facing updates should land in TUI Design Decisions, Codebase Map, and any runtime launch internals page touched by the implementation.
Host-side effects
Section titled “Host-side effects”The design may add a host-side diagnostics artifact under state owned by jackin’ and may write launch progress metadata tied to an instance. That is acceptable only if it stays under the existing host state convention for paths owned by jackin’, is surfaced through a compact diagnostics reference, and is never used to mutate unrelated host state. The launch path must not edit host Git configuration, host remotes, shell rc files, gh config, agent homes, or terminal settings as part of making the TUI work.
Acceptance criteria
Section titled “Acceptance criteria”- Full digital rain appears only at first-container start and last-container exit.
jackin loadand console-triggered launch share the same progress vocabulary native to jackin’ and the same renderer selection.- Rich terminals get a full-screen launch progress TUI; non-rich and non-interactive environments get compact deterministic output.
--debugincreases diagnostics detail without dumping raw debug text into the TUI.- No launch surface renders raw logs, Docker build output, command output, stack traces, or debug traces; those live only in diagnostics artifacts.
- Fatal failures show a short diagnosis plus diagnostics reference, expose only
Enter Close, and exit immediately after close; detailed evidence stays in diagnostics. - Launch stages are emitted as structured events and can be tested without a real terminal.
- Startup parallelization is introduced only after evented progress and cleanup behavior are testable.