@zenera/cli 1.1.11 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +20 -0
  2. package/dist/banner.js +69 -47
  3. package/dist/commands/index.js +3 -0
  4. package/dist/commands/init.js +8 -4
  5. package/dist/commands/memory.d.ts +3 -0
  6. package/dist/commands/memory.js +375 -0
  7. package/dist/engine.js +14 -9
  8. package/dist/main.js +9 -0
  9. package/dist/podman.js +43 -9
  10. package/dist/projects.js +10 -2
  11. package/dist/scaffold.js +22 -1
  12. package/dist/tui/app.js +19 -11
  13. package/dist/tui/theme.d.ts +7 -0
  14. package/dist/tui/theme.js +18 -11
  15. package/package.json +2 -2
  16. package/templates/editor/.github/copilot-instructions.md +151 -43
  17. package/templates/editor/.github/prompts/review-project.prompt.md +5 -0
  18. package/templates/editor/.github/prompts/sync-with-spec.prompt.md +7 -4
  19. package/templates/editor/.github/skills/zen-cli/SKILL.md +3 -0
  20. package/templates/editor/.github/skills/zen-cli/references/memory.md +113 -0
  21. package/templates/editor/.github/skills/zen-cli/references/rag.md +2 -2
  22. package/templates/editor/.github/skills/zen-cli/references/run.md +3 -1
  23. package/templates/editor/.github/skills/zen-memory/SKILL.md +555 -0
  24. package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +16 -16
  25. package/templates/editor/.github/skills/zen-rag-schema/SKILL.md +2 -2
  26. package/templates/editor/.vscode/settings.json +4 -2
  27. package/templates/parts/exa.prompt.md.tmpl +4 -0
  28. package/templates/parts/exa.spec.md.tmpl +2 -0
  29. package/templates/project/INSTRUCTIONS.md +8 -0
  30. package/templates/project/SPECIFICATION.md.tmpl +47 -0
  31. package/templates/project/agents/prompts/{default.md → default.md.tmpl} +4 -0
  32. package/templates/project/agents.yaml.tmpl +4 -0
  33. package/templates/project/gitignore +7 -1
  34. package/templates/project/scripts/_setup.sh +101 -0
  35. package/templates/project/SPECIFICATION.md +0 -6
@@ -141,8 +141,9 @@ my-project/
141
141
  │ ├── SKILL.md
142
142
  │ └── scripts/calculate.py run at /skills/refund_policy/scripts — §3.4.1
143
143
  ├── assets/ reference material, read-only at /assets
144
+ ├── memory/ the graph agents remember into — §5.3
144
145
  ├── sandbox/Dockerfile the image commands run in — §3.7
