@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.
- package/LICENSE +21 -0
- package/README.md +326 -0
- package/bin/zoo-flow.js +358 -0
- package/package.json +44 -0
- package/templates/full/.roo/commands/caveman.md +7 -0
- package/templates/full/.roo/commands/commit-and-document.md +202 -0
- package/templates/full/.roo/commands/diagnose.md +7 -0
- package/templates/full/.roo/commands/explore.md +13 -0
- package/templates/full/.roo/commands/feature.md +24 -0
- package/templates/full/.roo/commands/fix.md +19 -0
- package/templates/full/.roo/commands/grill-me.md +7 -0
- package/templates/full/.roo/commands/grill-with-docs.md +7 -0
- package/templates/full/.roo/commands/handoff.md +8 -0
- package/templates/full/.roo/commands/improve-codebase-architecture.md +7 -0
- package/templates/full/.roo/commands/prototype.md +9 -0
- package/templates/full/.roo/commands/refactor.md +17 -0
- package/templates/full/.roo/commands/setup-matt-pocock-skills.md +7 -0
- package/templates/full/.roo/commands/tdd.md +9 -0
- package/templates/full/.roo/commands/to-issues.md +7 -0
- package/templates/full/.roo/commands/to-prd.md +7 -0
- package/templates/full/.roo/commands/triage.md +7 -0
- package/templates/full/.roo/commands/tweak.md +9 -0
- package/templates/full/.roo/commands/update-docs.md +130 -0
- package/templates/full/.roo/commands/write-a-skill.md +7 -0
- package/templates/full/.roo/commands/zoom-out.md +7 -0
- package/templates/full/.roo/rules/00-paths.md +17 -0
- package/templates/full/.roo/rules/01-command-protocol.md +25 -0
- package/templates/full/.roo/rules/03-manual-reply-protocol.md +13 -0
- package/templates/full/.roo/rules-code-tweaker/00-scope.md +7 -0
- package/templates/full/.roo/rules-code-tweaker/01-completion.md +14 -0
- package/templates/full/.roo/rules-custom-orchestrator/00-routing.md +14 -0
- package/templates/full/.roo/rules-custom-orchestrator/01-delegation-message.md +12 -0
- package/templates/full/.roo/rules-system-architect/00-scope.md +9 -0
- package/templates/full/.roo/rules-system-architect/01-feature-prototype.md +10 -0
- package/templates/full/.roo/rules-system-architect/02-completion.md +11 -0
- package/templates/full/.roo/skills/docs/adr/0001-explicit-setup-pointer-only-for-hard-dependencies.md +18 -0
- package/templates/full/.roo/skills/engineering/README.md +12 -0
- package/templates/full/.roo/skills/engineering/diagnose/SKILL.md +73 -0
- package/templates/full/.roo/skills/engineering/diagnose/scripts/hitl-loop.template.sh +41 -0
- package/templates/full/.roo/skills/engineering/grill-with-docs/ADR-FORMAT.md +33 -0
- package/templates/full/.roo/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +45 -0
- package/templates/full/.roo/skills/engineering/grill-with-docs/SKILL.md +32 -0
- package/templates/full/.roo/skills/engineering/improve-codebase-architecture/DEEPENING.md +24 -0
- package/templates/full/.roo/skills/engineering/improve-codebase-architecture/HTML-REPORT.md +88 -0
- package/templates/full/.roo/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +45 -0
- package/templates/full/.roo/skills/engineering/improve-codebase-architecture/LANGUAGE.md +34 -0
- package/templates/full/.roo/skills/engineering/improve-codebase-architecture/SKILL.md +43 -0
- package/templates/full/.roo/skills/engineering/prototype/LOGIC.md +28 -0
- package/templates/full/.roo/skills/engineering/prototype/SKILL.md +27 -0
- package/templates/full/.roo/skills/engineering/prototype/UI.md +53 -0
- package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/SKILL.md +77 -0
- package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/domain.md +36 -0
- package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/issue-tracker-github.md +21 -0
- package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/issue-tracker-gitlab.md +23 -0
- package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/issue-tracker-local.md +20 -0
- package/templates/full/.roo/skills/engineering/setup-matt-pocock-skills/triage-labels.md +11 -0
- package/templates/full/.roo/skills/engineering/tdd/SKILL.md +52 -0
- package/templates/full/.roo/skills/engineering/tdd/deep-modules.md +9 -0
- package/templates/full/.roo/skills/engineering/tdd/interface-design.md +6 -0
- package/templates/full/.roo/skills/engineering/tdd/mocking.md +17 -0
- package/templates/full/.roo/skills/engineering/tdd/refactoring.md +9 -0
- package/templates/full/.roo/skills/engineering/tdd/tests.md +12 -0
- package/templates/full/.roo/skills/engineering/to-issues/SKILL.md +45 -0
- package/templates/full/.roo/skills/engineering/to-prd/SKILL.md +58 -0
- package/templates/full/.roo/skills/engineering/triage/AGENT-BRIEF.md +43 -0
- package/templates/full/.roo/skills/engineering/triage/OUT-OF-SCOPE.md +37 -0
- package/templates/full/.roo/skills/engineering/triage/SKILL.md +79 -0
- package/templates/full/.roo/skills/engineering/tweak/SKILL.md +17 -0
- package/templates/full/.roo/skills/engineering/zoom-out/SKILL.md +7 -0
- package/templates/full/.roo/skills/in-progress/README.md +8 -0
- package/templates/full/.roo/skills/in-progress/review/SKILL.md +39 -0
- package/templates/full/.roo/skills/in-progress/writing-beats/SKILL.md +32 -0
- package/templates/full/.roo/skills/in-progress/writing-fragments/SKILL.md +45 -0
- package/templates/full/.roo/skills/in-progress/writing-shape/SKILL.md +50 -0
- package/templates/full/.roo/skills/misc/README.md +6 -0
- package/templates/full/.roo/skills/misc/git-guardrails-claude-code/SKILL.md +64 -0
- package/templates/full/.roo/skills/misc/git-guardrails-claude-code/scripts/block-dangerous-git.sh +25 -0
- package/templates/full/.roo/skills/misc/migrate-to-shoehorn/SKILL.md +37 -0
- package/templates/full/.roo/skills/misc/scaffold-exercises/SKILL.md +61 -0
- package/templates/full/.roo/skills/misc/setup-pre-commit/SKILL.md +62 -0
- package/templates/full/.roo/skills/personal/README.md +6 -0
- package/templates/full/.roo/skills/personal/edit-article/SKILL.md +13 -0
- package/templates/full/.roo/skills/personal/obsidian-vault/SKILL.md +39 -0
- package/templates/full/.roo/skills/productivity/README.md +6 -0
- package/templates/full/.roo/skills/productivity/caveman/SKILL.md +28 -0
- package/templates/full/.roo/skills/productivity/grill-me/SKILL.md +13 -0
- package/templates/full/.roo/skills/productivity/handoff/SKILL.md +14 -0
- package/templates/full/.roo/skills/productivity/write-a-skill/SKILL.md +52 -0
- 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).
|
package/bin/zoo-flow.js
ADDED
|
@@ -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
|
+
}
|