cortex-agents 2.2.0 → 2.3.1

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
@@ -43,7 +43,7 @@ npx cortex-agents configure # Pick your models interactively
43
43
  # Restart OpenCode - done.
44
44
  ```
45
45
 
46
- That's it. Your OpenCode session now has 7 specialized agents, 22 tools, and 14 domain skills.
46
+ That's it. Your OpenCode session now has 8 specialized agents, 23 tools, and 14 domain skills.
47
47
 
48
48
  <br>
49
49
 
@@ -78,6 +78,8 @@ Create isolated development environments and launch them instantly:
78
78
 
79
79
  Plans are automatically propagated into the worktree's `.cortex/plans/` so the new session has full context.
80
80
 
81
+ **Cross-platform terminal support** via the terminal driver system — automatically detects and integrates with tmux, iTerm2, Terminal.app, kitty, wezterm, Konsole, and GNOME Terminal. Tabs opened by the launcher are tracked and automatically closed when the worktree is removed.
82
+
81
83
  ### Task Finalizer
82
84
 
83
85
  One tool to close the loop:
@@ -114,35 +116,48 @@ Handle complex, multi-step work. Use your best model.
114
116
 
115
117
  | Agent | Role | Superpower |
116
118
  |-------|------|-----------|
117
- | **build** | Full-access development | Two-step branching strategy, worktree launcher, task finalizer, docs prompting |
118
- | **plan** | Read-only analysis | Creates implementation plans with mermaid diagrams, hands off to build |
119
- | **debug** | Deep troubleshooting | Full bash/edit access with hotfix workflow |
119
+ | **build** | Full-access development | Skill-aware implementation, worktree launcher, quality gates, task finalizer |
120
+ | **plan** | Read-only analysis | Architectural plans with mermaid diagrams, NFR analysis, hands off to build |
121
+ | **debug** | Deep troubleshooting | Performance debugging, distributed tracing, hotfix workflow |
122
+ | **review** | Code quality assessment | Tech debt scoring, pattern review, refactoring advisor (read-only) |
120
123
 
121
124
  ### Subagents
122
125
 
123
- Focused specialists. Invoked with `@mention`. Use a fast/cheap model.
126
+ Focused specialists launched **automatically** as parallel quality gates. Each auto-loads its core domain skill for deeper analysis. Use a fast/cheap model.
127
+
128
+ | Agent | Role | Auto-Loads Skill | Triggered By |
129
+ |-------|------|-----------------|-------------|
130
+ | **@testing** | Writes tests, runs suite, reports coverage | `testing-strategies` | Build (always), Debug (always) |
131
+ | **@security** | OWASP audit, secrets scan, code-level fix patches | `security-hardening` | Build (always), Debug (if security-relevant) |
132
+ | **@fullstack** | Cross-layer implementation + feasibility analysis | Per-layer skills | Build (multi-layer features), Plan (analysis) |
133
+ | **@devops** | CI/CD validation, IaC review, deployment strategy | `deployment-automation` | Build (when CI/Docker/infra files change) |
134
+
135
+ Subagents return **structured reports** with severity levels (`BLOCKING`, `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`) that the orchestrating agent uses to decide whether to proceed or fix issues first.
136
+
137
+ ### Skill Routing
138
+
139
+ All agents detect the project's technology stack and **automatically load relevant skills** before working. This turns the 14 domain skills from passive knowledge into active intelligence:
124
140
 
125
- | Agent | Role |
126
- |-------|------|
127
- | **@fullstack** | End-to-end feature implementation across frontend + backend |
128
- | **@testing** | Test writing, coverage analysis, TDD workflow |
129
- | **@security** | Vulnerability scanning, secure coding review |
130
- | **@devops** | CI/CD pipelines, Docker, deployment automation |
141
+ ```
142
+ Build Agent detects: package.json has React + Express + Prisma
143
+ auto-loads: frontend-development, backend-development, database-design, api-design
144
+ implements with deep framework-specific knowledge
145
+ ```
131
146
 
132
147
  <br>
133
148
 
134
149
  ## Tools
135
150
 
136
- 22 tools bundled and auto-registered. No configuration needed.
151
+ 23 tools bundled and auto-registered. No configuration needed.
137
152
 
138
153
  <table>
139
154
  <tr><td width="50%">
140
155
 
141
156
  **Git Workflow**
142
157
  - `branch_status` - Current branch + change detection
143
- - `branch_create` - Convention-named branches
158
+ - `branch_create` - Convention-named branches (with toast notifications)
144
159
  - `branch_switch` - Safe branch switching
145
- - `worktree_create` - Isolated worktree in `.worktrees/`
160
+ - `worktree_create` - Isolated worktree in `.worktrees/` (with toast notifications)
146
161
  - `worktree_launch` - Launch worktree (terminal/PTY/background)
147
162
  - `worktree_list` / `worktree_remove` / `worktree_open`
148
163
 
@@ -151,7 +166,7 @@ Focused specialists. Invoked with `@mention`. Use a fast/cheap model.
151
166
  **Planning & Sessions**
152
167
  - `plan_save` / `plan_load` / `plan_list` / `plan_delete`
153
168
  - `session_save` / `session_list` / `session_load`
154
- - `cortex_init` / `cortex_status`
169
+ - `cortex_init` / `cortex_status` / `cortex_configure`
155
170
 
156
171
  </td></tr>
157
172
  <tr><td width="50%">
@@ -164,11 +179,12 @@ Focused specialists. Invoked with `@mention`. Use a fast/cheap model.
164
179
 
165
180
  </td><td width="50%">
166
181
 
167
- **Finalization**
182
+ **Finalization & Config**
168
183
  - `task_finalize` - Stage, commit, push, create PR
169
184
  - Auto-detects worktree (targets main)
170
185
  - Auto-populates PR from `.cortex/plans/`
171
186
  - Warns if docs are missing
187
+ - `cortex_configure` - Set models from within an agent session
172
188
 
173
189
  </td></tr>
174
190
  </table>
@@ -181,7 +197,6 @@ Focused specialists. Invoked with `@mention`. Use a fast/cheap model.
181
197
 
182
198
  | Skill | Covers |
183
199
  |-------|--------|
184
- | **web-development** | Full-stack patterns, REST/GraphQL, SSR, state management |
185
200
  | **frontend-development** | React, Vue, Svelte, CSS architecture, accessibility |
186
201
  | **backend-development** | API design, middleware, auth, caching, queue systems |
187
202
  | **mobile-development** | React Native, Flutter, native iOS/Android patterns |
@@ -201,10 +216,11 @@ Focused specialists. Invoked with `@mention`. Use a fast/cheap model.
201
216
 
202
217
  ## Model Configuration
203
218
 
204
- Cortex agents are **model-agnostic**. Pick any provider:
219
+ Cortex agents are **model-agnostic**. Configure globally or per-project:
205
220
 
206
221
  ```bash
