# Dory: the agent's manual

> Dory is a local, governed personal-memory daemon for AI agents. It reads
> the sources the person connected, remembers what they said, and serves a
> governed context capsule to the person's own AI tools over MCP
> and hooks. Everything runs on the person's Mac.

> This is the manual Dory's installed build prints with `dory help --agent`,
> published here so an agent can read it before Dory is installed. Copied
> from the build of 9 November 2026; the installed build's own copy wins.
> Dory is not installable yet: there is no notarized build. Its known limits
> are at https://dory.systems/limits.md.

Memory reaches an assistant only through the SAY gate: the assistant's own
sharing (Work, Personal, or nothing), the person's never-say rules, the
sensitive-topic floor, and containment (journals, notes and any personal-life
source are known to Dory and never said). Every delivery leaves a disclosure
record. This file is the agent's manual: every read and narrowing verb below
runs as written. `dory help --agent` prints this file as the installed build
shipped it; `dory help --json` lists every verb, its flags and its effect.

## The line you may not cross

You may read, and you may make Dory quieter. You may NOT widen what Dory says,
grant it data, spend the person's money, or erase anything: those are the
person's own acts at their own terminal or in the Dory app (SPEC-D243,
R-CHANNEL). If a task needs one, tell the person the exact command. A verb
that would widen asks the person on their Mac; when it cannot, it exits 4.

## The doorbell: when the person must say yes

A widening you ask for (a source to connect, a spend raise, a sharing
change) prompts no one: Dory files it as an intent and the verb exits 4 with
`human_action` in the stderr error — `kind`, `url` (`dory://approve/<intent>`,
the link to hand the person: they approve it in Dory with Touch ID),
`poll_interval` and `expires_in` (seconds; ten minutes) and `next_step`, the
argv that waits for their answer. To connect a source, run it with `--json`: it
never opens a browser or waits, and prints `{"human_action": {...,
"verification_url", "poll": {"argv", "interval_ms", "expires_in_ms"}}}`.

```
dory source connect --kind notion --json
dory approve wait <intent> --json
```

`dory approve wait` exits 0 when the person approved and it is done, 4 while
they have not answered by its bound (`--for-ms`, default two minutes; run it
again), 1 when they declined, it expired (or never existed), or it failed.
An intent is a request, never a grant: ask again after it expires. Only the
person approves or declines it; your wait reads its state, never the result.
Installing Dory into an assistant is permitted (below).

## Install: put Dory into an assistant (an agent may run these)

Registering Dory's MCP server and writing its rules block into an assistant
is yours to do; granting Dory data is not. `dory setup <assistant>`
registers the server through the assistant's own mechanism, places the rules
block and, where supported, the skill — idempotent, backed up, reversible
(`--uninstall` removes exactly what it wrote). The first-class assistants are
`claude-code`, `claude-desktop`, `cursor`, `codex` and `gemini-cli`;
`dory setup --catalogue --json` lists every client this build knows, with
its setup command. An unsupported one is refused with the reason.

```
dory setup claude-code --json
dory doctor --json
dory setup --repair
dory rules cursor
```

