autopilot

FAQ

Short answers to the questions that come up most often when running autopilot in anger. Most of these point at a deeper section in docs/concepts.md or docs/configuration.md — keep this page narrow and link out rather than duplicating prose.

Setup

I just want to try autopilot with no install. Does plain mode work from a fresh checkout?

Yes — the non-render layer (prompts.mjs, runner.mjs, events*.mjs, writer.mjs, tail.mjs, plain.mjs, bin/tui.mjs) is zero-dep. From the repo root:

node packages/tui/bin/tui.mjs --help

Only the Ink-rendered watch / run UIs require cd packages/tui && npm install.

Do I need any npm dependencies?

Not for plain mode (see the previous FAQ) — only Node ≥ 20 is required. The interactive Ink-rendered watch / run UI pulls Ink + React + Yoga + Commander via cd packages/tui && npm install.

How do I install a specific tagged release?

Today the install is a clone + npm link; pin a tag with git checkout before npm install:

git clone https://github.com/kloba/autopilot.git
cd autopilot
git checkout v0.7.0          # pin to a tagged release; tags are immutable
cd packages/tui
npm install
npm link                      # exposes `autopilot` on $PATH
autopilot --help

A future release will publish autopilot to npm so npm i -g autopilot@X.Y.Z works.

What happened to the ~/.copilot/extensions/ralph install?

The in-session Copilot CLI extension was retired in 0.7.0 — see the CHANGELOG.md extension-drop entry. The standalone autopilot binary is now the only product, and the legacy extension/ directory is gone. If you still have an ~/.copilot/extensions/ralph directory from an older install, it is inert (/extensions reload will no longer find a ralph extension); rm -rf ~/.copilot/extensions/ralph and switch to the autopilot CLI as documented in the README.

Running a loop

Why did my loop stop after exactly one iteration?

The most common cause is an early --completion-promise match. Both --completion-promise and --abort-promise use plain substring matching against the assistant’s response — if the agent quotes the trigger phrase mid-thought (e.g. “I’ll mark this COMPLETE when done”), the loop finishes. Pick a phrase the agent is unlikely to mention casually; LOOP_DONE_42 and similar unusual tokens work well. See configuration.md → Limitations.

Why does my loop never finish?

Three frequent causes:

  1. The prompt doesn’t actually instruct the agent to emit the --completion-promise literally. With a quoted/paraphrased completion phrase, only --max (or --stagnation-limit, --stop) ends the loop.
  2. Stagnation guard is disabled (--stagnation-limit 0) and the agent oscillates indefinitely. Re-enable with the default --stagnation-limit 3 or higher.
  3. min_iterations is high and the agent emits the completion promise too early — the runtime ignores the promise until min_iterations is reached. This is by design.

How do I stop a loop that’s running away?

Run autopilot run --stop <runId> from another terminal — it sets stopRequested in state.json. The currently-running iteration finishes normally; the driver emits a terminal abort event with reason: "user_stopped" afterwards. SIGINT / SIGTERM at the driver process flips the same flag.

Pause / resume — what’s the difference vs stop?

See docs/concepts.md → Pause / resume semantics for the state-machine writeup.

Output and observability

Where does a running loop’s event log live?

By default: ~/.copilot/autopilot/runs/<runId>/events.jsonl. Override the runs root with AUTOPILOT_RUNS_DIR. The <runId> shape is ${label}-${startedAt} — sortable, filesystem-safe, and surfaced in the armed event.

Legacy ~/.copilot/ralph-tui/runs is read on first run if the new path doesn’t exist; new emissions write to the autopilot path.

Which environment variables does autopilot read?

Canonical names are AUTOPILOT_RUNS_DIR, AUTOPILOT_COPILOT_BIN, and AUTOPILOT_NO_ATTRIBUTION. Legacy RALPH_TUI_* env-var names still work via fallback for one release with a one-line stderr deprecation notice.

How do I tail a running loop’s events?

autopilot watch              # tail the most recent run
autopilot watch <runId>      # tail a specific run
autopilot list               # enumerate recorded runs newest-first
autopilot replay <runId>     # print every event in a past run

How do I get a structured snapshot of a live run?

autopilot run --status <runId>

Reads the run’s state.json and renders iter counter, pause/stop flags, and (in --continue mode) the captured Copilot session id.

Commit attribution

How are loop-driven commits attributed?

Every commit produced inside a loop carries two Co-authored-by: trailers — one for the Copilot GitHub identity, one for the dedicated copilot-ralph bot account. The dual-trailer convention is baked into the SDLC prompts (--self-improve, --grow-project). See configuration.md → Commit attribution.

How do I opt out of the second copilot-ralph trailer?

Set AUTOPILOT_NO_ATTRIBUTION=1 in the environment before running the loop. The opt-out suppresses only the second trailer:

Co-authored-by: copilot-ralph <copilot-ralph@users.noreply.github.com>

The first Copilot trailer always ships. The legacy RALPH_NO_ATTRIBUTION=1 env var is still recognized for backwards compatibility. The opt-out is honored by the prompt, not enforced by the runtime — if a sub-agent ignores process.env, the trailer can still appear. Audit afterwards with git log -1 --pretty=%B to confirm.

Anything else?

If your question isn’t answered here, open an issue or skim configuration.md → Limitations — it covers the long-tail edge cases this page intentionally elides.