cli-five 0.2.12 → 0.2.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # cli-five
2
2
 
3
- > **Code Like I'm Five** — scaffold a 5-agent VS Code Copilot team into any repo.
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,9 @@
10
10
  npx cli-five init
11
11
  ```
12
12
 
13
- Interviews you, scaffolds agents + memory files + stack-specific instructions, discovers skills from **awesome-copilot** and **skills.sh**, and tells you what to do next.
13
+ Interviews you, lets you pick a target platform and model provider, scaffolds agents + memory files + stack-specific instructions, discovers skills, and tells you what to do next.
14
14
 
15
- ### Quick plugin install (personal use)
15
+ ### Quick plugin install (personal use, Copilot only)
16
16
 
17
17
  ```
18
18
  copilot plugin install idusortus/cli-five
@@ -20,20 +20,34 @@ copilot plugin install idusortus/cli-five
20
20
 
21
21
  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
22
 
23
+ ## Supported platforms
24
+
25
+ cli-five can scaffold for:
26
+
27
+ - **GitHub Copilot** — `.github/agents/*.agent.md` + `copilot-instructions.md`
28
+ - **OpenCode** — `.opencode/agents/*.md` + `opencode.json`
29
+
30
+ Both platforms can optionally include a **CodeGraph** MCP server and instructions.
31
+
32
+ Run `npx cli-five init` and choose your platform. If you want both, run it again in the same repo.
33
+
23
34
  ## What you get
24
35
 
36
+ ### GitHub Copilot layout
37
+
25
38
  ```
26
39
  your-repo/
27
40
  ├── .github/
28
41
  │ ├── agents/ # 5 agents — Orchestrator delegates autonomously
29
- │ │ ├── orchestrator.agent.md # Routes tasks: Planner → Coder/Designer → Reviewer
30
- │ │ ├── planner.agent.md # Researches codebase, produces implementation plans
31
- │ │ ├── coder.agent.md # Writes production code, runs tests
32
- │ │ ├── designer.agent.md # UI/UX design, layouts, theming
33
- │ │ └── reviewer.agent.md # Code review, convention compliance
42
+ │ │ ├── orchestrator.agent.md
43
+ │ │ ├── planner.agent.md
44
+ │ │ ├── coder.agent.md
45
+ │ │ ├── designer.agent.md
46
+ │ │ └── reviewer.agent.md
34
47
  │ ├── copilot-instructions.md # Persona + project mandates from interview
35
48
  │ ├── instructions/ # Stack-specific coding guidelines
36
49
  │ └── skills/ # Installed skills from awesome-copilot + skills.sh
50
+ ├── .vscode/mcp.json # CodeGraph MCP server (optional)
37
51
  ├── AGENTS.md # Tool-agnostic project context (agents.md standard)
38
52
  ├── PROJECT.md # Long-form vision (rarely changes)
39
53
  ├── STATE.md # Cross-session status (changes constantly)
@@ -42,9 +56,31 @@ your-repo/
42
56
  └── histories/ # Per-agent accumulated learnings
43
57
  ```
44
58
 
59
+ ### OpenCode layout
60
+
61
+ ```
62
+ your-repo/
63
+ ├── .opencode/
64
+ │ └── agents/ # 5 agents — Orchestrator delegates autonomously
65
+ │ ├── orchestrator.md
66
+ │ ├── planner.md
67
+ │ ├── coder.md
68
+ │ ├── designer.md
69
+ │ └── reviewer.md
70
+ ├── opencode.json # Project config, model defaults, CodeGraph MCP (optional)
71
+ ├── .github/instructions/ # Stack-specific coding guidelines
72
+ ├── .github/skills/ # Installed skills
73
+ ├── AGENTS.md # Project rules + optional CodeGraph block
74
+ ├── PROJECT.md
75
+ ├── STATE.md
76
+ ├── decisions.md
77
+ ├── agent-diary.md
78
+ └── histories/
79
+ ```
80
+
45
81
  ## How it works
46
82
 