`dory doctor` sends a synthetic recall through the MCP pipe and reports the
measured result; `dory setup --repair` previews what differs from the running
binary (`--yes` applies it). Where an assistant needs a pasted step (Cursor's
project rules, Claude Desktop's project instructions), `dory rules
<assistant>` prints the block: give it to the person with where to paste it.
After installing, the person grants folders and connects sources (`dory
source connect` rings the doorbell above; `dory source add-root` and `dory
source discover` are theirs alone).

Setting Dory up from nothing is one verb: `dory onboard --non-interactive
--json` (`dory-cli-onboard/1`) runs every step its flags choose (`--lane`,
`--budget-tokens`, `--source`, `--assistant`) and returns each step only the
person can take as `owed`, with the doorbell's link and the argv that carries
on (exit 4); `--resume` waits for those steps. The recovery card is never in
its output.

```
dory onboard --non-interactive --json --lane local --assistant claude-code
```

## The CLI contract (R-17)

Output: a terminal reads tables; a pipe reads JSON on every read verb
(`dory help --json` names each verb's `output_contract` and its JSON Schema
under `docs/schemas/`). `--human` forces the human rendering on any verb;
`--json` works on every verb: JSON wherever the verb has an answer
(`answers_json` in `dory help --json`), a typed `CLI_USAGE` refusal, never
prose, where it has none; a pipe needs neither. `--fields a,b.c` keeps only those dotted paths of a
JSON answer (an array along the path applies the rest to each element;
`contract` is always kept). Nothing is remembered between invocations:
every verb names its target.

Errors go to stderr as one object, `dory-error/2`: `{"error":{"contract",
"code","class","message","retryable","retry_after_ms","remediation","hint",
"explain","human_action","details"}}`. `code` is a stable SCREAMING_SNAKE
word (`DAEMON_UNREACHABLE`, `DAEMON_NOT_READY`, `HUMAN_ACTION_REQUIRED`,
`OPERATION_REFUSED`, `CLI_USAGE`, …); `dory help error <code>` explains it
offline. Retry only when `retryable` is true, after `retry_after_ms`.
`remediation` is `[{argv, effect, requires_human}]`: never run a step whose
`requires_human` is true — tell the person the command. On a doorbell,
`human_action` is `{kind, url, expires_in, poll_interval, next_step}`.

Exit codes, `dory-cli-exit/2`:

| Code | Word | Meaning |
|---|---|---|
| 0 | `ok` | the verb did what it says |
| 1 | `refused` | Dory or this machine refused, or the verb failed; nothing changed beyond what it printed |
| 2 | `usage` | the command line was wrong |
| 3 | `daemon_unreachable` | doryd did not answer: not running, still opening, or another build |
| 4 | `human_turn_required` | the change widens what Dory may say, or needs the person's own confirmation, and this invocation cannot give it |
| 5 | `transient` | doryd is opening, busy or rate-limiting; retry after `retry_after_ms` |

## Read: what Dory holds and what it would say

Ask the person's memory a question (the SAY-gated capsule, never raw memory;
`--json` is the versioned `dory-cli-json/2` envelope):

```
dory recall "what stack does the user's current project use?" --json
dory recall "<question>" --effort high --domain work
```

The person's own memory, by listing, id or phrase (JSON when piped; each row
carries its `atom_id`):

```
dory brain list --limit 20
dory brain list --text "<words>" --json
dory brain list --id <atom-id> --for claude-code
```

Why Dory holds a memory, and whether an assistant would be told it; what an
assistant may reach; the last delivery explained (all JSON when piped):

```
dory why <atom-id> --for claude-code
dory scope --for claude-code
dory scope
dory explain --last --for claude-code
```

What Dory worked out, run by run:

```
dory log --limit 5
dory log --since 2026-10-01 --json
dory log --run <run-id>
dory log --week
```

Health and diagnostics (content-blind: counts and closed words):

```
dory status --json
dory doctor --json
dory health report
dory digest --json
dory metrics --json
dory yield --json
dory graph census --json
dory source status
dory source registry
dory rule list
dory question list --json
dory ledger verify
dory backup list
dory recovery manifest --json
dory help --json
dory setup --catalogue --json
dory projection status --json
dory projection preview aider
dory remote credential list --json
dory remote reach status --json
```

## Narrow: make Dory quieter (an agent may run these)

```
dory sever <atom-id>
dory rule add --atom <atom-id>
dory rule add --name "<words>"
dory rule add --domain health
dory revert <run-id>
dory question pin "<question>"
dory question unpin <question-id>
dory source pause <source-id>
dory source disable <source-id>
dory remote credential revoke <credential-id>
dory remote reach off
dory projection remove aider
```

`dory sever` retires the memory (no longer current; reversible with the
`dory correct --undo` it prints) and adds a never-say rule for it. Removing a
rule (`dory rule remove <id>`), turning a sharing switch on (`dory
permissions`) or changing a source setting that widens are the person's turn:
the daemon asks them on their Mac.

## MCP

`dory setup <assistant>` registers the stdio server `dory mcp serve`. Four
tools, never more: `dory_recall` (a question; read), `dory_open` (a line it
served, by its handle `#k7f2a3` or `dory://line/<disclosure_ref>/<handle>`,
or an entity, read again with whose words it is, its source and date; read),
`remember_this` (a note to the person's memory; with `corrects` and a line's
handle, a correction of what that line said) and `dory_never_say` (a line, a
name or a topic made quiet for this assistant or all; at most 3 per assistant
a day, undone only by the person). Resources: `dory://capsule` (the standing
capsule), `dory://health` (the health report's closed words) and the
templates `dory://memory/{id}` and `dory://entity/{id}` — each served through
the same SAY gate as `dory_recall`, recorded like any delivery. An id or a
handle the assistant may not be given answers as one that names nothing.
Tool errors carry the same `dory-error/2` object as the CLI.

## Not for agents

`dory remember`, `dory forget`, `dory import`, `dory correct`, `dory source
authorize|add-root|discover`, `dory approve <intent>`, `dory lane connect`, `dory improve`,
`dory permissions`, extraction approvals, recovery, keys, updates and the
daemon's lifecycle are the person's, and so is `dory ask` (the person's
one-shot question to their own model lane, at their own terminal; from a pipe
or an agent's shell it exits 4). `dory help --json` marks each verb
`agent_may_run`; a `false` is the person's. `dory hook`, `dory slash` and
`dory mcp serve` are invoked by Dory's own integrations.
