USE DOCS · LOCAL CONTROL PLANE

Put Hopper to work,
from one Markdown file to a trusted merge.

This is operational documentation for daily use: initialize a vault, link a project, drop tasks, import GitHub Issues / ZenTao Stories, start runners, review evidence, merge changes, and recover the scene after failures.

$git clone https://github.com/Octo-o-o-o/Hopper.git && cd Hopper && npm ci && npm run build && node bin/hopper.mjs init
It's a local CLI with no server. Files and the event log stay on your machine; what actually goes out is the Claude / Codex runner and Hopper's own meta LLM calls.
initbuild vault linklink repo dropdrop task runisolate + gate reviewhuman decision mergemerge + archive events.jsonl — every step audited, replayable, reconcilable

FIG.00 — init → link → drop → run → review → merge, every step audited

SHEET 01
FIVE-MINUTE LOOP · FIRST RUN

Start with a low-risk task,
run the whole line.

Don't start with a big refactor. Run a README tweak, a doc addition, or a simple bugfix through init → link-project → drop → scan/triage → run → review → merge. That validates project config, runner login, verification commands, and the review loop all at once.

minimal loop · bash
# 0 · clone & build (Node ≥ 22; install from source until the npm package ships)
git clone https://github.com/Octo-o-o-o/Hopper.git && cd Hopper
npm ci && npm run build && npm link

# 1 · create the central vault
export HOPPER_VAULT="$HOME/Hopper"
hopper init

# 2 · link a project repo
hopper link-project --project my-app --repo /abs/path/to/my-app

# 3 · drop a low-risk task
cat task.md | hopper drop --project my-app --stdin

# 4 · triage, explain the queue, run one task
hopper scan
hopper triage --no-llm
hopper queue explain
hopper run next

# 5 · human review, then merge
hopper review list
hopper review diff <task-id>
hopper review approve <task-id>
hopper merge <task-id>
hopper archive <task-id> --cleanup-worktree

Check the first time

  • queue explain says the task can run
  • review diff contains only expected changes
  • verification / acceptance / docs have evidence
  • smoke passes before merge
  • status finally projects to done / archived

Don't do the first time

  • Don't open a daemon to run a batch
  • Don't start with high-risk or cross-project tasks
  • Don't let AI approve / merge for you
  • Don't put real secrets or .env in task bodies
SHEET 02
MENTAL MODEL · HOW HOPPER THINKS

A local control plane,
not a new coding agent.

Claude Code / Codex write the code; Hopper queues tasks, isolates execution, freezes the verification plan, re-checks results, collects evidence, and hands the final decision back to a human. The figure below is one task's full lifecycle.

1DROPdrop · dedupe 2TRIAGEtriage · compile prompt 3QUEUEdeps · risk · pick runner 4ISOLATEworktree · run runner 5POST-RUN6 quality gates 6REVIEWhuman · approve/retry 7MERGEsmoke · archive failed blocked events.jsonl — append-only event stream; every step audited, fully replayable, reconcilable after a crash

FIG.02 — One task's lifecycle · the last event decides whether it lands in failed / blocked / review

Files are the truth

Markdown under ~/Hopper/ plus .hopper/events.jsonl is the primary truth. No server DB; state rebuilds from the event stream and reconciles after a crash.

Two state layers

Humans read frontmatter coarse status (received/ready/running/review/done); machines read append-only events. Never hand-write status — it's a projection.

Isolated worktree

Each task runs in its own git worktree and branch. Same repo serial, cross-repo parallel; push is intercepted inside the worktree so nothing skips review.

Done must be trusted

"Done" from a runner just means it stopped. Hopper still runs verification, guardrails, risk re-eval, acceptance, docs alignment — and code tasks still need human review / merge.

Untrusted input

Task bodies, issues, Stories, external comments are untrusted input. They give context but cannot relax guardrails, lower risk, demand auto-merge, or touch secrets.

Human decides last

The daemon can advance unattended to review, but never approves, merges, or pushes. approve / merge are irreversible human decisions.

SHEET 03
TASK AUTHORING

