Runner Configuration
The runner is a local daemon that watches the Supabase tasks table for
queued work and executes it using an AI CLI (Claude Code or OpenAI Codex). It runs on
your machine where the CLI is installed with all your plugins, skills, and configuration.
What the Runner Does
The runner is the execution engine of oversight. It continuously polls for queued tasks and dispatches them to the configured AI CLI. Task types include:
- review — Full code review of a PR using Claude Code. Clones the repo, checks out the PR branch, and runs a detailed review prompt.
- analysis-pr / analysis-issue — Scans all open PRs or issues for a repo, computing engagement signals, staleness, and AI-generated summaries.
- resolve — Runs the full resolution workflow: multi-agent code review, bug fixing, commit reorganization, and push.
Starting the Runner
pnpm runner
On first launch, the runner copies .env.example to .env if
no .env exists. If required env vars are missing, it runs the interactive
setup wizard (pnpm runner:setup).
User Resolution
Tasks are shared but scoped: each runner only picks up tasks created by its authenticated user. The runner resolves its identity in this order:
- Disk cache —
~/.oversight/runner-user-idfrom a previous session. RUNNER_USER_IDenv var — explicit Supabase user UUID (useful for CI).- Auto-detect — if exactly one user exists in the database, uses them automatically.
- Browser OAuth — opens the browser to GitHub login, same flow as the dashboard.
Poll Interval
The runner polls the tasks table every 3 seconds for
new queued tasks. When a task is found, it is claimed atomically (status set to
running) to prevent double-execution by other runners.
MAX_CONCURRENT_TASKS limit defined in the shared package. When at
capacity, the runner skips polling until a slot opens up.
Nightly Auto-Refresh
Every night during the 2:00–2:59 AM local time window, the runner automatically queues fresh PR and issue analyses for all repos where it is the designated steward. This keeps dashboards up to date without manual intervention.
The nightly refresh:
- Checks on the heartbeat cycle (every 60 seconds), so the check itself is lightweight.
- Skips repos that were already auto-refreshed within the last 20 hours.
- Creates both a
analysis-prandanalysis-issuetask for each eligible repo. - Records the refresh timestamp in the
last_auto_refresh_atcolumn on therepostable.
Steward Mode
Each repo can have a designated steward — a user whose runner picks up tasks from other users when their runners are offline. The steward runner polls for additional tasks on repos it stewards, checking:
- The task creator's runner heartbeat is stale (more than 90 seconds old).
- The task creator has
stewardFallbackenabled in their user settings.
Heartbeat Monitoring
The runner sends a heartbeat to the runner_heartbeats table every
60 seconds, recording:
last_seen_at— timestamp of the last heartbeat.running_tasks— number of tasks currently executing.
The dashboard uses this to show runner status (online/offline). A runner is considered offline if its heartbeat is older than 90 seconds.
On shutdown, the runner sends a final heartbeat with running_tasks: 0
so the dashboard immediately reflects the offline state.
CLI Adapter System
The runner uses a pluggable adapter system to support different AI CLIs. Each adapter implements the same interface: spawning the process, parsing output, and detecting retryable errors.
| Adapter | CLI | Output Format | Retry Patterns |
|---|---|---|---|
ClaudeAdapter |
claude |
Stream JSON (--output-format stream-json) |
529, overloaded, rate limit, 502, 503, ETIMEDOUT, ECONNRESET |
CodexAdapter |
codex |
JSON events (--json --full-auto) |
429, 502, 503, rate limit, ETIMEDOUT, ECONNRESET, timeout |
Adapter Selection
Controlled by the OVERSIGHT_CLI environment variable:
OVERSIGHT_CLI=claude— use Claude Code.OVERSIGHT_CLI=codex— use OpenAI Codex.- Unset — auto-detect. Checks if
claudeis installed first, falls back tocodex.
Retry Logic
When the CLI process fails with a transient error (overloaded API, rate limit, network timeout), the runner automatically retries up to 3 times with increasing delays: 30s, 60s, 90s. Non-transient errors (e.g. invalid prompt, missing permissions) fail immediately.
Self-Update
The runner can update itself to the latest code when triggered remotely via the
runner_commands table. A self-update:
- Records the current git commit for rollback.
- Runs
git fetch origin. - Checks out and hard-resets to the target branch.
- Runs
pnpm install --frozen-lockfile. - If any step fails, rolls back to the original commit.
runner_commands table. The runner watches for these commands using
Supabase Realtime and restarts itself (with optional self-update) when triggered.
Repo Cache
The runner clones repositories into a local cache directory for review tasks. By
default this is $TMPDIR/oversight-repo-cache, which is lost on reboot.
For persistence, set OVERSIGHT_REPO_DIR to a stable path.
Each PR review checks out a fresh worktree from the cached clone, so reviews are isolated from each other and from the main clone.
Configuration Summary
| Setting | Value | Configurable |
|---|---|---|
| Poll interval | 3 seconds | Hardcoded |
| Heartbeat interval | 60 seconds | Hardcoded |
| Stale threshold | 90 seconds | Hardcoded |
| Nightly refresh window | 2:00–2:59 AM local | Hardcoded |
| Nightly refresh cooldown | 20 hours | Hardcoded |
| Max retry attempts | 3 | Hardcoded |
| CLI adapter | Auto-detect (claude > codex) | OVERSIGHT_CLI |
| Repo cache directory | $TMPDIR/oversight-repo-cache |
OVERSIGHT_REPO_DIR |
| Runner user identity | Auto-detect / browser login | RUNNER_USER_ID |