@zenera/cli 1.1.15 → 1.1.16

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 (30) hide show
  1. package/README.md +183 -119
  2. package/dist/banner.d.ts +5 -1
  3. package/dist/banner.js +2 -2
  4. package/dist/command.d.ts +5 -0
  5. package/dist/main.js +10 -6
  6. package/package.json +2 -2
  7. package/templates/editor/.github/copilot-instructions.md +253 -218
  8. package/templates/editor/.github/prompts/new-agent.prompt.md +6 -6
  9. package/templates/editor/.github/prompts/new-skill.prompt.md +7 -7
  10. package/templates/editor/.github/prompts/review-project.prompt.md +1 -1
  11. package/templates/editor/.github/prompts/sync-with-spec.prompt.md +26 -26
  12. package/templates/editor/.github/skills/zen-cli/SKILL.md +62 -6
  13. package/templates/editor/.github/skills/zen-cli/references/check.md +3 -3
  14. package/templates/editor/.github/skills/zen-cli/references/faker.md +14 -14
  15. package/templates/editor/.github/skills/zen-cli/references/frame.md +6 -6
  16. package/templates/editor/.github/skills/zen-cli/references/inspect.md +3 -3
  17. package/templates/editor/.github/skills/zen-cli/references/keys.md +9 -9
  18. package/templates/editor/.github/skills/zen-cli/references/memory.md +11 -11
  19. package/templates/editor/.github/skills/zen-cli/references/models.md +8 -8
  20. package/templates/editor/.github/skills/zen-cli/references/projects.md +3 -3
  21. package/templates/editor/.github/skills/zen-cli/references/rag.md +191 -56
  22. package/templates/editor/.github/skills/zen-cli/references/run.md +3 -3
  23. package/templates/editor/.github/skills/zen-cli/references/sandbox.md +8 -8
  24. package/templates/editor/.github/skills/zen-memory/SKILL.md +50 -50
  25. package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +71 -48
  26. package/templates/editor/.github/skills/zen-rag-schema/SKILL.md +67 -67
  27. package/templates/editor/.vscode/settings.json +5 -2
  28. package/templates/project/INSTRUCTIONS.md +1 -1
  29. package/templates/project/assets/README.md +1 -1
  30. package/templates/project/sandbox/Dockerfile.tmpl +3 -0
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-neo-dark.svg">
4
- <img src="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-neo-light.svg" alt="ZENERA NEO" width="720">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-cli-dark.svg">
4
+ <img src="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-cli-light.svg" alt="ZENERA CLI" width="720">
5
5
  </picture>
6
6
 