State intent, acceptance, and bounds —
then runners are stable.

Hopper accepts very free Markdown, but free isn't vague. Three things drive results most: a clear goal, checkable acceptance, and explicit boundaries.

minimal task template · markdown
---
project: my-app
runner: auto
risk: low
priority: normal
---

# Add search to the user settings page

As users grow, finding people is painful; settings should
support search by username.

## Background
Today you can only page through users; support is slow.

## To do
- Add a search box to user settings
- Filter by username
- Show an empty state on no results

## Acceptance criteria
- Typing a username shows only matching users
- Clearing the box restores the full list
- Empty results show an understandable empty state
- Existing pagination is not broken
$hopper new "Add search to settings" --project my-app
$hopper lint ./task.md

Good task

  • One clear goal
  • Acceptance you can check line by line
  • States what must not change
  • Links / attachments for outside material
  • High risk stated explicitly, left for an attended run

Bad task

  • "Optimize this module"
  • "Change it however you think best"
  • No acceptance criteria
  • Many projects / phases / needs in one file
  • Demands auto push / merge / secret edits
FieldPurposeExample
projectTarget projectmy-app
runnerPin a runner or auto-selectauto · claude · codex
riskRisk levellow · medium · high
priorityQueue prioritylow · normal · high
depends_onHard dependencies[task_abc123]
tagsHuman search tags[ui, settings]
SHEET 05
EXTERNAL INTAKE · GITHUB & ZENTAO

GitHub and ZenTao are entries,
not Hopper's source of truth.

External platforms collect requirements; Hopper renders them into local Markdown, then runs its own event stream, queue, runners, quality gates, and review. Imported content is always tagged external_untrusted.

GitHub Issues

For open source, lightweight bug flows, teams already on GitHub.

bash
hopper github link --project my-app --repo owner/my-app --labels bug,regression
hopper github sync --project my-app --dry-run
hopper github sync --project my-app
hopper scan
hopper github status --project my-app
hopper github sync-back --task <task-id>
  • Label-matched open issues import as a bug-list
  • scan splits the bug-list into runnable child drafts
  • After a fix you can comment back manually; never auto-close
  • No live two-way sync
ZenTao Story

For teams running products / modules / Stories / cases in ZenTao. Hopper takes Stories as a structured intake only.

bash
hopper zentao doctor
hopper zentao import --product 1 --dry-run
hopper zentao import --story 109
hopper zentao sync-back --task <id>        # preview
hopper zentao sync-back --task <id> --yes  # publish
hopper zentao pull --apply --yes
  • import is read-only, idempotent by zentao://
  • sync-back previews by default; --yes publishes
  • Comment write-back by default; custom fields are read-back verified
  • pull only suggests; never changes state silently
External platforms are not the source of truth. Don't let a GitHub issue or ZenTao Story drive execute / approve / merge directly. They provide input, write-back, and suggestions at most; Hopper's state stays governed by the local event stream.
Integration surface for external orchestrators

If your own orchestrator / ticket system needs to drive Hopper, use these stable interfaces instead of guessing at internal state:

  • The RunSettled terminal event: the end-of-processing signal for one run (a settle barrier) — consumers treat it as the run being settled, no mechanical inference
  • hopper capabilities: capability / version handshake; event types, task statuses, and mutation commands are enumerated from the single schema source
  • The --req-id idempotency key: replaying the same req_id returns the first result and never re-executes (supported by drop / review / cancel / unblock and more)
  • --origin / --receipt: audit labels and an opaque external-approval receipt echoed into the record — they only enter the event payload and never change permissions or gate verdicts
  • hopper run <task-id>: the targeted execution trigger; exact same gates as run next, not a backdoor around them
  • State files: the daemon heartbeat .hopper/daemon-heartbeat.json (a stale ts means the daemon is dead) and the vault identity .hopper/vault.json (vault_id is never rewritten)
integration preflight · bash
# startup assertion: capability / version handshake
hopper capabilities --json

# resolved project config snapshot (preflight before dispatch)
hopper project show my-app --json

# trigger one specific ready task (idempotent + audited)
hopper run <task-id> --json