145
- └── sessions/ run state, memory, whatever the agent wrote
146
+ └── sessions/ run state, whatever the agent wrote
146
147
  ```
147
148
 
148
149
  Only `agents.yaml` is required, and only `agents:` is required inside it.
@@ -224,6 +225,81 @@ agents do, for the same reason — it is a prefix somebody pays for:
224
225
  hand, so **edits inside `.github/` do not survive**. Project-specific conventions
225
226
  belong in `INSTRUCTIONS.md` and the agent prompts, which are never overwritten.
226
227
 
228
+ ### 2.5 What a running agent can actually see
229
+
230
+ The tree in §2.1 is the **author's** view. A running agent sees almost none of
231
+ it. Its entire world is the tools it was granted (§3.5) and four paths:
232
+
233
+ | Path | Is | Access |
234
+ | ------------ | ----------------------------------------- | ------------------------------------------------------ |
235
+ | `/workspace` | the session's workspace — the work itself | read/write; `zen run --read-only` withholds the writes |
236
+ | `/assets` | `assets/`, reference material — §3.11 | read-only |
237
+ | `/skills` | the whole skill catalog — §3.4.1 | read-only |
238
+ | `/memory` | files carried by remembered nodes — §5.3 | read-only, and only when `memory:` is configured |
239
+
240
+ Commands run inside the container `sandbox:` describes (§3.7): the same
241
+ `/workspace`, and whatever the image ships.
242
+
243
+ Everything else in the project directory is **invisible at run time** —
244
+ `agents.yaml`, `INSTRUCTIONS.md`, `agents/prompts/`, `agents/skills/` under that
245
+ name, `sandbox/Dockerfile`, `.env`, `.github/`, `sessions/`, and the project
246
+ root itself. `zen` reads them to build the run; they are never a path an agent
247
+ can open.
248
+
249
+ Two consequences:
250
+
251
+ - **The workspace is not the project.** It defaults to the session's own empty
252
+ folder, and is usually some other repository entirely — `--workspace`, or the
253
+ directory the user was standing in. A prompt saying "read `agents.yaml`" or
254
+ "the rules are in `agents/skills/`" names a file that is not there.
255
+ - **Write the mount path, never the repository path.**
256
+ `/skills/refund_policy/rates.csv`, not
257
+ `agents/skills/refund_policy/rates.csv`; `/assets/handbook.md`, not
258
+ `assets/handbook.md`. A relative path resolves against `/workspace`, which is
259
+ the one place the file is not.
260
+
261
+ An agent that must know something about its own configuration is **told it in
262
+ prose**, in the prompt — never sent to read the file that configured it.
263
+
264
+ #### Checklist — no path an agent cannot open
265
+
266
+ Run this over `INSTRUCTIONS.md`, every `agents/prompts/*.md` and every
267
+ `agents/skills/*/SKILL.md` after editing any of them. Every path-shaped token in
268
+ those files is read by a model as an instruction to open something:
269
+
270
+ - [ ] Every absolute path begins `/workspace`, `/assets`, `/skills` or
271
+ `/memory`. Nothing else exists.
272
+ - [ ] No project file is named: `agents.yaml`, `INSTRUCTIONS.md`,
273
+ `agents/prompts/…`, `agents/skills/…`, `sandbox/Dockerfile`, `.env`,
274
+ `.github/…`, `sessions/…`, `SPECIFICATION.md`, `README.md`, `docs/…`.
275
+ - [ ] Nothing escapes a mount: no `../`, no `~`, no host path (`/Users/…`,
276
+ `/home/<someone>`), no `/etc`, `/var` or `/tmp` expected to hold anything
277
+ the project put there.
278
+ - [ ] Each `/assets/…` and `/skills/<name>/…` path names a file that is actually
279
+ committed there — `zen check` lists what every skill folder ships (§3.4.1).
280
+ - [ ] A skill referring to its own sibling file writes the full
281
+ `/skills/<name>/` prefix, not `./rates.csv`: the body is rendered into a
282
+ prompt, not executed from its folder.
283
+ - [ ] `/memory` is named only in prompts for agents that have `memory:` (§5.3),
284
+ and `/assets` only where an `assets/` directory exists.
285
+ - [ ] The agent holding the prompt has the tool the path implies — `read_file`
286
+ to open one, `sandbox:*` to run one (§3.4.1).
287
+ - [ ] Every instruction that opens a file states what to do when it is not there
288
+ (§4.2, rule 6). Workspaces differ between runs; absence is normal.
289
+ - [ ] Relative paths appear only where `/workspace`-relative is what was meant.
290
+
291
+ Finding the candidates, from the project root — every path-shaped token in the
292
+ three trees, minus the ones under a mount:
293
+
294
+ ```sh
295
+ grep -Eohr '[~.]?/?[A-Za-z0-9_.-]*/[A-Za-z0-9_.*-]+' \
296
+ INSTRUCTIONS.md agents/prompts agents/skills \
297
+ | sort -u | grep -Ev '^/(workspace|assets|skills|memory)(/|$)'
298
+ ```
299
+
300
+ Everything it prints is either a false positive (a url, a `path/to` in a
301
+ sentence, `and/or`) or a path the agent cannot open. There is no third case.
302
+
227
303
  ---
228
304
 
229
305
  ## 3. File formats
@@ -1031,22 +1107,38 @@ agents:
1031
1107
 
1032
1108
  ### 5.3 Memory
1033
1109
 
1034
- Memory is the read-write twin of skills: written by the run, not authored. A
1035
- **scope** is a namespace string; agents bound to the same scope share what is
1036
- in it, and the default scope is the agent's own — so memory is private until
1037
- something says otherwise. Recall is automatic: matches for the current input
1038
- are injected before each call, which is what makes memory work without the
1039
- model remembering to look, and an agent with write access also gets tools to
1040
- search, add, update and delete entries.
1110
+ Memory is the read-write twin of skills: written by the run, not authored. It is
1111
+ a **graph** — a node is one thing worth keeping, an edge says how one led to
1112
+ another — so recall returns the connected piece rather than a ranked list, and a
1113
+ remembered script arrives with the request that asked for it.
1041
1114
 
1042
- It is a session-level facility rather than an `agents.yaml` key: `zen run`
1043
- binds each session's store under `sessions/`, so memory travels with the
1044
- session and is not part of this repository.
1115
+ It is configured in `agents.yaml`: a top-level `memory:` block says where the
1116
+ graph lives and what vectorises it, and `agents[].memory` says what each agent
1117
+ may do with it. It lives with the **project**, not the session — a memory that
1118
+ died with the session would be a cache. Recall is automatic on turns that follow
1119
+ new user input, which is what makes memory work without the model remembering to
1120
+ look.
1121
+
1122
+ ```yaml
1123
+ memory:
1124
+ embedding: main # without one, recall falls back to term overlap
1125
+ agents:
1126
+ - name: auditor
1127
+ memory: true # read, write, and recall before each new question
1128
+ ```
1129
+
1130
+ Every node carries an **audience**, and an agent's `sees` is the set it reads:
1131
+ one graph, masked per agent, never one graph each. The four `memory_*` tools are
1132
+ derived from `access` and are never listed in `tools:`.
1045
1133
 
1046
1134
  Do not treat memory as a database. It is for things learned that should
1047
1135
  persist. Anything authoritative — a rate, a policy clause, a procedure — belongs
1048
1136
  in a skill, where it is versioned and reviewable.
1049
1137
 
1138
+ The full treatment — kinds and relations, how ranking and stitching spend their
1139
+ budget, remembered files under `/memory`, audience design, and how to put memory
1140
+ in front of a `zen rag` index — is in the `zen-memory` skill.
1141
+
1050
1142
  ### 5.4 Cache discipline
1051
1143
 
1052
1144
  Rules that follow directly from "stable prefix = cache hit":
@@ -1601,9 +1693,9 @@ zen models pick --embedding # or --chat; the ref goes to stdout, alone
1601
1693
  Then re-run `zen check`.
1602
1694
 
1603
1695
  CLI (`zen --help` for the authoritative list): `zen init`, `zen run`, `zen check`,
1604
- `zen inspect`, `zen key`, `zen models`, `zen list`. **stdout is the answer, stderr
1605
- is the narration**; every command takes `--json`. Exit codes: `0` ok, `1` failed,
1606
- `2` usage, `3` invalid project, `4` no usable credential.
1696
+ `zen inspect`, `zen memory`, `zen key`, `zen models`, `zen list`. **stdout is the
1697
+ answer, stderr is the narration**; every command takes `--json`. Exit codes: `0`
1698
+ ok, `1` failed, `2` usage, `3` invalid project, `4` no usable credential.
1607
1699
 
1608
1700
  ---
1609
1701
 
@@ -1630,6 +1722,16 @@ Before finishing any change here:
1630
1722
  - [ ] No facts, rates or figures embedded in a prompt
1631
1723
  - [ ] No hedging, no meta-talk about the runtime
1632
1724
 
1725
+ **Paths (§2.5 — run its checklist over the three trees)**
1726
+
1727
+ - [ ] Every absolute path in `INSTRUCTIONS.md`, `agents/prompts/*.md` and
1728
+ `agents/skills/*/SKILL.md` is under `/workspace`, `/assets`, `/skills` or
1729
+ `/memory`
1730
+ - [ ] No prompt or skill names a project file — `agents.yaml`, a prompt path, a
1731
+ skill's repository path, `sandbox/Dockerfile`, `.env`, `sessions/`
1732
+ - [ ] No `../`, `~`, or host path; nothing assumes the workspace is the project
1733
+ - [ ] Every `/assets/…` and `/skills/<name>/…` path names a committed file
1734
+
1633
1735
  **Skills**
1634
1736
 
1635
1737
  - [ ] Every skill is `<name>/SKILL.md` — no bare `<name>.md` in the catalog
@@ -1674,35 +1776,37 @@ Before finishing any change here:
1674
1776
 
1675
1777
  ## 10. Where to change what
1676
1778
 
1677
- | Symptom | Change this |
1678
- | ------------------------------------------ | ------------------------------------------------------------------- |
1679
- | Wrong tone, wrong format, wrong length | `INSTRUCTIONS.md` (all agents) or the agent prompt |
1680
- | Says something forbidden | `INSTRUCTIONS.md` prohibition, stated specifically |
1681
- | Ignores a rule that only applies sometimes | Move the rule into a skill with a sharp description |
1682
- | Never loads the skill it should | The skill's `description`; or `preload` it |
1683
- | Loads too much, answers slowly | `allow:`, `maxIndexEntries:`, or `discovery: search` |
1684
- | Invents a number | A skill holding the figure, or a script that computes it — §3.4.1 |
1685
- | A skill in the catalog is never offered | It is a bare `<name>.md`; move it to `<name>/SKILL.md` — §3.4 |
1686
- | Cannot find a file its own skill names | Absolute `/skills/<name>/…` path, and `sandbox:*` — §3.4.1 |
1687
- | Rewrites a whole file to change one line | A prompt line preferring `apply_patch` — §3.6 |
1688
- | Edits files it should only be reading | Subtract the mutating tools, or `zen run --read-only` |
1689
- | Cannot run the build or the tests | Grant `sandbox:*`; add the toolchain to `sandbox/Dockerfile` |
1690
- | Installs the same packages on every run | Put them in `sandbox/Dockerfile`, or `sandbox.persist: true` — §3.7 |
1691
- | Answers from stale knowledge of the world | Grant `web_search` + `web_read`, and say when — §3.8 |
1692
- | Cites a page it only saw the excerpt of | A prompt line: `web_read` before quoting — §3.8 |
1693
- | Every web call refuses | No Exa key: `zen key add exa` — `zen check` warns — §3.8 |
1694
- | A model or embedder refuses every call | `zen models test <ref>` — if `blocked`, `zen models pick` — §8 |
1695
- | Answers instead of routing | Router prompt prohibition; check `handoffs:` |
1696
- | Routes to the wrong specialist | The target agents' `description:` fields |
1697
- | Gets stuck in the agent it routed to | The target needs a handoff back — §6.3 |
1698
- | Loses a detail after a handoff | Say it in the handoff; check the collapse policy |
1699
- | Works through N independent items serially | `fork:` on that agent, and a prompt line — §6.4 |
1700
- | Forks when the steps actually depend | Prompt line: branches cannot see each other |
1701
- | Slow and expensive on trivial cases | Demote that agent's model tier / reasoning effort |
1702
- | Fails only on genuinely hard cases | Promote that agent's tier, or split the hard path out |
1703
- | Shows no reasoning while it works | Turn summaries on for that model — §7.6 |
1704
- | Forgets across conversations | Continue the session rather than starting a new one |
1705
- | Breaks at load with a named path | Read the message — it names the exact key |
1779
+ | Symptom | Change this |
1780
+ | --------------------------------------------- | ------------------------------------------------------------------- |
1781
+ | Wrong tone, wrong format, wrong length | `INSTRUCTIONS.md` (all agents) or the agent prompt |
1782
+ | Says something forbidden | `INSTRUCTIONS.md` prohibition, stated specifically |
1783
+ | Ignores a rule that only applies sometimes | Move the rule into a skill with a sharp description |
1784
+ | Never loads the skill it should | The skill's `description`; or `preload` it |
1785
+ | Loads too much, answers slowly | `allow:`, `maxIndexEntries:`, or `discovery: search` |
1786
+ | Invents a number | A skill holding the figure, or a script that computes it — §3.4.1 |
1787
+ | A skill in the catalog is never offered | It is a bare `<name>.md`; move it to `<name>/SKILL.md` — §3.4 |
1788
+ | Cannot find a file its own skill names | Absolute `/skills/<name>/…` path, and `sandbox:*` — §3.4.1 |
1789
+ | Tries to open `agents.yaml` or its own prompt | The prompt names a file no agent can see — §2.5 |
1790
+ | Says a file is missing that is in the project | The workspace is not the project directory — §2.5 |
1791
+ | Rewrites a whole file to change one line | A prompt line preferring `apply_patch` — §3.6 |
1792
+ | Edits files it should only be reading | Subtract the mutating tools, or `zen run --read-only` |
1793
+ | Cannot run the build or the tests | Grant `sandbox:*`; add the toolchain to `sandbox/Dockerfile` |
1794
+ | Installs the same packages on every run | Put them in `sandbox/Dockerfile`, or `sandbox.persist: true` — §3.7 |
1795
+ | Answers from stale knowledge of the world | Grant `web_search` + `web_read`, and say when — §3.8 |
1796
+ | Cites a page it only saw the excerpt of | A prompt line: `web_read` before quoting — §3.8 |
1797
+ | Every web call refuses | No Exa key: `zen key add exa` — `zen check` warns — §3.8 |
1798
+ | A model or embedder refuses every call | `zen models test <ref>` — if `blocked`, `zen models pick` — §8 |
1799
+ | Answers instead of routing | Router prompt prohibition; check `handoffs:` |
1800
+ | Routes to the wrong specialist | The target agents' `description:` fields |
1801
+ | Gets stuck in the agent it routed to | The target needs a handoff back — §6.3 |
1802
+ | Loses a detail after a handoff | Say it in the handoff; check the collapse policy |
1803
+ | Works through N independent items serially | `fork:` on that agent, and a prompt line — §6.4 |
1804
+ | Forks when the steps actually depend | Prompt line: branches cannot see each other |
1805
+ | Slow and expensive on trivial cases | Demote that agent's model tier / reasoning effort |
1806
+ | Fails only on genuinely hard cases | Promote that agent's tier, or split the hard path out |
1807
+ | Shows no reasoning while it works | Turn summaries on for that model — §7.6 |
1808
+ | Forgets across conversations | Continue the session rather than starting a new one |
1809
+ | Breaks at load with a named path | Read the message — it names the exact key |
1706
1810
 
1707
1811
  ---
1708
1812
 
@@ -1715,6 +1819,10 @@ Before finishing any change here:
1715
1819
  versioned, cannot be shared, and is paid for on every call.
1716
1820
  - **The bare skill file.** `agents/skills/<name>.md` instead of a folder. It can
1717
1821
  never grow the table or script the next revision of the rule will want — §3.4.
1822
+ - **Pointing an agent at the project.** A prompt or skill naming `agents.yaml`,
1823
+ `INSTRUCTIONS.md`, `agents/skills/<name>/…` or `sandbox/Dockerfile`. None of
1824
+ them are on any path the agent can open, so the instruction fails on the turn
1825
+ that follows it — §2.5.
1718
1826
  - **Arithmetic in prose.** A skill that walks the model through a calculation it
1719
1827
  will get wrong, in a folder that could have held the script — §3.4.1.
1720
1828
  - **Politeness padding.** "Please try your best to be helpful." Costs tokens,
@@ -17,6 +17,11 @@ Work the checklist in §9 of the copilot instructions. In particular:
17
17
  `INSTRUCTIONS.md` that is true of only one agent.
18
18
  - **Facts.** Any number, threshold, fee or date living in a prompt is in the
19
19
  wrong file. Name it and say which skill it belongs in.
20
+ - **Paths.** Work the checklist in §2.5 over `INSTRUCTIONS.md`,
21
+ `agents/prompts/*.md` and `agents/skills/*/SKILL.md`. Every absolute path must
22
+ be under `/workspace`, `/assets`, `/skills` or `/memory`; nothing may name a
23
+ project file the agent cannot open, and nothing may assume the workspace is
24
+ this directory.
20
25
  - **Skill descriptions.** Each one a condition, not a title; no two overlapping.
21
26
  - **Tools.** Every grant justified by the agent's job; nothing mutating held by
22
27
  an agent that only reads; every granted tool mentioned by the prompt.
@@ -98,16 +98,19 @@ not a paragraph of instructions for a human.
98
98
  - `scripts/_setup.sh` is the **only** entry point — the leading underscore is
99
99
  what separates the runner from the steps it runs. It runs the steps in the
100
100
  order they depend on each other and is the single command that initialises the
101
- project. Consolidate any setup script that lives elsewhere into this shape,
102
- including one left at the project root.
101
+ project. `zen init` writes it; adding a step is adding `scripts/<name>.sh` and
102
+ its name to the `STEPS` list at the top of it. Consolidate any setup script
103
+ that lives elsewhere into this shape, including one left at the project root.
103
104
  - Every script starts `set -eu`, works from any working directory
104
105
  (`cd "$(dirname "$0")/.."` first), needs no arguments, and exits non-zero on
105
106
  failure so `scripts/_setup.sh` stops rather than continuing on a broken step.
106
107
  - **Re-entrancy is required.** Running `scripts/_setup.sh` a second time must be
107
108
  safe. A step whose output is present and newer than its inputs prints that it
108
- is up to date and returns 0; otherwise it redoes the work idempotently, writing
109
+ is up to date and exits **3**, which is how the runner tells `skipped` from
110
+ `ok`; otherwise it redoes the work idempotently, writing
109
111
  to a temporary path and moving it into place so an interrupted run never leaves
110
- a half-built artefact behind. `scripts/_setup.sh --force` redoes everything.
112
+ a half-built artefact behind. `scripts/_setup.sh --force` redoes everything,
113
+ and reaches each step as `$FORCE=1`.
111
114
  - **It must be watchable.** `scripts/_setup.sh` tees each step's output to
112
115
  `.tmp/logs/setup-<step>.log`, prints a heartbeat line while a long step runs,
113
116
  and finishes with one line per step: `ok`, `skipped`, or `failed`.
@@ -24,6 +24,7 @@ zen key <ls|add|use|check|rm|show|env> [ref] [options]
24
24
  zen models <providers|ls|search|show|test|pick> [ref] [options]
25
25
  zen check [name|dir] [--project <name|dir>] [--no-sandbox] [--no-models] [--strict] [--quiet]
26
26
  zen inspect [run] [--session <id>] [--open] [--rebuild] [--serve [port]]
27
+ zen memory [stats|ls|show|export|forget] [args] [options]
27
28
  zen sandbox [status|up|pull|clean|disk] [options]
28
29
  zen version
29
30
 
@@ -48,6 +49,7 @@ guess a flag, and do not read them all.
48
49
  | Which models exist, whether one works, recovering from a refusal | [models.md](./references/models.md) |
49
50
  | The container shell commands run in, images, `persist` | [sandbox.md](./references/sandbox.md) |
50
51
  | Run reports, trajectories, what a session directory holds | [inspect.md](./references/inspect.md) |
52
+ | What the agents remember, why something was recalled, forgetting | [memory.md](./references/memory.md) |
51
53
  | `zen faker` — a mock API from an OpenAPI/Swagger document | [faker.md](./references/faker.md) |
52
54
  | `zen rag` — searching an API description, or a pile of markdown | [rag.md](./references/rag.md) |
53
55
 
@@ -59,6 +61,7 @@ zen check validate everything before spending a turn
59
61
  zen run the TUI
60
62
  zen run "what changed?" one answer, this directory as the workspace
61
63
  zen inspect --open what the model was actually given
64
+ zen memory export --open the whole memory graph, as a page
62
65
  zen key ls --check which credentials still work
63
66
  zen models test <ref> whether one model actually answers
64
67
  zen models pick --embedding the first embedder that does, on stdout
@@ -0,0 +1,113 @@
1
+ # Memory — `zen memory`
2
+
3
+ ```
4
+ zen memory [stats|ls|show|export|forget] [args] [options]
5
+ ```
6
+
7
+ Alias: `mem`.
8
+
9
+ The memory graph from outside the agents. It exists to answer the question
10
+ memory always eventually raises: **why did it recall that?**
11
+
12
+ Only projects that enable memory have one, and the commands say so rather than
13
+ inventing an empty graph. Turning it on is the `memory:` block in `agents.yaml`.
14
+
15
+ This document is the command. For how the graph is organised, how to configure
16
+ it, and how to decide what an agent should remember, read the `zen-memory`
17
+ skill.
18
+
19
+ ## Subcommands
20
+
21
+ | Command | What it does |
22
+ | ------------------------- | ------------------------------------------- |
23
+ | `zen memory stats` | Size, vocabulary, whether it is embedded |
24
+ | `zen memory ls` | Nodes, newest first. Changes nothing |
25
+ | `zen memory show <id>` | One node in full, with what it links to |
26
+ | `zen memory export [f]` | The whole graph as one HTML page |
27
+ | `zen memory forget <id…>` | Remove nodes, their vectors and their files |
28
+
29
+ | Flag | Meaning |
30
+ | ----------------------- | -------------------------------------------- |
31
+ | `--project <name\|dir>` | Which project. Inferred from the directory |
32
+ | `--kind <name>` | Only this kind of node |
33
+ | `--audience <name>` | Only nodes committed under this label |
34
+ | `--files` | Only nodes that remember a file |
35
+ | `--stale` | Only nodes something has superseded |
36
+ | `--limit <n>` | Rows to list. Default 30 |
37
+ | `--out <file>` | Where `export` writes. Default `memory.html` |
38
+ | `--open` | Open the exported page |
39
+ | `--yes` | Do not ask before removing |
40
+
41
+ ## It reads unmasked, on purpose
42
+
43
+ Memory is masked per agent: a node's `audience` decides who can see it. Recall
44
+ is masked, ranked and truncated as well, so what an agent gets is never the
45
+ whole picture.
46
+
47
+ This command ignores all of that. When the mask is the thing that is wrong, the
48
+ part that was hidden is exactly the part you need — and this is a person at a
49
+ terminal in the project directory, not an agent inside a run.
50
+
51
+ It also contacts no model. The store is opened without an embedder, so
52
+ inspection is free and works offline; the price is that `ls` filters by text
53
+ rather than by meaning.
54
+
55
+ ## `export` is the one to reach for
56
+
57
+ ```sh
58
+ zen memory export --open
59
+ ```
60
+
61
+ One self-contained HTML file, three panes:
62
+
63
+ - **left** — every node, with a search box and filters for kind, audience,
64
+ files, superseded and unlinked
65
+ - **middle** — the graph as a Mermaid diagram, coloured by kind, with pan,
66
+ zoom, and a hop-focus selector for following one node's neighbourhood
67
+ - **right** — whatever you clicked, in full: the text, the metadata, the links,
68
+ and **the remembered file's actual content** — rendered as an image when it is
69
+ one, and as text otherwise
70
+
71
+ Clicking a node in either the list or the diagram selects it in both. Above 300
72
+ drawn nodes the diagram asks you to narrow it with the filters, because a
73
+ Mermaid graph that large is not a picture of anything.
74
+
75
+ It is a single file with no server behind it, so it attaches to a bug report.
76
+ The only network it does is fetching Mermaid; without that it degrades to a
77
+ working list and detail view.
78
+
79
+ ## Forgetting
80
+
81
+ ```sh
82
+ zen memory forget 01M1YPN0C8QRQS5BCZ03ABQ1G0
83
+ ```
84
+
85
+ Asks first, unless `--yes`, and refuses outright when there is no terminal to
86
+ ask at. A node, its vector row and its remembered file bytes go together —
87
+ there is one implementation of that, shared with the agent-facing tool, so the
88
+ three cannot drift apart.
89
+
90
+ **Forgetting is rarely the right correction.** The agents' own way to fix a
91
+ wrong memory is to commit the corrected node and supersede the old one, which
92
+ keeps the record of having been wrong. `zen memory ls --stale` lists what has
93
+ been superseded that way. Use `forget` for what should never have been stored —
94
+ a secret, a mistake, a pile of noise — not for what merely became untrue.
95
+
96
+ ## Reading `stats`
97
+
98
+ ```
99
+ nodes 7
100
+ edges 6
101
+ superseded 1
102
+ files 1 · 640 B
103
+ embedding none — recall falls back to term overlap
104
+ vectors —
105
+ ```
106
+
107
+ `embedding none` is worth noticing: without an embedder, recall matches on
108
+ shared terms rather than on meaning, which works but is much blunter. Set
109
+ `memory.embedding` in `agents.yaml` to change it.
110
+
111
+ A vector count lower than the node count means some nodes were committed while
112
+ no embedder was configured, and they will only ever be found by term overlap
113
+ until they are re-embedded.
@@ -360,7 +360,7 @@ Every document is **copied into the index**, and every quoted line is read back
360
360
  out of that copy — so the index is one portable thing and what it quotes is the
361
361
  document rather than a reconstruction of it. Each document is named by its path
362
362
  relative to the common root of everything indexed, which is what keeps
363
- `nsx_4.1.0/api/routing.md` and `nsx_4.2.0/api/routing.md` apart.
363
+ `acme_4.1.0/api/routing.md` and `acme_4.2.0/api/routing.md` apart.
364
364
 
365
365
  ```
