@zenera/cli 1.1.23 → 1.1.24
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.
- package/README.md +35 -2
- package/dist/ask.d.ts +51 -0
- package/dist/ask.js +143 -0
- package/dist/batch.d.ts +77 -0
- package/dist/batch.js +338 -0
- package/dist/command.d.ts +6 -0
- package/dist/commands/inspect.d.ts +11 -0
- package/dist/commands/inspect.js +388 -89
- package/dist/commands/list.js +128 -19
- package/dist/commands/memory.js +342 -12
- package/dist/commands/models.js +14 -2
- package/dist/commands/run.js +139 -34
- package/dist/commands/sandbox.js +72 -1
- package/dist/engine.d.ts +19 -0
- package/dist/engine.js +60 -8
- package/dist/liveness.js +6 -3
- package/dist/main.js +5 -2
- package/dist/podman.d.ts +16 -0
- package/dist/podman.js +115 -2
- package/dist/progress.d.ts +33 -0
- package/dist/progress.js +402 -0
- package/dist/request.d.ts +45 -0
- package/dist/request.js +300 -0
- package/dist/sandbox.js +10 -0
- package/dist/session.d.ts +26 -1
- package/dist/session.js +42 -3
- package/dist/term.d.ts +3 -0
- package/dist/term.js +17 -1
- package/dist/trace.d.ts +84 -0
- package/dist/trace.js +686 -0
- package/dist/validate.js +25 -3
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +11 -6
- package/templates/editor/.github/prompts/finetune.prompt.md +251 -0
- package/templates/editor/.github/skills/zen-cli/SKILL.md +9 -3
- package/templates/editor/.github/skills/zen-cli/references/check.md +7 -5
- package/templates/editor/.github/skills/zen-cli/references/inspect.md +262 -21
- package/templates/editor/.github/skills/zen-cli/references/memory.md +89 -19
- package/templates/editor/.github/skills/zen-cli/references/models.md +1 -1
- package/templates/editor/.github/skills/zen-cli/references/projects.md +12 -5
- package/templates/editor/.github/skills/zen-cli/references/run.md +201 -4
- package/templates/editor/.github/skills/zen-finetune/SKILL.md +1000 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/collect.sh +432 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/sample.sh +199 -0
- package/templates/editor/.github/skills/zen-inspect/SKILL.md +396 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +74 -29
- package/templates/editor/.github/skills/zen-memory-warmup/SKILL.md +363 -531
- package/templates/editor/.github/skills/zen-sandbox/SKILL.md +19 -0
- package/templates/editor/.github/skills/zen-sandbox-capacity/SKILL.md +334 -0
- package/templates/editor/.github/skills/zen-sandbox-capacity/references/loadtest.md +181 -0
- package/templates/editor/.github/skills/zen-sandbox-capacity/scripts/preflight_sandbox.sh +457 -0
- package/templates/editor/.vscode/agents.schema.json +1 -1
- package/templates/editor/.vscode/settings.json +1 -0
- package/templates/project/agents/files-instructions.md +13 -0
- package/templates/project/agents/fork-instructions.md +27 -0
- package/templates/project/agents/memory-instructions.md +80 -7
- package/templates/project/gitignore +3 -0
|
@@ -14,14 +14,18 @@ answers once on stdout and exits.
|
|
|
14
14
|
| `--project <name\|dir>` | Which project. Inferred from the directory otherwise |
|
|
15
15
|
| `--session <id>` | Continue a particular session |
|
|
16
16
|
| `--new` | Start a new session rather than continuing one |
|
|
17
|
+
| `--input <file>` | Read the whole request from JSON; `-` is stdin |
|
|
17
18
|
| `--workspace <dir>` | What the agent may read and write |
|
|
18
19
|
| `--memory <dir>` | Where the agents remember into, instead of the project's |
|
|
20
|
+
| `--memory-read-only` | Recall from it; write nothing back |
|
|
19
21
|
| `--model <ref>` | Override the default model for this run |
|
|
20
22
|
| `--image <ref>` | Override the container image commands run in |
|
|
21
23
|
| `--read-only` | Withhold every tool that can write |
|
|
22
24
|
| `--plain` | Never open the TUI; a prompt is then required |
|
|
23
25
|
| `--theme <dark\|light>` | Palette for the TUI; `auto` detects. `$ZENERA_THEME` |
|
|
24
26
|
| `--out <file>` | Put the answer in this file instead of on stdout |
|
|
27
|
+
| `--batch-dir <dir>` | Where a batch's runs live. `<project>/batches/<stamp>` |
|
|
28
|
+
| `--concurrency <n>` | How many of a batch run at once. Default 16, most 32 |
|
|
25
29
|
| `--yes` | Say yes to the workspace and install questions |
|
|
26
30
|
|
|
27
31
|
Flags always beat the file: the repository states intent, the invocation
|
|
@@ -38,6 +42,7 @@ the file is the only place it lands.
|
|
|
38
42
|
zen run "what changed?" > out.md answer in the file, progress on screen
|
|
39
43
|
zen run "what changed?" > out.md 2>/dev/null ... and nothing on screen at all
|
|
40
44
|
zen run --out out.md "what changed?" the same file, stdout left empty
|
|
45
|
+
zen run --json --out run.json "what changed?" the whole envelope, in a file
|
|
41
46
|
```
|
|
42
47
|
|
|
43
48
|
There is no `--quiet`. Narration is on stderr already, so a redirect is enough;
|
|
@@ -46,7 +51,9 @@ There is no `--quiet`. Narration is on stderr already, so a redirect is enough;
|
|
|
46
51
|
`--json` answers with the paths as well as the answer: the session and run
|
|
47
52
|
directories, every file the run left behind, and every tree the agent could see,
|
|
48
53
|
with the path it had on this machine beside the path it had inside the
|
|
49
|
-
container.
|
|
54
|
+
container. `--out` takes that envelope off stdout the same way it takes the
|
|
55
|
+
prose — with `--json` the envelope _is_ the answer, so the file holds all of it
|
|
56
|
+
and stdout is left empty.
|
|
50
57
|
|
|
51
58
|
```json
|
|
52
59
|
{
|
|
@@ -58,7 +65,8 @@ container.
|
|
|
58
65
|
"output": ".../output.md",
|
|
59
66
|
"state": ".../state.json",
|
|
60
67
|
"meta": ".../meta.json",
|
|
61
|
-
"report": ".../report.html"
|
|
68
|
+
"report": ".../report.html",
|
|
69
|
+
"graph": ".../graph.mmd"
|
|
62
70
|
},
|
|
63
71
|
"mounts": [
|
|
64
72
|
{ "host": "...", "at": "/workspace", "readOnly": false },
|
|
@@ -76,11 +84,198 @@ container.
|
|
|
76
84
|
`mounts` also lists the container's `$HOME` and, when keys are forwarded, the
|
|
77
85
|
credential files mounted under `/run/zenera/keys`.
|
|
78
86
|
|
|
87
|
+
## A request in a file
|
|
88
|
+
|
|
89
|
+
`--input <file.json>` is the whole invocation written down. It is the only way
|
|
90
|
+
to ask about a picture - a command line cannot carry one - and it is what makes
|
|
91
|
+
a run reproducible: a case is a file, so it can be checked in, diffed and re-run.
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"project": "acme",
|
|
96
|
+
"input": [{ "text": "what is in this picture?" }, { "image": "./shot.png" }],
|
|
97
|
+
"workspace": "./ws",
|
|
98
|
+
"memory": "./mem"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Only `input` is required, and it may be a plain string instead of an array. Each
|
|
103
|
+
part is a bare string, `{ "text": "…" }`, one of `{ "image" | "audio" | "video" |
|
|
104
|
+
"file": "…" }`, or the canonical `{ "type", "url", "mimeType" }` - the same shapes
|
|
105
|
+
the library's `Input` accepts, because the file is a JSON projection of it.
|
|
106
|
+
|
|
107
|
+
Three rules, and they are the whole of the format:
|
|
108
|
+
|
|
109
|
+
- **Paths are relative to the file**, not to the directory you ran from, so a
|
|
110
|
+
case travels with the images beside it. With `--input -` there is no file, so
|
|
111
|
+
they are relative to the cwd. A bare `project` is a registered name and is
|
|
112
|
+
left alone; one starting with `.` or `/` is a directory.
|
|
113
|
+
- **The file wins** over the same flag on the command line. A field it leaves
|
|
114
|
+
out falls through to the flag, then to the usual default. This is the one
|
|
115
|
+
place the rule above the options table is reversed - the file _is_ the
|
|
116
|
+
invocation, not a repository's standing intent.
|
|
117
|
+
- **A local media path is inlined** as a `data:` url, so the state a run resumes
|
|
118
|
+
from carries the picture rather than a path that meant something elsewhere.
|
|
119
|
+
`http(s):` and `data:` urls are passed through untouched. The bytes land in
|
|
120
|
+
`state.json` and are rewritten on every later turn of that session, so there
|
|
121
|
+
is a 20 MB ceiling and a warning well before it.
|
|
122
|
+
|
|
123
|
+
A request never opens the TUI and never asks about the workspace, exactly like a
|
|
124
|
+
prompt on the command line. Giving both a prompt and `--input` is an error.
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
zen run --input case.json --json | jq -r .output
|
|
128
|
+
cat case.json | zen run --input - --json
|
|
129
|
+
zen run --input case.json --json --out result.json everything, in a file
|
|
130
|
+
zen run --input case.json --session 20260825-143012-a7f3 continue, don't start
|
|
131
|
+
```
|
|
132
|
+
|
|
79
133
|
`--plain` never opens the TUI. The TUI is the only thing that can ask for a
|
|
80
134
|
prompt, so with `--plain` the prompt has to be there already - in the argument
|
|
81
135
|
or on stdin - and `zen run --plain` with neither is an error instead of a
|
|
82
136
|
window. Say it in a script that must not meet one.
|
|
83
137
|
|
|
138
|
+
## Many at once - `zen run batch`
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
zen run batch --input cases.json [--batch-dir <dir>] [--concurrency 16]
|
|
142
|
+
[--memory <dir>] [--memory-read-only] [--out <file>] [--json]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The same file, pluralised. One project, many questions, sixteen at a time by
|
|
146
|
+
default:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"batch": [
|
|
151
|
+
{ "id": "vat", "input": "what is the VAT threshold?" },
|
|
152
|
+
{ "input": [{ "text": "what is this?" }, { "image": "./shot.png" }] },
|
|
153
|
+
{ "id": "ws", "input": "read the notes", "workspace": "./cases/ws" }
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
An item takes `input`, an optional `id` and an optional `workspace`, and nothing
|
|
159
|
+
else. `project` and `memory` belong to the batch rather than to an item, so they
|
|
160
|
+
are flags: a file that names either is refused rather than half-honoured. An
|
|
161
|
+
`id` names a directory, so it has to be one - letters, digits, dot, dash and
|
|
162
|
+
underscore - and it defaults to the item's index. Two items may not share an
|
|
163
|
+
`id` or a `workspace`, because they run at the same time.
|
|
164
|
+
|
|
165
|
+
Everything refusable is refused before the first model call. A batch pays for a
|
|
166
|
+
mistake once per item.
|
|
167
|
+
|
|
168
|
+
### What it leaves behind
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
<batch-dir>/
|
|
172
|
+
README.md a live dashboard, rewritten every second
|
|
173
|
+
batch.json the index: every item, whether it worked, where it is
|
|
174
|
+
<id>/
|
|
175
|
+
workspace/ what that item could read and write
|
|
176
|
+
memory/ its own copy, in the copying mode only
|
|
177
|
+
output.json exactly what `zen run --json` prints for one run
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`README.md` is where the progress of a batch lives. Sixteen agents narrating at
|
|
181
|
+
once would be noise, so instead the file is rewritten once a second: a
|
|
182
|
+
fixed-height panel showing every worker - what it is running, the tail of what
|
|
183
|
+
it is thinking or writing, its turns and its tokens - over a `Tokens by model`
|
|
184
|
+
table, a table of the finished ones and a list of the ones still waiting. The
|
|
185
|
+
panel keeps its height while there is work left to start, so nothing jumps
|
|
186
|
+
between ticks. Watch it in an editor preview, or `watch -n1 cat "$DIR/README.md"`.
|
|
187
|
+
When the batch ends the same file is the report.
|
|
188
|
+
|
|
189
|
+
Tokens are reported **per model**: agents may each use a different one, so one
|
|
190
|
+
total belongs to none of them. Every model id gets a row with its calls and its
|
|
191
|
+
input, cached, output and thinking tokens, and the rows always add up to the
|
|
192
|
+
batch total. Tokens spent summarising, which no node attributes to a model, are
|
|
193
|
+
shown as `(compaction)`.
|
|
194
|
+
|
|
195
|
+
Each `output.json` is written the moment its item finishes, so a batch stopped
|
|
196
|
+
half way still has every answer it managed to get. `batch.json` is an index, not
|
|
197
|
+
a second copy - it points at the files:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"batch": {
|
|
202
|
+
"dir": "...",
|
|
203
|
+
"items": 3,
|
|
204
|
+
"ok": 2,
|
|
205
|
+
"failed": 1,
|
|
206
|
+
"concurrency": 16,
|
|
207
|
+
"memory": { "source": "...", "mode": "read-only" },
|
|
208
|
+
"usage": {
|
|
209
|
+
"inputTokens": 0,
|
|
210
|
+
"cachedInputTokens": 0,
|
|
211
|
+
"outputTokens": 0,
|
|
212
|
+
"reasoningTokens": 0
|
|
213
|
+
},
|
|
214
|
+
"models": [{ "model": "gemini-3-flash", "calls": 12, "usage": {} }],
|
|
215
|
+
"durationMs": 0
|
|
216
|
+
},
|
|
217
|
+
"batch_results": [
|
|
218
|
+
{ "index": 0, "id": "vat", "ok": true, "input": "…", "output": ".../vat/output.json" },
|
|
219
|
+
{
|
|
220
|
+
"index": 1,
|
|
221
|
+
"id": "1",
|
|
222
|
+
"ok": false,
|
|
223
|
+
"input": "…",
|
|
224
|
+
"output": "...",
|
|
225
|
+
"error": { "message": "…" }
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
A failure is data. One item that cannot be answered costs one answer, not the
|
|
232
|
+
other ninety-nine; the exit code says how many failed, and it is set after
|
|
233
|
+
everything is written.
|
|
234
|
+
|
|
235
|
+
stdout is the batch directory and nothing else, so `ls "$(zen run batch --input
|
|
236
|
+
cases.json)"` works. `--json` prints the index there instead. Progress is in
|
|
237
|
+
`<batch-dir>/README.md` either way. `--out` puts the index in a second file as
|
|
238
|
+
well.
|
|
239
|
+
|
|
240
|
+
### Memory, in two modes
|
|
241
|
+
|
|
242
|
+
A memory is a locked directory, so sixteen runs cannot hold one. Which leaves
|
|
243
|
+
two honest arrangements, and the flag picks between them:
|
|
244
|
+
|
|
245
|
+
| Mode | What happens |
|
|
246
|
+
| -------------------- | ------------------------------------------------------------------ |
|
|
247
|
+
| `--memory-read-only` | Every item recalls from the one graph. Nothing is written, no lock |
|
|
248
|
+
| default | Each item gets a copy under `<batch-dir>/<id>/memory` |
|
|
249
|
+
|
|
250
|
+
In the copying mode the project's own memory is never touched. Fold what the
|
|
251
|
+
items learned back in afterwards, having read it:
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
zen memory merge <batch-dir>/*/memory
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
An item that committed nothing leaves no `memory/` behind, so that line never
|
|
258
|
+
names a directory `merge` would refuse.
|
|
259
|
+
|
|
260
|
+
`--memory <dir>` names the source in both modes; without it the source is the
|
|
261
|
+
project's own memory, and a project with none runs the batch with none. A
|
|
262
|
+
source that does not exist yet is not an error in the copying mode: a project
|
|
263
|
+
declares its memory directory and the first run makes it, so every item simply
|
|
264
|
+
starts from an empty graph. That is how a cold project is warmed, and pointing
|
|
265
|
+
`--memory` at a directory that is not there is how you ask for it deliberately.
|
|
266
|
+
A batch refuses to start while another run holds that memory's lock.
|
|
267
|
+
|
|
268
|
+
`--memory-read-only` works on a single `zen run` too. It is how you ask a
|
|
269
|
+
question of what the agents know without changing what they know.
|
|
270
|
+
|
|
271
|
+
### What means nothing in a batch
|
|
272
|
+
|
|
273
|
+
`--session`, `--new`, `--workspace`, `--plain` and `--theme` are refused by
|
|
274
|
+
name rather than ignored. Every item is a new session of its own, they cannot
|
|
275
|
+
share a workspace, and a batch never draws the TUI.
|
|
276
|
+
|
|
277
|
+
For a project or a prompt actually called "batch", say `--project batch`.
|
|
278
|
+
|
|
84
279
|
## Which word is the project
|
|
85
280
|
|
|
86
281
|
The first positional is read as a project when it names one, and as the first
|
|
@@ -138,7 +333,7 @@ run history. Ids look like `20260825-143012-a7f3`.
|
|
|
138
333
|
```
|
|
139
334
|
<project>/sessions/<id>/
|
|
140
335
|
workspace/ what the agent sees, unless --workspace said otherwise
|
|
141
|
-
runs/<run-id>/ input.md, output.md, state.json, report.html, meta.json
|
|
336
|
+
runs/<run-id>/ input.md, output.md, state.json, report.html, graph.mmd, meta.json
|
|
142
337
|
.data/
|
|
143
338
|
state.json the live, resumable state, rewritten after every run
|
|
144
339
|
session.json when it was made, and the workspace it is rooted at
|
|
@@ -162,4 +357,6 @@ definition and is taken over.
|
|
|
162
357
|
## Afterwards
|
|
163
358
|
|
|
164
359
|
Each run writes a `report.html` next to its state; the run prints a
|
|
165
|
-
`file://` link to it.
|
|
360
|
+
`file://` link to it. It writes a `graph.mmd` beside it too - the same
|
|
361
|
+
trajectory as one Mermaid flowchart, which is what `zen inspect graph` prints.
|
|
362
|
+
See [inspect.md](inspect.md).
|