# approve with an idempotency key and audit label
hopper review approve <task-id> --req-id r-42 --origin my-orchestrator
The boundary stays put: external systems get the exact same gates as humans — --origin / --receipt are audit fields, not trust credentials; guardrails and the risk gate apply as usual.
SHEET 06
SCHEDULING · RUNNERS & QUEUE

It can run in parallel,
but defaults to conservative.

Before executing, Hopper checks task status, dependencies, risk, runner availability, usage / budget, repo lock, and global concurrency. Non-ready tasks aren't claimed; non-low-risk tasks aren't auto-run by the daemon.

execution · bash
hopper queue explain
hopper run next
hopper run --parallel
hopper drain --max 5
hopper drain stop
hopper daemon --max 10
hopper daemon pause
hopper daemon resume

Scheduling rules

  • Same repo serial; cross-repo parallel
  • Merge is always serial
  • Daemon auto-runs low risk only
  • Medium = attended run; high = explicit human handling
  • Conservative scheduling when usage is unknown

Before real runners

  • Command on PATH; Claude / Codex logged in
  • Codex: set home: ~/.codex explicitly
  • Run one low-risk task, check the four evidences
  • Only then consider daemon or parallelism

Trust tiers · four automation levels

Automation scales by trust tier rather than one switch:

  • observe: watch and record only, no auto-execution
  • assisted: the runner stops at plan-step boundaries with a breakpoint card; a human releases it
  • low_risk_autonomous: only low-risk tasks advance unattended, up to review
  • full_controlled: a wider automation surface, but S3-level sensitive operations always stay human

Budget envelopes

Set an envelope for a period's spend and get tiered alerts as it burns:

  • Alerts at the 70% / 85% / 100% thresholds
  • Runs with unknown cost are listed separately as unknownnever counted as zero; unreadable cost is never treated as free
  • Stacked on top of the existing usage hard gate and per-run cost ledger; visible via hopper usage / budget
multi runner profiles · ~/.hopper/config.yml
runners:
  claude:                # default Claude account
    kind: claude
    home: "~/.claude"
    command: claude
  claude-work:           # second Claude (separate login)
    kind: claude
    home: "~/.claude-work"
    command: claude
  codex:                 # Codex account
    kind: codex
    home: "~/.codex"
    command: codex

Task frontmatter: runner: auto picks one · kind:claude rotates same kind · claude-work pins exactly. hopper runner detect scans ~/.claude* ~/.codex* to suggest config; same repo serial, only cross-repo truly parallel.

SHEET 07
HUMAN GATE · REVIEW FIRST

After the runner stops,
the human makes the call.

Hopper stops once a task reaches review. You inspect the diff, verification, acceptance evidence, docs alignment, and risk re-eval, then approve, request changes, reject, retry, or merge.

review & act · bash
hopper review list
hopper review show <task-id>
hopper review diff <task-id>
hopper review patch <task-id> --out /tmp/h.patch
hopper review open <task-id>

hopper review approve <task-id>
hopper review approve <task-id> --waive docs:README.md --reason "confirmed"
hopper review request-changes <task-id> --message "add tests"
hopper review reject <task-id> --message "wrong direction"

hopper retry <task-id> --message "add tests per review"
hopper retry <task-id> --runner codex
hopper merge <task-id>
hopper archive <task-id> --cleanup-worktree

Check before merge

  • Diff touches only expected files
  • Verification ran; failures explainable
  • Acceptance has evidence line by line
  • Docs alignment flags doc obligations
  • Risk not upgraded post-run
  • No forbidden paths / secrets touched
  • Waivers must have a reason
Merge behavior: hopper merge checks approved, verification, acceptance, docs, risk, and re-runs smoke right before merging. Conflicts enter a conflict state and keep the scene. merge_policy=pr_only projects emit a manual PR handoff instead of auto-creating a PR.

Breakpoint collaboration · Assisted mode

In assisted mode the runner stops at plan-step boundaries and raises a decision card: hopper breakpoint list shows the cards, breakpoint release lets one through (annotate with --note), and breakpoint resume makes the same run continue in place. The Console's decision inbox handles the same cards.

