tunestra 0.4.0 → 0.6.0

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 CHANGED
@@ -70,14 +70,31 @@ the manifest only holds metadata and overrides.
70
70
  rules/<key>.md # rules, one topic per file
71
71
  skills/<key>/SKILL.md # skills (Agent Skills format)
72
72
  commands/<key>.md # slash commands
73
+ agents/<key>.md # subagents
73
74
  mcp/<key>.yaml # MCP servers
74
75
  ```
75
76
 
77
+ A subagent is a markdown file with frontmatter; the text after it is the instructions:
78
+
79
+ ```md
80
+ ---
81
+ description: Reviews a diff for bugs and missing tests # required: when to use it
82
+ model: # optional: the model for each agent
83
+ claude: sonnet # otherwise the agent uses the model of the main session
84
+ codex: gpt-5.5
85
+ effort: medium # optional: low | medium | high | xhigh
86
+ readOnly: true # optional: the subagent must not change files
87
+ ---
88
+ Review the diff. Report each finding with a file and a line.
89
+ ```
90
+
91
+ The file name is the name of the subagent: lowercase letters, digits and single hyphens.
92
+
76
93
  ### Manifest: `tunestra.preset.yaml`
77
94
 
78
95
  ```yaml
79
96
  name: team # required, unique in the chain
80
- level: team # required: base | domain | team
97
+ level: team # required: base | domain | team | local
81
98
  description: Frontend team conventions
82
99
  extends: # optional, from general to specific
83
100
  - ../base
@@ -110,11 +127,49 @@ exclude: {}
110
127
  overrides: {}
111
128
  ```
112
129
 
130
+ ### Personal level: `tunestra.local.yaml`
131
+
132
+ A developer can tune the setup for themselves with `tunestra.local.yaml` and `.tunestra.local/`
133
+ in the project; `tunestra init --local` creates both. tunestra always puts both in
134
+ `.gitignore`. The personal level comes after the project, so it can add artifacts, override
135
+ them by key and exclude them, like any other level.
136
+
137
+ ```yaml
138
+ name: local # optional, defaults to local
139
+ extends: # optional: personal presets with level: local
140
+ - ~/presets/me
141
+ exclude:
142
+ skills: [storybook]
143
+ env:
144
+ HTTPS_PROXY: http://localhost:3128
145
+ permissions:
146
+ allow: [Bash(make *)]
147
+ ```
148
+
149
+ A personal preset has `level: local` in its manifest and can be shared between your projects.
150
+ The personal level can extend only such presets, and no shared level can extend them.
151
+
152
+ The committed files stay the same for the whole team: AGENTS.md, CLAUDE.md and
153
+ `.claude/settings.json` are built without the personal level. Every other generated file
154
+ follows the chain with it. A personal level cannot exclude `env` or permissions, because
155
+ Claude Code joins the personal settings with the committed ones and cannot remove a
156
+ committed entry.
157
+
158
+ | Agent | What it gets |
159
+ |---|---|
160
+ | Claude Code | `CLAUDE.local.md`, which it reads after CLAUDE.md: what the personal level adds, overrides and turns off. Personal `env` and permissions are added to `.claude/settings.local.json` |
161
+ | Codex | `AGENTS.override.md`, which it reads instead of AGENTS.md: the whole index with the personal level |
162
+
163
+ Claude Code writes `.claude/settings.local.json` too, for example when you allow a command for
164
+ good. tunestra remembers which entries it added and changes only those: your settings and
165
+ the rules of Claude Code stay. A variable that you changed by hand is yours and stays too.
166
+
113
167
  ### Sources
114
168
 
115
169
  | Reference | Example |
116
170
  |---|---|
117
171
  | Relative path | `../presets/team` (relative to the file that references it) |
172
+ | Home directory | `~/presets/me`, for personal presets |
118
173
  | GitHub | `github:<owner>/<repo>/<path>#<ref>` |
119
174
  | GitLab | `gitlab:<owner>/<repo>/<path>#<ref>` |
