@gethmy/agent
Push-based agent daemon for Harmony, the shared surface for human–agent teams. It watches board assignments via Supabase Realtime, then implements and reviews cards with Claude CLI runs in isolated git worktrees. The agent runs where you put it: your laptop, a VPS, a VM, CI. Harmony owns the work, not the machine.
Built for failsafe auto mode: crashed daemons recover on restart, misconfigured columns fail fast, runaway costs trip a daily budget, and cards that can't pass build land in a dead-letter queue instead of bouncing forever.
Prerequisites
- Node.js >= 20 or Bun >= 1.0
- Claude Code CLI installed
- Git
- A Harmony account with an API key
- The repository connected (
hmy connect, or npx @gethmy/mcp connect with nothing installed)
Installation
npm i -g @gethmy/cli
hmy agent
npx @gethmy/agent@latest
Install when the machine is yours; use npx for a container, a CI step or a
one-off. Both forms stay supported.
npx can serve a stale build. The npx cache keeps serving the version it
first installed, @latest included — a restart six minutes after 1.38.0
published still ran 1.37.0 — so you get stale startup logs and CLI behavior.
If you suspect a stale run, clear the cache with rm -rf ~/.npm/_npx, or
install @gethmy/cli and run hmy agent to skip npx caching entirely.
Configuration
- Connect the repository first:
hmy connect
npx @gethmy/mcp connect
- Add agent config to
~/.hmy/agent/config.json. Every field is optional — the snippet below shows the common options with their defaults. For the full schema (worktree, verification, completion, priority labels), see docs/agent-daemon.md:
{
"agent": {
"poolSize": 3,
"pickupColumns": ["To Do"],
"claude": { "model": "claude-opus-5-5", "escalateModel": "claude-fable-5-1", "reviewModel": "sonnet", "deepReviewModel": "sonnet" },
"review": {
"enabled": true,
"poolSize": 2,
"pickupColumns": ["Review"],
"moveToColumn": "Done",
"failColumn": "To Do"
},
"budget": {
"maxAttemptsPerCard": 3, // give up on a card after N failed runs
"dailyBudgetCents": 40000 // $400.00/day across all workers; -1 = no cap
// 10x sdk.maxBudgetUsd (#1058); keep in proportion
},
"sweep": {
"enabled": false, // the daemon claims its own next card
"maxCardsPerSweep": 10 // cards one sweep may claim before it stops.
// -1 opts out, and then dailyBudgetCents
// must be set. Only `sweep resume` clears
// it, so http.enabled must be true.
},
"http": {
"enabled": true,
"port": 47821,
"bindAddr": "127.0.0.1" // LOOPBACK ONLY. The control server is
// unauthenticated, so this is its whole
// access control — POST /sweep/stop is the
// kill switch. 0.0.0.0, "" or a LAN address
// refuse the daemon at startup (#1061);
// tunnel to loopback for remote access.
},
"timing": {
"heartbeatMs": 30000,
"staleHeartbeatMs": 120000,
"reconcileIntervalMs": 60000,
"worktreeGcIntervalMs": 300000
},
"retention": { // the daemon's own history; -1 = keep forever, 0 rejected
"runRecordDays": 14, // ended RunRecords in the state file
"runLogDays": 30 // ~/.hmy/agent/runs/*.log
}
}
}
CLI
harmony-agent [run]
harmony-agent status
harmony-agent sweep
harmony-agent sweep stop
harmony-agent sweep resume
harmony-agent health
harmony-agent doctor
harmony-agent gc
harmony-agent dlq list
harmony-agent dlq clear <cardId>
harmony-agent help
--pretty
--json
status, health, and dlq clear route through the running daemon's HTTP server (127.0.0.1:47821 by default). dlq clear falls back to a direct state-store write only when the daemon is offline.
What the daemon does
- Watches the board in real time via Supabase Realtime.
- Picks up cards assigned to your agent user from configured columns.
- Implements changes in an isolated git worktree using a full-tool Claude run.
- Verifies the build + lint pass. Failures trigger an auto-fix attempt. Persistent failures move the card back to the
verification.failColumn (default: To Do).
- Pushes the branch and moves the card to
Review.
- Reviews the diff with a read-only Claude run against a live dev server. Verdict is either
approved (PR created, Ready to Merge label) or rejected (findings posted, card moved back to pickup).
Guarantees
- Resumable. A crash never orphans a card. On restart the daemon reconciles its own ghosts, returns implement cards to the pickup column with an
agent-recovered label, ends their Harmony sessions, and cleans up worktrees.
- Trustworthy. The review worker refuses to approve if the dev server didn't respond to an HTTP probe. Infrastructure failures are distinguished from code failures, so valid PRs don't get bounced back to rework.
- Bounded. Per-card attempt and cost caps plus a daily budget cap prevent runaway spend. When caps hit, cards go to a dead-letter queue with a label instead of silently re-queuing.
- Observable. Structured JSON logs on stderr (pipe to
jq), a local HTTP status endpoint, and per-worker heartbeats so the reconciler can detect zombie runs within 2 minutes.
- Safe. Claude subprocesses run in their own process group. Cancellation (SIGINT → SIGTERM → SIGKILL) terminates the whole subprocess tree, including build tools and dev servers Claude spawned.
State
Durable state lives at ~/.hmy/agent/state/<projectId>.json — one file per project, so two daemons on one machine never read or write each other's runs (#1057). Tracks live runs, per-card attempts and costs, daily spend, and DLQ markers. Atomic writes via write-to-tmp + rename. On the first start after upgrading, the daemon splits its own records out of the old machine-global ~/.hmy/agent/agent-state.json (a .pre-scope-backup copy is kept). The split is gated on its own <projectId>.json.migrated marker, so a failed or skipped attempt retries on the next start; a card record no worktree can attribute is copied into every project file rather than dropped.
Worktrees live at .harmony-worktrees/ inside your repo. A background sweep every 5 minutes removes directories older than 1 hour that no live run claims.
Debugging
Every Claude CLI run writes a per-run log at ~/.hmy/agent/runs/<runId>-card-<shortId>.log — full stdout (NDJSON), stderr, parse errors, and an exit footer with tool-call and cost totals. Start there when a run ends silently or the card activity log shows only "Still working..." heartbeats.
See Debugging a Silent Run for interpretation table and retention notes.
See docs/agent-daemon.md for the full architecture.