47
- Select the **Orchestrator** agent in Copilot Chat and describe what you want. The Orchestrator autonomously calls Planner → Coder/Designer → Reviewer without any manual handoff clicks.
83
+ Select the **Orchestrator** agent and describe what you want. The Orchestrator autonomously calls Planner → Coder/Designer → Reviewer without any manual handoff clicks.
48
84
 
49
85
  ```
50
86
  User: implement from plan.md
@@ -53,13 +89,13 @@ Orchestrator → [calls Planner] → [calls Coder] → [calls Reviewer] → done
53
89
 
54
90
  No buttons. No "click here to continue". Just results.
55
91
 
56
- The plugin agents and scaffolded `.github/agents/*.agent.md` templates are intentionally kept in sync. The repository test suite now checks that parity so the quick-install path does not quietly degrade.
92
+ 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
93
 
58
94
  ## Commands
59
95
 
60
96
  ```bash
61
97
  npx cli-five init # interview + scaffold + skill discovery
62
- npx cli-five doctor # validate an existing setup
98
+ npx cli-five doctor # validate an existing cli-five setup
63
99
  npx cli-five list-stacks # show detectable tech stacks
64
100
  npx cli-five help
65
101
  ```
@@ -72,34 +108,69 @@ npx cli-five help
72
108
  | `--force` | Overwrite without confirmation (use with `--yes`) |
73
109
  | `--dry-run` | Print actions, write nothing |
74
110
  | `--no-skills` | Skip skills.sh discovery step |
75
- | `--cost-mode <m>` | Set cost mode: `premium`, `cheap`, or `mixed` |
111
+ | `--no-codegraph` | Skip CodeGraph MCP + instructions |
112
+ | `--target <t>` | Target platform: `copilot` or `opencode` (default: `copilot`) |
113
+ | `--provider <p>` | Model provider: `copilot`, `opencode`, `opencode-go` (default: platform default) |
114
+ | `--cost-mode <m>` | Set cost mode for Copilot: `premium`, `cheap`, or `mixed` |
115
+ | `--doc <file>` | Read project docs to pre-fill interview (repeatable) |
76
116
  | `--cwd <path>` | Run against a different directory |
77
117
 
78
118
  ## What `init` does
79
119
 
80
120
  1. **Detect** — fingerprints stack (Node/TS, Python, .NET, Kotlin, Rust, Go, etc.). Brownfield-aware.
81
- 2. **git init** — if needed. Asks first.
82
- 3. **Overwrite gate** — double-confirms ("Proceed?" then "R U Sure?"). Only `--force --yes` bypasses.
83
- 4. **Interview** — name, one-liner, stack, frameworks, goals, constraints, cost mode, persona toggle.
84
- 5. **Scaffold** — writes 18 files. Substitutes answers into templates. Swaps `model:` per cost mode.
85
- 6. **Skill discovery** — the hero feature. Multi-source discovery from **awesome-copilot** (30k+ ★ community marketplace) and **skills.sh**. Color-coded recommendations, source attribution, multiselect install, and post-install breadcrumbs with copy-paste commands for the awesome-copilot suggestion skill and MCP server.
86
- 7. **Custom instructions** — generates stack-specific `.instructions.md` files for detected languages.
87
- 8. **Next steps** — tells you to open Copilot Chat, select Orchestrator, and start building. No button-clicking required.
121
+ 2. **Choose platform** — GitHub Copilot or OpenCode, with optional CodeGraph pairing.
122
+ 3. **git init** — if needed. Asks first.
123
+ 4. **Overwrite gate** — double-confirms ("Proceed?" then "R U Sure?"). Only `--force --yes` bypasses.
124
+ 5. **Project info** — name, one-liner, stack, frameworks, goals, constraints, persona toggle.
125
+ 6. **Model configuration** — pick a provider and optionally override each agent's model.
126
+ 7. **Scaffold** — writes platform-specific files. Swaps `model:` per provider/selection.
127
+ 8. **Skill discovery** — multi-source discovery from **awesome-copilot** and **skills.sh**.
128
+ 9. **Custom instructions** — generates stack-specific `.instructions.md` files for detected languages.
129
+ 10. **Next steps** — platform-specific instructions. No button-clicking required.
130
+
131
+ ## Model providers
132
+
133
+ During `init` you can choose the model provider and optionally customize each agent's model.
88
134
 
89
- ## Cost modes
135
+ | Provider | Platform | Example model |
136
+ |---|---|---|
137
+ | GitHub Copilot | Copilot | `Claude Sonnet 4.6 (copilot)` |
138
+ | OpenCode Zen | OpenCode | `opencode/gpt-5.3-codex` |
139
+ | OpenCode Go | OpenCode | `opencode-go/qwen3.8-max` |
140
+
141
+ `--yes` uses the provider's defaults. `--provider opencode-go --yes` skips the provider prompt.
142
+
143
+ ### Copilot cost modes
90
144
 
91
145
  | Agent | `premium` (1x–3x) | `cheap` (0x) | `mixed` |
92
146
  |---|---|---|---|
93
147
  | Orchestrator | Claude Sonnet 4.6 | GPT-4.1 | GPT-4.1 |
94
148
  | Planner | Claude Opus 4.6 | GPT-4o | GPT-4o |
95
149
  | Coder | GPT-5.3-Codex | GPT-4.1 | GPT-5.3-Codex |
96
- | Designer | Claude Opus 4.6 | GPT-4o | GPT-4o |
97
- | Reviewer | Claude Opus 4.6 | GPT-5 mini | Claude Opus 4.6 |
150
+ | Designer | Gemini 3.1 Pro (Preview) | GPT-4o | GPT-4o |
151
+ | Reviewer | Claude Sonnet 4.6 | GPT-5 mini | Claude Sonnet 4.6 |
98
152
 
99
153
  Override from CLI: `npx cli-five init --cost-mode cheap`
100
- Change anytime by editing the `model:` line in `.github/agents/*.agent.md`.
154
+ Change anytime by editing the `model:` line in the agent files.
155
+
156
+ ## CodeGraph
101
157
 
102
- ## Required VS Code settings
158
+ CodeGraph adds a local, graph-backed codebase context server. When enabled, cli-five:
159
+
160
+ - Registers the CodeGraph MCP server in `opencode.json` (OpenCode) or `.vscode/mcp.json` (Copilot).
161
+ - Adds a marker-fenced CodeGraph section to `AGENTS.md`.
162
+ - Tells you to run `codegraph init` to index the project.
163
+
164
+ cli-five does **not** install or run the CodeGraph CLI automatically. After scaffolding:
165
+
166
+ ```bash
167
+ npm i -g @colbymchenry/codegraph
168
+ codegraph init
169
+ ```
170
+
171
+ ## Required settings
172
+
173
+ ### GitHub Copilot
103
174
 
104
175
  ```jsonc
105
176
  {
@@ -107,6 +178,10 @@ Change anytime by editing the `model:` line in `.github/agents/*.agent.md`.
107
178
  }
108
179
  ```
109
180
 
181
+ ### OpenCode
182
+
183
+ No extra settings required. Project agents live in `.opencode/agents/` and the project config in `opencode.json`.
184
+
110
185
  ## Skill discovery
111
186
 
112
187
  cli-five searches **two sources** for skills matching your detected stack:
@@ -127,7 +202,7 @@ Take time to read each installed skill so you understand what it does and can ca
127
202
  ## What this is not
128
203
 
129
204
  - **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.
205
+ - **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
206
  - **Not Ralph.** No issue-polling daemons, no autonomous loops, no crypto tokens.
132
207
 
133
208
  ## Why the name
@@ -144,6 +219,7 @@ ELI5 → CLI5. Code Like I'm Five. Five agents. Get it? Yeah, it's a stretch. Bu
144
219
 
145
220
  - The plugin install path and the scaffolded project path are both supported and now validated against each other.
146
221
  - `npm test` includes agent integrity checks in addition to the existing skill-step tests.
222
+ - Google Antigravity AGY CLI support is planned but not implemented yet.
147
223
 
148
224
  ## Local development
149
225
 
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "cli-five",
3
- "version": "0.2.12",
4
- "description": "Code Like I'm Five — scaffold a 5-agent VS Code Copilot team into any repo.",
3
+ "version": "0.2.15",
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: Claude Opus 4.6 (copilot)
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** | Claude Opus 4.6 | 3x |
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 Sonnet 4.6 | 1x |
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.
package/src/cli.mjs CHANGED
@@ -8,13 +8,13 @@ import { listStacks } from './commands/list-stacks.mjs';
8
8
  import { STACK_SIGNATURES } from './steps/detect.mjs';
9
9
 
10
10
  const HELP = `${kleur.bold('cli-five')} ${kleur.gray('— Code Like I\'m Five')}
11
- Scaffold a 5-agent Copilot team into any repo.
11
+ Scaffold a 5-agent AI team into any repo.
12
12
 
13
13
  ${kleur.bold('Usage')}
14
14
  npx cli-five <command> [options]
15
15
 
16
16
  ${kleur.bold('Commands')}
17
- init Interview + scaffold .github/* and project memory files
17
+ init Interview + scaffold agents + project memory files
18
18
  doctor Validate an existing cli-five setup
19
19
  list-stacks Show detectable tech stacks
20
20
  help Show this message
@@ -26,6 +26,9 @@ ${kleur.bold('Flags')}
26
26
  --no-skills Skip the skills.sh discovery step
27
27
  --doc <file> Read project docs to pre-fill interview (repeatable)
28
28
  --cost-mode <m> Override cost mode (premium, cheap, mixed) — skips interview question
29
+ --target <t> Target platform: copilot or opencode (default: copilot)
30
+ --provider <p> Model provider: copilot, opencode, opencode-go (default: platform default)
31
+ --no-codegraph Skip CodeGraph MCP + instructions
29
32
  --cwd <path> Run against a directory other than the current one
30
33
  --version, -v Print version and exit
31
34
  `;
@@ -60,15 +63,30 @@ export async function run(argv) {
60
63
  }
61
64
 
62
65
  function parse(argv) {
63
- const out = { _: [], yes: false, force: false, dryRun: false, skills: true, docs: [], costMode: null, cwd: process.cwd() };
66
+ const out = {
67
+ _: [],
68
+ yes: false,
69
+ force: false,
70
+ dryRun: false,
71
+ skills: true,
72
+ codegraph: true,
73
+ docs: [],
74
+ costMode: null,
75
+ target: null,
76
+ provider: null,
77
+ cwd: process.cwd(),
78
+ };
64
79
  for (let i = 0; i < argv.length; i++) {
65
80
  const a = argv[i];
66
81
  if (a === '--yes' || a === '-y') out.yes = true;
67
82
  else if (a === '--force') out.force = true;
68
83
  else if (a === '--dry-run') out.dryRun = true;
69
84
  else if (a === '--no-skills') out.skills = false;
85
+ else if (a === '--no-codegraph') out.codegraph = false;
70
86
  else if (a === '--doc') out.docs.push(argv[++i]);
71
87
  else if (a === '--cost-mode') out.costMode = argv[++i];
88
+ else if (a === '--target') out.target = argv[++i];
89
+ else if (a === '--provider') out.provider = argv[++i];
72
90
  else if (a === '--cwd') out.cwd = argv[++i];
73
91
  else if (a === '--help' || a === '-h') out._.push('help');
74
92
  else if (a === '--version' || a === '-v') out._.push('--version');
@@ -2,9 +2,15 @@ import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import kleur from 'kleur';
4
4
  import { log } from '../util/log.mjs';
5
- import { AGENT_FILES, validateAgentSource } from '../util/agents.mjs';
5
+ import {
6
+ AGENT_FILES,
7
+ OPENCODE_AGENT_FILES,
8
+ validateAgentSource,
9
+ validateOpenCodeAgentSource,
10
+ } from '../util/agents.mjs';
11
+ import { PLATFORM_COPILOT, PLATFORM_OPENCODE } from '../util/platforms.mjs';
6
12
 
7
- const REQUIRED = [
13
+ const COPILOT_REQUIRED = [
8
14
  '.github/copilot-instructions.md',
9
15
  '.github/agents/orchestrator.agent.md',
10
16
  '.github/agents/planner.agent.md',
@@ -17,6 +23,19 @@ const REQUIRED = [
17
23
  'agent-diary.md',
18
24
  ];
19
25
 
26
+ const OPENCODE_REQUIRED = [
27
+ 'opencode.json',
28
+ '.opencode/agents/orchestrator.md',
29
+ '.opencode/agents/planner.md',
30
+ '.opencode/agents/coder.md',
31
+ '.opencode/agents/designer.md',
32
+ '.opencode/agents/reviewer.md',
33
+ 'PROJECT.md',
34
+ 'STATE.md',
35
+ 'decisions.md',
36
+ 'agent-diary.md',
37
+ ];
38
+
20
39
  const OPTIONAL = [
21
40
  '.github/instructions',
22
41
  '.github/skills',
@@ -26,11 +45,15 @@ const OPTIONAL = [
26
45
 
27
46
  export async function doctor(args) {
28
47
  const cwd = args.cwd;
48
+ const platform = detectPlatform(cwd);
29
49
  log.raw(kleur.bold().magenta('\ncli-five doctor') + kleur.gray(` ${cwd}`));
50
+ log.info(`Detected platform: ${kleur.bold(platform)}`);
30
51
  let fail = 0;
31
52
 
53
+ const required = platform === PLATFORM_OPENCODE ? OPENCODE_REQUIRED : COPILOT_REQUIRED;
54
+
32
55
  log.step('Required');
33
- for (const p of REQUIRED) {
56
+ for (const p of required) {
34
57
  const ok = existsSync(join(cwd, p));
35
58
  if (ok) log.ok(p);
36
59
  else {
@@ -40,22 +63,60 @@ export async function doctor(args) {
40
63
  }
41
64
 
42
65
  log.step('Agent integrity');
43
- for (const file of AGENT_FILES) {
44
- const relPath = join('.github', 'agents', file);
45
- const fullPath = join(cwd, relPath);
46
- if (!existsSync(fullPath)) continue;
66
+ if (platform === PLATFORM_OPENCODE) {
67
+ for (const file of OPENCODE_AGENT_FILES) {
68
+ const relPath = join('.opencode', 'agents', file);
69
+ const fullPath = join(cwd, relPath);
70
+ if (!existsSync(fullPath)) continue;
47
71
 
48
- const errors = validateAgentSource(readFileSync(fullPath, 'utf8'), file);
49
- if (errors.length === 0) {
50
- log.ok(relPath);
51
- continue;
72
+ const errors = validateOpenCodeAgentSource(readFileSync(fullPath, 'utf8'), file);
73
+ if (errors.length === 0) {
74
+ log.ok(relPath);
75
+ continue;
76
+ }
77
+
78
+ log.err(relPath);
79
+ for (const error of errors) {
80
+ log.raw(kleur.red(` - ${error}`));
81
+ }
82
+ fail++;
52
83
  }
84
+ } else {
85
+ for (const file of AGENT_FILES) {
86
+ const relPath = join('.github', 'agents', file);
87
+ const fullPath = join(cwd, relPath);
88
+ if (!existsSync(fullPath)) continue;
89
+
90
+ const errors = validateAgentSource(readFileSync(fullPath, 'utf8'), file);
91
+ if (errors.length === 0) {
92
+ log.ok(relPath);
93
+ continue;
94
+ }
95
+
96
+ log.err(relPath);
97
+ for (const error of errors) {
98
+ log.raw(kleur.red(` - ${error}`));
99
+ }
100
+ fail++;
101
+ }
102
+ }
53
103
 
54
- log.err(relPath);
55
- for (const error of errors) {
56
- log.raw(kleur.red(` - ${error}`));
104
+ if (platform === PLATFORM_OPENCODE) {
105
+ log.step('OpenCode config');
106
+ const opencodePath = join(cwd, 'opencode.json');
107
+ if (existsSync(opencodePath)) {
108
+ try {
109
+ const cfg = JSON.parse(readFileSync(opencodePath, 'utf8'));
110
+ if (cfg.mcp?.codegraph) {
111
+ log.ok('opencode.json has CodeGraph MCP entry');
112
+ } else {
113
+ log.warn('opencode.json missing CodeGraph MCP entry (ok if CodeGraph disabled)');
114
+ }
115
+ } catch (err) {
116
+ log.err(`opencode.json is not valid JSON: ${err.message}`);
117
+ fail++;
118
+ }
57
119
  }
58
- fail++;
59
120
  }
60
121
 
61
122
  log.step('Optional');
@@ -72,3 +133,9 @@ export async function doctor(args) {
72
133
  process.exit(1);
73
134
  }
74
135
  }
136
+
137
+ function detectPlatform(cwd) {
138
+ if (existsSync(join(cwd, '.opencode', 'agents'))) return PLATFORM_OPENCODE;
139
+ if (existsSync(join(cwd, '.github', 'agents', 'orchestrator.agent.md'))) return PLATFORM_COPILOT;
140
+ return PLATFORM_COPILOT;
141
+ }
@@ -9,21 +9,30 @@ import { interview } from '../steps/interview.mjs';
9
9
  import { scaffold, summarize } from '../steps/scaffold.mjs';
10
10
  import { skillDiscovery } from '../steps/skills.mjs';
11
11
  import { instructionGeneration } from '../steps/instructions.mjs';
12
+ import { choosePlatform, chooseModels } from '../steps/platform.mjs';
12
13
  import { isGitRepo, gitInit } from '../util/git.mjs';
14
+ import { platformLabel } from '../util/platforms.mjs';
13
15
 
14
16
  export async function init(args) {
15
17
  const cwd = args.cwd;
16
18
  log.raw(kleur.bold().magenta('\ncli-five init') + kleur.gray(` ${cwd}`));
17
19
 
18
20
  // 1. Detect
19
- log.step('1/6 Detect workspace');
21
+ log.step('1/8 Detect workspace');
20
22
  const detected = detect(cwd);
21
23
  log.info(`Project: ${kleur.bold(detected.projectName)}`);
22
24
  log.info(`Mode: ${detected.isBrownfield ? kleur.yellow('brownfield') : kleur.green('greenfield')}`);
23
25
  if (detected.stacks.length) log.info(`Stack: ${detected.stacks.map((s) => s.label).join(', ')}`);
24
26
  if (!detected.hasGit) log.warn('Not a git repository.');
25
27
 
26
- // 2. git init if needed
28
+ // 2. Platform + CodeGraph
29
+ log.step('2/8 Choose platform');
30
+ const { platform, codegraph } = await choosePlatform(args);
31
+ log.info(`Target: ${kleur.bold(platformLabel(platform))}`);
32
+ if (codegraph) log.info(`CodeGraph: ${kleur.green('enabled')}`);
33
+ else log.info('CodeGraph: disabled');
34
+
35
+ // 3. git init if needed
27
36
  if (!detected.hasGit) {
28
37
  if (args.yes || (await ask('Run `git init`?', true))) {
29
38
  gitInit(cwd);
@@ -33,8 +42,8 @@ export async function init(args) {
33
42
  }
34
43
  }
35
44
 
36
- // 3. Overwrite gate
37
- log.step('2/6 Confirm overwrites');
45
+ // 4. Overwrite gate
46
+ log.step('3/8 Confirm overwrites');
38
47
  const ok = await confirmOverwriteIfNeeded(detected, args);
39
48
  if (!ok) {
40
49
  log.warn('Aborted. Nothing written.');
@@ -42,8 +51,8 @@ export async function init(args) {
42
51
  }
43
52
  if (!detected.hasAgents && !detected.hasCopilotInstructions) log.dim('No collisions.');
44
53
 
45
- // 4. Input mode — docs or manual interview
46
- log.step('3/6 Project info');
54
+ // 5. Input mode — docs or manual interview
55
+ log.step('4/8 Project info');
47
56
  let docHints;
48
57
 
49
58
  if (args.docs.length > 0) {
@@ -64,7 +73,15 @@ export async function init(args) {
64
73
  if (docHints.oneLiner) log.dim(` → description: ${docHints.oneLiner}`);
65
74
  }
66
75
 
67
- // 5. Interview (pre-filled from docs if available, otherwise manual)
76
+ // 6. Model configuration
77
+ log.step('5/8 Model configuration');
78
+ const modelConfig = await chooseModels(platform, args);
79
+ log.info(`Provider: ${kleur.bold(modelConfig.provider)}`);
80
+ if (modelConfig.customized) log.info('Models: customized');
81
+ else log.info('Models: defaults');
82
+
83
+ // 7. Interview (pre-filled from docs if available, otherwise manual)
84
+ args.__platform = platform;
68
85
  const answers = await interview(detected, args, docHints);
69
86
 
70
87
  // CLI --cost-mode override
@@ -72,24 +89,31 @@ export async function init(args) {
72
89
  answers.costMode = args.costMode;
73
90
  }
74
91
 
92
+ // Attach platform/model choices to answers so scaffold can use them.
93
+ answers.platform = platform;
94
+ answers.codegraph = codegraph;
95
+ answers.provider = modelConfig.provider;
96
+ answers.modelMap = modelConfig.modelMap;
97
+ answers.customizedModels = modelConfig.customized;
98
+
75
99
  if (answers.presetId && answers.presetId !== 'custom') {
76
100
  log.info(`Preset: ${answers.presetId}`);
77
101
  }
78
102
  if (answers.frameworks.length) log.info(`Stack: ${answers.stack.join(', ')} + ${answers.frameworks.join(', ')}`);
79
103
 
80
- // 5. Scaffold
81
- log.step('4/6 Scaffold');
104
+ // 8. Scaffold
105
+ log.step('6/8 Scaffold');
82
106
  const written = scaffold({ cwd, answers, args });
83
107
  if (args.dryRun) log.warn('--dry-run: no files written. Plan:');
84
108
  log.raw(summarize(written, cwd));
85
109
  if (!args.dryRun) log.ok(`Wrote ${written.length} files.`);
86
110
 
87
- // 6. Skill discovery
88
- log.step('5/6 Skill discovery');
111
+ // 9. Skill discovery
112
+ log.step('7/8 Skill discovery');
89
113
  await skillDiscovery({ cwd, answers, args });
90
114
 
91
- // 7. Custom instructions
92
- log.step('6/6 Custom instructions');
115
+ // 10. Custom instructions
116
+ log.step('8/8 Custom instructions');
93
117
  const instrWritten = await instructionGeneration({ cwd, answers, args });
94
118
  if (instrWritten && instrWritten.length > 0) {
95
119
  if (args.dryRun) log.warn('--dry-run: instruction plan:');
@@ -99,7 +123,7 @@ export async function init(args) {
99
123
  if (!args.dryRun) log.ok(`Wrote ${instrWritten.length} instruction file${instrWritten.length > 1 ? 's' : ''}.`);
100
124
  }
101
125
 
102
- // 8. Next steps
126
+ // 11. Next steps
103
127
  printNextSteps(answers);
104
128
  }
105
129
 
@@ -110,15 +134,29 @@ async function ask(message, initial = false) {
110
134
 
111
135
  function printNextSteps(answers) {
112
136
  const hasDocs = answers.docFiles?.length > 0;
137
+ const platform = answers.platform || 'copilot';
138
+ const codegraph = answers.codegraph;
113
139
 
114
140
  log.raw('');
115
141
  log.raw(kleur.bold().green('Done. Next steps:'));
116
142
  log.raw('');
117
- log.raw(` 1. Open this folder in VS Code Insiders.`);
118
- log.raw(` 2. Enable Copilot subagent invocations (settings.json):`);
119
- log.raw(kleur.gray(` "chat.subagents.allowInvocationsFromSubagents": true`));
120
- log.raw(` 3. Open Copilot Chat — select an agent from the dropdown (${kleur.bold('not')} @mention).`);
121
- log.raw(` 4. Select ${kleur.bold('Orchestrator')} — it routes tasks autonomously to Planner, Coder, Designer, and Reviewer.`);
143
+
144
+ if (platform === 'opencode') {
145
+ log.raw(` 1. Install the CodeGraph CLI if you haven't:`);
146
+ log.raw(kleur.gray(` npm i -g @colbymchenry/codegraph`));
147
+ log.raw(` 2. Index this project with CodeGraph:`);
148
+ log.raw(kleur.gray(` codegraph init`));
149
+ log.raw(` 3. Run OpenCode from this directory:`);
150
+ log.raw(kleur.gray(` opencode`));
151
+ log.raw(` 4. Select ${kleur.bold('Orchestrator')} and describe what you want built.`);
152
+ } else {
153
+ log.raw(` 1. Open this folder in VS Code Insiders.`);
154
+ log.raw(` 2. Enable Copilot subagent invocations (settings.json):`);
155
+ log.raw(kleur.gray(` "chat.subagents.allowInvocationsFromSubagents": true`));
156
+ log.raw(` 3. Open Copilot Chat — select an agent from the dropdown (${kleur.bold('not')} @mention).`);
157
+ log.raw(` 4. Select ${kleur.bold('Orchestrator')} — it routes tasks autonomously to Planner, Coder, Designer, and Reviewer.`);
158
+ }
159
+
122
160
  log.raw(` 5. ${hasDocs ? 'Kickoff prompt (paste this into Orchestrator):' : 'Start building:'}`);
123
161
  if (hasDocs) {
124
162
  const docList = answers.docFiles.join(', ');
@@ -129,11 +167,22 @@ function printNextSteps(answers) {
129
167
  }
130
168
  log.raw(` 6. Review generated instruction files in .github/instructions/.`);
131
169
  log.raw(kleur.gray(` Edit applyTo globs and guidelines to fit your project.`));
132
- log.raw('');
133
- log.raw(kleur.dim(' Quick plugin install (personal, no project config):'));
134
- log.raw(kleur.dim(' copilot plugin install idusortus/cli-five'));
135
- log.raw('');
136
- log.raw(kleur.dim('Edit cost mode anytime by changing `model:` in .github/agents/*.agent.md.'));
170
+
171
+ if (codegraph) {
172
+ log.raw('');
173
+ log.raw(kleur.dim(' CodeGraph is configured. Remember to run `codegraph init` before asking agents to explore the codebase.'));
174
+ }
175
+
176
+ if (platform === 'copilot') {
177
+ log.raw('');
178
+ log.raw(kleur.dim(' Quick plugin install (personal, no project config):'));
179
+ log.raw(kleur.dim(' copilot plugin install idusortus/cli-five'));
180
+ log.raw('');
181
+ log.raw(kleur.dim('Edit cost mode anytime by changing `model:` in .github/agents/*.agent.md.'));
182
+ } else {
183
+ log.raw('');
184
+ log.raw(kleur.dim('Edit agent models anytime by changing `model:` in .opencode/agents/*.md.'));
185
+ }
137
186
  log.raw('');
138
187
  }
139
188
 
@@ -34,5 +34,7 @@ function collideList(detected) {
34
34
  const out = [];
35
35
  if (detected.hasAgents) out.push('.github/agents/');
36
36
  if (detected.hasCopilotInstructions) out.push('.github/copilot-instructions.md');
37
+ if (detected.hasOpencodeAgents) out.push('.opencode/agents/');
38
+ if (detected.hasOpencodeConfig) out.push('opencode.json');
37
39
  return out;
38
40
  }