@zenera/cli 1.1.0 → 1.1.3

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 (61) hide show
  1. package/README.md +88 -11
  2. package/dist/audit.d.ts +8 -6
  3. package/dist/audit.js +14 -22
  4. package/dist/commands/check.js +79 -19
  5. package/dist/commands/init.js +71 -11
  6. package/dist/commands/key.js +126 -36
  7. package/dist/commands/models.js +3 -3
  8. package/dist/commands/open.js +2 -2
  9. package/dist/commands/run.js +3 -0
  10. package/dist/commands/sandbox.js +226 -22
  11. package/dist/engine.d.ts +3 -1
  12. package/dist/engine.js +10 -2
  13. package/dist/image.d.ts +16 -0
  14. package/dist/image.js +85 -0
  15. package/dist/keys.d.ts +95 -12
  16. package/dist/keys.js +175 -34
  17. package/dist/lib.d.ts +2 -2
  18. package/dist/lib.js +2 -2
  19. package/dist/liveness.d.ts +16 -6
  20. package/dist/liveness.js +74 -23
  21. package/dist/main.js +0 -0
  22. package/dist/podman.d.ts +57 -1
  23. package/dist/podman.js +177 -12
  24. package/dist/projects.d.ts +18 -0
  25. package/dist/projects.js +60 -1
  26. package/dist/sandbox.d.ts +14 -1
  27. package/dist/sandbox.js +88 -8
  28. package/dist/scaffold.d.ts +21 -15
  29. package/dist/scaffold.js +133 -167
  30. package/dist/term.d.ts +2 -0
  31. package/dist/term.js +14 -0
  32. package/dist/validate.d.ts +20 -3
  33. package/dist/validate.js +309 -14
  34. package/package.json +2 -18
  35. package/templates/{.github → editor/.github}/copilot-instructions.md +161 -48
  36. package/templates/{.github → editor/.github}/prompts/new-skill.prompt.md +13 -6
  37. package/templates/editor/.github/skills/api-schema-index/SKILL.md +292 -0
  38. package/templates/editor/.github/skills/zen-cli/SKILL.md +74 -0
  39. package/templates/editor/.github/skills/zen-cli/references/check.md +92 -0
  40. package/templates/editor/.github/skills/zen-cli/references/faker.md +111 -0
  41. package/templates/editor/.github/skills/zen-cli/references/frame.md +119 -0
  42. package/templates/editor/.github/skills/zen-cli/references/inspect.md +61 -0
  43. package/templates/editor/.github/skills/zen-cli/references/keys.md +114 -0
  44. package/templates/editor/.github/skills/zen-cli/references/projects.md +99 -0
  45. package/templates/editor/.github/skills/zen-cli/references/rag.md +159 -0
  46. package/templates/editor/.github/skills/zen-cli/references/run.md +104 -0
  47. package/templates/editor/.github/skills/zen-cli/references/sandbox.md +91 -0
  48. package/templates/editor/.vscode/settings.json +6 -0
  49. package/templates/parts/exa.yaml.tmpl +5 -0
  50. package/templates/parts/model.yaml.tmpl +4 -0
  51. package/templates/parts/models.yaml.tmpl +10 -0
  52. package/templates/project/INSTRUCTIONS.md +7 -0
  53. package/templates/project/SPECIFICATION.md +6 -0
  54. package/templates/project/agents/prompts/default.md +15 -0
  55. package/templates/project/agents.yaml.tmpl +44 -0
  56. package/templates/project/assets/README.md +12 -0
  57. package/templates/project/gitignore +9 -0
  58. package/templates/project/sandbox/Dockerfile +21 -0
  59. package/templates/.github/skills/zen-cli/SKILL.md +0 -110
  60. /package/templates/{.github → editor/.github}/prompts/new-agent.prompt.md +0 -0
  61. /package/templates/{.github → editor/.github}/prompts/review-project.prompt.md +0 -0
@@ -133,11 +133,15 @@ my-project/
133
133
  │ │ └── adjuster.md
134
134
  │ └── skills/
135
135
  │ ├── house_style/
136
- │ │ ├── SKILL.md folder skill
137
- │ │ └── examples.md sibling files become `resources`
136
+ │ │ ├── SKILL.md the instructions
137
+ │ │ └── examples.md its own files, reachable at /skills/house_style
138
138
  │ ├── water_damage/