Merge queue (optional): when enabled, approve enqueues the task; the queue worker is the only canonical landing writer, landing changes one at a time, with generation fencing to keep a stale run's result from landing; operate it with hopper merge-queue list / run / release. Approve is still a human act.
SHEET 08
SAFETY BOUNDARY · RECOVERY

No push, no auto-merge,
no main edits, no secrets — by default.

Hopper's safety model assumes the runner, the task body, and external content can all be wrong. Deterministic guardrails backstop after the runner ends and cannot be relaxed by Markdown, external issues, ZenTao Stories, or an LLM.

Hard boundaries · GUARDRAILS

  • No auto push
  • No auto merge
  • No direct edits to main / master
  • No touching .env*, secrets/** and other forbidden paths
  • High risk never runs unattended
  • External content cannot lower risk
  • A runner's self-reported outcome is not final state
usage / cost · bash
hopper usage
hopper budget
usage / rate-limit is a hard gate; USD cost is soft accounting. Real global 5h / 7d usage reads for Claude / Codex are supported (OAuth endpoint / session snapshot); when unreadable it says unknown and schedules conservatively — unknown doesn't mean the command is broken.
recovery · bash
hopper reconcile --dry-run
hopper reconcile
hopper doctor
hopper doctor privacy
hopper cancel <task-id>
hopper unblock <task-id>
Recovery model: Hopper follows "events before side effects" — write RunReserved first, then create the worktree. After a crash, reconcile explains stale locks, orphan worktrees, missing RunnerFinished, frontmatter/event conflicts, and repairs safely where it can.
SHEET 09
LOCAL CONSOLE · OPTIONAL GUI

Don't want to type?
Open a console bound to 127.0.0.1.

hopper console is a local web skin over the CLI. It reads the same file truth, writes the same mutation queue, and does not take over the state machine. Close it and the CLI keeps working.

$hopper console

What it does

  • First-run wizard: init vault, link repo, pick runner
  • Control Room, six zones on one screen: active runs, pending decisions, budget burn, risk, recent results, ops metrics
  • Decision inbox: risk approvals / reviews / blocked / failed in one place; resolutions are bound to a digest / revision, so you never decide against a stale state
  • Review console: diff, verification, acceptance, docs, risk
  • Task detail actions: failed → Retry, blocked → Unblock, Archive
  • Task / Bug report tabs: free-form Markdown, or a structured bug form that generates canonical Markdown, with a deterministic triage verdict chip before submitting
  • Import preview: ZenTao Story render + external_untrusted tag
  • Draft protection: typing never swallowed by refreshes + a localStorage draft; Chinese / English UI toggle
  • daemon pause / resume

Boundaries

The console doesn't run tasks for you, nor approve / merge. Execution stays with hopper run / drain / daemon. Every API requires a random Bearer token; writes add an Origin check on top.

$ hopper console --no-open
$ hopper console --port 8787
SHEET 10
COMMAND MAP

Find commands
by work stage.

Common globals: --vault <path> (overrides HOPPER_VAULT or the default ~/Hopper), --json (machine-readable, for scripts and AI agents), --debug.

Init & authoringinit · setup · new · lint
hopper init · setup · git initCreate vault / minimal first-run / init as Git repo
hopper link-project --project --repoLink a repo, write config + symlink
hopper new <title> --project · lint <file>Scaffold a task / read-only quality check
Intake & externaldrop · github · zentao
hopper drop [file] --project --stdinDrop Markdown into the Inbox, deduped
hopper scan · triage --no-llmRegister files + deterministic / optional-LLM triage
hopper github link/sync/status/sync-backGitHub Issues intake and write-back
hopper zentao doctor/import/sync-back/pullZenTao Story import, write-back, suggestions
Queue & executiondep · queue · run · daemon
hopper dep add/remove/accept/graph/explain/readyDependency management and explanation
hopper queue explainExplain why each ready task can(not) run
hopper run next · run <task-id> · run --parallel · drainRun one / one specific task / a batch / continuously
hopper daemon --max <n> · pause · resumeControlled auto-run (to review only)
Status · review · afterstatus · review · merge
hopper status · show · logs · usage · budgetState projection, details, logs, usage
hopper review list/show/diff/patch/openReview list / details / diff / patch
hopper review approve/request-changes/rejectApprove (with waiver) / request changes / reject
hopper retry · merge · archiveRetry / merge / archive
hopper check --base --staged --criteriaRun the four gates standalone on any repo's diff; trust report out
Recovery · Schema · Runner · Consoledoctor · runner · console
hopper reconcile · doctor [privacy]Reconcile + safe repair / health & privacy self-check
hopper cancel · unblock · move · reassignCancel / unblock / reassign tasks
hopper schema validate/export · runner list/show/probe/detectSchema validate/export / runner capability probe
hopper console --no-open --portLocal GUI console (bound to 127.0.0.1)
Platform ops · integration handshakecmd · stop · breakpoint · merge-queue
hopper cmd <verb> <target> · stop --release --statusUnified command service (durable / idempotent) / emergency stop & release
hopper breakpoint list/release/resumeAssisted-mode breakpoint cards: list / release / resume the same run
hopper merge-queue list/run/release · credentials resumeMerge queue ops / one-shot recovery from a credential pause
hopper intake list/resolve · attest request/confirm/reject/listIntake proposal resolution / human verdict → signed receipt
hopper project contract/gate/coverage/enroll · project show · capabilitiesDelivery contract chain / project config snapshot / capability handshake
SHEET 11
TROUBLESHOOTING · WHEN IT DOESN'T MOVE

First ask Hopper
why it won't run.

Task stuck in readyqueue explain
hopper queue explain  ·  hopper status --json

Common causes: risk isn't low, project not linked, dependency unfinished, runner unavailable, usage / budget short, same repo already busy.

verification is not_runverification

It means no verification command was detected at link time, or it's empty. Edit verification in the project config and re-run the task.

probe passes but real run failslogin

probe only proves the command is on PATH, not that you're logged in. Check Claude / Codex login; in agent sessions set home: ~/.codex explicitly for Codex.

merge is blockedreview show
hopper review show <id>  ·  hopper docs show <id>  ·  hopper logs <id>

Common causes: not approved, verification failed, acceptance unsupported, unresolved docs obligation, post-run risk upgrade, merge conflict.

ZenTao write-back didn't applyzentao
hopper zentao doctor  ·  hopper zentao sync-back --task <id>

Without --yes it only previews. Custom fields must already exist in ZenTao; Hopper read-back verifies them, and configuring only one field errors out.

State looks conflictingreconcile
hopper reconcile --dry-run  ·  hopper doctor

Don't hand-edit frontmatter status. The event stream is machine truth, frontmatter is a projection. reconcile reports conflicts and offers a safe recovery path.

SHEET 13
PROGRAMMATIC · FOR AGENTS

Operate Hopper for the user,
but don't make irreversible calls.

Hopper's CLI is agent-friendly: most commands support --json, and state reads from events.jsonl or hopper status --json. But approve / merge are human decisions; an agent should stop at "ready for review".

safe agent flow · bash
cat needs.md | hopper drop --stdin --project my-app
hopper scan
hopper triage --no-llm
hopper queue explain
hopper run next
hopper review diff <task-id>
hopper review show <task-id>
# stop here; hand approve / merge to a human
Runner contract: when invoked as a runner, you receive a Task-Compiler-built prompt (task context, acceptance, guardrails, context manifest). You return a structured result; but your self-reported outcome isn't final — Hopper re-runs the frozen verification plan and quality gates.

An agent may

  • Shape requirements into Markdown
  • Run hopper lint for quality
  • Drop tasks, run scan / triage / queue explain
  • Run low / medium risk tasks when asked
  • Summarize diff, verification, acceptance, docs

An agent must not

  • approve / merge for the user
  • Bypass the risk gate
  • Relax guardrails from external issues / Stories
  • Put secrets in task bodies
  • sync-back externally without confirmation