207
- npx cortex-agents configure
222
+ npx cortex-agents configure # Global (all projects)
223
+ npx cortex-agents configure --project # Per-project (saves to .opencode/models.json)
208
224
  ```
209
225
 
210
226
  ```
@@ -223,6 +239,19 @@ npx cortex-agents configure
223
239
  Same as primary
224
240
  ```
225
241
 
242
+ ### In-Agent Configuration
243
+
244
+ Agents can also configure models during a session via the `cortex_configure` tool — no need to leave OpenCode. The agent will prompt you to select models when `.cortex/` is first initialized.
245
+
246
+ ### Per-Project vs Global
247
+
248
+ | Scope | Where | Use Case |
249
+ |-------|-------|----------|
250
+ | **Global** | `~/.config/opencode/opencode.json` | Default for all projects |
251
+ | **Per-project** | `.opencode/models.json` + `opencode.json` | Different models for different repos |
252
+
253
+ Per-project config takes priority. Team members get the same model settings when they clone the repo (`.opencode/models.json` is git-tracked).
254
+
226
255
  ### Supported Providers
227
256
 
228
257
  | Provider | Premium | Standard | Fast |
@@ -246,6 +275,8 @@ your-project/
246
275
  config.json Configuration
247
276
  plans/ Implementation plans (git tracked)
248
277
  sessions/ Session summaries (gitignored)
278
+ .opencode/
279
+ models.json Per-project model config (git tracked)
249
280
  .worktrees/ Git worktrees (gitignored)
250
281
  feature-auth/ Isolated development copy
251
282
  bugfix-login/
@@ -261,11 +292,13 @@ your-project/
261
292
  ## CLI Reference
262
293
 
263
294
  ```bash