139
139
  │ │ └── SKILL.md
140
- │ └── shipping_delays.md flat skill (frontmatter + body)
140
+ │ └── refund_policy/
141
+ │ ├── SKILL.md
142
+ │ └── scripts/calculate.py run at /skills/refund_policy/scripts — §3.4.1
143
+ ├── assets/ reference material, read-only at /assets
144
+ ├── sandbox/Dockerfile the image commands run in — §3.7
141
145
  └── sessions/ run state, memory, whatever the agent wrote
142
146
  ```
143
147
 
@@ -240,6 +244,7 @@ model: fast # fallback for agents that do not pin their own
240
244
  embeddings: {} # named vectorisers — §3.1.1
241
245
  embedding: small # the one `AgentProject.embedder()` returns when asked for no name
242
246
  skills: agents/skills # one directory, or a list
247
+ assets: assets # reference material, read-only at /assets — §3.11
243
248
 
244
249
  agents: # the only required key; at least one entry
245
250
  - name: intake
@@ -465,18 +470,24 @@ yet.
465
470
 
466
471
  ### 3.4 Skills
467
472
 
468
- A skill is curated, reusable instruction content — plus optional tools — loaded
469
- **on demand** instead of permanently occupying the system prompt. Two layouts,
470
- discovered in the same scan:
473
+ A skill is curated, reusable instruction content — plus the files and tools it
474
+ needs — loaded **on demand** instead of permanently occupying the system prompt.
475
+ One layout, and only one:
471
476
 
472
477
  ```
473
- agents/skills/refund_policy.md flat: frontmatter + body
474
- agents/skills/refund_policy/SKILL.md folder: sibling files become `resources`
478
+ agents/skills/refund_policy/SKILL.md the instructions
479
+ agents/skills/refund_policy/rates.csv whatever they refer to
475
480
  ```
476
481
 
482
+ The folder name is the skill name. A bare `agents/skills/refund_policy.md` is
483
+ **not a skill location**: `zen check` reports it as `skill.flat`, and the fix is
484
+ to move it to `refund_policy/SKILL.md`. A skill with nowhere to put a table, an
485
+ example or a script can only ever be prose, which is the half of the idea that
486
+ does not need a file.
487
+
477
488
  Frontmatter is a deliberately small subset of YAML — `key: value`, plus `[a, b]`
478
489
  flow lists for `tags` and `tools`. **Every key is optional**: `name` defaults to
479
- the file/folder name, `description` to the first non-empty line of the body.
490
+ the folder name, `description` to the first non-empty line of the body.
480
491
 
481
492
  ```markdown
482
493
  ---
@@ -510,8 +521,58 @@ skill is needed_, not as a title:
510
521
  provider from turn 0 (the schema never changes) but **refuse to execute** until
511
522
  the skill is active. This is how a tool can be gated without breaking the cache.
512
523
 
513
- Use a folder skill when the content needs companions — a CSV rate table, an
514
- example letter, a JSON schema. Siblings become `resources` the model can read.
524
+ ### 3.4.1 Skills that ship files and scripts
525
+
526
+ The whole catalog is mounted **read-only at `/skills`** before anything is
527
+ loaded, so a skill's own files sit at `/skills/<name>/...`. The runtime says so
528
+ in the activation, once, when the skill loads:
529
+
530
+ > This skill's files are at /skills/refund_policy, read-only. Paths written in
531
+ > it are relative to that directory.
532
+
533
+ That line is what turns a script in a skill from decoration into something the
534
+ agent can run:
535
+
536
+ ```
537
+ agents/skills/refund_policy/
538
+ ├── SKILL.md
539
+ ├── rates.csv
540
+ └── scripts/calculate.py
541
+ ```
542
+
543
+ ```markdown
544
+ Run `python /skills/refund_policy/scripts/calculate.py <order-id>` and use the
545
+ figure it prints. Read `/skills/refund_policy/rates.csv` if you need the band.
546
+ Do not compute the amount yourself.
547
+ ```
548
+
549
+ **Reach for a script whenever the answer is arithmetic, a lookup or a fixed
550
+ transformation.** It is the cheapest tool there is: no schema in the prefix, no
551
+ vendor, versioned beside the prose that calls it, and its output is a fact
552
+ rather than a guess (§1.4).
553
+
554
+ Rules that follow from the mount:
555
+
556
+ - The agent needs `sandbox:*` to run the script and `read_file` to open a data
557
+ file. Grant them, or the skill's own instructions cannot be followed (§3.5).
558
+ - **The interpreter must already be in the sandbox image.** A skill whose
559
+ script needs `pandas` is a `sandbox/Dockerfile` line that was never written —
560
+ not a first line that runs `pip install` on every turn (§3.7).
561
+ - **`/skills` is read-only.** A script that produces a file must take an output
562
+ path and write it under `/workspace`.
563
+ - **Write the absolute `/skills/<name>/...` path** in the skill body. The text is
564
+ loaded into a prompt, not executed from its directory, and the working
565
+ directory is `/workspace`.
566
+ - Say what to do when the script fails, as with any other instruction (§4.2).
567
+ - With several `skills:` directories, one catalog is the whole of `/skills` and
568
+ several take `/skills/<folder>` each — check the rendered path before writing
569
+ it into the body.
570
+ - The mount is created before anything is loaded, so `allow:` limits what an
571
+ agent can **load**, not what it can **read**. Do not put anything in the
572
+ catalog that some agents must not see.
573
+
574
+ `zen check` lists what each skill folder ships, so a script that was never
575
+ committed shows up as a skill with no files.
515
576
 
