cli-five 0.2.13 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -32
- package/package.json +14 -3
- package/plugin-agents/designer.agent.md +2 -2
- package/plugin-agents/planner.agent.md +1 -1
- package/src/addons/registry.mjs +96 -0
- package/src/cli.mjs +47 -4
- package/src/commands/add.mjs +55 -0
- package/src/commands/doctor.mjs +82 -15
- package/src/commands/init.mjs +164 -51
- package/src/commands/list-addons.mjs +40 -0
- package/src/steps/confirm.mjs +2 -0
- package/src/steps/detect.mjs +4 -0
- package/src/steps/interview.mjs +99 -34
- package/src/steps/platform.mjs +239 -0
- package/src/steps/scaffold.mjs +135 -34
- package/src/util/agents.mjs +63 -11
- package/src/util/merge.mjs +170 -0
- package/src/util/models.mjs +148 -0
- package/src/util/platforms.mjs +25 -0
- package/src/util/project.mjs +140 -0
- package/templates/AGENTS.md.tmpl +2 -0
- package/templates/opencode/agents/coder.md +74 -0
- package/templates/opencode/agents/designer.md +65 -0
- package/templates/opencode/agents/orchestrator.md +92 -0
- package/templates/opencode/agents/planner.md +76 -0
- package/templates/opencode/agents/reviewer.md +94 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# cli-five
|
|
2
2
|
|
|
3
|
-
> **Code Like I'm Five** — scaffold a 5-agent
|
|
3
|
+
> **Code Like I'm Five** — scaffold a 5-agent AI team into any repo.
|
|
4
4
|
|
|
5
5
|
## Two ways to install
|
|
6
6
|
|
|
@@ -10,9 +10,16 @@
|
|
|
10
10
|
npx cli-five init
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
By default `init` is **minimal**: it scaffolds the 5-agent team and the tooling they need, asking only for the target platform and (when it can't find them) your project name and one-liner. Name and description are auto-pulled from `package.json` and `README.md`. Optional integrations — including CodeGraph, skills, and instruction files — are **not** installed unless you ask.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npx cli-five init --full-interview # legacy: docs, goals, persona, model picker, CodeGraph, skills, instructions
|
|
17
|
+
npx cli-five init --codegraph # minimal, but add the CodeGraph MCP + AGENTS.md block
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`--full-interview` (or passing `--doc`) restores the complete guided setup: stack presets, goals, constraints, persona toggle, per-agent model overrides, Copilot cost modes, CodeGraph, skill discovery, and stack-specific instruction generation. Individual pieces can also be toggled with `--codegraph`, `--skills`, `--instructions`, and `--persona`.
|
|
21
|
+
|
|
22
|
+
### Quick plugin install (personal use, Copilot only)
|
|
16
23
|
|
|
17
24
|
```
|
|
18
25
|
copilot plugin install idusortus/cli-five
|
|
@@ -20,20 +27,34 @@ copilot plugin install idusortus/cli-five
|
|
|
20
27
|
|
|
21
28
|
Installs the 5 agents to your Copilot profile. No project config, no interview — just the agents with the same autonomous contracts shipped by the scaffolded templates.
|
|
22
29
|
|
|
30
|
+
## Supported platforms
|
|
31
|
+
|
|
32
|
+
cli-five can scaffold for:
|
|
33
|
+
|
|
34
|
+
- **GitHub Copilot** — `.github/agents/*.agent.md` + `copilot-instructions.md`
|
|
35
|
+
- **OpenCode** — `.opencode/agents/*.md` + `opencode.json`
|
|
36
|
+
|
|
37
|
+
Both platforms can optionally include a **CodeGraph** MCP server and instructions.
|
|
38
|
+
|
|
39
|
+
Run `npx cli-five init` and choose your platform. If you want both, run it again in the same repo.
|
|
40
|
+
|
|
23
41
|
## What you get
|
|
24
42
|
|
|
43
|
+
### GitHub Copilot layout
|
|
44
|
+
|
|
25
45
|
```
|
|
26
46
|
your-repo/
|
|
27
47
|
├── .github/
|
|
28
48
|
│ ├── agents/ # 5 agents — Orchestrator delegates autonomously
|
|
29
|
-
│ │ ├── orchestrator.agent.md
|
|
30
|
-
│ │ ├── planner.agent.md
|
|
31
|
-
│ │ ├── coder.agent.md
|
|
32
|
-
│ │ ├── designer.agent.md
|
|
33
|
-
│ │ └── reviewer.agent.md
|
|
34
|
-
│ ├── copilot-instructions.md #
|
|
35
|
-
│ ├── instructions/ #
|
|
36
|
-
│ └── skills/ #
|
|
49
|
+
│ │ ├── orchestrator.agent.md
|
|
50
|
+
│ │ ├── planner.agent.md
|
|
51
|
+
│ │ ├── coder.agent.md
|
|
52
|
+
│ │ ├── designer.agent.md
|
|
53
|
+
│ │ └── reviewer.agent.md
|
|
54
|
+
│ ├── copilot-instructions.md # Project mandates (persona is opt-in)
|
|
55
|
+
│ ├── instructions/ # Container; stack guidelines via --instructions
|
|
56
|
+
│ └── skills/ # Container; skills via --skills
|
|
57
|
+
├── .vscode/mcp.json # CodeGraph MCP server (optional)
|
|
37
58
|
├── AGENTS.md # Tool-agnostic project context (agents.md standard)
|
|
38
59
|
├── PROJECT.md # Long-form vision (rarely changes)
|
|
39
60
|
├── STATE.md # Cross-session status (changes constantly)
|
|
@@ -42,9 +63,31 @@ your-repo/
|
|
|
42
63
|
└── histories/ # Per-agent accumulated learnings
|
|
43
64
|
```
|
|
44
65
|
|
|
66
|
+
### OpenCode layout
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
your-repo/
|
|
70
|
+
├── .opencode/
|
|
71
|
+
│ └── agents/ # 5 agents — Orchestrator delegates autonomously
|
|
72
|
+
│ ├── orchestrator.md
|
|
73
|
+
│ ├── planner.md
|
|
74
|
+
│ ├── coder.md
|
|
75
|
+
│ ├── designer.md
|
|
76
|
+
│ └── reviewer.md
|
|
77
|
+
├── opencode.json # Project config, model defaults, CodeGraph MCP (optional)
|
|
78
|
+
├── .github/instructions/ # Container; stack guidelines via --instructions
|
|
79
|
+
├── .github/skills/ # Container; skills via --skills
|
|
80
|
+
├── AGENTS.md # Project rules + optional CodeGraph block
|
|
81
|
+
├── PROJECT.md
|
|
82
|
+
├── STATE.md
|
|
83
|
+
├── decisions.md
|
|
84
|
+
├── agent-diary.md
|
|
85
|
+
└── histories/
|
|
86
|
+
```
|
|
87
|
+
|
|
45
88
|
## How it works
|
|
46
89
|
|
|
47
|
-
Select the **Orchestrator** agent
|
|
90
|
+
Select the **Orchestrator** agent and describe what you want. The Orchestrator autonomously calls Planner → Coder/Designer → Reviewer without any manual handoff clicks.
|
|
48
91
|
|
|
49
92
|
```
|
|
50
93
|
User: implement from plan.md
|
|
@@ -53,13 +96,16 @@ Orchestrator → [calls Planner] → [calls Coder] → [calls Reviewer] → done
|
|
|
53
96
|
|
|
54
97
|
No buttons. No "click here to continue". Just results.
|
|
55
98
|
|
|
56
|
-
The plugin agents and scaffolded `.github/agents/*.agent.md` templates are intentionally kept in sync. The repository test suite
|
|
99
|
+
The plugin agents and scaffolded `.github/agents/*.agent.md` templates are intentionally kept in sync. The repository test suite checks that parity so the quick-install path does not quietly degrade.
|
|
57
100
|
|
|
58
101
|
## Commands
|
|
59
102
|
|
|
60
103
|
```bash
|
|
61
|
-
npx cli-five init #
|
|
62
|
-
npx cli-five
|
|
104
|
+
npx cli-five init # minimal scaffold (5 agents + required tooling)
|
|
105
|
+
npx cli-five init --full-interview # full guided setup (interview, models, skills, instructions)
|
|
106
|
+
npx cli-five add <name> # install an optional add-on (dispatcher; targets land later)
|
|
107
|
+
npx cli-five list-addons # show installed vs. available add-ons
|
|
108
|
+
npx cli-five doctor # validate an existing cli-five setup
|
|
63
109
|
npx cli-five list-stacks # show detectable tech stacks
|
|
64
110
|
npx cli-five help
|
|
65
111
|
```
|
|
@@ -68,38 +114,99 @@ npx cli-five help
|
|
|
68
114
|
|
|
69
115
|
| Flag | Effect |
|
|
70
116
|
|---|---|
|
|
71
|
-
| `--yes`, `-y` | Accept
|
|
117
|
+
| `--yes`, `-y` | Accept defaults (overwrite gate still active) |
|
|
72
118
|
| `--force` | Overwrite without confirmation (use with `--yes`) |
|
|
73
119
|
| `--dry-run` | Print actions, write nothing |
|
|
74
|
-
| `--
|
|
75
|
-
| `--
|
|
120
|
+
| `--full-interview`, `--full` | Run the full legacy interview (docs, goals/constraints/persona, model picker). Also enables CodeGraph, skills + instructions |
|
|
121
|
+
| `--skills` / `--no-skills` | Force skill discovery on/off |
|
|
122
|
+
| `--instructions` / `--no-instructions` | Force stack-specific instruction generation on/off |
|
|
123
|
+
| `--persona` / `--no-persona` | Include / omit the snarky persona block |
|
|
124
|
+
| `--codegraph` / `--no-codegraph` | Force CodeGraph MCP + instructions on/off (default: on with `--full-interview`, off otherwise) |
|
|
125
|
+
| `--target <t>` | Target platform: `copilot` or `opencode` (default: `copilot`) |
|
|
126
|
+
| `--provider <p>` | Model provider: `copilot`, `opencode`, `opencode-go` (default: platform default) |
|
|
127
|
+
| `--cost-mode <m>` | Set cost mode for Copilot: `premium`, `cheap`, or `mixed` |
|
|
128
|
+
| `--doc <file>` | Read project docs to pre-fill interview (repeatable; implies `--full-interview`) |
|
|
76
129
|
| `--cwd <path>` | Run against a different directory |
|
|
77
130
|
|
|
78
131
|
## What `init` does
|
|
79
132
|
|
|
133
|
+
Default (`npx cli-five init`):
|
|
134
|
+
|
|
80
135
|
1. **Detect** — fingerprints stack (Node/TS, Python, .NET, Kotlin, Rust, Go, etc.). Brownfield-aware.
|
|
81
|
-
2. **
|
|
82
|
-
3. **
|
|
83
|
-
4. **
|
|
84
|
-
5. **
|
|
85
|
-
6. **
|
|
86
|
-
7. **
|
|
87
|
-
8. **
|
|
136
|
+
2. **Choose platform** — explicit `--target`, auto-detected from an existing scaffold, or prompted.
|
|
137
|
+
3. **git init** — if needed. Asks first.
|
|
138
|
+
4. **Overwrite gate** — double-confirms ("Proceed?" then "R U Sure?"). Only `--force --yes` bypasses.
|
|
139
|
+
5. **Project info** — name and one-liner auto-pulled from `package.json` / `README.md`; asks only when missing or ambiguous.
|
|
140
|
+
6. **Model configuration** — platform/provider defaults, no prompt.
|
|
141
|
+
7. **Scaffold** — writes the 5 agents + required project memory/tooling files. Swaps `model:` per provider defaults.
|
|
142
|
+
8. **Done** — prints platform-specific next steps.
|
|
143
|
+
|
|
144
|
+
`--full-interview` additionally runs:
|
|
145
|
+
|
|
146
|
+
- **Docs / manual interview** — project docs, stack preset, goals, constraints.
|
|
147
|
+
- **Model customization** — provider picker + per-agent model overrides.
|
|
148
|
+
- **Persona toggle** — snarky persona block.
|
|
149
|
+
- **CodeGraph** — MCP registration + `AGENTS.md` block (also available standalone via `--codegraph`).
|
|
150
|
+
- **Skill discovery** — multi-source discovery from **awesome-copilot** and **skills.sh**.
|
|
151
|
+
- **Custom instructions** — stack-specific `.instructions.md` files for detected languages.
|
|
152
|
+
|
|
153
|
+
## Add-ons
|
|
154
|
+
|
|
155
|
+
Optional integrations live outside the default scaffold and are installed with `cli-five add <name>`.
|
|
88
156
|
|
|
89
|
-
|
|
157
|
+
```bash
|
|
158
|
+
npx cli-five add # list known targets
|
|
159
|
+
npx cli-five add codegraph # stub in this release
|
|
160
|
+
npx cli-five list-addons # installed vs. available status
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
This release ships the **dispatcher and merge utility** only — no integration is wired in yet. Jev and the CodeGraph migration are future commits.
|
|
164
|
+
|
|
165
|
+
Add-ons use `mergeBlock(file, markerFence, content)` to layer a fenced block into an existing JSON or Markdown file without touching the rest of it (distinct from init's blunt overwrite gate). Markdown gets `<!-- NAME_START -->` / `<!-- NAME_END -->` fences; JSON is deep-merged with existing keys preserved.
|
|
166
|
+
|
|
167
|
+
## Model providers
|
|
168
|
+
|
|
169
|
+
During `init --full-interview` you can choose the model provider and optionally customize each agent's model. The minimal `init` path uses provider defaults (honouring `--provider` and `--cost-mode`).
|
|
170
|
+
|
|
171
|
+
| Provider | Platform | Example model |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| GitHub Copilot | Copilot | `Claude Sonnet 4.6 (copilot)` |
|
|
174
|
+
| OpenCode Zen | OpenCode | `opencode/gpt-5.3-codex` |
|
|
175
|
+
| OpenCode Go | OpenCode | `opencode-go/qwen3.8-max` |
|
|
176
|
+
|
|
177
|
+
`--yes` uses the provider's defaults. `--provider opencode-go --yes` skips the provider prompt.
|
|
178
|
+
|
|
179
|
+
### Copilot cost modes
|
|
90
180
|
|
|
91
181
|
| Agent | `premium` (1x–3x) | `cheap` (0x) | `mixed` |
|
|
92
182
|
|---|---|---|---|
|
|
93
183
|
| Orchestrator | Claude Sonnet 4.6 | GPT-4.1 | GPT-4.1 |
|
|
94
184
|
| Planner | Claude Opus 4.6 | GPT-4o | GPT-4o |
|
|
95
185
|
| Coder | GPT-5.3-Codex | GPT-4.1 | GPT-5.3-Codex |
|
|
96
|
-
| Designer |
|
|
97
|
-
| Reviewer | Claude
|
|
186
|
+
| Designer | Gemini 3.1 Pro (Preview) | GPT-4o | GPT-4o |
|
|
187
|
+
| Reviewer | Claude Sonnet 4.6 | GPT-5 mini | Claude Sonnet 4.6 |
|
|
98
188
|
|
|
99
189
|
Override from CLI: `npx cli-five init --cost-mode cheap`
|
|
100
|
-
Change anytime by editing the `model:` line in
|
|
190
|
+
Change anytime by editing the `model:` line in the agent files.
|
|
101
191
|
|
|
102
|
-
##
|
|
192
|
+
## CodeGraph
|
|
193
|
+
|
|
194
|
+
CodeGraph adds a local, graph-backed codebase context server. It is **off by default** in the minimal scaffold; enable it with `--codegraph` or `--full-interview`. When enabled, cli-five:
|
|
195
|
+
|
|
196
|
+
- Registers the CodeGraph MCP server in `opencode.json` (OpenCode) or `.vscode/mcp.json` (Copilot).
|
|
197
|
+
- Adds a marker-fenced CodeGraph section to `AGENTS.md`.
|
|
198
|
+
- Tells you to run `codegraph init` to index the project.
|
|
199
|
+
|
|
200
|
+
cli-five does **not** install or run the CodeGraph CLI automatically. After scaffolding:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
npm i -g @colbymchenry/codegraph
|
|
204
|
+
codegraph init
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Required settings
|
|
208
|
+
|
|
209
|
+
### GitHub Copilot
|
|
103
210
|
|
|
104
211
|
```jsonc
|
|
105
212
|
{
|
|
@@ -107,9 +214,13 @@ Change anytime by editing the `model:` line in `.github/agents/*.agent.md`.
|
|
|
107
214
|
}
|
|
108
215
|
```
|
|
109
216
|
|
|
217
|
+
### OpenCode
|
|
218
|
+
|
|
219
|
+
No extra settings required. Project agents live in `.opencode/agents/` and the project config in `opencode.json`.
|
|
220
|
+
|
|
110
221
|
## Skill discovery
|
|
111
222
|
|
|
112
|
-
cli-five searches **two sources** for skills matching your detected stack:
|
|
223
|
+
Skill discovery runs during `init --full-interview` (or when you pass `--skills`). cli-five searches **two sources** for skills matching your detected stack:
|
|
113
224
|
|
|
114
225
|
| Source | What it has | Stars |
|
|
115
226
|
|---|---|---|
|
|
@@ -127,7 +238,7 @@ Take time to read each installed skill so you understand what it does and can ca
|
|
|
127
238
|
## What this is not
|
|
128
239
|
|
|
129
240
|
- **Not a runtime.** Once scaffolded, your repo doesn't depend on `cli-five`. You can uninstall the package and the agents still work.
|
|
130
|
-
- **Not a workflow engine.** No `/plan-phase`, no `/ship`, no 50 slash commands. Use `/agent-customization` in Copilot Chat to extend.
|
|
241
|
+
- **Not a workflow engine.** No `/plan-phase`, no `/ship`, no 50 slash commands. Use `/agent-customization` in Copilot Chat or OpenCode commands to extend.
|
|
131
242
|
- **Not Ralph.** No issue-polling daemons, no autonomous loops, no crypto tokens.
|
|
132
243
|
|
|
133
244
|
## Why the name
|
|
@@ -144,6 +255,7 @@ ELI5 → CLI5. Code Like I'm Five. Five agents. Get it? Yeah, it's a stretch. Bu
|
|
|
144
255
|
|
|
145
256
|
- The plugin install path and the scaffolded project path are both supported and now validated against each other.
|
|
146
257
|
- `npm test` includes agent integrity checks in addition to the existing skill-step tests.
|
|
258
|
+
- Google Antigravity AGY CLI support is planned but not implemented yet.
|
|
147
259
|
|
|
148
260
|
## Local development
|
|
149
261
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-five",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Code Like I'm Five — scaffold a 5-agent
|
|
3
|
+
"version": "0.2.16",
|
|
4
|
+
"description": "Code Like I'm Five — scaffold a 5-agent AI team (GitHub Copilot or OpenCode) into any repo.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/idusortus/cli-five.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/idusortus/cli-five#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/idusortus/cli-five/issues"
|
|
13
|
+
},
|
|
6
14
|
"bin": {
|
|
7
15
|
"cli-five": "bin/cli-five.mjs"
|
|
8
16
|
},
|
|
@@ -24,6 +32,8 @@
|
|
|
24
32
|
},
|
|
25
33
|
"keywords": [
|
|
26
34
|
"copilot",
|
|
35
|
+
"opencode",
|
|
36
|
+
"codegraph",
|
|
27
37
|
"vscode",
|
|
28
38
|
"agents",
|
|
29
39
|
"scaffold",
|
|
@@ -33,6 +43,7 @@
|
|
|
33
43
|
"dependencies": {
|
|
34
44
|
"kleur": "^4.1.5",
|
|
35
45
|
"prompts": "^2.4.2",
|
|
36
|
-
"skills": "^1.5.0"
|
|
46
|
+
"skills": "^1.5.0",
|
|
47
|
+
"yaml": "^2.8.3"
|
|
37
48
|
}
|
|
38
49
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Designer
|
|
3
3
|
description: "Handles all UI/UX design tasks. Use when: creating screens, layouts, theming, navigation flows, design systems."
|
|
4
|
-
model:
|
|
4
|
+
model: Gemini 3.1 Pro (Preview) (copilot)
|
|
5
5
|
tools: ['read', 'edit', 'search', 'web', 'io.github.upstash/context7/*', 'vscode/memory']
|
|
6
6
|
agents: []
|
|
7
7
|
---
|
|
@@ -10,7 +10,7 @@ agents: []
|
|
|
10
10
|
|
|
11
11
|
| Mode | Model | Premium Cost |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
| **Default** |
|
|
13
|
+
| **Default** | Gemini 3.1 Pro (Preview) (copilot) | 1x |
|
|
14
14
|
| **Cheap** | GPT-4o | 0x (free) |
|
|
15
15
|
|
|
16
16
|
To switch: change the `model` key in frontmatter above.
|
|
@@ -13,7 +13,7 @@ You create plans. You do NOT write code.
|
|
|
13
13
|
|
|
14
14
|
| Mode | Model | Premium Cost |
|
|
15
15
|
|---|---|---|
|
|
16
|
-
| **Default** | Claude
|
|
16
|
+
| **Default** | Claude Opus 4.6 | 3x |
|
|
17
17
|
| **Cheap** | GPT-4o | 0x (free) |
|
|
18
18
|
|
|
19
19
|
To switch: change the `model` key in frontmatter above.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Add-on registry for `cli-five add <name>`.
|
|
6
|
+
*
|
|
7
|
+
* An add-on describes an optional integration that can be layered onto an
|
|
8
|
+
* already-scaffolded repo. Entries without a `run` function are reserved
|
|
9
|
+
* (dispatcher/stub) targets — the mechanism is live, the integration is not.
|
|
10
|
+
*
|
|
11
|
+
* To wire a real target later: give it a `run({ cwd, args })` function (the
|
|
12
|
+
* `add` command will invoke it) and update `available`/`note` accordingly.
|
|
13
|
+
*/
|
|
14
|
+
export const ADDONS = {
|
|
15
|
+
codegraph: {
|
|
16
|
+
name: 'codegraph',
|
|
17
|
+
label: 'CodeGraph',
|
|
18
|
+
description: 'Graph-backed codebase context MCP server and agent instructions.',
|
|
19
|
+
available: false,
|
|
20
|
+
note: 'Currently installed by init (on by default). `add` migration is a future commit.',
|
|
21
|
+
detect: detectCodeGraph,
|
|
22
|
+
run: null,
|
|
23
|
+
},
|
|
24
|
+
jev: {
|
|
25
|
+
name: 'jev',
|
|
26
|
+
label: 'Jev',
|
|
27
|
+
description: 'Optional Jev integration (purpose to be defined in a future commit).',
|
|
28
|
+
available: false,
|
|
29
|
+
note: 'Reserved target. No integration wired in this release.',
|
|
30
|
+
detect: () => [],
|
|
31
|
+
run: null,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const ADDON_NAMES = Object.keys(ADDONS);
|
|
36
|
+
|
|
37
|
+
export function listAddons() {
|
|
38
|
+
return Object.values(ADDONS);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getAddon(name) {
|
|
42
|
+
if (!name) return undefined;
|
|
43
|
+
return ADDONS[String(name).toLowerCase()];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Inspect a workspace for evidence that an add-on is already present.
|
|
48
|
+
* Returns a list of human-readable signals (empty when not detected).
|
|
49
|
+
*/
|
|
50
|
+
export function detectAddon(addon, cwd) {
|
|
51
|
+
if (!addon || typeof addon.detect !== 'function') return [];
|
|
52
|
+
try {
|
|
53
|
+
return addon.detect(cwd) || [];
|
|
54
|
+
} catch {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── Detectors ─────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Detect CodeGraph artifacts written by init today. Read-only: this inspects
|
|
63
|
+
* existing registration without modifying it.
|
|
64
|
+
*/
|
|
65
|
+
export function detectCodeGraph(cwd) {
|
|
66
|
+
const signals = [];
|
|
67
|
+
|
|
68
|
+
const opencodePath = join(cwd, 'opencode.json');
|
|
69
|
+
const opencodeCfg = readJson(opencodePath);
|
|
70
|
+
if (opencodeCfg?.mcp?.codegraph) signals.push('opencode.json mcp.codegraph');
|
|
71
|
+
|
|
72
|
+
const mcpPath = join(cwd, '.vscode', 'mcp.json');
|
|
73
|
+
const mcpCfg = readJson(mcpPath);
|
|
74
|
+
if (mcpCfg?.servers?.codegraph) signals.push('.vscode/mcp.json servers.codegraph');
|
|
75
|
+
|
|
76
|
+
const agentsPath = join(cwd, 'AGENTS.md');
|
|
77
|
+
if (existsSync(agentsPath)) {
|
|
78
|
+
try {
|
|
79
|
+
const body = readFileSync(agentsPath, 'utf8');
|
|
80
|
+
if (body.includes('<!-- CODEGRAPH_START -->')) signals.push('AGENTS.md CodeGraph section');
|
|
81
|
+
} catch {
|
|
82
|
+
/* ignore */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return signals;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readJson(filePath) {
|
|
90
|
+
if (!existsSync(filePath)) return null;
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(readFileSync(filePath, 'utf8'));
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/cli.mjs
CHANGED
|
@@ -5,16 +5,20 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { init } from './commands/init.mjs';
|
|
6
6
|
import { doctor } from './commands/doctor.mjs';
|
|
7
7
|
import { listStacks } from './commands/list-stacks.mjs';
|
|
8
|
+
import { add } from './commands/add.mjs';
|
|
9
|
+
import { listAddonsCommand } from './commands/list-addons.mjs';
|
|
8
10
|
import { STACK_SIGNATURES } from './steps/detect.mjs';
|
|
9
11
|
|
|
10
12
|
const HELP = `${kleur.bold('cli-five')} ${kleur.gray('— Code Like I\'m Five')}
|
|
11
|
-
Scaffold a 5-agent
|
|
13
|
+
Scaffold a 5-agent AI team into any repo.
|
|
12
14
|
|
|
13
15
|
${kleur.bold('Usage')}
|
|
14
16
|
npx cli-five <command> [options]
|
|
15
17
|
|
|
16
18
|
${kleur.bold('Commands')}
|
|
17
|
-
init
|
|
19
|
+
init Scaffold the 5 agents + required tooling (minimal by default)
|
|
20
|
+
add <name> Install an optional add-on (dispatcher; targets land later)
|
|
21
|
+
list-addons Show installed vs. available add-ons
|
|
18
22
|
doctor Validate an existing cli-five setup
|
|
19
23
|
list-stacks Show detectable tech stacks
|
|
20
24
|
help Show this message
|
|
@@ -23,9 +27,19 @@ ${kleur.bold('Flags')}
|
|
|
23
27
|
--yes, -y Accept defaults and skip confirmations (still gated on overwrite)
|
|
24
28
|
--force Overwrite without confirmation. Dangerous. Use with --yes.
|
|
25
29
|
--dry-run Print actions without writing files
|
|
30
|
+
--full-interview Run the full legacy interview (docs, goals, persona, models). Enables CodeGraph by default
|
|
31
|
+
--skills Force skill discovery (default: full interview only)
|
|
26
32
|
--no-skills Skip the skills.sh discovery step
|
|
27
|
-
--
|
|
33
|
+
--instructions Force stack-specific instruction generation
|
|
34
|
+
--no-instructions Skip instruction generation
|
|
35
|
+
--persona Include the snarky persona block
|
|
36
|
+
--no-persona Omit the snarky persona block
|
|
37
|
+
--codegraph Add CodeGraph MCP + instructions (default: only with --full-interview)
|
|
38
|
+
--no-codegraph Skip CodeGraph MCP + instructions
|
|
39
|
+
--doc <file> Read project docs to pre-fill interview (repeatable; implies --full-interview)
|
|
28
40
|
--cost-mode <m> Override cost mode (premium, cheap, mixed) — skips interview question
|
|
41
|
+
--target <t> Target platform: copilot or opencode (default: copilot)
|
|
42
|
+
--provider <p> Model provider: copilot, opencode, opencode-go (default: platform default)
|
|
29
43
|
--cwd <path> Run against a directory other than the current one
|
|
30
44
|
--version, -v Print version and exit
|
|
31
45
|
`;
|
|
@@ -37,6 +51,10 @@ export async function run(argv) {
|
|
|
37
51
|
switch (cmd) {
|
|
38
52
|
case 'init':
|
|
39
53
|
return init(args);
|
|
54
|
+
case 'add':
|
|
55
|
+
return add(args);
|
|
56
|
+
case 'list-addons':
|
|
57
|
+
return listAddonsCommand(args);
|
|
40
58
|
case 'doctor':
|
|
41
59
|
return doctor(args);
|
|
42
60
|
case 'list-stacks':
|
|
@@ -60,15 +78,40 @@ export async function run(argv) {
|
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
function parse(argv) {
|
|
63
|
-
const out = {
|
|
81
|
+
const out = {
|
|
82
|
+
_: [],
|
|
83
|
+
yes: false,
|
|
84
|
+
force: false,
|
|
85
|
+
dryRun: false,
|
|
86
|
+
fullInterview: false,
|
|
87
|
+
skills: null,
|
|
88
|
+
instructions: null,
|
|
89
|
+
persona: null,
|
|
90
|
+
codegraph: null,
|
|
91
|
+
docs: [],
|
|
92
|
+
costMode: null,
|
|
93
|
+
target: null,
|
|
94
|
+
provider: null,
|
|
95
|
+
cwd: process.cwd(),
|
|
96
|
+
};
|
|
64
97
|
for (let i = 0; i < argv.length; i++) {
|
|
65
98
|
const a = argv[i];
|
|
66
99
|
if (a === '--yes' || a === '-y') out.yes = true;
|
|
67
100
|
else if (a === '--force') out.force = true;
|
|
68
101
|
else if (a === '--dry-run') out.dryRun = true;
|
|
102
|
+
else if (a === '--full-interview' || a === '--full') out.fullInterview = true;
|
|
103
|
+
else if (a === '--skills') out.skills = true;
|
|
69
104
|
else if (a === '--no-skills') out.skills = false;
|
|
105
|
+
else if (a === '--instructions') out.instructions = true;
|
|
106
|
+
else if (a === '--no-instructions') out.instructions = false;
|
|
107
|
+
else if (a === '--persona') out.persona = true;
|
|
108
|
+
else if (a === '--no-persona') out.persona = false;
|
|
109
|
+
else if (a === '--codegraph') out.codegraph = true;
|
|
110
|
+
else if (a === '--no-codegraph') out.codegraph = false;
|
|
70
111
|
else if (a === '--doc') out.docs.push(argv[++i]);
|
|
71
112
|
else if (a === '--cost-mode') out.costMode = argv[++i];
|
|
113
|
+
else if (a === '--target') out.target = argv[++i];
|
|
114
|
+
else if (a === '--provider') out.provider = argv[++i];
|
|
72
115
|
else if (a === '--cwd') out.cwd = argv[++i];
|
|
73
116
|
else if (a === '--help' || a === '-h') out._.push('help');
|
|
74
117
|
else if (a === '--version' || a === '-v') out._.push('--version');
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import kleur from 'kleur';
|
|
2
|
+
import { log } from '../util/log.mjs';
|
|
3
|
+
import { ADDON_NAMES, getAddon, listAddons } from '../addons/registry.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `cli-five add <name>` — dispatch to a registered add-on.
|
|
7
|
+
*
|
|
8
|
+
* This pass ships the dispatcher only. Registered targets without a `run`
|
|
9
|
+
* function respond with a clear stub so the mechanism can be exercised
|
|
10
|
+
* end-to-end without pretending an integration exists.
|
|
11
|
+
*/
|
|
12
|
+
export async function add(args) {
|
|
13
|
+
const name = args._[1];
|
|
14
|
+
|
|
15
|
+
if (!name || name === '--help' || name === '-h' || name === 'help') {
|
|
16
|
+
printAddHelp();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const addon = getAddon(name);
|
|
21
|
+
if (!addon) {
|
|
22
|
+
log.err(`Unknown add-on: ${name}`);
|
|
23
|
+
printAvailable(addon => addon.name);
|
|
24
|
+
process.exitCode = 2;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof addon.run !== 'function') {
|
|
29
|
+
log.warn(`${addon.label} is registered but not implemented yet.`);
|
|
30
|
+
log.info('The add dispatcher works — this target is reserved for a future release.');
|
|
31
|
+
if (addon.note) log.dim(addon.note);
|
|
32
|
+
log.dim('Nothing was written to your project.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
log.step(`add ${addon.name}`);
|
|
37
|
+
await addon.run({ cwd: args.cwd, args });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function printAddHelp() {
|
|
41
|
+
process.stdout.write(`${kleur.bold('cli-five add')} — install an optional add-on\n\n`);
|
|
42
|
+
process.stdout.write(`${kleur.bold('Usage')}\n npx cli-five add <name>\n\n`);
|
|
43
|
+
printAvailable();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function printAvailable() {
|
|
47
|
+
process.stdout.write(`${kleur.bold('Available add-ons')}\n`);
|
|
48
|
+
for (const addon of listAddons()) {
|
|
49
|
+
const addable = typeof addon.run === 'function';
|
|
50
|
+
const statusText = (addable ? 'available' : 'planned').padEnd(10);
|
|
51
|
+
const status = addable ? kleur.green(statusText) : kleur.yellow(statusText);
|
|
52
|
+
process.stdout.write(` ${addon.name.padEnd(12)} ${status} ${kleur.dim(addon.description)}\n`);
|
|
53
|
+
}
|
|
54
|
+
process.stdout.write(`\n${kleur.dim(`Known names: ${ADDON_NAMES.join(', ')}`)}\n`);
|
|
55
|
+
}
|