@mnbny/woof 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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +472 -2
  3. package/cli/templates/add-draft.md +21 -0
  4. package/cli/templates/add-error.md +5 -0
  5. package/cli/templates/add-result.md +10 -0
  6. package/cli/templates/edit-draft.md +22 -0
  7. package/cli/templates/edit-error.md +3 -0
  8. package/cli/templates/edit-path.md +3 -0
  9. package/cli/templates/edit-result.md +7 -0
  10. package/cli/templates/edit-unchanged.md +3 -0
  11. package/cli/templates/editor.html +338 -0
  12. package/cli/templates/explain-ambiguous.md +5 -0
  13. package/cli/templates/explain-error.md +5 -0
  14. package/cli/templates/explain-result.md +5 -0
  15. package/cli/templates/export-error.md +3 -0
  16. package/cli/templates/export-result.md +6 -0
  17. package/cli/templates/get-ambiguous.md +5 -0
  18. package/cli/templates/get-cancelled.md +5 -0
  19. package/cli/templates/get-candidates.md +5 -0
  20. package/cli/templates/get-error.md +5 -0
  21. package/cli/templates/get-home-dependencies.md +1 -0
  22. package/cli/templates/get-no-match.md +3 -0
  23. package/cli/templates/get-search-empty.md +3 -0
  24. package/cli/templates/get-search.md +5 -0
  25. package/cli/templates/import-backup.md +7 -0
  26. package/cli/templates/import-choice-rejected.md +1 -0
  27. package/cli/templates/import-decision.md +16 -0
  28. package/cli/templates/import-error.md +3 -0
  29. package/cli/templates/import-finding-incomplete.md +1 -0
  30. package/cli/templates/import-finding-unreadable.md +1 -0
  31. package/cli/templates/import-findings-configuration.md +3 -0
  32. package/cli/templates/import-findings.md +3 -0
  33. package/cli/templates/import-imported.md +3 -0
  34. package/cli/templates/import-rechecked.md +1 -0
  35. package/cli/templates/import-rechecks.md +1 -0
  36. package/cli/templates/import-report.md +1 -0
  37. package/cli/templates/import-reusable.md +2 -0
  38. package/cli/templates/import-unchanged.md +1 -0
  39. package/cli/templates/import-validation-findings.md +1 -0
  40. package/cli/templates/init-error.md +3 -0
  41. package/cli/templates/init-home.md +7 -0
  42. package/cli/templates/init-location.md +7 -0
  43. package/cli/templates/init-registered.md +5 -0
  44. package/cli/templates/init-repository.md +5 -0
  45. package/cli/templates/init-target.md +11 -0
  46. package/cli/templates/invocation-error.md +5 -0
  47. package/cli/templates/migration-notice.md +1 -0
  48. package/cli/templates/projects-error.md +3 -0
  49. package/cli/templates/projects-result.md +3 -0
  50. package/cli/templates/readme-error.md +5 -0
  51. package/cli/templates/skill-missing.md +10 -0
  52. package/cli/templates/skill-outdated.md +7 -0
  53. package/cli/templates/validate-ambiguous.md +5 -0
  54. package/cli/templates/validate-error.md +5 -0
  55. package/cli/templates/validate-result.md +3 -0
  56. package/cli/woof.bundle.mjs +244 -0
  57. package/package.json +73 -4
  58. package/skills/woof-execution/SKILL.md +84 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yulolimum
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,473 @@
1
- # Temporary Holding Version
1
+ <h1 align="center">woof</h1>
2
+ <p align="center">Design tokens for your coding agent's instructions.</p>
2
3
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
4
+ <p align="center">
5
+ <img width="240" height="240" alt="image" src="https://github.com/user-attachments/assets/d31f6463-f17d-4229-af75-f915adbcef7e" />
6
+ </p>
7
+
8
+ My prompts, conventions, skills, and scripts were everywhere: copied between repos, stashed in ignored folders, slowly drifting apart. Every new project started the same way. Dig up the last agent file, copy it, fix the few lines that differ. All of it Markdown, and Markdown doesn't compose.
9
+
10
+ Design systems solved this a long time ago. You don't paste a hex code into every component. You name the color once, point an alias like `color.primary` at it, and dark mode changes what the alias means. woof brings that to your agent instructions. You write each convention, prompt, or script once, as a named token. Tokens reference each other and build bigger instructions. Each of your projects overrides only what's different. Keep tokens shared or private, in the repo or out of it.
11
+
12
+ You don't run woof. Your agent does:
13
+
14
+ <img src=".github/assets/readme/commit.jpg" alt="you: use woof to commit this. agent: runs woof get commit convention, finds git.commit, runs woof get git.commit, follows the seven rules of a great commit message, and commits with the message Add export command.">
15
+
16
+ In a repo that overrides `git.commit` with Conventional Commits, the same request gets you `feat(cli): add export command` instead. Nothing copied. A companion skill teaches your agent to search woof, use what it finds, and check with you before it changes anything.
17
+
18
+ ## How it works
19
+
20
+ ### Shared defaults, project overrides
21
+
22
+ Your shared tokens live in your woof home, and your agent can find them from any project. A project overrides only what's different. Everything else comes from the shared tokens.
23
+
24
+ ```text
25
+ shared
26
+ ├─ git.commits.seven_rules "Follow the seven rules of a great commit message…"
27
+ ├─ git.commits.conventional "Use Conventional Commits: type(scope): summary…"
28
+ └─ git.commit → git.commits.seven_rules
29
+
30
+ acme (project)
31
+ └─ git.commit → git.commits.conventional
32
+
33
+ globex (project)
34
+ └─ git.commit "Start every subject with the ticket ID, such as GLX-142…"
35
+ ```
36
+
37
+ `acme` points the alias at the other shared rule. `globex` writes its own. Every other project keeps the seven rules.
38
+
39
+ Say `acme` is your team's repo. Its woof configuration lives in the repo, and everyone gets it through Git. `globex` is a client repo you can't commit to, so its configuration stays private in your woof home. woof finds it by path, worktrees included.
40
+
41
+ ### Build instructions from pieces
42
+
43
+ A token can pull in other tokens with `{{…}}`. Build your agent instructions from pieces you already have:
44
+
45
+ ```text
46
+ agents.instructions
47
+ # Working in this repo
48
+ - Commits: {{git.commit}}
49
+ - Testing: {{testing.policy}}
50
+ - Style: {{code.style}}
51
+ ```
52
+
53
+ Your AGENTS.md or CLAUDE.md shrinks to one line, and the same line works in every repo:
54
+
55
+ ```markdown
56
+ Run `woof get agents.instructions` and follow it.
57
+ ```
58
+
59
+ In `acme`, the commit line comes out as Conventional Commits. In `globex`, it's the ticket rule. You never touch `agents.instructions`.
60
+
61
+ ### Tokens that run
62
+
63
+ A token can also be a bash, node, tsx, or bun script. Some scripts feed your instructions. Others just do a job.
64
+
65
+ ```text
66
+ git.branch bash git branch --show-current
67
+ checks.all bash pnpm lint && pnpm test && pnpm build
68
+ ```
69
+
70
+ `You're on {{git.branch}}.` reads as `You're on feat/export.` And when you say "run the checks", your agent runs `checks.all`. Projects override scripts like any other token, so the same ask does the right thing in every repo.
71
+
72
+ ### Ask in plain words
73
+
74
+ You don't have to remember token names. Give a token a description and tags, and your agent finds it by what it's for. Search reads only names, descriptions, and tags. It never loads every prompt or runs a script, so your agent fetches just the one it needs.
75
+
76
+ The companion skill, `woof-execution`, teaches your agent that loop: search, fetch, follow. It also writes tokens for you, so you never hand-edit JSON. Or Markdown. (Sorry, Markdown. It's not you, it's me.)
77
+
78
+ <img src=".github/assets/readme/save-token.jpg" alt="you: save that review checklist to woof. agent: runs woof get review checklist --search, finds nothing similar, drafts review.checklist with the description PR review checklist, and asks to save it. you: yes. agent: runs woof add review.checklist and saves it.">
79
+
80
+ Edits, sharing, and repo setup work the same way. Your agent proposes, and you approve.
81
+
82
+ ### Share with a coworker
83
+
84
+ If you can commit to a repo, like `acme`, keep its woof configuration there, and Git shares it with your team. Client repos are another story. Your agent instructions don't always belong in someone else's codebase, but your coworkers on that client could still use them. So keep the configuration in your woof home instead, like `globex`, and share it as a file.
85
+
86
+ Ask your agent to export it. woof packs `globex`, your shared tokens, and every file they use into one zip:
87
+
88
+ <img src=".github/assets/readme/export.jpg" alt="you: share my globex setup with sam. agent: runs woof export --project globex, saves ~/.woof/exports/globex.woof.zip, and says to send it to Sam.">
89
+
90
+ On Sam's side, anything new comes straight in. Anything that differs from what Sam already has waits for Sam's choice, one at a time:
91
+
92
+ <img src=".github/assets/readme/import.jpg" alt="sam: import globex.woof.zip. agent: runs woof import globex.woof.zip, says git.commit is different from theirs, and asks to keep yours, take theirs, or save theirs under a new name. sam: keep mine.">
93
+
94
+ Before it writes anything, woof saves a backup.
95
+
96
+ ## Getting started
97
+
98
+ woof runs through npx, so there's nothing to install. You need Node.js 22.13+, 24, or 26+.
99
+
100
+ Paste this into your agent:
101
+
102
+ ```text
103
+ Run `npx @mnbny/woof readme` and set up woof for me.
104
+ ```
105
+
106
+ Your agent reads this guide. The first time it runs woof, woof suggests the companion skill, and your agent asks you before installing it.
107
+
108
+ Next, fill it up. woof is only as good as the tokens you give it, so start with primitives: the conventions, prompts, docs, and skills you already have. Point your agent at them, and it saves each one as a token:
109
+
110
+ - **"Save our commit rules to woof."** Your agent drafts the token, shows it to you, and saves it once you say yes.
111
+ - **"Add the docs in `docs/conventions/` to woof."** Each doc becomes a token with a name and a description your agent can search.
112
+ - **"Turn my code review skill into a woof token."** Its instructions are now available in every project.
113
+ - **"Point my AGENTS.md at woof."** It moves your instructions into tokens and leaves one line behind.
114
+
115
+ Then put them to work:
116
+
117
+ - **"What does woof have for code review?"** It searches names, descriptions, and tags, and shows you what fits.
118
+ - **"Use the woof token for code review."** It fetches the matching token and follows its instructions.
119
+ - **"Use woof to commit this."** It finds your commit convention and follows it.
120
+ - **"Set up woof for this repo."** It creates the repo's woof configuration, committed or private. Your call.
121
+
122
+ ## Under the hood
123
+
124
+ Everything below is plain JSON, and your agent writes it for you. Here's how it fits together, one piece at a time.
125
+
126
+ ### Where tokens live
127
+
128
+ Your shared tokens live in one file in your woof home, `~/.woof/woof.config.json`. Your agent edits it through woof, and you can edit it by hand.
129
+
130
+ ### Tokens
131
+
132
+ A token is a key in that file. Nested keys build its path:
133
+
134
+ ```json
135
+ {
136
+ "git": {
137
+ "commits": {
138
+ "seven_rules": "Follow the seven rules of a great commit message: …"
139
+ }
140
+ }
141
+ }
142
+ ```
143
+
144
+ That's `git.commits.seven_rules`. A plain string is a prompt.
145
+
146
+ To help your agent find a token, swap the string for the long form, with a description and tags:
147
+
148
+ ```json
149
+ {
150
+ "$type": "prompt",
151
+ "$exec": "Follow the seven rules of a great commit message: …",
152
+ "$description": "How to write commit messages",
153
+ "$tags": ["git"]
154
+ }
155
+ ```
156
+
157
+ Keys that start with `$` belong to woof. Everything else is yours to name.
158
+
159
+ For a long prompt, keep it in a file. A plain string or `$exec` can point at it:
160
+
161
+ ```json
162
+ "<root>/resources/review-checklist.md"
163
+ ```
164
+
165
+ `<root>` is your woof home. In a repo's config, `<repo>` points at the repo.
166
+
167
+ ### Aliases
168
+
169
+ A string that is exactly one reference is an alias:
170
+
171
+ ```json
172
+ {
173
+ "git": {
174
+ "commit": "{{git.commits.seven_rules}}"
175
+ }
176
+ }
177
+ ```
178
+
179
+ Point `git.commit` at a different token, and everything that uses it follows.
180
+
181
+ ### Composites
182
+
183
+ References work anywhere in text:
184
+
185
+ ```json
186
+ {
187
+ "agents": {
188
+ "instructions": "# Working in this repo\n\n- Commits: {{git.commit}}\n- Testing: {{testing.policy}}"
189
+ }
190
+ }
191
+ ```
192
+
193
+ woof applies overrides first, then resolves references, so an override reaches every composite. Write `{{{{` and `}}}}` for literal double braces. A missing token or a loop fails before anything runs.
194
+
195
+ ### Scripts
196
+
197
+ Set `$type` to `bash`, `node`, `tsx`, or `bun`, and `$exec` becomes the script. Here's `git.branch`:
198
+
199
+ ```json
200
+ {
201
+ "$type": "bash",
202
+ "$exec": "git branch --show-current"
203
+ }
204
+ ```
205
+
206
+ The script runs in the repo root, and its output becomes the value. `$exec` can also be a file, like `"<root>/scripts/checks.sh"`, or a list of scripts that run in order and stop at the first failure.
207
+
208
+ ### Projects
209
+
210
+ A project changes tokens for one codebase. It holds only what's different, and everything else comes from your shared tokens. A project lives in one of two places.
211
+
212
+ #### In your woof home
213
+
214
+ A private project never enters the repo, so it works even where you can't commit, like `globex`. Ask your agent to set up a private woof project for the repo. It adds the project to your shared file under `$projects`, with the paths that select it:
215
+
216
+ ```json
217
+ {
218
+ "$projects": {
219
+ "globex": {
220
+ "$metadata": {
221
+ "$basePaths": ["~/code/globex"],
222
+ "$worktreePaths": ["~/code/globex-*"]
223
+ },
224
+ "git": {
225
+ "commit": "Start every subject with the ticket ID, such as GLX-142…"
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ woof selects `globex` anywhere inside `~/code/globex`, and in every worktree that matches `~/code/globex-*`.
233
+
234
+ #### In the repo
235
+
236
+ Ask your agent to set up woof for the repo. It creates a `woof.config.json` at the repo root, or in `.agents/` or `.claude/`. Commit it, and woof uses it whenever you work inside the repo, in any clone or worktree, so your whole team gets it. Here's `acme`'s, which points one alias elsewhere:
237
+
238
+ ```json
239
+ {
240
+ "git": {
241
+ "commit": "{{git.commits.conventional}}"
242
+ }
243
+ }
244
+ ```
245
+
246
+ #### Which project applies
247
+
248
+ woof picks one project per run: the one you name, then the repo's own config, then the private project whose paths match. If nothing matches, your shared tokens apply alone.
249
+
250
+ ## Reference
251
+
252
+ That's the tour. From here, it gets detailed fast: the full config, every rule, and every command. Your agent reads this part closely. You can skim.
253
+
254
+ ### Config schema
255
+
256
+ Here's everything from the tour in one file, `~/.woof/woof.config.json`:
257
+
258
+ ```json
259
+ {
260
+ "$schemaVersion": 2,
261
+ "git": {
262
+ "commits": {
263
+ "seven_rules": {
264
+ "$type": "prompt",
265
+ "$exec": "Follow the seven rules of a great commit message: …",
266
+ "$description": "How to write commit messages",
267
+ "$tags": ["git"]
268
+ },
269
+ "conventional": "Use Conventional Commits: type(scope): summary…"
270
+ },
271
+ "commit": "{{git.commits.seven_rules}}",
272
+ "branch": {
273
+ "$type": "bash",
274
+ "$exec": "git branch --show-current"
275
+ }
276
+ },
277
+ "testing": {
278
+ "policy": "Run the tests before you push."
279
+ },
280
+ "checks": {
281
+ "all": {
282
+ "$type": "bash",
283
+ "$exec": ["pnpm lint", "pnpm test", "pnpm build"]
284
+ }
285
+ },
286
+ "review": {
287
+ "checklist": "<root>/resources/review-checklist.md"
288
+ },
289
+ "agents": {
290
+ "instructions": "# Working in this repo\n\n- Commits: {{git.commit}}\n- Testing: {{testing.policy}}"
291
+ },
292
+ "$projects": {
293
+ "globex": {
294
+ "$metadata": {
295
+ "$basePaths": ["~/code/globex"],
296
+ "$worktreePaths": ["~/code/globex-*"]
297
+ },
298
+ "git": {
299
+ "commit": "Start every subject with the ticket ID, such as GLX-142…"
300
+ }
301
+ },
302
+ "initech": "<root>/projects/initech.json"
303
+ }
304
+ }
305
+ ```
306
+
307
+ And `acme`'s repo config:
308
+
309
+ ```json
310
+ {
311
+ "$schemaVersion": 2,
312
+ "git": {
313
+ "commit": "{{git.commits.conventional}}"
314
+ }
315
+ }
316
+ ```
317
+
318
+ #### Values
319
+
320
+ | Value | Example | Means |
321
+ | --- | --- | --- |
322
+ | String | `"Run the tests before you push."` | Prompt |
323
+ | String that is exactly one reference | `"{{git.commits.seven_rules}}"` | Alias |
324
+ | String with references inside | `"Commits: {{git.commit}}"` | Composite prompt |
325
+ | String that starts with `<root>/` or `<repo>/` | `"<root>/resources/review-checklist.md"` | Prompt read from a file |
326
+ | Object with `$type` | `{ "$type": "bash", "$exec": "…" }` | Resource: a prompt or a script |
327
+ | Any other object | `{ "commits": { … } }` | Namespace |
328
+
329
+ #### Reserved keys
330
+
331
+ | Key | Belongs in | Value |
332
+ | --- | --- | --- |
333
+ | `$schemaVersion` | Every config file, at the top level | `2` |
334
+ | `$type` | A resource | `prompt`, `bash`, `node`, `tsx`, or `bun` |
335
+ | `$exec` | A resource | Prompt text, script source, or a `<root>/` or `<repo>/` file. Scripts also take a list. |
336
+ | `$description` | A resource | Optional text for search |
337
+ | `$tags` | A resource | Optional list of strings for search |
338
+ | `$projects` | Your shared file | Private projects by name: inline, or a `<root>/` path to the project's own file, like `initech` |
339
+ | `$metadata` | A private project | Optional `$basePaths` and `$worktreePaths` |
340
+ | `$basePaths` | `$metadata` | Paths that select the project, including everything below them |
341
+ | `$worktreePaths` | `$metadata` | Patterns that match the current directory or one of its parents |
342
+
343
+ #### Rules
344
+
345
+ - Token names use ASCII letters, digits, `_`, and `-`, and they're case-sensitive. Dots join names into a path.
346
+ - An unknown `$` key fails.
347
+ - A value is a string, a resource, or a namespace. Numbers, booleans, `null`, and bare arrays fail.
348
+ - `<root>` is your woof home. `<repo>` is the root of the selected project's checkout: the current checkout inside the project's paths, or else the project's first base path that exists. Without either, `<repo>` files fail. Shared tokens can't use `<repo>`. A file path can't be absolute or empty, can't use `..`, and must resolve to a regular file inside its root.
349
+ - Paths in `$basePaths` and `$worktreePaths` are absolute or start with `~/`. woof ignores paths that don't exist on your machine, so teammates can list their own.
350
+ - Shared tokens must resolve without a project. They can't reference project-only tokens or `<repo>` files.
351
+ - An override replaces the whole token, including its description and tags. A project can't replace a shared namespace with a token, or a token with a namespace.
352
+ - A missing reference or a cycle fails before any script runs. A token that references itself is a cycle.
353
+ - A checkout holds one repo config: `woof.config.json`, `.agents/woof.config.json`, or `.claude/woof.config.json`. Two different files fail.
354
+ - Every config file declares `"$schemaVersion": 2`. woof never upgrades a file on its own. When it asks for a migration, rerun the command with `--migrate`.
355
+
356
+ ### Commands
357
+
358
+ Your agent runs these as `npx @mnbny/woof <command>`. Add `--help` to any command for its full options.
359
+
360
+ | Command | What it does | Options |
361
+ | --- | --- | --- |
362
+ | `woof readme` | Prints this guide. Agents run it first. | — |
363
+ | `woof get [query…]` | Prints a token's value when the query is its exact path. Otherwise, searches. | `--search` to always search, `--project <name>` |
364
+ | `woof add [path]` | Adds a token | `--type`, `--content`, `--description`, `--tag`, and one of `--shared`, `--repo`, or `--project <name>` |
365
+ | `woof edit [path]` | Changes a token's content, description, or tags | `--content`, `--description`, `--tag`, `--shared` or `--override`, `--project <name>` |
366
+ | `woof init [location]` | Creates a repo config or a private project | `--repo`, or `--name <name>` with `--base-path` and `--worktree-path` |
367
+ | `woof projects` | Shows which project the current directory selects, and lists private projects | — |
368
+ | `woof explain [path]` | Traces how a token resolves, without running scripts | `--project <name>` |
369
+ | `woof validate [path]` | Checks every token, or one token's graph, without running scripts | `--project <name>` |
370
+ | `woof export` | Packs a private project into a zip in `~/.woof/exports/` | `--project <name>` |
371
+ | `woof import <archive>` | Asks about each conflict in an archive, then applies it | `--decisions <file>` |
372
+
373
+ Every command also takes `--agent` and `--migrate`. `woof --help` and `woof --version` work too.
374
+
375
+ #### Options
376
+
377
+ - `--content` takes text, the path of an existing file, or `-` to read standard input.
378
+ - `--tag`, `--base-path`, and `--worktree-path` repeat: `--tag git --tag commits`.
379
+ - In `edit`, an empty `--description` or `--tag` removes it. `--shared` changes a shared token for every project, and `--override` overrides it in the selected project only.
380
+ - A qualified address, such as `'$projects.globex.git.commit'`, selects a project the same way `--project globex` does. Quote it so the shell leaves `$projects` alone.
381
+
382
+ #### Agent mode and exit status
383
+
384
+ - woof detects coding agents from markers in their environment. `--agent` covers any other caller.
385
+ - Agent mode runs the same operations, with plain text and no questions.
386
+ - When a command needs a decision, it prints the choices and the exact command to continue, writes nothing, and exits with status 1.
387
+ - `get` prints the value exactly as resolved, so you can pipe it.
388
+ - Exit status is `0` on success, `1` on a failure or a handoff, and `130` on a cancellation.
389
+
390
+ ### Scripts
391
+
392
+ A script token runs each time your agent gets it, and whatever it prints becomes the value.
393
+
394
+ #### Runtimes
395
+
396
+ - `bash`: your bash.
397
+ - `node`: the same Node.js that runs woof.
398
+ - `tsx`: TypeScript through a pinned tsx, from npx. It doesn't type-check.
399
+ - `bun`: a pinned Bun, from npx.
400
+
401
+ #### Where the script lives
402
+
403
+ `$exec` holds the script itself, or points at a file:
404
+
405
+ - `<root>/…`: a file in your woof home.
406
+ - `<repo>/…`: a file in the selected project's checkout. Project tokens only.
407
+
408
+ #### Notes
409
+
410
+ - Scripts run in the selected project's checkout, the same root as `<repo>`. Without one, they run in the current repo root, or in the current directory outside a repo.
411
+ - A list of scripts runs in order and stops at the first failure.
412
+ - The first `tsx` or `bun` run may need the network.
413
+ - If a script fails, the lookup fails. woof doesn't undo what a script already did, and there's no timeout.
414
+ - Only `get` runs scripts. Searching, `explain`, and `validate` never do.
415
+
416
+ ### Files and folders
417
+
418
+ Everything woof keeps lives in your woof home, `~/.woof`.
419
+
420
+ #### In your woof home
421
+
422
+ - `woof.config.json`: your shared tokens and private projects.
423
+ - `resources/`: files woof copied in for your tokens.
424
+ - `exports/`: archives from `woof export`.
425
+ - `.backups/`: backups that `woof import` saves before it writes.
426
+
427
+ #### In a repo
428
+
429
+ - `woof.config.json`, `.agents/woof.config.json`, or `.claude/woof.config.json`: the repo's project. Keep only one.
430
+
431
+ #### Notes
432
+
433
+ - woof creates its home and `woof.config.json` the first time it needs them.
434
+ - woof keeps every backup. To restore one, extract it over woof home.
435
+
436
+ ### Limits and decisions
437
+
438
+ #### Limits
439
+
440
+ What woof doesn't do yet:
441
+
442
+ - There's no rename, move, or delete command. Edit the JSON by hand, or ask your agent to, then run `woof validate`.
443
+ - One project applies per run, so you can't layer personal overrides on top of a repo's config.
444
+ - Scripts take no arguments. Each run uses the script as written.
445
+ - On Windows, cancelling a script stops the script itself but not the processes it started. macOS and Linux clean up everything.
446
+ - The `woof edit` page loads its styles from a CDN, so it's unstyled offline.
447
+
448
+ #### Deliberate decisions
449
+
450
+ What woof does on purpose:
451
+
452
+ - An override replaces the whole token. To build on a shared value, reference its pieces from your override. A token can't reference itself.
453
+ - A change to a shared token reaches every project at once, the way a design token does. There's no version pinning.
454
+ - Repo configs travel through Git. Only private projects export.
455
+ - Script output is plain text. woof never looks for references in it.
456
+ - A composite that references a script runs it on every lookup, so keep scripts with side effects out of composites.
457
+ - Scripts run as you, with no sandbox, timeout, or undo. Before you get tokens from an unfamiliar repo, check its config with `woof explain`.
458
+ - Search matches names, descriptions, and tags as text. It isn't semantic, so good descriptions pay off.
459
+ - woof borrows design-token ideas, not the DTCG file format, so DTCG tools can't read woof files.
460
+ - woof runs locally and never calls a model. Your agent does the thinking.
461
+
462
+ ## Development
463
+
464
+ ```sh
465
+ git clone https://github.com/mnbny/woof.git
466
+ cd woof
467
+ pnpm install
468
+ node cli/setup.mjs # links ~/.local/bin/woof to this checkout
469
+ pnpm validate # formats, lints, typechecks, and builds
470
+ pnpm test
471
+ ```
472
+
473
+ Design notes for contributors and agents live in [`.agents/docs/`](.agents/docs/index.md).
@@ -0,0 +1,21 @@
1
+ woof needs more input to add a token: {{missing}}.
2
+
3
+ Draft the token from the conversation:
4
+
5
+ 1. Work out what the user wants to keep. Write the content as standalone instructions that make sense without this conversation.
6
+ 2. Check for a similar token with woof get 'TERMS' --search --agent. If one exists, ask the user whether to add a new token or to change the existing token with woof edit 'PATH' --agent.
7
+ 3. Choose a path that fits the existing namespaces below. Each name in the path contains only ASCII letters, digits, underscores and hyphens.
8
+ 4. Choose the type: prompt for instructions or other text, or bash, node, tsx or bun for a script.
9
+ 5. Write a one-line description and a few tags, so that discovery can find the token.
10
+ 6. Choose one target below. Shared tokens are available in every project. A project token exists only in that project, and it overrides a shared token at the same path.
11
+ 7. Show the user the path, target, type, description, tags and content. Save only after the user approves.
12
+
13
+ Existing namespaces:
14
+ {{namespaces}}
15
+
16
+ Targets:
17
+ {{targets}}
18
+
19
+ Then run this command with the approved values. Put the content between the WOOF lines, so that it goes to standard input:
20
+
21
+ {{command}}
@@ -0,0 +1,5 @@
1
+ woof could not add the token.
2
+
3
+ {{details}}
4
+
5
+ Retry with the complete command.
@@ -0,0 +1,10 @@
1
+ Added {{path}}.
2
+
3
+ Configuration: {{file}}
4
+ Type: {{type}}
5
+ Content: {{content}}
6
+ Description: {{description}}
7
+ Tags: {{tags}}
8
+ Overrides a shared token: {{override}}
9
+
10
+ Check the token with {{command}}.
@@ -0,0 +1,22 @@
1
+ Edit {{path}}.
2
+
3
+ Type: {{type}}
4
+ Defined in: {{where}}
5
+ Configuration: {{configuration}}
6
+ Content: {{location}}
7
+ Description: {{description}}
8
+ Tags: {{tags}}
9
+
10
+ Current content:
11
+ {{content}}
12
+
13
+ Layers:
14
+ {{layers}}
15
+
16
+ 1. Work out the change from the conversation.
17
+ 2. Show the user the current and the new version. Apply the change only after the user approves.
18
+ 3. Pass only the fields that change. Tags replace the current set. --description '' removes the description, and --tag '' removes all tags.
19
+ 4. Put new content between the WOOF lines, so that it goes to standard input. If the content is in a script file, edit that file directly. woof then changes only the description and tags. To change a shared script for this project only, first run the command with --override alone. woof copies the script into the project and reports the copy. Then edit the copy.
20
+ 5. If the command has LAYER, replace it with one flag from Layers.
21
+
22
+ {{command}}
@@ -0,0 +1,3 @@
1
+ woof could not edit the token.
2
+
3
+ {{details}}
@@ -0,0 +1,3 @@
1
+ Name the token to edit.
2
+
3
+ Find it with woof get 'TERMS' --search{{project}} --agent. Then run woof edit 'PATH'{{project}} --agent to see the current token.
@@ -0,0 +1,7 @@
1
+ Edited {{path}}.
2
+
3
+ Configuration: {{file}}
4
+ Content file: {{contentFile}}
5
+ Changed in: {{where}}
6
+
7
+ Check the token with {{command}}.
@@ -0,0 +1,3 @@
1
+ No changes to {{path}}.
2
+
3
+ The new values match the current token. Nothing was written.