264
- npx cortex-agents install # Install plugin, agents, and skills
265
- npx cortex-agents configure # Interactive model selection
266
- npx cortex-agents configure --reset # Reset to OpenCode defaults
267
- npx cortex-agents uninstall # Clean removal of everything
268
- npx cortex-agents status # Show installation status
295
+ npx cortex-agents install # Install plugin, agents, and skills
296
+ npx cortex-agents configure # Global model selection
297
+ npx cortex-agents configure --project # Per-project model selection
298
+ npx cortex-agents configure --reset # Reset global models
299
+ npx cortex-agents configure --project --reset # Reset per-project models
300
+ npx cortex-agents uninstall # Clean removal of everything
301
+ npx cortex-agents status # Show installation and model status
269
302
  ```
270
303
 
271
304
  <br>
@@ -278,20 +311,50 @@ Every time the build agent starts, it follows a structured pre-implementation ch
278
311
 
279
312
  ```
280
313
  Step 1 branch_status Am I on a protected branch?
281
- Step 2 cortex_status Is .cortex initialized?
314
+ Step 2 cortex_status Is .cortex initialized? Offer model config if new project.
282
315
  Step 3 plan_list / plan_load Is there a plan for this work?
283
- Step 4 Ask: strategy Branch or worktree?
284
- Step 4b Ask: launch mode Stay / terminal / PTY / background?
285
- Step 5 Execute Create branch or launch worktree
316
+ Step 4 Ask: strategy Worktree (recommended) or branch?
317
+ Step 4b Ask: launch mode Terminal tab (recommended) / stay / PTY / background?
318
+ Step 5 Execute Create worktree/branch, auto-detect terminal
286
319
  Step 6 Implement Write code following the plan
287
- Step 7 Ask: documentation Decision doc / feature doc / flow doc?
288
- Step 8 session_save Record what was done and why
289
- Step 9 task_finalize Commit, push, create PR
290
- Step 10 Ask: cleanup Remove worktree? (if applicable)
320
+ Step 7 Quality Gate Launch @testing + @security in parallel
321
+ Step 8 Ask: documentation Decision doc / feature doc / flow doc?
322
+ Step 9 session_save Record what was done and why
323
+ Step 10 task_finalize Commit, push, create PR
324
+ Step 11 Ask: cleanup Remove worktree + close terminal tab? (if applicable)
291
325
  ```
292
326
 
293
327
  This isn't just documentation - it's enforced by the agent's instructions. The AI follows this workflow every time.
294
328
 
329
+ ### Sub-Agent Quality Gates
330
+
331
+ After implementation (Step 7), the build agent **automatically** launches sub-agents in parallel as quality gates:
332
+
333
+ ```
334
+ Build Agent completes implementation
335
+ |
336
+ +-- launches in parallel (single message) --+
337
+ | |
338
+ v v
339
+ @testing @security
340
+ Writes unit tests OWASP audit
341
+ Runs test suite Secrets scan
342
+ Reports coverage Severity ratings
343
+ Returns: PASS/FAIL Returns: PASS/FAIL
344
+ | |
345
+ +-------- results reviewed by Build ---------+
346
+ |
347
+ v
348
+ Quality Gate Summary included in PR body
349
+ ```
350
+
351
+ The debug agent uses the same pattern: `@testing` for regression tests (always) and `@security` when the fix touches sensitive code.
352
+
353
+ Sub-agents use **structured return contracts** so results are actionable:
354
+ - `BLOCKING` / `CRITICAL` / `HIGH` findings block finalization
355
+ - `MEDIUM` findings are noted in the PR body
356
+ - `LOW` findings are deferred
357
+
295
358
  ### Agent Handover
296
359
 
297
360
  When agents switch, a toast notification tells you what mode you're in:
@@ -300,9 +363,10 @@ When agents switch, a toast notification tells you what mode you're in:
300
363
  Agent: build Development mode - ready to implement
301
364
  Agent: plan Planning mode - read-only analysis
302
365
  Agent: debug Debug mode - troubleshooting and fixes
366
+ Agent: review Review mode - code quality assessment
303
367
  ```