516
577
  ### 3.5 Tools
517
578
 
@@ -560,12 +621,13 @@ container involved there is no second name and everything stays relative.
560
621
 
561
622
  **Selecting them.** A `tools:` entry is a selector, not only a name:
562
623
 
563
- | Selector | Selects |
564
- | ------------- | ------------------------------------------------- |
565
- | `read_file` | that one tool |
566
- | `workspace:*` | every tool in the group |
567
- | `'*'` | every tool the runtime provides |
568
- | `-<any>` | removes what it matches from the selection so far |
624
+ | Selector | Selects |
625
+ | --------------------- | ------------------------------------------------- |
626
+ | `read_file` | that one tool |
627
+ | `workspace:read_file` | the same tool, written out in full |
628
+ | `workspace:*` | every tool in the group |
629
+ | `'*'` | every tool the runtime provides |
630
+ | `-<any>` | removes what it matches from the selection so far |
569
631
 
570
632
  ```yaml
571
633
  agents:
@@ -635,6 +697,7 @@ sandbox:
635
697
  | Field | Default | Meaning |
636
698
  | --------- | --------------------------------------------- | -------------------------------------------- |
637
699
  | `image` | `docker.io/library/python:3.14-slim-bookworm` | The base image commands run in |
700
+ | `build` | none | A Dockerfile to build instead |
638
701
  | `cpus` | the host's | Fractional cores |
639
702
  | `memory` | the host's | MiB |
640
703
  | `network` | `bridge` | `bridge` / `none` / `host` |
@@ -648,6 +711,30 @@ sandbox:
648
711
  repository — and anything credential-shaped (`KEY`, `TOKEN`, `SECRET`,
649
712
  `PASSWORD`, `CREDENTIAL`) is refused at load.
650
713
 
714
+ **`build:`, when no published image fits.** A project that needs two runtimes,
715
+ or a pinned toolchain, names a Dockerfile instead of an image — `zen init`
716
+ writes one at `sandbox/Dockerfile` with Python and Node in it:
717
+
718
+ ```yaml
719
+ sandbox:
720
+ persist: true
721
+ build:
722
+ dockerfile: sandbox/Dockerfile
723
+ # context: . # what the build may COPY from; the Dockerfile's folder by default
724
+ ```
725
+
726
+ `image:` and `build:` cannot both be set — a Dockerfile names its own base in
727
+ its `FROM` line. The tag is a hash of the Dockerfile and its context, so
728
+ editing it produces a new image and, like any other change here, a new
729
+ container. `zen check` builds it and runs a command in it, so a Dockerfile that
730
+ does not build fails the check rather than the next run.
731
+
732
+ **Put what the project always needs in the image, not in a prompt.** This is the
733
+ real use of `build:`: a `RUN apt-get install ripgrep` in the Dockerfile is
734
+ installed once, for everyone, forever. The same instruction written into a
735
+ prompt is executed on every run, by an agent that is root in a filesystem that
736
+ is about to be thrown away.
737
+
651
738
  Agents share one container, because they share the workspace and a hand-off is
652
739
  meant to be continuous. An agent that needs something else says so and gets its
653
740
  own, with its block merged over the top-level one:
@@ -682,15 +769,16 @@ sandbox:
682
769
  ```