120
175
 
@@ -143,6 +198,7 @@ chain once, before both of them.
143
198
  | Level instructions (`AGENTS.md`) | `instructions@<preset name>` | never collides: every level keeps its own | `exclude.rules` |
144
199
  | Skill | `name` from `SKILL.md`, otherwise the folder name | replaces it | `exclude.skills` |
145
200
  | Command | file name without `.md` | replaces it | `exclude.commands` |
201
+ | Subagent | file name without `.md` | replaces it | `exclude.subagents` |
146
202
  | MCP server | file name without `.yaml` | replaces it | `exclude.mcp` |
147
203
  | Environment variable | name in `env` | replaces it | `exclude.env` |
148
204
  | Permission rule | the rule, like `Bash(npm test *)` | lists are joined: every level adds its rules | `exclude.permissions`, only for `allow` and `ask` |
@@ -166,7 +222,9 @@ are merged by key (the specific value wins); `command`, `args` and `url` are rep
166
222
  - an `env` value refers to another variable, like `${TOKEN}`: agents do not expand it in
167
223
  their settings, so write the value itself and keep secrets out of presets;
168
224
  - `env` sets a variable that Claude Code ignores in project settings (see below);
169
- - `exclude.permissions` tries to remove a `deny` rule.
225
+ - `exclude.permissions` tries to remove a `deny` rule;
226
+ - a subagent has no `description` or no instructions, an unknown field, or a file name that
227
+ cannot be a subagent name.
170
228
 
171
229
  All problems are reported at once, in the order of the files, so you can fix them in one pass.
172
230
 
@@ -176,10 +234,11 @@ For every agent:
176
234
 
177
235
  | Path | Content | Committed |
178
236
  |---|---|---|
179
- | `AGENTS.md` | Index: hierarchy, rules, skills, commands, MCP servers | yes |
237
+ | `AGENTS.md` | Index: hierarchy, rules, skills, commands, MCP servers, subagents | yes |
180
238
  | `.agents/rules/<NN>-<level>-<key>.md` | Rule texts, ordered from specific to general | no |
181
239
  | `.agents/skills/<key>/` | Skills | no |
182
240
  | `.tunestra/state/` | What tunestra generated last time | no |
241
+ | `AGENTS.override.md`, `CLAUDE.local.md` | The personal level, when there is one | no |
183
242
  | `.gitignore` | A block between `# >>> tunestra` and `# <<< tunestra` | yes |
184
243
 
185
244
  ### Claude Code
@@ -190,6 +249,7 @@ For every agent:
190
249
  | `.claude/rules/tunestra/<NN>-<level>-<key>.md` | Copies of the rules; Claude Code loads them in every session | no |
191
250
  | `.claude/skills/<key>` | Symlinks to `.agents/skills/<key>` | no |
192
251
  | `.claude/commands/<key>.md` | Commands | no |
252
+ | `.claude/agents/<key>.md` | Subagents | no |
193
253
  | `.mcp.json` | MCP servers | no |
194
254
  | `.claude/settings.json` | `env` and `permissions`, when presets set them | yes |
195
255
 
@@ -207,6 +267,9 @@ the ones that choose its own directories (`HOME`, `XDG_*`, `CLAUDE_CONFIG_DIR`).
207
267
  on them, because they would not work; set them in managed settings, `~/.claude/settings.json`
208
268
  or your shell. Values that turn telemetry off, like `OTEL_LOGS_EXPORTER: none`, are allowed.
209
269
 
270
+ A read-only subagent of Claude Code loses the tools that change files: `Write`, `Edit`,
271
+ `NotebookEdit` and `Bash`. It keeps the tools that read and search, and MCP tools.
272
+
210
273
  ### Codex
211
274
 
212
275
  Codex reads `AGENTS.md` and `.agents/skills/` by itself. It does not follow the links in
