tunestra 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +227 -2
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +1881 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +1 -0
- package/dist/src-DSbrKtiC.mjs +5 -0
- package/package.json +67 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aleksandr Sokolov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,228 @@
|
|
|
1
|
-
#
|
|
1
|
+
# tunestra
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/sensetive5/tunestra/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/sensetive5/tunestra)
|
|
5
|
+
[](https://www.npmjs.com/package/tunestra)
|
|
6
|
+
[](package.json)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
> Tune your AI agents to play as one orchestra.
|
|
10
|
+
|
|
11
|
+
> [!WARNING]
|
|
12
|
+
> **Early version.** v0.1 supports Claude Code; Codex comes in v0.2. The formats may still
|
|
13
|
+
> change before v1.0.
|
|
14
|
+
|
|
15
|
+
tunestra gives Claude Code, Codex and other AI coding agents **one shared source** of rules,
|
|
16
|
+
skills, commands and MCP servers, and generates each agent's native configuration from it.
|
|
17
|
+
|
|
18
|
+
The source is a chain of **presets**, from general to specific:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
base — your organization: security, general principles, shared tools
|
|
22
|
+
↓ extends
|
|
23
|
+
team — your team: conventions, stack, team skills
|
|
24
|
+
↓ extends
|
|
25
|
+
project — this repository: architecture, domain model, project skills
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
More specific levels **override** general ones by artifact key or **exclude** them.
|
|
29
|
+
Agents receive the result from specific to general: when two instructions conflict, the more
|
|
30
|
+
specific one wins.
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npx tunestra init --extends github:<organisation_name>/<presets_repo>/team#v1
|
|
36
|
+
npx tunestra setup # generates AGENTS.md, CLAUDE.md, .claude/, .agents/, .mcp.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`init` creates `tunestra.yaml`:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
extends:
|
|
43
|
+
- github:<organisation_name>/<presets_repo>/team#v1
|
|
44
|
+
agents: [claude]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Commit `tunestra.yaml`, `.tunestra/`, `AGENTS.md` and `CLAUDE.md`. Everything else that
|
|
48
|
+
tunestra generates is listed in `.gitignore` automatically.
|
|
49
|
+
|
|
50
|
+
## Principles
|
|
51
|
+
|
|
52
|
+
1. **Sources are the only truth.** Presets and `.tunestra/` are edited by people.
|
|
53
|
+
Everything tunestra writes for agents is generated.
|
|
54
|
+
2. **Generated files are never edited by hand.** Every `tunestra setup` rebuilds them from
|
|
55
|
+
scratch. A manual edit is overwritten with a warning that tells you which source to change.
|
|
56
|
+
3. **Open standards first.** Rules follow [`AGENTS.md`](https://agents.md), skills follow
|
|
57
|
+
[Agent Skills](https://agentskills.io) (`SKILL.md`), MCP servers use the `.mcp.json` shape.
|
|
58
|
+
|
|
59
|
+
## Presets
|
|
60
|
+
|
|
61
|
+
A preset is a directory with a fixed layout. Artifacts are collected from the folders;
|
|
62
|
+
the manifest only holds metadata and overrides.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
<preset>/
|
|
66
|
+
tunestra.preset.yaml # manifest
|
|
67
|
+
AGENTS.md # optional: main instructions of this level
|
|
68
|
+
rules/<key>.md # rules, one topic per file
|
|
69
|
+
skills/<key>/SKILL.md # skills (Agent Skills format)
|
|
70
|
+
commands/<key>.md # slash commands
|
|
71
|
+
mcp/<key>.yaml # MCP servers
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Manifest: `tunestra.preset.yaml`
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
name: team # required, unique in the chain
|
|
78
|
+
level: team # required: base | domain | team
|
|
79
|
+
description: Frontend team conventions
|
|
80
|
+
extends: # optional, from general to specific
|
|
81
|
+
- ../base
|
|
82
|
+
exclude: # optional: drop inherited artifacts by key
|
|
83
|
+
skills: [code-review]
|
|
84
|
+
overrides: # optional: patch inherited MCP servers
|
|
85
|
+
mcp:
|
|
86
|
+
tracker:
|
|
87
|
+
env:
|
|
88
|
+
QUEUE: TEAM
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Project: `tunestra.yaml`
|
|
92
|
+
|
|
93
|
+
The project is the most specific level. Its artifacts live in `.tunestra/` with the same layout
|
|
94
|
+
as a preset.
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
name: my-service # optional, defaults to the directory name
|
|
98
|
+
extends:
|
|
99
|
+
- ../presets/team
|
|
100
|
+
agents: [claude] # v0.1 supports claude
|
|
101
|
+
exclude: {}
|
|
102
|
+
overrides: {}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Sources
|
|
106
|
+
|
|
107
|
+
| Reference | Example |
|
|
108
|
+
|---|---|
|
|
109
|
+
| Relative path | `../presets/team` (relative to the file that references it) |
|
|
110
|
+
| GitHub | `github:<owner>/<repo>/<path>#<ref>` |
|
|
111
|
+
| GitLab | `gitlab:<owner>/<repo>/<path>#<ref>` |
|
|
112
|
+
|
|
113
|
+
Pin git sources to a tag or commit. tunestra downloads the whole repository at that ref
|
|
114
|
+
into `.tunestra/state/sources/` on every setup, so a preset can extend other presets of its
|
|
115
|
+
repository with a relative path, like `../base`. A relative path cannot leave the repository.
|
|
116
|
+
Git is not needed: repositories are downloaded as archives over HTTPS.
|
|
117
|
+
|
|
118
|
+
For a private repository, set the `TUNESTRA_GIT_TOKEN` environment variable to a token with
|
|
119
|
+
read access. Lockfiles and npm sources are planned for v0.3.
|
|
120
|
+
|
|
121
|
+
## Inheritance
|
|
122
|
+
|
|
123
|
+
The chain is linearized from general to specific: every preset comes after the presets it
|
|
124
|
+
extends. Each level is applied on top of the accumulated result.
|
|
125
|
+
|
|
126
|
+
A level can extend a more general level or a level of the same kind: a `team` preset can
|
|
127
|
+
build on another `team` preset. When two presets extend the same preset, it joins the
|
|
128
|
+
chain once, before both of them.
|
|
129
|
+
|
|
130
|
+
### Artifact keys
|
|
131
|
+
|
|
132
|
+
| Artifact | Key | Same key on a more specific level | Remove |
|
|
133
|
+
|---|---|---|---|
|
|
134
|
+
| Rule | file name without `.md` | replaces it | `exclude.rules` |
|
|
135
|
+
| Level instructions (`AGENTS.md`) | `instructions@<preset name>` | never collides: every level keeps its own | `exclude.rules` |
|
|
136
|
+
| Skill | `name` from `SKILL.md`, otherwise the folder name | replaces it | `exclude.skills` |
|
|
137
|
+
| Command | file name without `.md` | replaces it | `exclude.commands` |
|
|
138
|
+
| MCP server | file name without `.yaml` | replaces it | `exclude.mcp` |
|
|
139
|
+
|
|
140
|
+
`overrides.mcp.<key>` patches an inherited server instead of replacing it: `env` and `headers`
|
|
141
|
+
are merged by key (the specific value wins); `command`, `args` and `url` are replaced.
|
|
142
|
+
|
|
143
|
+
### Validation
|
|
144
|
+
|
|
145
|
+
`tunestra setup` stops with an error when:
|
|
146
|
+
|
|
147
|
+
- a preset extends a more specific level (for example, `base` extends `team`);
|
|
148
|
+
- `extends` contains a cycle;
|
|
149
|
+
- two levels have the same name;
|
|
150
|
+
- a manifest has an unknown field or a missing required field;
|
|
151
|
+
- `exclude` or `overrides` refers to a key that is not inherited;
|
|
152
|
+
- after a patch, an MCP server has both `command` and `url`, or neither.
|
|
153
|
+
|
|
154
|
+
All problems are reported at once, in the order of the files, so you can fix them in one pass.
|
|
155
|
+
|
|
156
|
+
## What gets generated (Claude Code)
|
|
157
|
+
|
|
158
|
+
| Path | Content | Committed |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `AGENTS.md` | Index: hierarchy, rules, skills, commands, MCP servers | yes |
|
|
161
|
+
| `CLAUDE.md` | `@AGENTS.md` | yes |
|
|
162
|
+
| `.agents/rules/<NN>-<level>-<key>.md` | Rule texts, ordered from specific to general | no |
|
|
163
|
+
| `.agents/skills/<key>/` | Skills | no |
|
|
164
|
+
| `.claude/rules/tunestra/<NN>-<level>-<key>.md` | Copies of the rules; Claude Code loads them in every session | no |
|
|
165
|
+
| `.claude/skills/<key>` | Symlinks to `.agents/skills/<key>` | no |
|
|
166
|
+
| `.claude/commands/<key>.md` | Commands | no |
|
|
167
|
+
| `.mcp.json` | MCP servers | no |
|
|
168
|
+
| `.tunestra/state/` | What tunestra generated last time | no |
|
|
169
|
+
| `.gitignore` | A block between `# >>> tunestra` and `# <<< tunestra` | yes |
|
|
170
|
+
|
|
171
|
+
`<NN>` orders rules from specific to general: `10` project, `20` team, `30` domain, `40` base.
|
|
172
|
+
Level instructions get the key `instructions`, and the preset name when it differs from the
|
|
173
|
+
level: `20-team-instructions.md`, but `20-team-instructions-frontend.md` for a `team` preset
|
|
174
|
+
named `frontend`.
|
|
175
|
+
|
|
176
|
+
Every generated rule starts with its origin:
|
|
177
|
+
|
|
178
|
+
```md
|
|
179
|
+
<!-- Generated by tunestra from team:rules/code-style.md. Do not edit. -->
|
|
180
|
+
> Level: team, preset: team. Overrides: base.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Skills and commands are copied as is: their frontmatter must stay on the first line.
|
|
184
|
+
|
|
185
|
+
## Running setup again
|
|
186
|
+
|
|
187
|
+
tunestra keeps a list of what it wrote in `.tunestra/state/outputs.json` and compares every
|
|
188
|
+
run with it:
|
|
189
|
+
|
|
190
|
+
| Situation | What setup does |
|
|
191
|
+
|---|---|
|
|
192
|
+
| A generated file is still needed | Writes it again |
|
|
193
|
+
| A generated file was edited by hand | Writes it again and warns which source file to edit instead |
|
|
194
|
+
| A file is no longer generated (for example, a rule was deleted from a preset) | Removes it and the folders it leaves empty; warns if the file was edited by hand |
|
|
195
|
+
| A file is in the way, and tunestra did not create it | Stops and asks you to move it away |
|
|
196
|
+
| `.tunestra/state/` was deleted | Accepts its own files by their header or content and goes on |
|
|
197
|
+
|
|
198
|
+
Generated files are never kept because of manual edits: change the sources instead.
|
|
199
|
+
|
|
200
|
+
## Commands
|
|
201
|
+
|
|
202
|
+
| Command | What it does |
|
|
203
|
+
|---|---|
|
|
204
|
+
| `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 |
|
|
205
|
+
| `tunestra setup` | Resolves the chain and regenerates every output |
|
|
206
|
+
| `tunestra setup --dry-run` | Prints what would be written or removed, and the warnings |
|
|
207
|
+
| `tunestra setup --verbose` | Also prints where every artifact comes from and what it overrides |
|
|
208
|
+
| `tunestra uninstall` | Removes everything tunestra generated and its block in `.gitignore`; `tunestra.yaml` and `.tunestra/` stay. `--dry-run` shows the list first |
|
|
209
|
+
|
|
210
|
+
`tunestra setup` refuses to overwrite an `AGENTS.md` or `CLAUDE.md` that it did not generate
|
|
211
|
+
and tells you where to move their text.
|
|
212
|
+
|
|
213
|
+
## Roadmap
|
|
214
|
+
|
|
215
|
+
| Release | Scope |
|
|
216
|
+
|---|---|
|
|
217
|
+
| v0.1 | Inheritance for Claude Code (this document) |
|
|
218
|
+
| v0.2 | Codex |
|
|
219
|
+
| v0.3 | Spaces, npm sources, lockfile |
|
|
220
|
+
| v0.4 | `required` / `locked` policies, CI check |
|
|
221
|
+
| v0.5 | Hooks |
|
|
222
|
+
| v0.6 | LLM gateway, permissions |
|
|
223
|
+
| v0.7 | Local plugins |
|
|
224
|
+
| v0.8 | Isolated remote plugins |
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
[MIT](LICENSE)
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|