@aywengo/mercury
v0.2.0
Published
Durable long-running coding orchestration for PrimeAgent and other agent backends
Maintainers
Readme
Mercury
Mercury is a durable control plane for long-running coding agents, managing runs, state, workspaces, events, retries, and human input independently of browser sessions. Agents execute the coding work, while Mercury safely orchestrates when, where, and with which tools and instructions they run.
It is a harness for harnesses. Mercury never inspects a repository, edits a file, or runs a test; every one of those decisions belongs to the agent backend. What Mercury owns is everything that has to survive the agent process: the Run's identity and state, its workspace, its event history, the queue and lease that decide when it runs, and the human-input loop that resumes it. That separation is why one control plane can drive PrimeAgent, Claude, Hermes, a local CLI, a remote API, or a fake adapter in tests without any of them knowing about the others.
Mercury is a working Node.js and SQLite implementation. Creating a Run without
an agent field uses the built-in fake adapter (no extra CLI). PrimeAgent,
Hermes, Claude, and declarative local/RPC/remote adapters are optional backends
behind AgentAdapter.
What Mercury provides
- durable Runs whose lifetime is independent of HTTP, SSE and browser sessions;
- a separate API process and background worker;
- SQLite-backed scheduling, leases, state and event history;
- isolated Git worktrees and optional container sandboxing;
- structured progress events with resumable SSE;
- cancellation, retry and human-input flows;
- deterministic skill selection and per-Run skill records;
- a static operations dashboard;
- declarative local, remote and RPC agent adapters.
Control plane
flowchart TD
User[User] --> Surfaces["API, dashboard and chat"]
subgraph controlPlane [Mercury control plane]
Surfaces --> RunService[RunService]
RunService --> RunStore["Run state and snapshots"]
RunService --> Queue["Durable queue and leases"]
RunService --> EventStore["Structured event store"]
end
Queue --> Worker[Worker]
subgraph executionHarness [Execution harness]
Worker --> Workspace["Isolated workspace"]
Worker --> Skills["Selected skills"]
Worker --> Sandbox["Optional sandbox"]
Worker --> Adapter[AgentAdapter]
end
subgraph agentBackends [Agent backends]
PrimeAgent[PrimeAgent]
Hermes[Hermes]
Claude[Claude]
LocalAgent["Local CLI agents"]
RpcAgent["RPC agents"]
RemoteAgent["Remote API agents"]
FakeAgent["Fake agent for tests"]
end
Adapter --> PrimeAgent
Adapter --> Hermes
Adapter --> Claude
Adapter --> LocalAgent
Adapter --> RpcAgent
Adapter --> RemoteAgent
Adapter --> FakeAgent
Adapter --> Translation["Event translation"]
Translation --> EventStore
EventStore --> SurfacesMercury controls orchestration and process lifetime. Agent backends retain
responsibility for inspecting repositories, editing code, running tools and
producing results. Backends other than fake need their CLI (or remote API)
installed separately; npm install does not ship them.
Install
Requires Node.js ≥ 22.18 (built-in node:sqlite and TypeScript type stripping).
What each channel ships and how it is built:
docs/distribution.md.
On a fresh machine — the host installer. The guided path for macOS/Linux:
download, inspect, run. It installs the pinned package into your user npm prefix
(no sudo) and hands off to mercury host setup:
curl -fsSL https://github.com/aywengo/mercury/releases/latest/download/install.sh | bash
# or: npx @aywengo/mercury host installThe install.sh asset ships with the next host release (0.1.0/0.1.1 predate
the installer and carry no asset), so the one-liner resolves from then on. Full
walkthrough and the curl | bash safety note:
docs/host-installer.md.
From a checkout — works today. This also installs both commands, mercury (the
host) and mercuryctl (the operator client), because they ship in one package:
git clone https://github.com/aywengo/mercury.git
cd mercury
npm ci
npm install -g .
mercury --versionnpm ci compiles dist/ as part of installing, so the binaries work immediately.
Installing with npm install <git-url> instead of a clone also works.
From npm and Homebrew. These serve the published artifacts; see
Releases for what is currently
available. Prereleases are published under a matching dist-tag, so ask for one explicitly with
@aywengo/mercury@rc:
npm install -g @aywengo/mercury@rc
brew tap aywengo/mercury https://github.com/aywengo/mercury
brew install mercury-ai # not `mercury`: that is a different projectlatest is the stable channel and @rc is the prerelease channel. Both are moving dist-tags rather
than fixed versions: npm install -g @aywengo/mercury follows stable, and adding @rc follows release
candidates. Ask for an exact version with @aywengo/[email protected] if you need one to stay put.
One historical wrinkle worth knowing: 0.1.0-rc1 was published by hand without --tag, so npm applied
latest to a prerelease and refuses to delete the tag (400 Bad Request). Publishing 0.1.0 moved
latest onto a real version, which is the only correction npm allows. See issue #368.
There is no CLI-only channel. mercuryctl is inside the host package, so any install
that provides one provides the other.
Quick start
For prerequisites and a complete first-run walkthrough, see
QUICKSTART.md. The commands below run Mercury from a source
checkout without installing it.
npm install
MERCURY_EMBEDDED_WORKER=true \
MERCURY_API_TOKENS="tok-alice:alice" \
npm run devThe dashboard is available at http://127.0.0.1:3000/. Sign in with tok-alice
(the token, left of the colon — not the owner id alice). A first Run can omit
agent and will use fake.
Commands
| Command | Purpose |
| --- | --- |
| npm run dev | Start the API and, when enabled, the embedded development worker |
| npm run server | Start the API only |
| npm run worker | Start the background worker only |
| npm run migrate | Apply database migrations (also applied automatically on start) |
| npm run gc | Run one workspace-retention and quota pass |
| npm run typecheck | Run TypeScript checks |
| npm test | Run the core and Fleet test suites |
| npm run fleet | Manage federated Mercury hosts |
Operating Runs from a terminal
mercuryctl is the remote operator client: it talks to a running Mercury over its
HTTP API and never starts a server or a worker.
export MERCURY_CLIENT_URL=https://mercury.example.com:3000
export MERCURY_CLIENT_TOKEN="$MY_TOKEN" # never a flag: argv is readable with ps
npx mercuryctl agents list
npx mercuryctl runs create --task "fix the flaky test" --repo https://github.com/acme/api.git
npx mercuryctl runs list --status running --json | jq -r '.runs[].id'
npx mercuryctl runs watch "$RUN_ID"--json emits exactly one machine-readable value on stdout, exit codes are stable
and documented, and mercuryctl --help lists the commands this build implements.
The design is in docs/cli-tui-design.md.
Fleet
fleet/ is a separate product in this repository: a federation layer
that runs several independent Mercury instances as one fleet. It talks to each
Mercury over its public HTTP API, never touches a Mercury database, and imports
no Mercury code — a coupling test enforces the boundary.
The fleet CLI manages the host registry and probes it. fleet serve is the
part that has to outlive the operator who started it: submitting and routing Runs
across hosts, reconciling their state after a crash, aggregating events, and
serving one Prometheus rollup.
npm run fleet -- hosts add mac-studio --url https://studio.lan:3000 --credential mac-studio
npm run fleet -- hosts list --live
FLEET_API_TOKENS="tok-admin:admin" npm run fleet -- serveFleet has its own tests (npm run test:fleet), configuration, changelog, and
operator documentation. Its design is in
docs/fleet-design.md.
Documentation
Start with the documentation index, or go directly to:
System overviewAPI and dashboardConfigurationAgent backendsOperationsTestingCurrent status and limitationsDeploymentArchitecture specificationCrew designFleet design
Current constraints
Mercury is intentionally single-host because its coordination store is SQLite.
PrimeAgent RPC is the supported coding-agent transport; create-Run omits agent
as fake unless MERCURY_DEFAULT_AGENT is set. Daemon mode is experimental and
not production-ready. Named network destinations are not currently enforced, and
stored skill snapshots are not yet the bytes materialized by the worker.
See docs/status.md for the complete and current limitations.
License and contributing
Mercury is MIT licensed. Host changes are recorded in
CHANGELOG.md; Fleet has fleet/CHANGELOG.md.
How to cut a release: docs/releasing.md.