@@ -217,6 +280,7 @@ Codex reads `AGENTS.md` and `.agents/skills/` by itself. It does not follow the
217
280
  | `.codex/config.toml` | `developer_instructions` with every rule, from specific to general, `[shell_environment_policy] set` with `env`, and `[mcp_servers]` | no |
218
281
  | `.codex/rules/tunestra.rules` | `deny` and `ask` rules for shell commands as `prefix_rule`: `forbidden` and `prompt` | no |
219
282
  | `.agents/skills/<command>/` | Each command as a skill that runs only when you call it: `$release-notes` | no |
283
+ | `.codex/agents/<key>.toml` | Subagents | no |
220
284
 
221
285
  Codex reads `.codex/config.toml` only in a trusted project: trust the project when Codex asks.
222
286
  Codex gets `env` as the environment of the commands it runs; it does not change how Codex
@@ -232,7 +296,12 @@ Codex has no `type` for MCP servers and does not support SSE: an SSE server is s
232
296
  note, and `headers` become `http_headers`. tunestra owns the whole `.codex/config.toml`; keep
233
297
  your personal Codex settings in `~/.codex/config.toml`.
234
298
 
235
- `<NN>` orders rules from specific to general: `10` project, `20` team, `30` domain, `40` base.
299
+ A Codex subagent gets the sandbox, the permissions and the MCP servers of the main session; its
300
+ file can change only the model and the instructions. So Codex cannot make a subagent
301
+ read-only: tunestra turns off its shell (`features.shell_tool = false`) and asks it not to
302
+ edit files in the instructions, and setup says so in a note.
303
+
304
+ `<NN>` orders rules from specific to general: `00` personal, `10` project, `20` team, `30` domain, `40` base.
236
305
  Level instructions get the key `instructions`, and the preset name when it differs from the
237
306
  level: `20-team-instructions.md`, but `20-team-instructions-frontend.md` for a `team` preset
238
307
  named `frontend`.
@@ -268,10 +337,11 @@ Generated files are never kept because of manual edits: change the sources inste
268
337
  | Command | What it does |
269
338
  |---|---|
270
339
  | `tunestra init` | Creates `tunestra.yaml`; `--extends <presets...>` fills `extends`. Moves a hand-written `AGENTS.md` to `.tunestra/AGENTS.md` and a `CLAUDE.md` with its own text to `.tunestra/rules/claude-md.md`; a `CLAUDE.md` that only imports `AGENTS.md` is removed |
340
+ | `tunestra init --local` | Creates your personal level, `tunestra.local.yaml` and `.tunestra.local/rules/`, in a project with `tunestra.yaml`. `--extends` adds personal presets |
271
341
  | `tunestra setup` | Resolves the chain and regenerates every output |
272
342
  | `tunestra setup --dry-run` | Prints what would be written or removed, and the warnings |
273
343
  | `tunestra setup --verbose` | Also prints where every artifact comes from and what it overrides |
274
- | `tunestra uninstall` | Removes everything tunestra generated and its block in `.gitignore`; `tunestra.yaml` and `.tunestra/` stay. `--dry-run` shows the list first |
344
+ | `tunestra uninstall` | Removes everything tunestra generated and its block in `.gitignore`, and takes its entries out of `.claude/settings.local.json`; the sources stay. `--dry-run` shows the list first |
275
345
 
276
346
  `tunestra setup` refuses to overwrite an `AGENTS.md` or `CLAUDE.md` that it did not generate
277
347
  and tells you where to move their text.
@@ -282,7 +352,7 @@ and tells you where to move their text.
282
352
  |---|---|
283
353
  | v0.1 | Inheritance for Claude Code |
284
354
  | v0.2 | Codex (this document) |
285
- | v0.3 | `env` and permissions, then subagents and a personal `local` level |
355
+ | v0.3 | `env`, permissions, subagents and a personal `local` level |
286
356
  | v0.4 | Spaces, npm sources, lockfile |
287
357
  | v0.5 | `required` / `locked` policies, CI check |
288
358
  | v0.6 | Hooks |