683
770
 
684
771
  With it, the container is _stopped_ rather than removed, and the next run of
685
- that session starts the same one back up with everything still installed. The
686
- cost is containers that outlive their sessions `zen sandbox status` lists them
687
- and `zen sandbox clean` removes them.
772
+ that session starts the same one back up with everything still installed. A
773
+ container is per session rather than per project, so they accumulate: `zen
774
+ sandbox status` lists them, `zen sandbox disk` totals what they and the project
775
+ directories cost, and `zen sandbox clean` removes them.
688
776
 
689
777
  Changing any field renames the container, so bumping the image gets a fresh one
690
778
  rather than an old one quietly persisting with the wrong contents. That is also
691
779
  the one sharp edge of `persist: true`: a config change abandons the old
692
780
  container with whatever was installed in it, so a long-lived setup still belongs
693
- in `image:` rather than in an accumulated rootfs.
781
+ in `image:` — or in `sandbox/Dockerfile` — rather than in an accumulated rootfs.
694
782
 
695
783
  Granting the group is what makes the project need Podman: `zen run` checks the
696
784
  engine before the first turn and exits `5` with an install command if it is
@@ -792,7 +880,7 @@ zen run "what changed?" one shot; stdout is the answer
792
880
  zen run --session <id> continue a session
793
881
  zen run --workspace ./repo what the agent may read and write
794
882
  zen run --model careful override the default model for this run
795
- zen run --image <ref> override the sandbox image for this run
883
+ zen run --image <ref> override the sandbox image for this run, ignoring build:
796
884
  zen run --read-only withhold every tool that can write