7
7
  [![npm](https://img.shields.io/npm/v/@zenera/cli.svg)](https://www.npmjs.com/package/@zenera/cli)
@@ -12,23 +12,27 @@
12
12
 
13
13
  # @zenera/cli
14
14
 
15
- **`zen` — build specialist agents. Share them. Run them from the command line.**
15
+ **`zen` - build specialist agents. Share them. Run them from the command line.**
16
16
 
17
- Not one general assistant that is passable at everything — a team built for the
17
+ `@zenera/cli` is the command-line package in the
18
+ [ZeneraNeo](https://github.com/andreyryabov/ZeneraNeo) toolkit. It creates,
19
+ runs, tests and improves the specialized agent systems defined by a project.
20
+
21
+ Not one general assistant that is passable at everything - a team built for the
18
22
  work you actually keep doing, under a name you can type:
19
23
 
20
24
  ```sh
21
- zen run accountant "Q3 — match the receipts drawer to the ledger, then update the return"
22
- zen run accountant "this MSA against our playbook — redlines, and what I must not sign"
23
- zen run analyst "why churn doubled in the EU accounts — the exports are in this folder"
25
+ zen run accountant "Q3 - match the receipts drawer to the ledger, then update the return"
26
+ zen run accountant "this MSA against our playbook - redlines, and what I must not sign"
27
+ zen run analyst "why churn doubled in the EU accounts - the exports are in this folder"
24
28
  zen run analyst "what changed in EU battery regulation this year, with sources"
25
- zen run devops "this week's advisories — which of them actually reach our code"
26
- zen run devops "the 03:12 outage — timeline, contributing factors, owners"
29
+ zen run devops "this week's advisories - which of them actually reach our code"
30
+ zen run devops "the 03:12 outage - timeline, contributing factors, owners"
27
31
  ```
28
32
 
29
33
  Three agents there, six things asked of them: an agent you have built is not a
30
34
  script with one job, it is a specialist you keep going back to. And it is work
31
- that comes back — every quarter, every sprint, every deal — which is exactly the
35
+ that comes back - every quarter, every sprint, every deal - which is exactly the
32
36
  work nobody has shipped you a product for.
33
37
 
34
38
  Once the agent exists it is a command: it works on the files you are standing
@@ -37,25 +41,25 @@ records every token it spent doing it.
37
41
 
38
42
  Getting there is three beats:
39
43
 
40
- 1. **Describe it.** You write `SPECIFICATION.md` — what the system is for,
44
+ 1. **Describe it.** You write `SPECIFICATION.md` - what the system is for,
41
45
  which specialists it needs, what each may reach for, what _done_ means. The
42
46
  rest of the folder is built to implement it.
43
47
  2. **Test it.** `zen check` validates the project and every file it names,
44
48
  `zen run` exercises it for real, `zen inspect` opens the record of what it
45
49
  actually did. When it comes out wrong you fix the specification, not the
46
50
  prompts, and go round again.
47
- 3. **Share it.** It is a folder — commit it, review it in a pull request, send
51
+ 3. **Share it.** It is a folder - commit it, review it in a pull request, send
48
52
  it. One `zen init <dir>` on a project that arrived by clone registers it
49
53
  without touching a thing, and it is their command now too.
50
54
 
51
55
  > Part of [ZeneraNeo](https://github.com/andreyryabov/ZeneraNeo). This is an
52
- > open-source side project for experimentation and chore work — **not** the
56
+ > open-source side project for experimentation and chore work - **not** the
53
57
  > official Zenera AI Platform. It carries no support or stability promises.
54
58
 
55
59
  ## What you build
56
60
 
57
61
  Half a page of specification turns into a system like one of these. Nothing here
58
- ships with the CLI — each is a folder somebody wrote, and could send you.
62
+ ships with the CLI - each is a folder somebody wrote, and could send you.
59
63
 
60
64
  | Project | The team inside it |
61
65
  | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -63,37 +67,37 @@ ships with the CLI — each is a folder somebody wrote, and could send you.
63
67
  | **analyst** | A planner that splits the question into branches; researchers that run in parallel over your files and the web; a statistician that writes and runs Python in the sandbox; an editor that joins it into one answer where every claim carries its source. |
64
68
  | **devops** | A gatherer that pulls advisories, logs, alerts and deploys into one picture; a tracer that works out whether a vulnerable path is reachable at all, or which change actually broke it; an engineer that plans the fix, applies it a step at a time, and stops the moment a check fails. |
65
69
 
66
- Build one, commit it, and it runs the same on anyone else's machine — on
70
+ Build one, commit it, and it runs the same on anyone else's machine - on
67
71
  whichever models they prefer, and without carrying your keys.
68
72
 
69
73
  ## What makes it different
70
74
 
71
- A coding agent with custom instructions can already play several roles, and a
72
- framework can already wire agents together. What neither gives you:
73
-
74
- - **A system that outlives the session.** Custom instructions and subagents live
75
- in a chat that ends. Here the system is a directory — versioned, reviewable,
76
- diffable, sendable. Improving it is a commit, not a paste.
77
- - **A specification that is enforced, not decorative.** `SPECIFICATION.md` is
78
- the source; where it and the files disagree, it wins. `/sync-with-spec`
79
- reconciles the two in both directions and `zen check` fails the project when
80
- they drift — with a code, a location and a fix per finding. A prose document
81
- nobody checks is a README; this one is checked.
82
- - **No application to build.** Frameworks hand you a library and leave you
83
- owning a program: graph code, state plumbing, retries, transport. Here an
84
- agent is an instruction, a model, tools, skills, who it may hand work to, and
85
- how it fans out. That is the whole list, and it is YAML. There is no glue code
86
- to maintain because there is no glue.
87
- - **A complete record, by default.** Every run writes its input, output and
88
- state, plus a self-contained `report.html` — the graph, every request, every
89
- token, every cost. Not a tracing vendor you sign up for; a file in the folder.
90
- - **Your keys stay yours.** They live in `~/.zenera`, never in the project. What
91
- you share is the system; the recipient runs it on their own credentials and
92
- their own choice of vendor.
75
+ Most tools give you one agent, or a framework and an empty file. This is a
76
+ factory: it designs the system for you, then keeps it honest.
77
+
78
+ - **You state the problem; a meta-agent designs the system.** Specialists,
79
+ prompts, tool grants, hand-offs, where it fans out - all of it drawn from what
80
+ you wrote, and checked before it ever runs.
81
+ - **A self-improving loop, not a one-off build.** Build, run, read the record,
82
+ change what was wrong, run again - and the system can drive that loop on
83
+ itself. Failures come back as findings with a cause and a fix, so the next
84
+ version is written rather than debugged.
85
+ - **It watches itself work.** Every run is recorded against the architecture it
86
+ declared - the agent nobody called, the skill that never fired, where the
87
+ tokens went. Nothing to instrument, nothing to sign up for.
88
+ - **Customisable all the way down.** Live in the specification and never look
89
+ lower. Or set the model, tools and memory of a single agent. Or take the
90
+ kernel itself and manage the trajectory turn by turn. No layer is sealed.
91
+ - **Your documents, searchable.** Hybrid retrieval over your files and your API
92
+ descriptions, plus a memory that is a graph rather than a bucket of rows - so
93
+ what an agent learned in March is still there in September.
94
+ - **Integrations it writes itself.** No MCP server to find, no connector to wait
95
+ for. If it has to reach your ERP, your database or a twenty-year-old SOAP
96
+ endpoint, it writes the call and runs it in a sandbox.
93
97
 
94
98
  ## Install
95
99
 
96
- Node.js 24+. One command — the OpenAI, Anthropic, Google and OpenRouter SDKs
100
+ Node.js 24+. One command - the OpenAI, Anthropic, Google and OpenRouter SDKs
97
101
  all ship with the CLI, so any provider works out of the box.
98
102
 
99
103
  ```sh
@@ -108,19 +112,28 @@ npx @zenera/cli --help
108
112
 
109
113
  ## Quickstart
110
114
 
111
- Four commands, from nothing to an answer:
115
+ From nothing to a specialized agent system:
112
116
 
113
117
  ```sh
114
118
  npm i -g @zenera/cli # every vendor SDK comes with it
115
119
  zen key add openai # asks for the key without showing it; stored in ~/.zenera
116
120
  zen init my-project # scaffolds a project and registers it
117
- zen run my-project "introduce yourself"
121
+ zen open my-project # open the specification and project in your editor
122
+ ```
123
+
124
+ In the editor, describe the job in `SPECIFICATION.md`, then send this in the
125
+ agent chat:
126
+
127
+ ```
128
+ /sync-with-spec
118
129
  ```
119
130
 
120
- The name works from anywhere after that, and the directory you are standing in
121
- is what it works on:
131
+ It creates the specialists, responsibilities, tool access and handoffs the job
132
+ needs. Back in the terminal, validate the generated system and run it against a
133
+ real workspace:
122
134
 
123
135
  ```sh
136
+ zen check my-project
124
137
  cd ~/code/some-repo
125
138
  zen run my-project "summarise this repo and write NOTES.md"
126
139
  ```
@@ -142,9 +155,8 @@ Giving a prompt on the command line skips every question: it starts a fresh
142
155
  session and uses the current directory as the workspace, with write access.
143
156
  `--session`, `--workspace` and `--read-only` override that.
144
157
 
145
- To change what the system does, open the project in your editor with
146
- `zen open`, edit `SPECIFICATION.md` to say what you actually want built, and
147
- send `/sync-with-spec` in the editor's chat. That is the next section.
158
+ To change what the system does, update `SPECIFICATION.md` and send
159
+ `/sync-with-spec` again. The next section explains that workflow in detail.
148
160
 
149
161
  ## You write the specification; a coding agent writes the system
150
162
 
@@ -152,7 +164,7 @@ send `/sync-with-spec` in the editor's chat. That is the next section.
152
164
  implements it. Where the two disagree the specification wins, so a change to
153
165
  what the system does starts there and not in `agents.yaml`.
154
166
 
155
- The one `zen init` writes is not a heading list — it is a true specification of
167
+ The one `zen init` writes is not a heading list - it is a true specification of
156
168
  the project just scaffolded, so you can read it against the files beside it
157
169
  before changing a word:
158
170
 
@@ -166,7 +178,7 @@ nobody to hand work to, because there is no second job to hand on.
166
178
 
167
179
  - The change asked for is in the workspace, or the question is answered from
168
180
  what is actually in it.
169
- - Everything the agent claims a command did, that command actually did — it was
181
+ - Everything the agent claims a command did, that command actually did - it was
170
182
  run, and its output was read.
171
183
  - The reply names what changed, file by file, and says what it deliberately did
172
184
  not do.
@@ -174,7 +186,7 @@ nobody to hand work to, because there is no second job to hand on.
174
186
 
175
187
  ### How you actually edit it
176
188
 
177
- `SPECIFICATION.md` is ordinary Markdown, so any editor will do — but the loop is
189
+ `SPECIFICATION.md` is ordinary Markdown, so any editor will do - but the loop is
178
190
  meant to be driven from a coding agent's chat, and `zen init` installs the
179
191
  prompts that make each step a single command:
180
192
 
@@ -188,14 +200,14 @@ or IntelliJ it can find. `--editor <cmd>` names one outright.
188
200
 
189
201
  In the window that opens:
190
202
 
191
- 1. **Edit `SPECIFICATION.md`** — what the system is for, which agents exist,
203
+ 1. **Edit `SPECIFICATION.md`** - what the system is for, which agents exist,
192
204
  what each may reach for, and what _done_ means.
193
205
  2. **Open the chat panel and send `/sync-with-spec`.** It reads the
194
206
  specification and every file implementing it, works out the difference in
195
207
  both directions, and changes the smallest thing that closes each gap.
196
208
  3. **Read `SPECIFICATION-FEEDBACK.md`**, which it writes for anything it could
197
209
  not do without guessing. Answer its questions by editing `SPECIFICATION.md`
198
- — not by editing prompts — and send `/sync-with-spec` again.
210
+ - not by editing prompts - and send `/sync-with-spec` again.
199
211
 
200
212
  Back in the terminal: `zen check`, then `zen run`.
201
213
 
@@ -204,40 +216,52 @@ Back in the terminal: `zen check`, then `zen run`.
204
216
 
205
217
  They are prompt files under `.github/prompts/`, which VS Code and its forks
206
218
  offer as chat slash-commands. Both `zen init` and `zen open` write them fresh,
207
- so they never go stale — and edits to them do not survive.
219
+ so they never go stale - and edits to them do not survive.
208
220
 
209
221
  | In chat | Does |
210
222
  | ----------------- | ----------------------------------------------------------- |
211
223
  | `/sync-with-spec` | Makes every file match `SPECIFICATION.md`, both directions. |
212
224
  | `/review-project` | Reads the project as a reviewer would, and reports. |
213
- | `/new-agent` | Adds an agent — prompt, wiring and hand-offs. |
225
+ | `/new-agent` | Adds an agent - prompt, wiring and hand-offs. |
214
226
  | `/new-skill` | Adds a skill under `agents/skills/`. |
215
227
 
216
228
  In an editor that does not support prompt files, paste the contents of
217
- `.github/prompts/sync-with-spec.prompt.md` into its chat instead — it is only a
229
+ `.github/prompts/sync-with-spec.prompt.md` into its chat instead - it is only a
218
230
  prompt. Alongside them, `.github/copilot-instructions.md` is the standing brief
219
231
  that explains this runtime to whatever agent is reading, and
220
232
  `.github/skills/zen-cli/` is the CLI's own reference for it.
221
233
 
222
234
  </details>
223
235
 
224
- ### The loop
236
+ ### The self-improving loop
225
237
 
226
238
  ```
227
- edit SPECIFICATION.md → /sync-with-spec → zen check → scripts/_setup.sh
228
- ↑ ↓
229
- └──────────────── read the report ←──────── zen run ─────┘
239
+ edit SPECIFICATION.md → /sync-with-spec → zen check → zen run
240
+ ↑ ↓
241
+ └───── refine the spec <-──── zen inspect <-───────┘
230
242
  ```
231
243
 
232
- The last turn is the one that matters. When a run comes out wrong, the fix is
233
- the sentence that was missing from the specification; the prompt edit follows
244
+ `zen inspect` makes the record visible: the run trace, timing and token
245
+ statistics, agent architecture, and memory used during the run.
246
+
247
+ ![Run inspection: trace, agent architecture, and memory](https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/0910_480.gif)
248
+
249
+ Every step is a command, and everything each one reads or writes is a plain
250
+ file: the specification, the findings `zen check` prints with a code, a location
251
+ and a fix, the record `zen inspect` renders of what the run actually did. So the
252
+ loop does not need you standing in it. Hand the whole cycle to the agent in your
253
+ editor and it runs on the system it just built - test it, read the failure,
254
+ change the sentence in the specification that caused it, rebuild, run again.
255
+ "Fix my project" is one instruction. (The first time round, `scripts/_setup.sh`
256
+ prepares the container the tools run in.)
257
+
258
+ The last turn is the one that matters. When a run comes out wrong the fix is the
259
+ sentence that was missing from the specification, and the prompt edit follows
234
260
  from that. Prompts patched directly drift away from the document meant to
235
261
  describe them, and a project whose specification is no longer true is a project
236
262
  with no specification.
237
263
 
238
- You are not expected to hand-author any of this. `zen check` is written to be
239
- read by a model as much as by a person — every finding carries a code, a
240
- location and its fix — so "fix my project" is one instruction. Full guide:
264
+ Full guide:
241
265
  [docs/specification.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/specification.md).
242
266
 
243
267
  ## A worked example
@@ -249,7 +273,7 @@ zen init repo-notes && cd repo-notes
249
273
  zen open # opens this folder in your editor
250
274
  ```
251
275
 
252
- Replace `SPECIFICATION.md` with what you want. This is the whole input — no
276
+ Replace `SPECIFICATION.md` with what you want. This is the whole input - no
253
277
  YAML, no prompt files:
254
278
 
255
279
  ```markdown
@@ -261,9 +285,9 @@ Read a codebase and leave a short written note about it in the workspace.
261
285
 
262
286
  ## Agents
263
287
 
264
- - `reader` — explores the workspace and forms a picture of it. May read files
288
+ - `reader` - explores the workspace and forms a picture of it. May read files
265
289
  and list directories, and nothing else. Hands off to `writer`.
266
- - `writer` — turns that picture into `NOTES.md`. May write to the workspace.
290
+ - `writer` - turns that picture into `NOTES.md`. May write to the workspace.
267
291
 
268
292
  ## Done means
269
293
 
@@ -271,7 +295,7 @@ Read a codebase and leave a short written note about it in the workspace.
271
295
  - Every claim in it comes from a file that was actually read.
272
296
  ```
273
297
 
274
- Send `/sync-with-spec` in the editor's chat. It writes `agents.yaml` — who
298
+ Send `/sync-with-spec` in the editor's chat. It writes `agents.yaml` - who
275
299
  exists, and what each may reach for:
276
300
 
277
301
  ```yaml
@@ -292,7 +316,7 @@ agents:
292
316
  handoffs: [reader] # a hand-off does not return by itself; give it a way back
293
317
  ```
294
318
 
295
- — and one prompt file per agent.
319
+ - and one prompt file per agent.
296
320
 
297
321
  <details>
298
322
  <summary>The prompt files it writes</summary>
@@ -320,15 +344,15 @@ lines. Then say where you put it and stop.
320
344
  | Key | Is |
321
345
  | ------------- | --------------------------------------------------------------------- |
322
346
  | `name` | how everything else refers to this agent |
323
- | `description` | what it is for — read by the _other_ agents when deciding to hand off |
347
+ | `description` | what it is for - read by the _other_ agents when deciding to hand off |
324
348
  | `system` | its own brief, in prose, at `agents/prompts/<name>.md` |
325
349
  | `model` | this agent's model; the top-level one otherwise |
326
- | `tools` | what it may reach for — `workspace:*`, `sandbox:*`, a named tool |
350
+ | `tools` | what it may reach for - `workspace:*`, `sandbox:*`, a named tool |
327
351
  | `handoffs` | who it may pass the work to |
328
352
  | `skills` | knowledge pulled in mid-run instead of carried in every prompt |
329
353
 
330
354
  The file is validated strictly at load: an unknown tool, a handoff to nobody, a
331
- missing prompt file — each fails immediately, naming the offending key, rather
355
+ missing prompt file - each fails immediately, naming the offending key, rather
332
356
  than surfacing three turns into a run as a confused model. Full reference:
333
357
  [docs/agents-yaml.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/agents-yaml.md).
334
358
 
@@ -345,21 +369,21 @@ zen inspect --project repo-notes --open # what it actually did
345
369
 
346
370
  That is the end of it: `repo-notes` is now a command like any other, in any
347
371
  directory, for as long as the folder exists. Commit the folder and whoever
348
- clones it types `zen init repo-notes` once — a directory that is already a
349
- project is registered, not rebuilt, and nothing in it is touched — and the name
372
+ clones it types `zen init repo-notes` once - a directory that is already a
373
+ project is registered, not rebuilt, and nothing in it is touched - and the name
350
374
  is a command on their machine too.
351
375
 
352
376
  ## A project is a folder
353
377
 
354
- Prompts, agent wiring, skills and tool selections are all files — Markdown and
355
- YAML — rather than code buried inside an application. So the folder can be
378
+ Prompts, agent wiring, skills and tool selections are all files - Markdown and
379
+ YAML - rather than code buried inside an application. So the folder can be
356
380
  committed, copied to another machine, reviewed in a pull request, and handed to
357
381
  someone else who runs it with one command. Credentials live in `$HOME`, never in
358
382
  the project, so there is no secret to strip before sharing it.
359
383
 
360
384
  ```
361
385
  my-project/
362
- SPECIFICATION.md what this is for — the intent
386
+ SPECIFICATION.md what this is for - the intent
363
387
  INSTRUCTIONS.md house rules, prepended to every agent
364
388
  agents.yaml who exists, what they may reach for
365
389
  agents/
@@ -379,29 +403,50 @@ happened when it ran. Nothing here is tied to the machine it was written on,
379
403
  which is the point of the CLI: it makes agentic systems shareable the way
380
404
  repositories are shareable.
381
405
 
382
- `zen init` also writes `.vscode/` and a `.github/` tree — a standing brief that
406
+ `zen init` also writes `.vscode/` and a `.github/` tree - a standing brief that
383
407
  explains this runtime to whatever coding agent you open the folder with, plus
384
408
  the prompts and skills it needs to keep the project matching its specification.
385
409
 
386
410
  ## Concepts
387
411
 
388
- - **Project** — a named directory holding a complete agent definition and the
412
+ - **Project** - a named directory holding a complete agent definition and the
389
413
  sessions that have run against it. It is self-describing: `agents.yaml` is
390
414
  what makes a directory a project, so moving or cloning it loses nothing.
391
- - **Session** — a context that persists across runs: one workspace, one memory,
415
+ - **Session** - a context that persists across runs: one workspace, one memory,
392
416
  one store for large files, and a record of everything that happened, added to
393
417
  as it goes. Resumable.
394
- - **Run** — one prompt in, one answer out, inside a session. Recorded in full,
418
+ - **Run** - one prompt in, one answer out, inside a session. Recorded in full,
395
419
  whether or not you were watching.
396
- - **Workspace** — the directory the agents may read and write. A prompt given on
420
+ - **Workspace** - the directory the agents may read and write. A prompt given on
397
421
  the command line uses the current directory; the TUI offers the session's own
398
422
  empty folder instead, and asks before using anything outside it.
399
- - **Keyring** — `~/.zenera/neo`, readable only by you. See
423
+ - **Keyring** - `~/.zenera/neo`, readable only by you. See
400
424
  [Credentials](#credentials).
401
- - **Cache** — `~/.zenera/neo/cache`, one place for work already done: vectors,
425
+ - **Cache** - `~/.zenera/neo/cache`, one place for work already done: vectors,
402
426
  parses, model listings, generated mocks. Shared by every project on the
403
427
  machine, and never emptied by anything but you. See [Cache](#cache--work-you-have-already-paid-for).
404
428
 
429
+ ## Sandbox commands
430
+
431
+ Agents use an isolated container when a project grants them command-line tools.
432
+ `zen run` prepares it automatically before the first command, but these commands
433
+ make setup, diagnostics and cleanup explicit - useful on a new machine or when
434
+ you want to validate a project's execution environment before a run.
435
+
436
+ ```sh
437
+ zen sandbox status # engine, project image and active containers
438
+ zen sandbox up # prepare the execution environment for this project
439
+ zen sandbox pull # pull or build this project's image only
440
+ zen sandbox status --project my-app # inspect a named project from anywhere
441
+ zen sandbox disk # storage used by the engine and known projects
442
+ zen sandbox clean # remove containers created by zen
443
+ ```
444
+
445
+ `status`, `up` and `pull` use the project in the current directory, or accept
446
+ `--project <name|dir>`. `--image <ref>` selects an image explicitly. `clean` and
447
+ `disk` are machine-wide operations, so use them when you mean to inspect or
448
+ remove resources beyond the current project.
449
+
405
450
  ## Commands
406
451
 
407
452
  | Command | Does |
@@ -409,11 +454,11 @@ the prompts and skills it needs to keep the project matching its specification.
409
454
  | `init` | Creates a project here, or in `<dir>`, and registers it. |
410
455
  | `list` | Every known project: sessions, last run, whether one is live. |
411
456
  | `open` | Opens a project in your editor. |
412
- | `key` | The credential keyring — add, check, switch, remove. |
413
- | `models` | What this machine can use — list, search, test, pick. |
414
- | `run` | Runs the project — the TUI on a terminal, a single answer otherwise. |
457
+ | `key` | The credential keyring - add, check, switch, remove. |
458
+ | `models` | What this machine can use - list, search, test, pick. |
459
+ | `run` | Runs the project - the TUI on a terminal, a single answer otherwise. |
415
460
  | `inspect` | Opens or rebuilds a run's `report.html`. |
416
- | `memory` | What the agents remember — size, listing, one node, or a whole page. |
461
+ | `memory` | What the agents remember - size, listing, one node, or a whole page. |
417
462
  | `check` | Validates the project and every file it names, and asks the models. |
418
463
  | `sandbox` | Checks and prepares the container that command-line tools run in. |
419
464
  | `cache` | What work has been kept, and getting rid of it. |
@@ -433,17 +478,36 @@ an installed one costs nothing until it is used.
433
478
  | `faker` | `@zenera/faker` | A mock API from an openapi/swagger document. |
434
479
  | `rag` | `@zenera/rag` | Search an openapi/swagger document as a graph. |
435
480
 
481
+ **`zen faker`** turns an OpenAPI or Swagger description into a working mock
482
+ server. It generates behavior for each route, checks the result against the
483
+ response contract, and reuses the generated implementation on later requests.
484
+
436
485
  ```sh
437
486
  npm i -g @zenera/faker
438
487
  zen faker serve api/openapi.yaml --port 8787 # a working mock, bodies written by a model
439
488
 
489
+ curl -s localhost:8787/users/12324
490
+ # { "user_id": 12324, "email": "brooke.hoffman@example.org", … }
491
+ ```
492
+
493
+ **`zen rag`** adds advanced retrieval for the knowledge an agent needs to work
494
+ from: documentation and API schemas. Document indexes support semantic,
495
+ full-text and hybrid search with passages returned alongside their source lines.
496
+ Schema indexes add graph-aware retrieval across operations, types, fields,
497
+ requests and responses, so an answer can include the connected API context
498
+ rather than an isolated match.
499
+
500
+ ```sh
440
501
  npm i -g @zenera/rag
441
502
  zen rag schema index --embedding openai:text-embedding-3-small ./specs/*.yaml
442
503
  zen rag schema search --output-property "user billing history" --format ts
504
+
505
+ zen rag docs index ./handbook --embedding openai:text-embedding-3-small
506
+ zen rag docs search "how does failover work when the primary is unreachable"
443
507
  ```
444
508
 
445
- They use this keyring and these credentials, so there is nothing new to
446
- configure. Details:
509
+ Use [@zenera/rag](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/rag/README.md)
510
+ for its complete retrieval capabilities and examples. Details:
447
511
  [@zenera/faker](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/faker/README.md)
448
512
  ·
449
513
  [@zenera/rag](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/rag/README.md).
@@ -455,7 +519,7 @@ The binary is installed under three names: `zen`, `zn` and `zenera`.
455
519
  Global flags: `-h/--help`, `-v/--version`, `--json`, `-C <dir>`.
456
520
 
457
521
  `stdout` carries the answer and `stderr` carries the narration, and `--json`
458
- works on every command — so `zen run … | jq` is a supported way to use this, not
522
+ works on every command - so `zen run … | jq` is a supported way to use this, not
459
523
  an accident.
460
524
 
461
525
  | Exit code | Meaning |
@@ -479,7 +543,7 @@ zen key add <provider> < key.txt # or pipe it in
479
543
 
480
544
  The value is never passed as an argument. A command line is visible to anyone
481
545
  listing running processes, is saved in your shell history and is captured in CI
482
- logs — so the hidden prompt and piping it in are the only two ways.
546
+ logs - so the hidden prompt and piping it in are the only two ways.
483
547
 
484
548
  Entries live in `~/.zenera/neo/keys.json`, in a file only you can read. They are
485
549
  copied into the environment just before a run, which has two consequences worth
@@ -490,14 +554,14 @@ checked out on a machine without `zen` still runs.
490
554
  | ------------ | ------------------------------------- | -------------------------------- |
491
555
  | `openai` | a secret | `OPENAI_API_KEY` |
492
556
  | `anthropic` | a secret | `ANTHROPIC_API_KEY` |
493
- | `google` | a secret — AI Studio | `GEMINI_API_KEY` |
557
+ | `google` | a secret - AI Studio | `GEMINI_API_KEY` |
494
558
  | `vertex` | a path to a service-account JSON file | `GOOGLE_APPLICATION_CREDENTIALS` |
495
559
  | `openrouter` | a secret | `OPENROUTER_API_KEY` |
496
- | `exa` | a secret — for the search tool | `EXA_API_KEY` |
560
+ | `exa` | a secret - for the search tool | `EXA_API_KEY` |
497
561
 
498
562
  `zen key add` verifies the credential against the provider before it finishes,
499
- but stores it either way: a key that cannot be checked right now — offline,
500
- behind a proxy — is not a key that is wrong. `--no-check` skips the call.
563
+ but stores it either way: a key that cannot be checked right now - offline,
564
+ behind a proxy - is not a key that is wrong. `--no-check` skips the call.
501
565
 
502
566
  ### Which key a model uses
503
567
 
@@ -533,12 +597,12 @@ been one does a short built-in list stand in.
533
597
  `zen models test` separates three kinds of failure, because each calls for a
534
598
  different action:
535
599
 
536
- - **refused** — the provider rejected the credential. Fix or replace the key.
537
- - **blocked** — the credential was accepted and the account then said no: an API
600
+ - **refused** - the provider rejected the credential. Fix or replace the key.
601
+ - **blocked** - the credential was accepted and the account then said no: an API
538
602
  switched off, an empty balance, a model this key was never granted. The key is
539
603
  fine; the account needs changing, and the command that changes it is printed
540
604
  with the error.
541
- - **unknown** — the question never arrived (offline, proxy, timeout). Nothing is
605
+ - **unknown** - the question never arrived (offline, proxy, timeout). Nothing is
542
606
  wrong with the key; try again.
543
607
 
544
608
  ```
@@ -559,11 +623,11 @@ zen rag schema index --embedding "$(zen models pick --embedding)" ./specs/*.yaml
559
623
 
560
624
  ### Setting up each provider
561
625
 
562
- The shape is the same everywhere — `zen key add <provider>`, then answer the
626
+ The shape is the same everywhere - `zen key add <provider>`, then answer the
563
627
  prompt. Open the one you need for its specifics.
564
628
 
565
629
  <details>
566
- <summary><strong>OpenAI</strong> — one secret, exported as <code>OPENAI_API_KEY</code></summary>
630
+ <summary><strong>OpenAI</strong> - one secret, exported as <code>OPENAI_API_KEY</code></summary>
567
631
 
568
632
  ```sh
569
633
  zen key add openai
@@ -575,7 +639,7 @@ zen key add openai
575
639
  </details>
576
640
 
577
641
  <details>
578
- <summary><strong>Anthropic</strong> — one secret, exported as <code>ANTHROPIC_API_KEY</code></summary>
642
+ <summary><strong>Anthropic</strong> - one secret, exported as <code>ANTHROPIC_API_KEY</code></summary>
579
643
 
580
644
  ```sh
581
645
  zen key add anthropic
@@ -585,7 +649,7 @@ zen run --model anthropic:claude-sonnet-4-5 "summarise this repo"
585
649
  </details>
586
650
 
587
651
  <details>
588
- <summary><strong>OpenRouter</strong> — one secret, exported as <code>OPENROUTER_API_KEY</code></summary>
652
+ <summary><strong>OpenRouter</strong> - one secret, exported as <code>OPENROUTER_API_KEY</code></summary>
589
653
 
590
654
  One credential for many vendors' models. The model id keeps its own vendor
591
655
  prefix, after the `openrouter:` one:
@@ -599,7 +663,7 @@ zen run --model openrouter:anthropic/claude-haiku-4.5 "summarise this repo"
599
663
  </details>
600
664
 
601
665
  <details>
602
- <summary><strong>Google AI Studio</strong> — one secret, exported as <code>GEMINI_API_KEY</code></summary>
666
+ <summary><strong>Google AI Studio</strong> - one secret, exported as <code>GEMINI_API_KEY</code></summary>
603
667
 
604
668
  One key and nothing else to configure: the shortest way to a working Gemini
605
669
  model.
@@ -610,7 +674,7 @@ zen check # google:gemini-3.5-flash now resolves
610
674
  ```
611
675
 
612
676
  The same Gemini models are also served by Vertex AI, under a different
613
- credential. Both can be configured at once — they are separate entries for
677
+ credential. Both can be configured at once - they are separate entries for
614
678
  separate services, and the prefix on the model reference decides which is used:
615
679
 
616
680
  ```sh
@@ -621,12 +685,12 @@ zen run --model vertex:gemini-3.5-flash "summarise this repo"
621
685
  </details>
622
686
 
623
687
  <details>
624
- <summary><strong>Vertex AI</strong> — a service-account file, or an express-mode key</summary>
688
+ <summary><strong>Vertex AI</strong> - a service-account file, or an express-mode key</summary>
625
689
 
626
690
  Vertex accepts two kinds of credential, and you never declare which one you are
627
691
  giving: if the value is a path to a file that exists it is treated as a
628
692
  service-account key, otherwise as an API key. The name you give the entry has no
629
- bearing on this — `vertex/express` is just an entry called `express`, exactly as
693
+ bearing on this - `vertex/express` is just an entry called `express`, exactly as
630
694
  `vertex/prod` is one called `prod`, and either name can hold either kind.
631
695
 
632
696
  **A service-account JSON file** is the usual one, and what production normally
@@ -638,7 +702,7 @@ zen key add vertex --gcp-location us-central1
638
702
  # Paste the key, or a path to the file: /Users/you/keys/vertex-sa.json
639
703
  ```
640
704
 
641
- The prompt is read by `zen`, not by your shell, so give a full path there — `~`
705
+ The prompt is read by `zen`, not by your shell, so give a full path there - `~`
642
706
  is not expanded. In a script, pipe the path in instead:
643
707
 
644
708
  ```sh
@@ -657,7 +721,7 @@ moving or cleaning up the original later cannot break it.
657
721
  - Which models a location serves varies per model and is not guessable. In one
658
722
  project, `gemini-embedding-2` answered at `us` but 404'd at `us-central1`,
659
723
  while `gemini-2.5-flash` did the opposite. New models often reach `global`,
660
- `us` and `eu` first. `zen models test vertex:<model>` is what settles it —
724
+ `us` and `eu` first. `zen models test vertex:<model>` is what settles it -
661
725
  `zen key add` only establishes that the credential itself works.
662
726
  - `--gcp-project <id>` is only needed when the `project_id` inside the file is
663
727
  not the project you want to bill:
@@ -686,7 +750,7 @@ keyring, so it is always visible which credential a run will actually use.
686
750
  </details>
687
751
 
688
752
  <details>
689
- <summary><strong>Exa</strong> — one secret, exported as <code>EXA_API_KEY</code></summary>
753
+ <summary><strong>Exa</strong> - one secret, exported as <code>EXA_API_KEY</code></summary>
690
754
 
691
755
  Not a model provider: this is what backs the search tool an agent reaches for
692
756
  when it has to look something up on the web.
@@ -706,7 +770,7 @@ Entries are named, so a provider can hold several, one of which is active:
706
770
  zen key add openai/work # a second entry
707
771
  zen key use openai/work # the one that runs will use
708
772
  zen key ls --check # everything stored, and whether it still works
709
- zen key show vertex/default # masked — --reveal prints the secret
773
+ zen key show vertex/default # masked - --reveal prints the secret
710
774
  zen key env openai # shell exports, for other tools
711
775
  zen key rm openai/work
712
776
  ```
@@ -722,12 +786,12 @@ zen key use vertex/dev # which one the next run uses
722
786
  ```
723
787
 
724
788
  `zen key ls` marks the active entry with `*`, and anything it found outside the
725
- keyring — in your environment, or in a `gcloud` login — with `~`, so it is always
789
+ keyring - in your environment, or in a `gcloud` login - with `~`, so it is always
726
790
  clear where a working provider actually comes from.
727
791
 
728
792
  </details>
729
793
 
730
- ## Cache — work you have already paid for
794
+ ## Cache - work you have already paid for
731
795
 
732
796
  Embedding a paragraph, parsing a document, asking a provider what it serves: all
733
797
  of these are slow or costly, and all of them give the same answer every time. So
@@ -756,7 +820,7 @@ time.
756
820
  ## The library underneath
757
821
 
758
822
  This is a shell over
759
- [`@zenera/neo`](https://www.npmjs.com/package/@zenera/neo) — agents, models,
823
+ [`@zenera/neo`](https://www.npmjs.com/package/@zenera/neo) - agents, models,
760
824
  tools, skills, memory and a running record of everything that happened. Use it
761
825
  directly when you want the runtime inside your own application rather than on a
762
826
  terminal:
@@ -765,19 +829,19 @@ terminal:
765
829
  ## Documentation
766
830
 
767
831
  - [docs/specification.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/specification.md)
768
- — writing the specification the project implements.
832
+ - writing the specification the project implements.
769
833
  - [docs/projects.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/projects.md)
770
- — what the project folder contains, file by file.
834
+ - what the project folder contains, file by file.
771
835
  - [docs/agents-yaml.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/agents-yaml.md)
772
- — every key in the configuration file.
836
+ - every key in the configuration file.
773
837
  - [docs/knowledge.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/knowledge.md)
774
- — building a searchable document index.
838
+ - building a searchable document index.
775
839
  - [docs/integrations.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/integrations.md)
776
- — making an API description searchable and mockable.
840
+ - making an API description searchable and mockable.
777
841
  - [docs/memory.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/memory.md)
778
- — what agents keep between sessions.
842
+ - what agents keep between sessions.
779
843
 
780
844
  ## License
781
845
 
782
- Early days and moving fast — issues, questions and pull requests are welcome.
846
+ Early days and moving fast - issues, questions and pull requests are welcome.
783
847
  [MIT](LICENSE).