@fernado03/zoo-flow 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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +326 -0
  3. package/bin/zoo-flow.js +358 -0
  4. package/package.json +44 -0
  5. package/templates/full/.roo/commands/caveman.md +7 -0
  6. package/templates/full/.roo/commands/commit-and-document.md +202 -0
  7. package/templates/full/.roo/commands/diagnose.md +7 -0
  8. package/templates/full/.roo/commands/explore.md +13 -0
  9. package/templates/full/.roo/commands/feature.md +24 -0
  10. package/templates/full/.roo/commands/fix.md +19 -0
  11. package/templates/full/.roo/commands/grill-me.md +7 -0
  12. package/templates/full/.roo/commands/grill-with-docs.md +7 -0
  13. package/templates/full/.roo/commands/handoff.md +8 -0
  14. package/templates/full/.roo/commands/improve-codebase-architecture.md +7 -0
  15. package/templates/full/.roo/commands/prototype.md +9 -0
  16. package/templates/full/.roo/commands/refactor.md +17 -0
  17. package/templates/full/.roo/commands/setup-matt-pocock-skills.md +7 -0
  18. package/templates/full/.roo/commands/tdd.md +9 -0
  19. package/templates/full/.roo/commands/to-issues.md +7 -0
  20. package/templates/full/.roo/commands/to-prd.md +7 -0
  21. package/templates/full/.roo/commands/triage.md +7 -0
  22. package/templates/full/.roo/commands/tweak.md +9 -0
  23. package/templates/full/.roo/commands/update-docs.md +130 -0
  24. package/templates/full/.roo/commands/write-a-skill.md +7 -0
  25. package/templates/full/.roo/commands/zoom-out.md +7 -0
  26. package/templates/full/.roo/rules/00-paths.md +17 -0
  27. package/templates/full/.roo/rules/01-command-protocol.md +25 -0
  28. package/templates/full/.roo/rules/03-manual-reply-protocol.md +13 -0
  29. package/templates/full/.roo/rules-code-tweaker/00-scope.md +7 -0
  30. package/templates/full/.roo/rules-code-tweaker/01-completion.md +14 -0
  31. package/templates/full/.roo/rules-custom-orchestrator/00-routing.md +14 -0
  32. package/templates/full/.roo/rules-custom-orchestrator/01-delegation-message.md +12 -0
  33. package/templates/full/.roo/rules-system-architect/00-scope.md +9 -0
  34. package/templates/full/.roo/rules-system-architect/01-feature-prototype.md +10 -0
  35. package/templates/full/.roo/rules-system-architect/02-completion.md +11 -0
  36. package/templates/full/.roo/skills/docs/adr/0001-explicit-setup-pointer-only-for-hard-dependencies.md +18 -0
  37. package/templates/full/.roo/skills/engineering/README.md +12 -0
  38. package/templates/full/.roo/skills/engineering/diagnose/SKILL.md +73 -0
  39. package/templates/full/.roo/skills/engineering/diagnose/scripts/hitl-loop.template.sh +41 -0
  40. package/templates/full/.roo/skills/engineering/grill-with-docs/ADR-FORMAT.md +33 -0
  41. package/templates/full/.roo/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +45 -0
  42. package/templates/full/.roo/skills/engineering/grill-with-docs/SKILL.md +32 -0
  43. package/templates/full/.roo/skills/engineering/improve-codebase-architecture/DEEPENING.md +24 -0
  44. package/templates/full/.roo/skills/engineering/improve-codebase-architecture/HTML-REPORT.md +88 -0
  45. package/templates/full/.roo/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +45 -0
  46. package/templates/full/.roo/skills/engineering/improve-codebase-architecture/LANGUAGE.md +34 -0
  47. package/templates/full/.roo/skills/engineering/improve-codebase-architecture/SKILL.md +43 -0
  48. package/templates/full/.roo/skills/engineering/prototype/LOGIC.md +28 -0
  49. package/templates/full/.roo/skills/engineering/prototype/SKILL.md +27 -0
  50. package/templates/full/.roo/skills/engineering/prototype/UI.md +53 -0
  51. package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/SKILL.md +77 -0
  52. package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/domain.md +36 -0
  53. package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/issue-tracker-github.md +21 -0
  54. package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/issue-tracker-gitlab.md +23 -0
  55. package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/issue-tracker-local.md +20 -0
  56. package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/triage-labels.md +11 -0
  57. package/templates/full/.roo/skills/engineering/tdd/SKILL.md +52 -0
  58. package/templates/full/.roo/skills/engineering/tdd/deep-modules.md +9 -0
  59. package/templates/full/.roo/skills/engineering/tdd/interface-design.md +6 -0
  60. package/templates/full/.roo/skills/engineering/tdd/mocking.md +17 -0
  61. package/templates/full/.roo/skills/engineering/tdd/refactoring.md +9 -0
  62. package/templates/full/.roo/skills/engineering/tdd/tests.md +12 -0
  63. package/templates/full/.roo/skills/engineering/to-issues/SKILL.md +45 -0
  64. package/templates/full/.roo/skills/engineering/to-prd/SKILL.md +58 -0
  65. package/templates/full/.roo/skills/engineering/triage/AGENT-BRIEF.md +43 -0
  66. package/templates/full/.roo/skills/engineering/triage/OUT-OF-SCOPE.md +37 -0
  67. package/templates/full/.roo/skills/engineering/triage/SKILL.md +79 -0
  68. package/templates/full/.roo/skills/engineering/tweak/SKILL.md +17 -0
  69. package/templates/full/.roo/skills/engineering/zoom-out/SKILL.md +7 -0
  70. package/templates/full/.roo/skills/in-progress/README.md +8 -0
  71. package/templates/full/.roo/skills/in-progress/review/SKILL.md +39 -0
  72. package/templates/full/.roo/skills/in-progress/writing-beats/SKILL.md +32 -0
  73. package/templates/full/.roo/skills/in-progress/writing-fragments/SKILL.md +45 -0
  74. package/templates/full/.roo/skills/in-progress/writing-shape/SKILL.md +50 -0
  75. package/templates/full/.roo/skills/misc/README.md +6 -0
  76. package/templates/full/.roo/skills/misc/git-guardrails-claude-code/SKILL.md +64 -0
  77. package/templates/full/.roo/skills/misc/git-guardrails-claude-code/scripts/block-dangerous-git.sh +25 -0
  78. package/templates/full/.roo/skills/misc/migrate-to-shoehorn/SKILL.md +37 -0
  79. package/templates/full/.roo/skills/misc/scaffold-exercises/SKILL.md +61 -0
  80. package/templates/full/.roo/skills/misc/setup-pre-commit/SKILL.md +62 -0
  81. package/templates/full/.roo/skills/personal/README.md +6 -0
  82. package/templates/full/.roo/skills/personal/edit-article/SKILL.md +13 -0
  83. package/templates/full/.roo/skills/personal/obsidian-vault/SKILL.md +39 -0
  84. package/templates/full/.roo/skills/productivity/README.md +6 -0
  85. package/templates/full/.roo/skills/productivity/caveman/SKILL.md +28 -0
  86. package/templates/full/.roo/skills/productivity/grill-me/SKILL.md +13 -0
  87. package/templates/full/.roo/skills/productivity/handoff/SKILL.md +14 -0
  88. package/templates/full/.roo/skills/productivity/write-a-skill/SKILL.md +52 -0
  89. package/templates/full/.roomodes +47 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zoo Flow contributors
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 ADDED
@@ -0,0 +1,326 @@
1
+ # Zoo Flow
2
+
3
+ > **Smoke-tested workflow control plane for Zoo Code.**
4
+
5
+ Zoo Flow is a small, opinionated template that turns [Zoo Code](https://docs.zoocode.dev/)
6
+ into a predictable mode + command + skill orchestrator. It defines three
7
+ modes, a fixed routing matrix, a command protocol, and path-safety rules.
8
+ Drop it into a workspace and your AI assistant stops freelancing.
9
+
10
+ ## Why this exists
11
+
12
+ Out of the box, AI coding assistants tend to skip planning when you want
13
+ planning, plan when you want a tweak, and quietly invent file paths that do
14
+ not exist. Adding a pile of skills makes it worse.
15
+
16
+ Zoo Flow takes a different bet:
17
+
18
+ - A **router mode** chooses the workflow.
19
+ - An **architect mode** plans, diagnoses, and triages — and cannot edit
20
+ source code.
21
+ - A **tweaker mode** implements, runs tests, prototypes, and commits — only
22
+ when explicitly approved.
23
+ - A small set of **slash commands** acts as the public API between you and
24
+ the modes.
25
+ - A few **always-on rules** keep the path layout honest and stop skill paths
26
+ from drifting under `.roo/rules/`.
27
+
28
+ Everything else is optional. The skills bundled in the template are a
29
+ sensible starting point, not the point of the project.
30
+
31
+ ## Why are the folders still named `.roo/`?
32
+
33
+ Zoo Code keeps compatibility with Roo-style workspace paths. Project
34
+ modes still live in `.roomodes`, project slash commands still live in
35
+ `.roo/commands/`, and mode-specific rules still live in
36
+ `.roo/rules-{mode-slug}/`.
37
+
38
+ Zoo Flow uses Zoo Code as the primary target, but keeps those `.roo/`
39
+ paths because they are the official Zoo Code configuration paths. See
40
+ [the Zoo Code docs](https://docs.zoocode.dev/) for the canonical
41
+ reference.
42
+
43
+ Zoo Flow keeps skill discovery in [`docs/skills-index.md`](docs/skills-index.md),
44
+ not `.roo/rules/`, so the always-loaded rule set stays small. Zoo Code
45
+ loads everything in `.roo/rules/` on every turn, so that folder only
46
+ contains rules needed every turn: path safety, the command protocol,
47
+ and the manual-reply protocol.
48
+
49
+ ## Core workflow
50
+
51
+ ```mermaid
52
+ flowchart TD
53
+ User([User])
54
+ Orchestrator[🪃 custom-orchestrator<br/>router only]
55
+ Architect[🏗️ system-architect<br/>plan / diagnose / triage<br/>Markdown edits only]
56
+ Tweaker[⚡ code-tweaker<br/>implement / test / prototype / commit]
57
+
58
+ User -- "free-form request" --> Orchestrator
59
+ Orchestrator -- "proposes /command, waits" --> User
60
+ User -- "/tweak, /tdd, /update-docs,<br/>/commit-and-document, /prototype" --> Orchestrator
61
+ User -- "/fix, /feature, /refactor,<br/>/explore, /triage" --> Orchestrator
62
+
63
+ Orchestrator -- "new_task" --> Tweaker
64
+ Orchestrator -- "new_task" --> Architect
65
+
66
+ Architect -- "switch_mode (same window)" --> Tweaker
67
+ Tweaker -- "switch_mode (same window)" --> Architect
68
+
69
+ Tweaker -- "attempt_completion" --> Orchestrator
70
+ Architect -- "attempt_completion" --> Orchestrator
71
+ Orchestrator -- "summarize, HALT" --> User
72
+ ```
73
+
74
+ ## Modes
75
+
76
+ | Slug | Name | Role | Edits allowed | Delegation |
77
+ | --------------------- | --------------------- | ---------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------- |
78
+ | `custom-orchestrator` | 🪃 Custom Orchestrator | Router. Picks workflow, delegates, waits for the user. | None | `new_task` to architect or tweaker |
79
+ | `system-architect` | 🏗️ System Architect | Planning, diagnosis, refactor design, exploration, triage. | Markdown, `.scratch/`, `docs/` | `switch_mode` to tweaker in same window |
80
+ | `code-tweaker` | ⚡ Code Tweaker | Implementation, TDD, docs updates, prototypes, commits. | Full repo edits within the assigned command | `switch_mode` to architect in same window |
81
+
82
+ Modes are defined in [`templates/full/.roomodes`](templates/full/.roomodes).
83
+ The file is intentionally minimal — each mode's `customInstructions`
84
+ points at the matching `.roo/rules-{modeSlug}/` folder, where the actual
85
+ behavior lives. See [`docs/mode-rules.md`](docs/mode-rules.md) for the
86
+ layout and the rationale.
87
+
88
+ > Zoo Flow uses the preferred `.roo/rules-{modeSlug}/` directory form
89
+ > only. Legacy single-file fallbacks such as `.roorules-{modeSlug}` and
90
+ > `.clinerules-{modeSlug}` are not used by this template.
91
+
92
+ ## Commands
93
+
94
+ The orchestrator's routing matrix only routes the **core workflow
95
+ commands**. Helper commands are still part of the template — you can run
96
+ them directly in `system-architect` or `code-tweaker` when you need
97
+ them. They are intentionally outside the routing matrix so the
98
+ orchestrator stays focused on the workflows that benefit from
99
+ delegation.
100
+
101
+ ### Core commands (routed by the orchestrator)
102
+
103
+ | Command | Routes to | What it does |
104
+ | ------------------------ | -------------------- | ----------------------------------------------------------- |
105
+ | `/tweak` | `code-tweaker` | Direct implementation of small, known changes. |
106
+ | `/tdd` | `code-tweaker` | Test-first implementation loop. |
107
+ | `/prototype` | `code-tweaker` | Throwaway prototype to settle a design uncertainty. |
108
+ | `/update-docs` | `code-tweaker` | Reconcile docs with code reality. |
109
+ | `/commit-and-document` | `code-tweaker` | Stage, message, commit, journal — pauses for approval. |
110
+ | `/fix` | `system-architect` | Diagnose → implement → post-mortem chain. |
111
+ | `/feature` | `system-architect` | Sharpen → optional prototype → PRD → issues → TDD chain. |
112
+ | `/refactor` | `system-architect` | Plan and stage architecture changes. |
113
+ | `/explore` | `system-architect` | Map unfamiliar code before touching it. |
114
+ | `/triage` | `system-architect` | Clean and prioritize an issue queue. |
115
+
116
+ ### Helper commands (run directly when needed)
117
+
118
+ | Command | Best run in | What it does |
119
+ | -------------------------------- | -------------------- | ----------------------------------------------------------- |
120
+ | `/diagnose` | `system-architect` | Standalone diagnosis loop with HITL checkpoints. |
121
+ | `/grill-with-docs` | `system-architect` | Sharpen a feature spec via QA against current docs. |
122
+ | `/improve-codebase-architecture` | `system-architect` | Generate a deep architecture review report. |
123
+ | `/to-prd` | `system-architect` | Turn sharpened context into a PRD. |
124
+ | `/to-issues` | `system-architect` | Slice a PRD into issues. |
125
+ | `/zoom-out` | `system-architect` | Pull back to architectural altitude. |
126
+ | `/handoff` | either | Produce a clean handoff package for another agent or human. |
127
+ | `/grill-me` | either | Adversarial Q&A to sharpen an idea. |
128
+ | `/caveman` | either | Ultra-compressed communication mode. |
129
+ | `/write-a-skill` | `code-tweaker` | Author a new skill following the bucket layout. |
130
+ | `/setup-matt-pocock-skills` | `code-tweaker` | One-shot setup helper for the bundled skill set. |
131
+
132
+ The full routing matrix lives in the orchestrator's `customInstructions`
133
+ inside [`templates/full/.roomodes`](templates/full/.roomodes). The command
134
+ files themselves live in
135
+ [`templates/full/.roo/commands/`](templates/full/.roo/commands).
136
+
137
+ ## Install
138
+
139
+ Run this from the root of the project where you use Zoo Code:
140
+
141
+ ```bash
142
+ npx @fernado03/zoo-flow@latest init
143
+ ```
144
+
145
+ If the project already has `.roomodes` or `.roo/`, Zoo Flow will stop
146
+ instead of overwriting.
147
+
148
+ To back up and overwrite existing config:
149
+
150
+ ```bash
151
+ npx @fernado03/zoo-flow@latest init --force
152
+ ```
153
+
154
+ Zoo Flow installs only the runtime template:
155
+
156
+ - `.roomodes`
157
+ - `.roo/`
158
+
159
+ It does not copy this repository's `docs/` folder into your project.
160
+
161
+ > Zoo Flow overwrites `.roomodes` and `.roo/` only when you pass
162
+ > `--force` or run `update`. It always creates a backup in
163
+ > `.zoo-flow-backup/<timestamp>/`.
164
+
165
+ After install, reload VS Code:
166
+
167
+ > Command Palette → **Developer: Reload Window**
168
+
169
+ Then open Zoo Code, switch to `custom-orchestrator`, and run the smoke
170
+ test:
171
+
172
+ > change a harmless comment in `README`
173
+
174
+ When choices appear, manually type the number, e.g. `1`. Do not click
175
+ suggestions that contain slash commands or mode names. See
176
+ [`docs/troubleshooting.md`](docs/troubleshooting.md#clickable-suggestions-can-route-incorrectly).
177
+
178
+ ## Quick start
179
+
180
+ ```bash
181
+ npx @fernado03/zoo-flow@latest init
182
+ ```
183
+
184
+ Then reload VS Code and run this in `custom-orchestrator`:
185
+
186
+ > change a harmless comment in `README`
187
+
188
+ When choices appear, type the number manually, for example `1`.
189
+
190
+ ## Manual install
191
+
192
+ If you would rather copy the template by hand:
193
+
194
+ ### macOS / Linux
195
+
196
+ ```sh
197
+ git clone https://github.com/Fernado03/zoo-flow.git /tmp/zoo-flow
198
+ cp /tmp/zoo-flow/templates/full/.roomodes .
199
+ cp -R /tmp/zoo-flow/templates/full/.roo .
200
+ ```
201
+
202
+ ### Windows (PowerShell)
203
+
204
+ ```powershell
205
+ git clone https://github.com/Fernado03/zoo-flow.git C:\Temp\zoo-flow
206
+ Copy-Item C:\Temp\zoo-flow\templates\full\.roomodes .
207
+ Copy-Item -Recurse C:\Temp\zoo-flow\templates\full\.roo .
208
+ ```
209
+
210
+ After copying:
211
+
212
+ 1. Open the project in an editor running Zoo Code.
213
+ 2. Confirm the three custom modes appear: `🪃 Custom Orchestrator`,
214
+ `🏗️ System Architect`, `⚡ Code Tweaker`.
215
+ 3. Switch to `custom-orchestrator` and start a new task.
216
+
217
+ If a slash command does not run, see
218
+ [`docs/troubleshooting.md`](docs/troubleshooting.md).
219
+
220
+ ## Update Zoo Flow
221
+
222
+ Run this from your project root:
223
+
224
+ ```bash
225
+ npx @fernado03/zoo-flow@latest update
226
+ ```
227
+
228
+ Zoo Flow backs up your current runtime config before replacing it:
229
+
230
+ - `.roomodes`
231
+ - `.roo/`
232
+
233
+ Backups are stored in:
234
+
235
+ ```text
236
+ .zoo-flow-backup/<timestamp>/
237
+ ```
238
+
239
+ Preview without changing files:
240
+
241
+ ```bash
242
+ npx @fernado03/zoo-flow@latest update --dry-run
243
+ ```
244
+
245
+ Zoo Flow does not copy this repository's `docs/` folder into your
246
+ project.
247
+
248
+ ## Smoke tests
249
+
250
+ The repo ships a fixed set of smoke tests in
251
+ [`docs/smoke-tests.md`](docs/smoke-tests.md). They are short scripts you can
252
+ run by hand inside Zoo Code to verify routing, mode boundaries,
253
+ and skill loading. The first one — README tweak with no slash command —
254
+ takes about a minute.
255
+
256
+ When the orchestrator asks which workflow to use, **type the number
257
+ manually**, for example `1`. Do not click suggestions that contain slash
258
+ commands or mode names — clicking them can route incorrectly. See
259
+ [`docs/troubleshooting.md`](docs/troubleshooting.md#clickable-suggestions-can-route-incorrectly).
260
+
261
+ Example choice list:
262
+
263
+ ```text
264
+ 1. /tweak — small known implementation change
265
+ 2. /update-docs — documentation-focused change
266
+ 3. Hold — I will specify more detail
267
+
268
+ Reply by typing only the number, e.g. 1.
269
+ ```
270
+
271
+ Worked examples for the most common flows live in
272
+ [`examples/`](examples/):
273
+
274
+ - [`tweak-smoke-test.md`](examples/tweak-smoke-test.md)
275
+ - [`fix-flow.md`](examples/fix-flow.md)
276
+ - [`feature-flow.md`](examples/feature-flow.md)
277
+
278
+ ## Screenshots
279
+
280
+ Screenshots and short clips of the orchestrator routing, the architect
281
+ hand-off, and the tweaker running a slash command will land in
282
+ [`assets/`](assets/) before the first tagged release.
283
+
284
+ ## Roadmap
285
+
286
+ - `templates/minimal/` — a stripped-down template with only the three modes,
287
+ the path-safety rules, and `/tweak` + `/fix`.
288
+ - Optional CI workflow that runs the smoke-test JSON validation on every
289
+ PR.
290
+ - A short demo video in `assets/`.
291
+ - ADRs covering the three-mode split, the routing matrix, and the
292
+ path-safety choice.
293
+ - Guidance on integrating Zoo Flow alongside other workflow tools.
294
+
295
+ ## How this is different
296
+
297
+ Zoo Flow is not a methodology and it is not a giant skills pack. It is a
298
+ **Zoo-native control plane**: a thin layer that turns three modes,
299
+ a routing matrix, and a path-safety contract into a predictable workflow.
300
+
301
+ For a longer comparison with adjacent projects, see
302
+ [`docs/comparison.md`](docs/comparison.md).
303
+
304
+ ## Migration note
305
+
306
+ Zoo Flow started as a Roo Flow template and was renamed for Zoo Code.
307
+ The `.roo/` folder names are intentionally preserved because Zoo Code
308
+ still uses those paths for project modes, commands, rules, and skills.
309
+ If you are migrating from a Roo Code workspace, copying the same
310
+ `.roo/` directory and `.roomodes` file into a Zoo Code workspace is
311
+ expected to keep working.
312
+
313
+ ## Inspiration
314
+
315
+ This project was inspired by Matt Pocock's agent-skills workflow ideas
316
+ and his emphasis on small, composable, task-focused skills for coding
317
+ agents.
318
+
319
+ Zoo Flow is not affiliated with, endorsed by, or maintained by Matt
320
+ Pocock. It is an independent Zoo Code workflow-control template
321
+ focused on custom modes, delegation, command routing, and smoke-tested
322
+ agent workflows.
323
+
324
+ ## License
325
+
326
+ [MIT](LICENSE).
@@ -0,0 +1,358 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const packageRoot = path.resolve(__dirname, "..");
10
+ const templateRoot = path.join(packageRoot, "templates", "full");
11
+
12
+ const command = process.argv[2];
13
+
14
+ const HELP = `
15
+ Zoo Flow
16
+
17
+ Usage:
18
+ npx @fernado03/zoo-flow@latest init
19
+ npx @fernado03/zoo-flow@latest init --force
20
+ npx @fernado03/zoo-flow@latest update
21
+ npx @fernado03/zoo-flow@latest update --dry-run
22
+ npx @fernado03/zoo-flow@latest update --force
23
+ npx @fernado03/zoo-flow@latest doctor --template-only
24
+
25
+ Commands:
26
+ init Install Zoo Flow into the current project
27
+ update Back up current config and copy the latest template
28
+ doctor Validate the bundled template
29
+
30
+ Options:
31
+ --force Overwrite existing .roomodes and .roo after backup
32
+ --dry-run Print what update would do without changing files
33
+ --template-only Validate this package's template instead of current project
34
+ `;
35
+
36
+ function exitWithError(message) {
37
+ console.error(`\nError: ${message}\n`);
38
+ process.exit(1);
39
+ }
40
+
41
+ function pathExists(targetPath) {
42
+ return fs.existsSync(targetPath);
43
+ }
44
+
45
+ function copyRecursive(src, dest) {
46
+ if (!pathExists(src)) {
47
+ throw new Error(`Missing source: ${src}`);
48
+ }
49
+
50
+ const stat = fs.statSync(src);
51
+
52
+ if (stat.isDirectory()) {
53
+ fs.mkdirSync(dest, { recursive: true });
54
+
55
+ for (const entry of fs.readdirSync(src)) {
56
+ copyRecursive(path.join(src, entry), path.join(dest, entry));
57
+ }
58
+
59
+ return;
60
+ }
61
+
62
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
63
+ fs.copyFileSync(src, dest);
64
+ }
65
+
66
+ function removeRecursive(targetPath) {
67
+ if (!pathExists(targetPath)) return;
68
+ fs.rmSync(targetPath, { recursive: true, force: true });
69
+ }
70
+
71
+ function backupIfExists(projectRoot, backupDir, relativePath) {
72
+ const src = path.join(projectRoot, relativePath);
73
+
74
+ if (!pathExists(src)) {
75
+ return false;
76
+ }
77
+
78
+ const dest = path.join(backupDir, relativePath);
79
+ copyRecursive(src, dest);
80
+ return true;
81
+ }
82
+
83
+ function makeTimestamp() {
84
+ return new Date().toISOString().replace(/[:.]/g, "-");
85
+ }
86
+
87
+ function readJson(filePath) {
88
+ try {
89
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
90
+ } catch (error) {
91
+ throw new Error(`Invalid JSON: ${filePath}\n${error.message}`);
92
+ }
93
+ }
94
+
95
+ function walkFiles(rootDir) {
96
+ const files = [];
97
+
98
+ function walk(current) {
99
+ if (!pathExists(current)) return;
100
+
101
+ const stat = fs.statSync(current);
102
+
103
+ if (stat.isDirectory()) {
104
+ for (const entry of fs.readdirSync(current)) {
105
+ if (entry === ".git" || entry === "node_modules") continue;
106
+ walk(path.join(current, entry));
107
+ }
108
+ return;
109
+ }
110
+
111
+ files.push(current);
112
+ }
113
+
114
+ walk(rootDir);
115
+ return files;
116
+ }
117
+
118
+ function validateTemplate(rootDir) {
119
+ const roomodesPath = path.join(rootDir, ".roomodes");
120
+ const rooDir = path.join(rootDir, ".roo");
121
+ const commandsDir = path.join(rooDir, "commands");
122
+ const skillsDir = path.join(rooDir, "skills");
123
+ const rulesDir = path.join(rooDir, "rules");
124
+
125
+ const failures = [];
126
+
127
+ if (!pathExists(roomodesPath)) failures.push("Missing .roomodes");
128
+ if (!pathExists(rooDir)) failures.push("Missing .roo/");
129
+ if (!pathExists(commandsDir)) failures.push("Missing .roo/commands/");
130
+ if (!pathExists(skillsDir)) failures.push("Missing .roo/skills/");
131
+ if (!pathExists(rulesDir)) failures.push("Missing .roo/rules/");
132
+
133
+ if (pathExists(roomodesPath)) {
134
+ try {
135
+ const parsed = readJson(roomodesPath);
136
+ if (!Array.isArray(parsed.customModes)) {
137
+ failures.push(".roomodes must contain customModes array");
138
+ }
139
+ } catch (error) {
140
+ failures.push(error.message);
141
+ }
142
+ }
143
+
144
+ const allFiles = walkFiles(rootDir);
145
+ const textFileExtensions = new Set([".md", ".json", ".txt", ".yaml", ".yml"]);
146
+
147
+ for (const file of allFiles) {
148
+ const ext = path.extname(file);
149
+ if (!textFileExtensions.has(ext)) continue;
150
+
151
+ const text = fs.readFileSync(file, "utf8");
152
+
153
+ const badPatterns = [
154
+ ".roo/skills///SKILL.md",
155
+ ".roo/commands/.md",
156
+ "your-org/roo-flow",
157
+ ".zoo/"
158
+ ];
159
+
160
+ for (const pattern of badPatterns) {
161
+ if (text.includes(pattern)) {
162
+ failures.push(`Bad pattern "${pattern}" in ${path.relative(rootDir, file)}`);
163
+ }
164
+ }
165
+ }
166
+
167
+ const requiredRules = [
168
+ ".roo/rules/00-paths.md",
169
+ ".roo/rules/01-command-protocol.md",
170
+ ".roo/rules/03-manual-reply-protocol.md"
171
+ ];
172
+
173
+ for (const rule of requiredRules) {
174
+ if (!pathExists(path.join(rootDir, rule))) {
175
+ failures.push(`Missing required global rule: ${rule}`);
176
+ }
177
+ }
178
+
179
+ const requiredModeRules = [
180
+ ".roo/rules-code-tweaker",
181
+ ".roo/rules-system-architect",
182
+ ".roo/rules-custom-orchestrator"
183
+ ];
184
+
185
+ for (const ruleDir of requiredModeRules) {
186
+ if (!pathExists(path.join(rootDir, ruleDir))) {
187
+ failures.push(`Missing mode rule folder: ${ruleDir}`);
188
+ }
189
+ }
190
+
191
+ return failures;
192
+ }
193
+
194
+ function install() {
195
+ const args = new Set(process.argv.slice(3));
196
+ const force = args.has("--force");
197
+ const projectRoot = process.cwd();
198
+
199
+ const sourceRoomodes = path.join(templateRoot, ".roomodes");
200
+ const sourceRoo = path.join(templateRoot, ".roo");
201
+
202
+ if (!pathExists(sourceRoomodes) || !pathExists(sourceRoo)) {
203
+ exitWithError("Bundled template is missing templates/full/.roomodes or templates/full/.roo/");
204
+ }
205
+
206
+ const targetRoomodes = path.join(projectRoot, ".roomodes");
207
+ const targetRoo = path.join(projectRoot, ".roo");
208
+ const hasExistingConfig = pathExists(targetRoomodes) || pathExists(targetRoo);
209
+
210
+ if (hasExistingConfig && !force) {
211
+ console.log(`
212
+ Zoo Flow found existing config in this project.
213
+
214
+ Existing:
215
+ ${pathExists(targetRoomodes) ? " - .roomodes\n" : ""}${pathExists(targetRoo) ? " - .roo/\n" : ""}
216
+ Run again with --force to back up and overwrite:
217
+
218
+ npx @fernado03/zoo-flow@latest init --force
219
+ `);
220
+ process.exit(0);
221
+ }
222
+
223
+ const backupDir = path.join(projectRoot, ".zoo-flow-backup", makeTimestamp());
224
+ let didBackup = false;
225
+
226
+ if (hasExistingConfig) {
227
+ fs.mkdirSync(backupDir, { recursive: true });
228
+ didBackup = backupIfExists(projectRoot, backupDir, ".roomodes") || didBackup;
229
+ didBackup = backupIfExists(projectRoot, backupDir, ".roo") || didBackup;
230
+
231
+ removeRecursive(targetRoomodes);
232
+ removeRecursive(targetRoo);
233
+ }
234
+
235
+ copyRecursive(sourceRoomodes, targetRoomodes);
236
+ copyRecursive(sourceRoo, targetRoo);
237
+
238
+ console.log(`
239
+ Zoo Flow installed.
240
+
241
+ Copied:
242
+ - .roomodes
243
+ - .roo/
244
+
245
+ ${didBackup ? `Backup:\n ${backupDir}\n` : ""}Next:
246
+ 1. Reload VS Code
247
+ 2. Open Zoo Code
248
+ 3. Switch to custom-orchestrator
249
+ 4. Smoke test:
250
+ change a harmless comment in README
251
+
252
+ When workflow choices appear, type the number manually, e.g. 1.
253
+ `);
254
+ }
255
+
256
+ function doctor() {
257
+ const args = new Set(process.argv.slice(3));
258
+ const rootToCheck = args.has("--template-only") ? templateRoot : process.cwd();
259
+ const failures = validateTemplate(rootToCheck);
260
+
261
+ if (failures.length > 0) {
262
+ console.error("\nZoo Flow doctor found problems:\n");
263
+ for (const failure of failures) {
264
+ console.error(`- ${failure}`);
265
+ }
266
+ console.error("");
267
+ process.exit(1);
268
+ }
269
+
270
+ console.log(`Zoo Flow doctor passed: ${rootToCheck}`);
271
+ }
272
+
273
+ function update() {
274
+ const args = new Set(process.argv.slice(3));
275
+ const dryRun = args.has("--dry-run");
276
+ const projectRoot = process.cwd();
277
+
278
+ const sourceRoomodes = path.join(templateRoot, ".roomodes");
279
+ const sourceRoo = path.join(templateRoot, ".roo");
280
+
281
+ if (!pathExists(sourceRoomodes) || !pathExists(sourceRoo)) {
282
+ exitWithError("Bundled template is missing templates/full/.roomodes or templates/full/.roo/");
283
+ }
284
+
285
+ const targetRoomodes = path.join(projectRoot, ".roomodes");
286
+ const targetRoo = path.join(projectRoot, ".roo");
287
+ const hasRoomodes = pathExists(targetRoomodes);
288
+ const hasRoo = pathExists(targetRoo);
289
+
290
+ if (!hasRoomodes && !hasRoo) {
291
+ console.log(`
292
+ Zoo Flow is not installed in this project yet.
293
+
294
+ Run:
295
+ npx @fernado03/zoo-flow@latest init
296
+ `);
297
+ process.exit(0);
298
+ }
299
+
300
+ if (dryRun) {
301
+ console.log(`
302
+ Zoo Flow update dry run.
303
+
304
+ Would back up:
305
+ ${hasRoomodes ? " - .roomodes\n" : ""}${hasRoo ? " - .roo/\n" : ""}
306
+ Would replace with latest template:
307
+ - .roomodes
308
+ - .roo/
309
+
310
+ Run this to update:
311
+ npx @fernado03/zoo-flow@latest update
312
+ `);
313
+ process.exit(0);
314
+ }
315
+
316
+ const backupDir = path.join(projectRoot, ".zoo-flow-backup", makeTimestamp());
317
+ fs.mkdirSync(backupDir, { recursive: true });
318
+
319
+ let didBackup = false;
320
+ didBackup = backupIfExists(projectRoot, backupDir, ".roomodes") || didBackup;
321
+ didBackup = backupIfExists(projectRoot, backupDir, ".roo") || didBackup;
322
+
323
+ removeRecursive(targetRoomodes);
324
+ removeRecursive(targetRoo);
325
+
326
+ copyRecursive(sourceRoomodes, targetRoomodes);
327
+ copyRecursive(sourceRoo, targetRoo);
328
+
329
+ console.log(`
330
+ Zoo Flow updated.
331
+
332
+ Replaced:
333
+ - .roomodes
334
+ - .roo/
335
+
336
+ ${didBackup ? `Backup:\n ${backupDir}\n\nTo restore the previous config:\n rm -rf .roomodes .roo\n cp -R ${backupDir}/. .\n` : ""}
337
+ Next:
338
+ 1. Reload VS Code
339
+ 2. Open Zoo Code
340
+ 3. Confirm the three custom modes still appear
341
+ `);
342
+ }
343
+
344
+ if (!command || command === "--help" || command === "-h") {
345
+ console.log(HELP);
346
+ process.exit(0);
347
+ }
348
+
349
+ if (command === "init") {
350
+ install();
351
+ } else if (command === "update") {
352
+ update();
353
+ } else if (command === "doctor") {
354
+ doctor();
355
+ } else {
356
+ console.log(HELP);
357
+ process.exit(1);
358
+ }