797
885
  ```
798
886
 
@@ -816,6 +904,22 @@ EXA_API_KEY=...
816
904
  Never commit. Never inline a key into `agents.yaml` — use `${VAR}`. Never print a
817
905
  key in a log line, a test fixture, or a chat message.
818
906
 
907
+ ### 3.11 `assets/`
908
+
909
+ `assets/` next to `agents.yaml` — or `assets: <path>` — is reference material
910
+ every agent can read and none can write. It is mounted at `/assets`: the file
911
+ tools read, list and search it, `run_command` sees it bind-mounted read-only,
912
+ and every tool that would change it refuses.
913
+
914
+ Put a handbook, a specification, a schema or a style guide there — what agents
915
+ consult while working, as opposed to the workspace, which is the work. Do not
916
+ point `assets:` at the project root: that hands every agent the `sessions/`
917
+ directory, every transcript of every run, including the one reading it.
918
+ `zen check` warns when it would.
919
+
920
+ It is project-wide by design. An agent that may see only part of the material
921
+ is a different project, not a different key.
922
+
819
923
  ---
820
924
 
821
925
  ## 4. Writing prompts
@@ -1468,10 +1572,13 @@ Before finishing any change here:
1468
1572
 
1469
1573
  **Skills**
1470
1574
 
1575
+ - [ ] Every skill is `<name>/SKILL.md` — no bare `<name>.md` in the catalog
1471
1576
  - [ ] Every skill has a `description` that says _when it is needed_
1472
1577
  - [ ] `preload` is reserved for content the model would never decline
1473
1578
  - [ ] `preload` entries also appear in `allow` where `allow` is used
1474
1579
  - [ ] Catalog >~30 entries → `discovery: search`
1580
+ - [ ] A skill that ships a script writes its `/skills/<name>/...` path, the agent
1581
+ holds `sandbox:*`, and the sandbox image already has the interpreter
1475
1582
 
1476
1583
  **Tools**
1477
1584
 
@@ -1481,7 +1588,7 @@ Before finishing any change here:
1481
1588
  - [ ] `sandbox:*` is granted only where a shell is actually needed
1482
1589
  - [ ] `sandbox.persist: true`, unless a throwaway rootfs is wanted on purpose
1483
1590
  - [ ] The `sandbox:` image carries what the work needs, rather than the prompt
1484
- installing it every run
1591
+ installing it every run — add it to `sandbox/Dockerfile` if `build:` is used
1485
1592
  - [ ] `sandbox.env` lists names only, and nothing credential-shaped
1486
1593
  - [ ] `exa:*` is granted only where the live web is actually needed, and the
1487
1594
  prompt says when to trust it over what the model already believes
@@ -1507,31 +1614,33 @@ Before finishing any change here:
1507
1614
 
1508
1615
  ## 10. Where to change what
1509
1616
 
1510
- | Symptom | Change this |
1511
- | ------------------------------------------ | ---------------------------------------------------------- |
1512
- | Wrong tone, wrong format, wrong length | `INSTRUCTIONS.md` (all agents) or the agent prompt |
1513
- | Says something forbidden | `INSTRUCTIONS.md` prohibition, stated specifically |
1514
- | Ignores a rule that only applies sometimes | Move the rule into a skill with a sharp description |
1515
- | Never loads the skill it should | The skill's `description`; or `preload` it |
1516
- | Loads too much, answers slowly | `allow:`, `maxIndexEntries:`, or `discovery: search` |
1517
- | Invents a number | A skill holding the figure, or a command that computes it |
1518
- | Rewrites a whole file to change one line | A prompt line preferring `apply_patch` — §3.6 |
1519
- | Edits files it should only be reading | Subtract the mutating tools, or `zen run --read-only` |
1520
- | Cannot run the build or the tests | Grant `sandbox:*`; pick an `image:` that has the toolchain |
1521
- | Installs the same packages on every run | `sandbox.persist: true`, or set `sandbox.image` §3.7 |
1522
- | Answers from stale knowledge of the world | Grant `web_search` + `web_read`, and say when — §3.8 |
1523
- | Cites a page it only saw the excerpt of | A prompt line: `web_read` before quoting — §3.8 |
1524
- | Every web call refuses | No Exa key: `zen key add exa` `zen check` warns — §3.8 |
1525
- | Answers instead of routing | Router prompt prohibition; check `handoffs:` |
1526
- | Routes to the wrong specialist | The target agents' `description:` fields |
1527
- | Loses a detail after a handoff | Say it in the handoff; check the collapse policy |
1528
- | Works through N independent items serially | `fork:` on that agent, and a prompt line — §6.4 |
1529
- | Forks when the steps actually depend | Prompt line: branches cannot see each other |
1530
- | Slow and expensive on trivial cases | Demote that agent's model tier / reasoning effort |
1531
- | Fails only on genuinely hard cases | Promote that agent's tier, or split the hard path out |
1532
- | Shows no reasoning while it works | Turn summaries on for that model §7.6 |
1533
- | Forgets across conversations | Continue the session rather than starting a new one |
1534
- | Breaks at load with a named path | Read the message it names the exact key |
1617
+ | Symptom | Change this |
1618
+ | ------------------------------------------ | ------------------------------------------------------------------- |
1619
+ | Wrong tone, wrong format, wrong length | `INSTRUCTIONS.md` (all agents) or the agent prompt |
1620
+ | Says something forbidden | `INSTRUCTIONS.md` prohibition, stated specifically |
1621
+ | Ignores a rule that only applies sometimes | Move the rule into a skill with a sharp description |
1622
+ | Never loads the skill it should | The skill's `description`; or `preload` it |
1623
+ | Loads too much, answers slowly | `allow:`, `maxIndexEntries:`, or `discovery: search` |
1624
+ | Invents a number | A skill holding the figure, or a script that computes it — §3.4.1 |
1625
+ | A skill in the catalog is never offered | It is a bare `<name>.md`; move it to `<name>/SKILL.md` — §3.4 |
1626
+ | Cannot find a file its own skill names | Absolute `/skills/<name>/…` path, and `sandbox:*` §3.4.1 |
1627
+ | Rewrites a whole file to change one line | A prompt line preferring `apply_patch` §3.6 |
1628
+ | Edits files it should only be reading | Subtract the mutating tools, or `zen run --read-only` |
1629
+ | Cannot run the build or the tests | Grant `sandbox:*`; add the toolchain to `sandbox/Dockerfile` |
1630
+ | Installs the same packages on every run | Put them in `sandbox/Dockerfile`, or `sandbox.persist: true` — §3.7 |
1631
+ | Answers from stale knowledge of the world | Grant `web_search` + `web_read`, and say when — §3.8 |
1632
+ | Cites a page it only saw the excerpt of | A prompt line: `web_read` before quoting — §3.8 |
1633
+ | Every web call refuses | No Exa key: `zen key add exa` — `zen check` warns — §3.8 |
1634
+ | Answers instead of routing | Router prompt prohibition; check `handoffs:` |
1635
+ | Routes to the wrong specialist | The target agents' `description:` fields |
1636
+ | Loses a detail after a handoff | Say it in the handoff; check the collapse policy |
1637
+ | Works through N independent items serially | `fork:` on that agent, and a prompt line — §6.4 |
1638
+ | Forks when the steps actually depend | Prompt line: branches cannot see each other |
1639
+ | Slow and expensive on trivial cases | Demote that agent's model tier / reasoning effort |
1640
+ | Fails only on genuinely hard cases | Promote that agent's tier, or split the hard path out |
1641
+ | Shows no reasoning while it works | Turn summaries on for that model §7.6 |
1642
+ | Forgets across conversations | Continue the session rather than starting a new one |
1643
+ | Breaks at load with a named path | Read the message — it names the exact key |
1535
1644
 
1536
1645
  ---
1537
1646
 
@@ -1542,6 +1651,10 @@ Before finishing any change here:
1542
1651
  prompt style. Collapse into one with a catalog.
1543
1652
  - **Facts in prompts.** A fee schedule inside `INSTRUCTIONS.md`. It cannot be
1544
1653
  versioned, cannot be shared, and is paid for on every call.
1654
+ - **The bare skill file.** `agents/skills/<name>.md` instead of a folder. It can
1655
+ never grow the table or script the next revision of the rule will want — §3.4.
1656
+ - **Arithmetic in prose.** A skill that walks the model through a calculation it
1657
+ will get wrong, in a folder that could have held the script — §3.4.1.
1545
1658
  - **Politeness padding.** "Please try your best to be helpful." Costs tokens,
1546
1659
  changes nothing.
1547
1660
  - **Commented implementation notes.** `agents.yaml` explaining how skill
@@ -10,9 +10,10 @@ change without the prompt changing.
10
10
 
11
11
  Ask what the skill must say and when it applies, if I have not already said.
12
12
 
13
- 1. Choose the layout. A flat `agents/skills/<name>.md` for text alone; a folder
14
- `agents/skills/<name>/SKILL.md` when it needs companions a rate table, an
15
- example letter, a schema. Siblings of `SKILL.md` become readable resources.
13
+ 1. Create `agents/skills/<name>/SKILL.md`. That is the only skill layout there
14
+ is — a bare `agents/skills/<name>.md` fails `zen check`and the folder is
15
+ what lets the skill carry companions later: a rate table, an example letter,
16
+ a schema, a script.
16
17
  2. Write the `description`. This is the routing key and the only thing the model
17
18
  sees before deciding to load the skill, so write it as **the condition under
18
19
  which the skill is needed**, not as a title. `Water policy` is a title;
@@ -23,12 +24,18 @@ Ask what the skill must say and when it applies, if I have not already said.
23
24
  wording, the boundaries of the rule, and what to do when the case falls
24
25
  outside it. Put the facts here rather than in a prompt — that is the point of
25
26
  the file.
26
- 4. Declare `tools:` in the frontmatter only for tools that must not run until
27
+ 4. Put anything the rule computes or looks up in a file beside `SKILL.md` and
28
+ name it from the body by its absolute path — `python
29
+ /skills/<name>/scripts/calculate.py <id>`, not `scripts/calculate.py`. The
30
+ folder is mounted read-only at `/skills/<name>/`, so the script writes
31
+ nothing there; the agent needs `sandbox:*` to run it, and the interpreter has
32
+ to be in the `sandbox:` image already.
33
+ 5. Declare `tools:` in the frontmatter only for tools that must not run until
27
34
  this skill is active. They are advertised from turn 0 and refuse to execute
28
35
  while the skill is dormant, which is how gating happens without breaking the
29
36
  prompt cache.
30
- 5. Leave `name` out unless it must differ from the file or folder name, and
31
- leave `version`/`tags` out unless something uses them.
37
+ 6. Leave `name` out unless it must differ from the folder name, and leave
38
+ `version`/`tags` out unless something uses them.
32
39
 
33
40
  Do not `preload:` it unless every case genuinely needs it — a preloaded skill is
34
41
  a longer prompt, paid for on every call. Bind it under `agents[].skills.allow`