366
366
  docs-db/
@@ -395,7 +395,7 @@ ask; the second call is the same question inside one part of the tree.
395
395
 
396
396
  ```
397
397
  zen rag docs search "how are rate limits counted"
398
- zen rag docs search --file "nsx_4.2.*/api/**" "rate limit for the users route"
398
+ zen rag docs search --file "acme_4.2.*/api/**" "rate limit for the users route"
399
399
  zen rag docs search --section "Rate limits" --kind table "requests per minute"
400
400
  zen rag docs search --mode text "X-RateLimit-Remaining"
401
401
  ```
@@ -83,12 +83,14 @@ run history. Ids look like `20260825-143012-a7f3`.
83
83
  .data/
84
84
  state.json the live, resumable state, rewritten after every run
85
85
  session.json when it was made, and the workspace it is rooted at
86
- memory/
87
86
  blobs/
88
87
  sandbox/home/ /home/agent inside the container
89
88
  .lock held while a run is in flight
90
89
  ```
91
90
 
91
+ Memory is **not** in here: the graph belongs to the project, at
92
+ `<project>/memory/`, so what one session learned is there for the next one.
93
+
92
94
  The recorded workspace is what makes resuming safe: a session that quietly
93
95
  changed what "the workspace" meant between turns would be unexplainable, so it
94
96
  is written once and reused.