open-overlord
v0.2606180944.0
Published
Overlord CLI — management, agent protocol, and runner for OpenOverlord
Maintainers
Readme
CLI Module
The ovld command-line surface — Overlord's primary, CLI-first product.
This module is the home for everything a user or agent invokes as ovld ….
Table of Contents
For Users
Setup
The CLI is client-only. Management commands, protocol sessions, and runner
queue operations all reach persistence through the backend URL you configure — only
help and version work without one. First-time setup is about pointing
ovld at a backend and verifying it is reachable.
First run
Install the published package:
install -g open-overlordAfter installing the published package:
ovld auth loginLogin verifies that a backend is configured. If none is set yet, it walks through
ovld config first — local setup offers http://127.0.0.1:4310 as the default
backend URL; cloud setup accepts a hosted backend URL.
Then confirm the connection and continue with projects, tickets, and agents:
ovld doctor
ovld config listSee Getting Started for the full walkthrough from install through first delivered ticket.
How the published CLI works
The npm package ships command parsing, config/auth onboarding, connector setup,
an HTTP backend client, and the local runner/agent launcher. It does not ship
SQLite, better-sqlite3, migrations, or the service-layer database runtime.
flowchart LR
cli["ovld npm CLI"] -->|"HTTP /api/*"| local["Desktop or local backend"]
cli -->|"HTTP /api/*"| cloud["Hosted backend"]
local --> sqlite["SQLite"]
cloud --> postgres["Postgres"]
cli -->|"spawn"| agent["Local agent CLI"]Local mode means ovld talks to a backend already running on your machine,
normally Desktop or a future db-only local backend. Cloud mode means ovld
talks to a hosted Overlord backend. In both modes, the backend owns persistence
and migrations; the CLI is a client of that backend.
Point the CLI at a backend
Configuration lives in overlord.toml (discovered from the current directory
upward, or in ~/.ovld/overlord.toml for a global install).
| Mode | Config key | How to set it |
| ---- | ---------- | ------------- |
| Local backend | backend_url | ovld config set local [url] — defaults to http://127.0.0.1:4310 |
| Hosted backend | backend_url | ovld config set cloud <url> |
ovld config set without arguments opens the interactive backend selector.
ovld config list shows the resolved target; ovld doctor checks that the
backend is reachable.
Environment overrides (useful in scripts and CI):
OVLD_HOME— relocate the entire global~/.ovlddata directory (SQLite, object storage, VCS baselines, native-session caches)OVERLORD_BACKEND_URL— backend the CLI targets; takes precedence over the resolvedoverlord.tomlbackend_urlOVERLORD_WEB_PORT— port the local backend binds when launchedOVERLORD_USER_TOKEN/OVLD_USER_TOKEN/USER_TOKEN— bearer token sent to the backend when set (checked in that order; takes precedence over stored credentials)DATABASE_URL— Postgres connection string read by a backend you run yourself (service layer + Better Auth); the client-only CLI does not open it
The local backend/Desktop package owns SQLite and migrations. The published npm CLI only stores the backend URL and sends HTTP requests.
Headless / container setup
In a container, CI job, or any non-TTY environment, configure ovld entirely
through environment variables and non-interactive flags — no interactive prompts
are required. Each item below is a single command:
# 1. Database URL — Postgres persistence for a backend you run in the same
# container (consumed by the service layer + Better Auth). Omit if the CLI
# only talks to an already-running remote backend.
export DATABASE_URL="postgres://user:password@host:5432/overlord"
# 2. Backend URL — where the CLI sends HTTP /api/* requests.
export OVERLORD_BACKEND_URL="https://overlord.example.com"
# 3. Auth token — bearer USER_TOKEN sent with every backend request.
# Generate one in Overlord Desktop: Settings > Tokens.
export OVERLORD_USER_TOKEN="out_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# 4. Agent connector — write the local agent connector config (non-interactive).
ovld agent-setup claude # one of: claude | codex | cursor | allThen verify the backend is reachable and authenticated:
ovld doctorNotes for headless use:
- No
ovld auth loginneeded. The token env vars (OVERLORD_USER_TOKEN,OVLD_USER_TOKEN, orUSER_TOKEN) are read directly and take precedence over stored credentials. To persist a token to~/.ovld/auth.jsoninstead, run the non-interactiveovld auth login --token out_...(works without a TTY). ovld agent-setupaccepts--home <dir>to target a specificOVLD_HOME,--dry-runto preview, and--jsonfor machine-readable output. List installable connectors withovld agent-setup --json.- Set
OVLD_HOME=/some/writable/dirif the default~/.ovldis not writable in your container; it relocates the entire CLI data directory. - Interactive
ovld auth login/ovld config set(no args) andovld setuprequire a TTY; use the env vars and explicit flags above in their place.
What requires the backend
These commands work without a backend: ovld help, ovld version,
ovld update, ovld config ..., and connector setup/inspection commands that only touch local
files. ovld update --check compares the installed package version with the latest
published npm version, and ovld update upgrades the global open-overlord
install through npm. Commands that read or mutate Overlord state — projects, tickets,
protocol calls, runner queue operations, and launch context assembly — call the
configured backend URL.
ovld runner is still local in the important sense: it claims work through the
backend API, then spawns the selected agent process on your machine in the
resolved project directory. The queue state remains in the backend.
For Developers
Contract Components
This module is the developer-facing home for three components defined in
CONTRACT.md:
| Component | Stable id | What it owns |
| -------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CLI Layer | cli | Management command names/shapes, project linking & discovery, config file locations (overlord.toml, .overlord/project.json), human-readable output conventions |
| Protocol Layer | protocol | ovld protocol subcommands and flags, session lifecycle (attach → (update\|heartbeat)* → (ask\|deliver)), context-assembly format, delivery payload + change-rationale recording |
| Runner Layer | runner | execution_requests queue claiming and launch, working-directory resolution, ovld runner commands, execution-target selection |
These stay distinct components in the contract (separate interaction surfaces
and ownership). They are grouped into one developer module because they are all
the ovld command surface and tend to be worked on together.
Documentation
Requirements and behavior specs are colocated in this module's
docs/ folder (see the root README for the
colocation convention):
- 01 — Core Domain and Lifecycle: projects, tickets, objectives, sessions, events, statuses, state transitions.
- 02 — CLI-First Product Surface: management commands, configuration, project linking, output contracts.
- 03 — Agent Protocol:
ovld protocollifecycle, context assembly, updates, delivery, attachments. - 04 — Runner and Launch Execution: execution requests, local runner, launch command generation, auto-advance.
- 05 — Review, Artifacts, and Change Tracking: delivery review records, artifacts, rationale coverage, local diff support.
- Test Plan: test plan for the
cli,protocol, andrunnercomponents — management commands, protocol lifecycle/attach-shape/validation conformance, runner queue atomicity, and surface smoke tests. Part of the root TEST_PLAN.md.
Code & Tests
The packaged CLI lives in this module as a self-contained Yarn sub-project:
yarn build:cli # compile TypeScript to cli/dist/
yarn test:cli # unit + subprocess smoke tests
yarn pack:cli # produce an installable tarball
node cli/bin/ovld.mjs versionLayout:
cli/
bin/ovld.mjs # published bin entry (imports compiled dist/)
src/ # TypeScript implementation
dist/ # build output (gitignored)
test/ # colocated tests, including cli/test/e2e/
package.json # bin map, build scripts, pack metadataThe CLI ships command parsing, config/auth onboarding, connector setup, backend
client calls, and local runner/agent launch logic. Run yarn build before using
the compiled CLI (node cli/bin/ovld.mjs …).
In-repo build vs installed CLI
Project-management work (ovld protocol attach/update/deliver, ticket creation,
launching) uses the installed ovld so those calls hit the installed
Desktop instance and real ticket data. Bare ovld on PATH always resolves to
the global install — keep it that way.
Testing in-repo CLI/Desktop changes must never touch that installed instance
(~/.ovld, :4310). Run the in-repo build against an isolated, throwaway
OVLD_HOME instead:
yarn ovld:dev <args>builds and runscli/bin/ovld.mjsunder a fresh ephemeralOVLD_HOMEand a dev backend port (:4320), e.g.yarn ovld:dev versionoryarn ovld:dev protocol discover-project.- The test suite (
yarn test,yarn test:cli, …) runs under the same isolation viascripts/with-ovld-home.mjs, so tests can never read or write the installed instance.
For a persistent local instance to smoke-test an in-repo Desktop/server build, export a stable home + dev port once, then run the server and CLI under it:
export OVLD_HOME="$(mktemp -d)" # or any throwaway dir outside the repo
export OVERLORD_WEB_PORT=4320
export OVERLORD_BACKEND_URL=http://127.0.0.1:4320
yarn workspace @overlord/webapp start # isolated backend on :4320
node cli/bin/ovld.mjs doctor # in-repo CLI → the isolated backendNever yarn link / npm link the workspace CLI (there is deliberately no
load:cli script): linking shadows the global ovld, so ovld protocol calls
would run untested working-tree code against your real ticket data.
Interaction Boundaries
Per the contract, the CLI/protocol/runner surfaces reach persistence only
through the configured REST/backend API — never direct table writes.
See the Interaction Surfaces section of CONTRACT.md before
making any cross-module change.
