Skip to content

Troubleshooting

Start here:

Terminal window
openloop doctor # prerequisites, providers, daemon health
openloop service status
openloop logs --lines 100
openloop events --since 1h

Symptom: service start warns the daemon may not have started, or status shows nothing.

  • Check the log tail: openloop logs.
  • A stale PID file (crashed daemon) is detected and cleared automatically, but a PID pointing at a foreign process is refused. Remove ~/.openloop/run/daemon.pid manually if you know it’s wrong.
  • The daemon self-pauses after 5 consecutive tick errors; openloop resume restarts scheduling once the cause is fixed (see logs).
  • Run it in the foreground to watch behavior directly: openloop service run.

You installed from npm and newer commands (doctor, setup, digest, issue, dashboard, mcp, approval) don’t exist; the registry release lags the repository. Install from source, or rebuild an existing clone (npm run build) and re-link.

A globally linked openloop can also go stale after pulling new commits without rebuilding:

Terminal window
cd /path/to/openloop && npm run build

Expected: the bundled CLI targets Bun (its shebang is #!/usr/bin/env bun). Run openloop (the linked bin) with Bun installed, or bun dist/index.js.

  • openloop task list -p <alias> --status ready, only ready tasks are scheduled. Proposals need planning first (or task update --status ready).
  • Check budget: openloop status, a hit ceiling pauses the daemon (budget-blocked events confirm).
  • Check backpressure: ≥3 pending promotions skip the project until reviewed.
  • Awaiting approval: tasks in awaiting-approval never run until task approve.
  • run-once -p <alias> --dry-run shows exactly what the scheduler would pick and why.
  • Provider missing: openloop config list-providers; the chosen agent binary must be on PATH.
  • Timeout: runs are killed at runtime.runTimeoutSeconds (default 30 min). Long tasks need either a higher limit or smaller scope.
  • Prompt inspection: run-once --dry-run prints the exact prompt; --verbose prints it during a real run.

By design, auto-merge requires all of: low-risk task, policy allowing it, validations configured and passing, no blocking review findings, no hook veto. Check in order:

  1. config project-show <alias>validation block non-empty?
  2. promotion show -p <alias> --task <task> → decision + reason.
  3. Policy: risk.requirePolicyForAutoMerge needs a real policy; scope drift downgrades.
  • Auto-merge/pr modes need git; PR creation needs an authenticated gh (or a custom runtime.prCommand).
  • Dirty working tree: with worktrees disabled, OpenLoop tolerates a dirty tree but conflicts still fail the apply, commit or stash first.
Terminal window
openloop task recover -p <alias> # in_progress → ready
openloop pause # hold the loop
openloop service restart

.openloop/backup/<timestamp>/ keeps pre---force state if initialization went sideways.

Open an issue with the output of openloop doctor, openloop status, and a log excerpt (openloop logs --lines 200): github.com/jaltez/openloop/issues.