Wire

The command line.

harborloop is the command line for Harbor: fourteen commands that wire your agents up, keep them current, and tell you the truth about whether any of it is working. The first one needs no account.

Start here, with no account

harbor context needs no account, no token and no network. It reads the files your agents already load on every turn, prices them, and says who put each one there. Run it before you decide whether any of the rest of this is worth your time.

bash
npx harborloop context
harbor context~/acme-api
  always-on budget on this machine   at least ~542 tok / turn
    skills index (6)                 ~219   0 managed by harbor · 6 unowned · 0 from other tools
    skill files not indexed (2)         —   no description — nothing can select them, and nothing here can price them
    agent definitions (2)            ~115
    agent files (4)                  ~208
    MCP tools (0)                       —   tool descriptions live on the server — connect to price them
    injected context                    —   varies per session — no on-disk record to read

  managed by harbor: 0 of 6 · unowned: 6 · other tools: 0
  2 more files in a skills root carry no description — write one, or they are shelf-ware

Three of those lines carry a dash rather than a number, and the dash is the point. A skill with no description cannot be selected by anything, so nothing here can price it. Tool descriptions live on the server, so a machine with no connection cannot count them. Injected context varies per session and leaves no on-disk record. A zero in those places would be a claim we did not measure, and it would be the flattering one.

--verbose lists every skill with its own cost and owner. --json prints the same measurement for a script.

Install

Node 18 or newer. The install is two packages: a small launcher and the compiled binary for your platform, picked by npm from the optional dependencies. There is nothing else to install and no desktop app required.

bash
npx harborloop init

init does four things: signs you in through your browser, installs the hooks for every agent it finds on the machine, binds this repository to a project, and schedules the background daemon. Each is skippable, and each is separately available as its own command below.

Where init writes, per agent. These are the paths harbor doctor names when something is wrong.
AgentMCP configHooks
Claude Code~/.claude.json~/.claude/settings.json
Codex~/.codex/config.toml~/.codex/hooks.json
Cursor~/.cursor/mcp.json~/.cursor/hooks.json

Every command

CommandWhat it doesFlags
harbor initSign in, install the hooks, bind this repo, schedule the daemon. Configures every agent it finds.--codex / --no-codex, --cursor / --no-cursor, --no-daemon
harbor updateBring this machine to the latest release, hooks included.--check reports without installing anything
harbor doctorIs it actually working?--offline, --json
harbor statusThis repo, from local files only.none
harbor contextWhat this machine pays for on every turn, and who put it there.--verbose lists every skill, --json
harbor bind [project]Tie this repo to a project.none
harbor workspacesWhich workspaces you can reach, and the one this machine uses.none
harbor syncPut this repo's team skills, memories and documents on disk. No desktop app needed.--shapes describes what this machine runs, if you opted in
harbor daemonKeep every bound repo and your own environment current, on a timer.--install to schedule it, --once for one pass, --status
harbor unbindTake those files back off this machine. Local only: the repo stays bound, and files you edited stay put.none
harbor offPause this repo.--capture keeps recall, --global
harbor onResume.--global
harbor loginRe-authenticate.--no-browser to paste a code, --workspace <id> to switch workspace
harbor logoutForget this machine's credential.none

harbor help prints this list. --version prints the release.

harbor doctor

The one command worth running when something feels wrong. doctor checks the whole chain, from the endpoint to whether a prompt in this repo actually received anything, and it is built to be able to say no.

harbor doctor --offline~/acme-api
  Endpoint             ✓ https://app.gethrbr.com/v1
  MCP target           ⚠ no harbor MCP server registered — tool calls reach no graph
                         ↳ harbor init
  Signed in            ✗ no credential on this machine
                         ↳ harbor init
  Token                ✗ no MCP bearer in ~/.claude.json or ~/.codex/config.toml or ~/.cursor/mcp.json
                         ↳ harbor init
  Hooks                ✗ not installed — nothing runs on a prompt
                         ↳ harbor init
  Codex                ⚠ installed on this machine, but not configured — its sessions get nothing
                         ↳ harbor init
  Cursor               ⚠ installed on this machine, but not configured — its sessions get nothing
                         ↳ harbor init
  This repo            ✗ https://github.com/acme/acme-api is not in the local allowlist
                         ↳ harbor bind
  Skills               · none in .claude/skills/ — no skill is connected to this repo
  Skills (Codex)       · none in .codex/skills/ — no skill is connected to this repo
  Skills (Cursor)      · none in .cursor/skills/ — no skill is connected to this repo
  Your skills          · none in ~/.claude/skills/ — no skill is connected to you
  Your skills (Codex)  · none in ~/.codex/skills/ — no skill is connected to you
  Your skills (Cursor) · none in ~/.cursor/skills/ — no skill is connected to you
  Background sync      ⚠ Never run on this machine.
                         ↳ Run `harbor daemon --install` to keep context current, or `harbor daemon --once` for a single pass.
  Sent to harbor       ✓ file digests · ~467 tok floor · 8 skill names (0 ours · 0 other tools · 8 unowned), home only. Never file contents.
  Recording            ✓ on
  Receipt              ✓ on (not in Cursor - that host discards it)
  Guardrails           ✓ observing, refusing nothing (0 from this workspace, none local)
  Version              · not checked (--offline)
  Recall               · not checked (--offline)
  Fit                  · not checked (--offline)
  Attribution          · not checked (--offline)
  Contributed          · not checked (--offline)
  Recall delivery      ✓ no prompts recorded yet