304
368
 
305
- The Plan agent creates plans with mermaid diagrams and hands off to Build. Build loads the plan and implements it. If something breaks, Debug takes over with full access.
369
+ The Plan agent creates plans with mermaid diagrams and hands off to Build. Build loads the plan, detects the tech stack, loads relevant skills, and implements. If something breaks, Debug takes over with performance debugging tools. Review provides code quality assessment and tech debt analysis on demand.
306
370
 
307
371
  <br>
308
372
 
@@ -346,7 +410,7 @@ cd ~/.config/opencode && npm unlink cortex-agents && npm install
346
410
 
347
411
  - **New skills** - Domain-specific knowledge packs (e.g., Rust, Go, DevOps for AWS)
348
412
  - **New agents** - Specialized agents (e.g., reviewer, migration, docs-writer)
349
- - **Platform support** - Improve terminal detection for Linux/Windows
413
+ - **Terminal drivers** - Improve detection/support for additional terminal emulators
350
414
  - **Tool improvements** - Better PR templates, test runners, linter integration
351
415
  - **Bug fixes** - Anything that doesn't work as expected
352
416
 
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import * as path from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import prompts from "prompts";
6
6
  import { PRIMARY_AGENTS, SUBAGENTS, ALL_AGENTS, getPrimaryChoices, getSubagentChoices, } from "./registry.js";
7
- const VERSION = "2.2.0";
7
+ const VERSION = "2.3.0";
8
8
  const PLUGIN_NAME = "cortex-agents";
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
@@ -38,6 +38,66 @@ function writeConfig(configPath, config) {
38
38
  fs.mkdirSync(path.dirname(configPath), { recursive: true });
39
39
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
40
40
  }
