Documentation
¶
Overview ¶
Package main — api_cmd.go implements the "api" subcommand handler.
runAPI sends a one-shot prompt to an HTTP API executor (OpenAI, Anthropic, or Google AI) using the same pkg/executor/api surface that aimux production uses. The ExecutorV2 is wrapped in the L1 debugExecutor so structured JSONL events are emitted alongside the response, identical to the "cli" subcommand.
Usage:
launcher api --provider openai --model gpt-4o-mini --prompt "say hi" launcher api --provider anthropic --prompt "hello" --stream --log out.jsonl launcher api --provider google --api-key-env GOOGLE_AI_API_KEY --prompt "test"
Package main implements the launcher debug tool for aimux executors.
Package main — debug_diag.go implements the diag-mode Send path for debugExecutor.
sendViaSendStream is extracted here to keep debug_executor.go within the NFR-4 ≤ 300 LOC limit. It is the only entry point; all types it uses are defined in debug_executor.go and jsonl.go.
Package main — debug_executor.go implements the L1 ExecutorV2 decorator.
debugExecutor wraps any types.ExecutorV2 and emits structured JSONL events before and after each Send/SendStream call. Works identically over CLI adapters (pipe/conpty/pty) and HTTP API executors.
Event sequence per Send: spawn_args → complete → classify → breaker_state? → cooldown_state? SendStream adds a chunk event per streaming fragment. diag=true routes Send through sendViaSendStream (debug_diag.go) for realtime per-line output without bypassing the adapter via LegacyAccessor.
Package main — heartbeat.go provides the idle-heartbeat goroutine for --diag mode.
startHeartbeat launches a background goroutine that emits KindHeartbeat events and stderr log lines whenever the monitored process has produced no output for heartbeatInterval seconds. Callers close the returned stop channel when the process exits to terminate the goroutine cleanly.
Package main — interactive.go implements bidirectional interactive (TUI) mode for the session subcommand when backed by ConPTY or PTY executors.
runInteractiveSession owns the full I/O loop for interactive sessions:
- A reader goroutine drains sess.Stdout() and forwards raw bytes to the operator's terminal, passing ANSI escape sequences through unmodified so the CLI's TUI (header bar, status bar, prompt input) renders correctly.
- An input goroutine reads raw bytes from operator stdin and writes to sess.Stdin(). Slash-commands (/quit, /dump, etc.) are processed inline without forwarding to the session. Raw reads preserve escape sequences (arrow keys, Tab, Ctrl+X) that line-buffered readers would block.
- The main loop selects on stdout data, operator input results, and context cancellation (SIGINT/SIGTERM).
Contrast with runREPL (repl.go), which is the request/response loop used by the pipe backend: it sends a prompt, waits for a full response, then emits a turn{agent} event. runInteractiveSession makes no such assumption — bytes flow as they arrive in both directions.
WARNING (NFR-7): when --log is active and --executor is conpty or pty, the raw_bytes events written to the log MAY contain terminal escape sequences, pasted secrets, or other sensitive data. A warning is printed to stderr at session start.
Package main — jsonl.go implements the JSONL event sink for the launcher debug tool.
The EventSink interface abstracts NDJSON output so that all higher-level components (debug_executor, raw_spawn, repl) emit structured events without knowing whether output goes to a file or is silently discarded.
Event layout:
{"seq":N,"ts":"...","kind":"<kind>","payload":{...}}
Every Emit call increments the monotonic sequence counter atomically, so concurrent goroutines always produce strictly ordered seq values even when timestamps collide on fast hardware.
Command launcher is a standalone debug tool for testing aimux executor backends directly — without starting the MCP daemon, loom, or guidance layers.
It exposes the same pkg/executor surface that aimux production uses, making it the canonical way to reproduce CLI spawn issues without rebuilding the full server.
Subcommands:
cli — one-shot prompt via the best available CLI executor (ConPTY/PTY/Pipe) api — one-shot prompt via HTTP API executor (openai|anthropic|google) session — interactive REPL (CLI: --cli <name>; API: --provider <p>) replay — replay a JSONL log with optional kind filtering validate — run CR-002 launcher validation scenarios
Usage:
go run ./tools/launcher cli --cli gemini --prompt "say hi" go build ./tools/launcher && ./launcher cli --cli codex --prompt "echo test" ./launcher api --provider openai --model gpt-4o-mini --prompt "say hi"
Package main — raw_spawn.go implements the L2 pipe-only raw subprocess capture.
runRawCLI reimplements the spawn loop from pkg/executor/pipe/pipe.go with one key mutation: io.TeeReader is inserted BEFORE the line scanner so raw bytes reach the JSONL log pre-StripANSI, pre-redact.
Pipeline topology per stream (stdout shown; stderr is symmetric):
handle.Stdout ──► TeeReader(rawPW) ──► teeOut ──► stripped scanner goroutine
│
rawPW
│
rawPR ──► emitRawLines goroutine
Memory discipline (NFR-8): each line is emitted immediately — no accumulation.
Package main — repl.go implements the interactive multi-turn REPL for the session subcommand.
runREPL drives a line-oriented conversation against a types.Session. Stdin lines beginning with "/" are parsed as slash-commands; all other lines are forwarded as prompts to sess.Send.
Slash-commands:
/quit — close session, return exit 0 /reset — close current session, start a new one via sessionFactory /dump — print current breaker/cooldown/classify state /save <path> — snapshot the current log to <path> /raw on|off — toggle L2 raw tee on the CLI session (if supported) /history — print recent user/agent turns /help — list slash-commands
Inactivity timer: while sess.Send is running, a background goroutine prints a "." to stderr every second so the operator knows the session is alive. If the underlying session inactivity timeout (5 s default) fires before new data arrives the message "[inactivity timeout — Session.Send returning]" is printed; the inner error is then returned by sess.Send and propagated normally.
Package main — repl_helpers.go contains REPL display helpers extracted from repl.go to keep that file within the 300-line NFR-4 budget.
replay.go implements the 'launcher replay' subcommand — a JSONL log reader with optional kind filtering and two output modes: human-readable (default) and raw NDJSON (--raw).
Package main — session_cmd.go implements the "session" subcommand handler.
runSession starts an interactive multi-turn REPL against either a CLI session (via SessionFactory.StartSession on the pipe/conpty/pty executor) or an API session (if the API executor implements SessionFactory — currently not implemented; returns a clear error instead).
Usage:
launcher session --cli codex --log /tmp/sess.jsonl launcher session --cli claude --executor pipe
Flags:
--cli <name> CLI session (mutually exclusive with --provider) --provider <p> API provider: openai|anthropic|google (mutually exclusive with --cli) --model <m> model override --config-dir <dir> aimux config directory (default: "config") --api-key-env <var> env var name for API key (default: per provider) --executor <choice> pipe|conpty|pty|auto (CLI mode only; default: pipe) --cwd <dir> working directory for the spawned process --log <path> append JSONL events to this file