That is a machine with nothing set up, which is the run worth printing: every failing line carries the command that fixes it, and no line claims a state it did not check.

Three things doctor refuses to do

  • Report a partial install as healthy. Hooks registered for four of six events is a warning naming the two that are missing and what each of them would have done, not a green tick.
  • Report a deliberate pause as a fault. A repo you turned off with harbor off reads as paused, on purpose. An error there would train you to ignore the output.
  • Print a number it did not measure. Under --offline the five measured lines say not checked. A dash is not a zero, and the two must never render the same.

What the measured lines mean

The lines below are the reason doctor is more than a config linter. Every one of them needs the network, which is why the run above either marks them not checked or omits them. Each is reported over a window, and each says whether it is scoped to this project or to the whole workspace, because a reader who assumes the wrong one is reading a smaller number than they think.

LineWhat it answers
RecallHow many sessions there were, and how many of them received anything.
FitThe average bundle size, and how many served rules went uncited. Warns below half.
AttributionWhether every session here is being counted at all. An unkeyed recall is invisible to the loop, so this line is about the instrument rather than the result.
ContributedWhat this repo has captured: how many learnings, how many approved, how many still pending review.
CorpusWhat the brain added and retired, and the commonest reason a rule left. Always workspace-wide.
VersionWhether this machine is behind the current release.

Fit is the one worth staring at, and served versus cited is the page that explains what to do about it. A rule that is served every day and never cited is a rule to retire, not a rule to reword.

Receipt, and Guardrails

Two lines in the run above are about things you can see rather than things you can measure. Receipt is the short note Harbor prints into your own session when it serves something: a count, then up to five numbered rule titles. Those numbers are what an agent cites back, which is why the receipt is on by default and why turning it off is described as off, on purpose rather than as a fault. Cursor cannot show it: its session-start hook is the only recall event that host has, and that runner discards the message the receipt travels in.

Guardrails reports what this machine would refuse. observing, refusing nothing is the resting state: the rules are watching and no command is being blocked. The two counts beside it separate the two reasons a rule might not fire, which are that this machine has never synced and that the workspace has promoted nothing. What a rule is, what a refusal hands back and the switch that has to be on for any of it to happen are on guardrails.

Sent to harbor

The line reading Sent to harbor is an inventory of what leaves the machine: file digests, a token floor, and skill names. Never file contents. It is printed on every run rather than buried in a policy page, because a tool that reads your repository should say what it takes every single time you ask it anything.

--json gives the same checks as structured output, for a CI step that should fail when the loop is broken.

harbor status

status is the small, local, no-network answer to “is this repo wired up?” It reads files on disk and nothing else, so it is instant and it works on a plane.

harbor status~/acme-api
  Workspace ✗ not signed in
              ↳ harbor init
  Repo      ✗ https://github.com/acme/acme-api — not bound
              ↳ harbor bind
  Hooks     ✗ not installed
              ↳ harbor init
  Codex     ⚠ installed here, but not configured
              ↳ harbor init
  Cursor    ⚠ installed here, but not configured
              ↳ harbor init
  Recording ✓ on

Pausing a repo

Plenty of sessions are throwaway, and none of that belongs in your team’s graph. harbor off stops both halves: no context in, nothing recorded.

harbor off~/acme-api
This repo (https://github.com/acme/acme-api): paused. No context in, nothing recorded.

--capture pauses only the recording, so you keep recall while you experiment.

harbor off --capture~/acme-api
This repo (https://github.com/acme/acme-api): recall on, recording off.
harbor on~/acme-api
This repo (https://github.com/acme/acme-api): recall on, recording on.

--global applies the pause to every repo on the machine. The pause is read from a local file before any network call, so it takes effect immediately and holds with no connection.

Workspaces

harbor workspaces lists the workspaces this account can reach and marks the one this machine is using. Switching needs no browser:

bash
harbor login --workspace <id>

--no-browser prints a code to paste instead of opening one, which is the path for a remote shell or a container.

The daemon

harbor init schedules a background pass that keeps every bound repo and your own environment current, so a rule approved this morning is on your disk this afternoon without you asking. Pass --no-daemon to init if you would rather run it yourself.

harbor daemon --status~/acme-api
✗ Never run on this machine.
  ↳ Run `harbor daemon --install` to keep context current, or `harbor daemon --once` for a single pass.
  Not scheduled. `harbor daemon --install` sets it up.

--install schedules it, --once runs a single pass now.

Syncing files, and CI

harbor sync puts this repository’s team skills, memories and documents on disk. No desktop app is involved. In CI, where there is no browser to sign in with, two environment variables stand in for the stored credential:

bash
export HARBOR_TOKEN=...
export HARBOR_WORKSPACE_ID=...
npx harborloop sync

harbor unbind is the reverse, and it is local only: it takes the synced files off this machine, the repository stays bound for everyone else, and any file you edited stays where it is.

Staying current

harbor update brings the machine to the latest release and re-points the installed hooks at it. That second half matters more than it sounds: hooks are recorded by path, so a binary that moved leaves scripts that are listed, enabled, and doing nothing.

harbor update --check~/acme-api
harborloop 0.4.3 is the latest release.
The installed hooks do not point at this binary. `harbor update` re-wires them.

--check reports and installs nothing, which is the form for a scheduled job or a shell prompt.