41
+ // ─── Per-Project Model Config (.opencode/models.json) ───────────────────────
42
+ const PROJECT_MODELS_FILE = "models.json";
43
+ function getProjectModelsPath() {
44
+ return path.join(process.cwd(), ".opencode", PROJECT_MODELS_FILE);
45
+ }
46
+ function hasProjectModelsConfig() {
47
+ return fs.existsSync(getProjectModelsPath());
48
+ }
49
+ function readProjectModels() {
50
+ const modelsPath = getProjectModelsPath();
51
+ if (!fs.existsSync(modelsPath))
52
+ return null;
53
+ try {
54
+ return JSON.parse(fs.readFileSync(modelsPath, "utf-8"));
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ function writeProjectModels(primary, subagent) {
61
+ const modelsPath = getProjectModelsPath();
62
+ const dir = path.dirname(modelsPath);
63
+ if (!fs.existsSync(dir)) {
64
+ fs.mkdirSync(dir, { recursive: true });
65
+ }
66
+ const config = {
67
+ primary: { model: primary },
68
+ subagent: { model: subagent },
69
+ agents: {},
70
+ };
71
+ for (const name of PRIMARY_AGENTS) {
72
+ config.agents[name] = { model: primary };
73
+ }
74
+ for (const name of SUBAGENTS) {
75
+ config.agents[name] = { model: subagent };
76
+ }
77
+ fs.writeFileSync(modelsPath, JSON.stringify(config, null, 2) + "\n");
78
+ }
79
+ /**
80
+ * Sync .opencode/models.json → local opencode.json agent model settings.
81
+ * Creates or merges into local opencode.json at project root.
82
+ */
83
+ function syncProjectModelsToConfig() {
84
+ const models = readProjectModels();
85
+ if (!models)
86
+ return false;
87
+ const localPath = path.join(process.cwd(), "opencode.json");
88
+ const config = fs.existsSync(localPath)
89
+ ? readConfig(localPath)
90
+ : { $schema: "https://opencode.ai/config.json" };
91
+ if (!config.agent)
92
+ config.agent = {};
93
+ for (const [name, entry] of Object.entries(models.agents)) {
94
+ if (!config.agent[name])
95
+ config.agent[name] = {};
96
+ config.agent[name].model = entry.model;
97
+ }
98
+ writeConfig(localPath, config);
99
+ return true;
100
+ }
41
101
  // ─── File Copy Helpers ───────────────────────────────────────────────────────
42
102
  function copyDirRecursive(src, dest) {
43
103
  fs.mkdirSync(dest, { recursive: true });
@@ -137,8 +197,16 @@ function install() {
137
197
  // Copy agents and skills into the global opencode config dir
138
198
  console.log("Installing agents and skills...");
139
199
  installAgentsAndSkills(globalDir);
200
+ // Sync per-project models if .opencode/models.json exists
201
+ if (hasProjectModelsConfig()) {
202
+ console.log("\nPer-project model config found (.opencode/models.json)");
203
+ if (syncProjectModelsToConfig()) {
204
+ console.log(" Synced model settings to local opencode.json");
205
+ }
206
+ }
140
207
  console.log("\nDone! Next steps:");
141
- console.log(` 1. Run 'npx ${PLUGIN_NAME} configure' to select your models`);
208
+ console.log(` 1. Run 'npx ${PLUGIN_NAME} configure' to select your models (global)`);
209
+ console.log(` Or 'npx ${PLUGIN_NAME} configure --project' for per-project config`);
142
210
  console.log(" 2. Restart OpenCode to load the plugin\n");
143
211
  }
144
212
  function uninstall() {
@@ -180,30 +248,89 @@ function uninstall() {
180
248
  async function configure() {
181
249
  const args = process.argv.slice(3);
182
250
  const isReset = args.includes("--reset");
251
+ const isProject = args.includes("--project");
183
252
  // Handle --reset flag
184
253
  if (isReset) {
185
- return configureReset();
254
+ return configureReset(isProject);
255
+ }
256
+ const scope = isProject ? "Per-Project" : "Global";
257
+ console.log(`\n🔧 Cortex Agents — ${scope} Model Configuration\n`);
258
+ if (isProject) {
259
+ const opencodeDir = path.join(process.cwd(), ".opencode");
260
+ if (!fs.existsSync(opencodeDir)) {
261
+ console.log(`⚠ No .opencode/ directory found in ${process.cwd()}.`);
262
+ console.log(` Run 'npx ${PLUGIN_NAME} install' first, or use 'configure' without --project for global config.\n`);
263
+ process.exit(1);
264
+ }
265
+ console.log(`Project: ${process.cwd()}`);
266
+ console.log(`Config: .opencode/models.json + opencode.json\n`);
186
267
  }
187
- console.log(`\n🔧 Cortex Agents Model Configuration\n`);
188
- // Ensure plugin is installed first
268
+ // Ensure plugin is installed first (for global mode)
189
269
  const configInfo = findOpencodeConfig();
190
270
  const config = configInfo
191
271
  ? readConfig(configInfo.path)
192
272
  : { $schema: "https://opencode.ai/config.json" };
193
- if (!config.plugin?.includes(PLUGIN_NAME)) {
273
+ if (!isProject && !config.plugin?.includes(PLUGIN_NAME)) {
194
274
  console.log(`⚠ Plugin not installed. Adding '${PLUGIN_NAME}' to config first.\n`);
195
275
  if (!config.plugin)
196
276
  config.plugin = [];
197
277
  config.plugin.push(PLUGIN_NAME);
198
278
  }
199
279
  // ── Primary model selection ────────────────────────────────
280
+ const { primary, subagent } = await promptModelSelection();
281
+ // ── Write config ───────────────────────────────────────────
282
+ if (isProject) {
283
+ // Per-project: write .opencode/models.json + sync to local opencode.json
284
+ writeProjectModels(primary, subagent);
285
+ syncProjectModelsToConfig();
286
+ const modelsPath = getProjectModelsPath();
287
+ const localConfigPath = path.join(process.cwd(), "opencode.json");
288
+ console.log("━".repeat(50));
289
+ console.log(`✓ Per-project config saved:\n`);
290
+ console.log(` Models: ${modelsPath}`);
291
+ console.log(` Runtime: ${localConfigPath}\n`);
292
+ }
293
+ else {
294
+ // Global: write to opencode.json (existing behavior)
295
+ if (!config.agent)
296
+ config.agent = {};
297
+ for (const name of PRIMARY_AGENTS) {
298
+ if (!config.agent[name])
299
+ config.agent[name] = {};
300
+ config.agent[name].model = primary;
301
+ }
302
+ for (const name of SUBAGENTS) {
303
+ if (!config.agent[name])
304
+ config.agent[name] = {};
305
+ config.agent[name].model = subagent;
306
+ }
307
+ const targetPath = configInfo?.path || path.join(getGlobalDir(), "opencode.json");
308
+ writeConfig(targetPath, config);
309
+ console.log("━".repeat(50));
310
+ console.log(`✓ Configuration saved to ${targetPath}\n`);
311
+ }
312
+ console.log(" Primary agents:");
313
+ for (const name of PRIMARY_AGENTS) {
314
+ console.log(` ${name.padEnd(10)} → ${primary}`);
315
+ }
316
+ console.log("\n Subagents:");
317
+ for (const name of SUBAGENTS) {
318
+ console.log(` ${name.padEnd(10)} → ${subagent}`);
319
+ }
320
+ console.log("\nRestart OpenCode to apply changes.\n");
321
+ }
322
+ /**
323
+ * Interactive prompt for primary + subagent model selection.
324
+ * Shared between global and per-project configure flows.
325
+ */
326
+ async function promptModelSelection() {
200
327
  const primaryChoices = getPrimaryChoices();
201
328
  primaryChoices.push({
202
329
  title: "Enter custom model ID",
203
330
  description: "provider/model format",
204
331
  value: "__custom__",
205
332
  });
206
- console.log("Primary agents (build, plan, debug) handle complex tasks.\nUse your best available model.\n");
333
+ console.log("Primary agents (build, plan, debug, review) handle complex tasks.\nUse your best available model.\n");
207
334
  const { primaryModel } = await prompts({
208
335
  type: "select",
209
336
  name: "primaryModel",
@@ -211,7 +338,6 @@ async function configure() {
211
338
  choices: primaryChoices,
212
339
  hint: "Use arrow keys, Enter to confirm",
213
340
  });
214
- // User cancelled (Ctrl+C)
215
341
  if (primaryModel === undefined) {
216
342
  console.log("\nConfiguration cancelled.\n");
217
343
  process.exit(0);
@@ -265,36 +391,54 @@ async function configure() {
265
391
  subagent = custom;
266
392
  }
267
393
  console.log(`✓ Subagent model: ${subagent}\n`);
268
- // ── Write to opencode.json ─────────────────────────────────
269
- if (!config.agent)
270
- config.agent = {};
271
- for (const name of PRIMARY_AGENTS) {
272
- if (!config.agent[name])
273
- config.agent[name] = {};
274
- config.agent[name].model = primary;
275
- }
276
- for (const name of SUBAGENTS) {
277
- if (!config.agent[name])
278
- config.agent[name] = {};
279
- config.agent[name].model = subagent;
280
- }
281
- const targetPath = configInfo?.path || path.join(getGlobalDir(), "opencode.json");
282
- writeConfig(targetPath, config);
283
- // ── Print summary ──────────────────────────────────────────
284
- console.log("━".repeat(50));
285
- console.log(`✓ Configuration saved to ${targetPath}\n`);
286
- console.log(" Primary agents:");
287
- for (const name of PRIMARY_AGENTS) {
288
- console.log(` ${name.padEnd(10)} → ${primary}`);
289
- }
290
- console.log("\n Subagents:");
291
- for (const name of SUBAGENTS) {
292
- console.log(` ${name.padEnd(10)} → ${subagent}`);
293
- }
294
- console.log("\nRestart OpenCode to apply changes.\n");
394
+ return { primary, subagent };
295
395
  }
296
- function configureReset() {
297
- console.log(`\n🔧 Cortex Agents Reset Model Configuration\n`);
396
+ function configureReset(isProject = false) {
397
+ const scope = isProject ? "Per-Project" : "Global";
398
+ console.log(`\n🔧 Cortex Agents — Reset ${scope} Model Configuration\n`);
399
+ if (isProject) {
400
+ // Reset per-project config
401
+ const modelsPath = getProjectModelsPath();
402
+ let removedModels = false;
403
+ if (fs.existsSync(modelsPath)) {
404
+ fs.unlinkSync(modelsPath);
405
+ console.log(`✓ Removed ${modelsPath}`);
406
+ removedModels = true;
407
+ }
408
+ // Also clean agent models from local opencode.json
409
+ const localConfigPath = path.join(process.cwd(), "opencode.json");
410
+ if (fs.existsSync(localConfigPath)) {
411
+ const config = readConfig(localConfigPath);
412
+ if (config.agent) {
413
+ let resetCount = 0;
414
+ for (const name of ALL_AGENTS) {
415
+ if (config.agent[name]?.model) {
416
+ delete config.agent[name].model;
417
+ resetCount++;
418
+ if (Object.keys(config.agent[name]).length === 0) {
419
+ delete config.agent[name];
420
+ }
421
+ }
422
+ }
423
+ if (Object.keys(config.agent).length === 0) {
424
+ delete config.agent;
425
+ }
426
+ if (resetCount > 0) {
427
+ writeConfig(localConfigPath, config);
428
+ console.log(`✓ Removed ${resetCount} agent model entries from ${localConfigPath}`);
429
+ removedModels = true;
430
+ }
431
+ }
432
+ }
433
+ if (!removedModels) {
434
+ console.log("No per-project model configuration found. Nothing to reset.\n");
435
+ return;
436
+ }
437
+ console.log("\nAgents will now fall back to global or OpenCode default models.");
438
+ console.log("Restart OpenCode to apply changes.\n");
439
+ return;
440
+ }
441
+ // Global reset (existing behavior)
298
442
  const configInfo = findOpencodeConfig();
299
443
  if (!configInfo) {
300
444
  console.log("No OpenCode config found. Nothing to reset.\n");
@@ -355,12 +499,20 @@ function status() {
355
499
  : 0;
356
500
  console.log(`\nAgents installed: ${agentCount}`);
357
501
  console.log(`Skills installed: ${skillCount}`);
358
- // Show model configuration
502
+ // Show per-project model configuration
503
+ const projectModels = readProjectModels();
504
+ if (projectModels) {
505
+ console.log("\nPer-Project Models (.opencode/models.json):");
506
+ console.log(` Primary agents: ${projectModels.primary.model}`);
507
+ console.log(` Subagents: ${projectModels.subagent.model}`);
508
+ }
509
+ // Show global/active model configuration
359
510
  if (config.agent) {
360
511
  const primaryModels = PRIMARY_AGENTS.map((n) => config.agent?.[n]?.model).filter(Boolean);
361
512
  const subagentModels = SUBAGENTS.map((n) => config.agent?.[n]?.model).filter(Boolean);
362
513
  if (primaryModels.length > 0 || subagentModels.length > 0) {
363
- console.log("\nModel Configuration:");
514
+ const source = projectModels ? "Active" : "Global";
515
+ console.log(`\n${source} Model Configuration (opencode.json):`);
364
516
  if (primaryModels.length > 0) {
365
517
  const unique = [...new Set(primaryModels)];
366
518
  console.log(` Primary agents: ${unique.join(", ")}`);
@@ -370,14 +522,16 @@ function status() {
370
522
  console.log(` Subagents: ${unique.join(", ")}`);
371
523
  }
372
524
  }
373
- else {
525
+ else if (!projectModels) {
374
526
  console.log("\nModels: Not configured (using OpenCode defaults)");
375
- console.log(` Run 'npx ${PLUGIN_NAME} configure' to select models.`);
527
+ console.log(` Run 'npx ${PLUGIN_NAME} configure' for global config`);
528
+ console.log(` Run 'npx ${PLUGIN_NAME} configure --project' for per-project config`);
376
529
  }
377
530
  }
378
- else {
531
+ else if (!projectModels) {
379
532
  console.log("\nModels: Not configured (using OpenCode defaults)");
380
- console.log(` Run 'npx ${PLUGIN_NAME} configure' to select models.`);
533
+ console.log(` Run 'npx ${PLUGIN_NAME} configure' for global config`);
534
+ console.log(` Run 'npx ${PLUGIN_NAME} configure --project' for per-project config`);
381
535
  }
382
536
  if (!isInstalled) {
383
537
  console.log(`\nRun 'npx ${PLUGIN_NAME} install' to add to config.`);
@@ -395,27 +549,32 @@ USAGE:
395
549
 
396
550
  COMMANDS:
397
551
  install Install plugin, agents, and skills into OpenCode config
398
- configure Interactive model selection for all agents
552
+ configure Interactive model selection (global)
553
+ configure --project Interactive model selection (per-project, saves to .opencode/)
399
554
  configure --reset Reset model configuration to OpenCode defaults
555
+ configure --project --reset Reset per-project model configuration
400
556
  uninstall Remove plugin, agents, skills, and model config
401
557
  status Show installation and model configuration status
402
558
  help Show this help message
403
559
 
404
560
  EXAMPLES:
405
- npx ${PLUGIN_NAME} install # Install plugin
406
- npx ${PLUGIN_NAME} configure # Select models interactively
407
- npx ${PLUGIN_NAME} configure --reset # Reset to default models
408
- npx ${PLUGIN_NAME} status # Check status
561
+ npx ${PLUGIN_NAME} install # Install plugin
562
+ npx ${PLUGIN_NAME} configure # Global model selection
563
+ npx ${PLUGIN_NAME} configure --project # Per-project models (.opencode/models.json)
564
+ npx ${PLUGIN_NAME} configure --reset # Reset global models
565
+ npx ${PLUGIN_NAME} configure --project --reset # Reset per-project models
566
+ npx ${PLUGIN_NAME} status # Check status
409
567
 
410
568
  AGENTS:
411
- Primary (build, plan, debug):
569
+ Primary (build, plan, debug, review):
412
570
  Handle complex tasks — select your best model.
413
571
 
414
572
  Subagents (fullstack, testing, security, devops):
415
573
  Handle focused tasks — a fast/cheap model works great.
416
574
 
417
- TOOLS (22):
575
+ TOOLS (23):
418
576
  cortex_init, cortex_status .cortex directory management
577
+ cortex_configure Per-project model configuration
419
578
  worktree_create, worktree_list Git worktree management
420
579
  worktree_remove, worktree_open
421
580
  worktree_launch Launch worktree (terminal/PTY/background)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAsBlD,eAAO,MAAM,YAAY,EAAE,MAmE1B,CAAC;AAGF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmJlD,eAAO,MAAM,YAAY,EAAE,MAuJ1B,CAAC;AAGF,eAAe,YAAY,CAAC"}