opencode-onboard 0.4.14 → 0.5.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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **One command to prepare any codebase for AI agent workflows in OpenCode.**
8
8
 
9
- Works with [OpenCode](https://opencode.ai), [OpenCode Ensemble](https://github.com/hueyexe/opencode-ensemble), [OpenSpec](https://github.com/fission-ai/openspec), GitHub, Azure DevOps, or no tracker/PR platform at all.
9
+ Works with [OpenCode](https://opencode.ai), [OpenCode Ensemble](https://github.com/hueyexe/opencode-ensemble), [OpenSpec](https://github.com/fission-ai/openspec), GitHub, Azure DevOps, or no tracker/PR platform at all.
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/opencode-onboard?style=flat-square&color=black)](https://www.npmjs.com/package/opencode-onboard)
12
12
  [![npm downloads](https://img.shields.io/npm/dm/opencode-onboard?style=flat-square&color=black)](https://www.npmjs.com/package/opencode-onboard)
@@ -74,8 +74,8 @@ The CLI runs a 10-step onboarding wizard. It keeps the current step visible, plu
74
74
  | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
75
75
  | **1. Source scope** | Choose current repo or sibling source roots for code analysis |
76
76
  | **2. Clean AI files** | Detects existing `AGENTS.md`, `.cursorrules`, `CLAUDE.md`, `.agents/` etc. and removes them, preserves your `.agents/skills/` |
77
- | **3. Choose platform** | GitHub, Azure DevOps, or None |
78
- | **4. Check platform CLI** | Verifies `gh` (GitHub) or `az` + `azure-devops` (Azure DevOps), or skips checks when platform is None |
77
+ | **3. Choose platform** | GitHub, Azure DevOps, or None |
78
+ | **4. Check platform CLI** | Verifies `gh` (GitHub) or `az` + `azure-devops` (Azure DevOps), or skips checks when platform is None |
79
79
  | **5. Copy scaffolding** | Copies agents + built-in skills + bootstrap docs, writes source-roots metadata, applies AGENTS bootstrap patching, copies `skills-lock.json`, then runs `npx skills` |
80
80
  | **6. Init OpenSpec** | Runs `npx @fission-ai/openspec init` silently for structured change management |
81
81
  | **7. Choose models** | Fetches live model list from [models.dev](https://models.dev), lets you pick plan / build / fast models with cost indicators and canonical pricing |
@@ -100,7 +100,7 @@ Custom slash commands are installed into `.opencode/commands/` and are available
100
100
  | Command | Description |
101
101
  | -------------- | ----------------------------------------------------------------------------------------------------- |
102
102
  | `/ob-init` | Initialize the project. Asks greenfield vs brownfield, then activates the agent team. Supports skipping doc generation for new projects. |
103
- | `/ob-plan <url>` | Parse a user story URL and produce a plan, proposal, specs, and tasks. Stops before implementation. Use platform mode, not `None`. |
103
+ | `/ob-plan <url>` | Parse a user story URL and produce a plan, proposal, specs, and tasks. Stops before implementation. Use platform mode, not `None`. |
104
104
  | `/ob-main <task>` | Quick direct implementation, no OpenSpec, no ensemble, no PRs. Just do it. |
105
105
  | `/ob-create-engineer <name> "<description>"` | Create a custom engineer agent from a description, with skills auto-installed from [skills.sh](https://www.skills.sh/) |
106
106
  | `/ob-create-architecture` | Generate or regenerate `ARCHITECTURE.md` from the codebase. Safe to rerun any time the architecture changes. |
@@ -123,14 +123,14 @@ devops-manager lead/orchestrator, planning, PR lifecycle
123
123
  basic-engineer implementation worker, ability-driven
124
124
  ```
125
125
 
126
- `basic-engineer` behavior is composed by abilities, not hardcoded role silos.
127
- Project-specific specialization comes from user-created custom engineers via `/ob-create-engineer`. During `/opsx-apply`, the lead should inspect the engineers that actually exist in `.opencode/agents/`, prefer matching custom engineers, and fall back to `basic-engineer` only when no specialist is a clear fit.
126
+ `basic-engineer` behavior is composed by abilities, not hardcoded role silos.
127
+ Project-specific specialization comes from user-created custom engineers via `/ob-create-engineer`. During `/opsx-apply`, the lead should inspect the engineers that actually exist in `.opencode/agents/`, prefer matching custom engineers, and fall back to `basic-engineer` only when no specialist is a clear fit.
128
128
 
129
- ### Skills, platform knowledge
130
-
131
- Skills define _what to know_. They provide project rules, platform behavior, and task-specific execution guidance. Agents auto-detect/load relevant skills; **you do not manually choose skills per prompt**.
132
-
133
- If you choose platform `None` during onboarding, no userstory or pull-request platform skills are injected into the workflow. The project works from direct conversation, local repo context, and optional OpenSpec artifacts only.
129
+ ### Skills, platform knowledge
130
+
131
+ Skills define _what to know_. They provide project rules, platform behavior, and task-specific execution guidance. Agents auto-detect/load relevant skills; **you do not manually choose skills per prompt**.
132
+
133
+ If you choose platform `None` during onboarding, no userstory or pull-request platform skills are injected into the workflow. The project works from direct conversation, local repo context, and optional OpenSpec artifacts only.
134
134
 
135
135
  Current loading model:
136
136
 
@@ -179,7 +179,7 @@ Models are fetched live from [models.dev](https://models.dev) (3000+ models, cac
179
179
 
180
180
  ## The pipeline
181
181
 
182
- When you give the lead agent a work item URL, execution follows this pipeline. If onboarding platform is `None`, skip the work item / PR stages and work directly from conversation plus optional OpenSpec artifacts:
182
+ When you give the lead agent a work item URL, execution follows this pipeline. If onboarding platform is `None`, skip the work item / PR stages and work directly from conversation plus optional OpenSpec artifacts:
183
183
 
184
184
  ```
185
185
  devops-manager (load ob-global first)
@@ -218,7 +218,7 @@ Each agent runs in its own isolated git worktree via [OpenCode Ensemble](https:/
218
218
 
219
219
  ```
220
220
  your-project/
221
- ├── AGENTS.md ← bootstrap mode, replaced after first "init"
221
+ ├── AGENTS.md ← bootstrap mode, replaced after first "/ob-init"
222
222
  ├── ARCHITECTURE.md ← prompt for agents to fill in from your codebase
223
223
  ├── DESIGN.md ← prompt for agents to fill in from your codebase
224
224
  ├── .opencode/
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Basic Engineer Agent.
3
3
  mode: primary
4
- color: #68A063
4
+ color: success
5
5
  permission:
6
6
  edit: allow
7
7
  bash: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Process agent. Reads work items and user stories at pipeline start. Creates PRs, posts screenshots, responds to review comments at pipeline end. Bridges the work tracker and the repository. Platform knowledge comes from skills.
3
- mode: primary
4
- color: #690a69
3
+ mode: subagent
4
+ color: primary
5
5
  permission:
6
6
  edit: allow
7
7
  bash: allow
@@ -46,7 +46,7 @@ Example: `/ob-create-engineer frontend-engineer "A frontend engineer specialized
46
46
  ---
47
47
  description: <description>
48
48
  mode: primary
49
- color: <pick a unique hex color>
49
+ color: <pick a theme color: primary|secondary|accent|success|warning|error|info>
50
50
  permission:
51
51
  edit: allow
52
52
  bash: allow
@@ -1,5 +1,8 @@
1
1
  {
2
2
  "dependencies": {
3
- "@opencode-ai/plugin": "1.14.19"
3
+ "@opencode-ai/plugin": "latest",
4
+ "opencode-plugin-openspec": "latest",
5
+ "@different-ai/opencode-browser": "latest",
6
+ "@hueyexe/opencode-ensemble": "latest"
4
7
  }
5
- }
8
+ }
package/content/AGENTS.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Trigger
8
8
 
9
- When the user says anything resembling initialization, "init", "initialize", "setup", "start", "bootstrap", "get started", "prepare", execute the steps below. Follow the greenfield/brownfield branching exactly.
9
+ When the user says anything resembling initialization, "/ob-init", "initialize", "setup", "start", "bootstrap", "get started", "prepare", execute the steps below. Follow the greenfield/brownfield branching exactly.
10
10
 
11
11
  ---
12
12
 
@@ -91,13 +91,27 @@ Replace every `<…>` with real values. Add a `rules:` section only if the codeb
91
91
 
92
92
  ---
93
93
 
94
- ### Step 6, Rewrite this file
94
+ ### Step 6, Install OpenCode plugins
95
+
96
+ OpenCode plugins declared in `.opencode/opencode.json` (under the `plugin` key) must be present in `.opencode/node_modules/` or OpenCode will fail to load them. The plugins are also listed in `.opencode/package.json` as dependencies.
97
+
98
+ ```bash
99
+ cd .opencode
100
+ npm install
101
+ cd ..
102
+ ```
103
+
104
+ This installs all plugin packages into `.opencode/node_modules/`. If you ever see "Plugin X not found" errors after init, run `npm install` in `.opencode/` again.
105
+
106
+ ---
107
+
108
+ ### Step 7, Rewrite this file
95
109
 
96
110
  Replace the entire contents of this file (`AGENTS.md`) with everything below the line `<!-- AGENTS-TEMPLATE-START -->` in this same file. Delete the bootstrap section and the template marker, the file should contain only the template content when done.
97
111
 
98
112
  ---
99
113
 
100
- ### Step 7, Confirm
114
+ ### Step 8, Confirm
101
115
 
102
116
  For **brownfield**, tell the user:
103
117
 
@@ -110,6 +124,7 @@ For **brownfield**, tell the user:
110
124
  - DESIGN.md generated
111
125
  - openspec/config.yaml populated
112
126
  - Project history archived in openspec
127
+ - OpenCode plugins installed
113
128
  - AGENTS.md updated with real guidance
114
129
 
115
130
  !! RESTART OPENCODE NOW !!
@@ -127,6 +142,7 @@ For **greenfield**, tell the user:
127
142
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
128
143
 
129
144
  - openspec/config.yaml populated
145
+ - OpenCode plugins installed
130
146
  - AGENTS.md updated with real guidance
131
147
  - ARCHITECTURE.md and DESIGN.md left as placeholders
132
148
 
@@ -150,6 +166,7 @@ After restarting you are ready to work.
150
166
  - Do NOT modify any project source files
151
167
  - Do NOT create CLI wrapper files or scripts
152
168
  - Only read source files for analysis, write only to ARCHITECTURE.md, DESIGN.md, AGENTS.md, openspec/config.yaml, and openspec/
169
+ - `npm install` (step 6) is allowed to modify `.opencode/package-lock.json` and `.opencode/node_modules/`
153
170
 
154
171
  <!-- AGENTS-TEMPLATE-START -->
155
172
  # AGENTS.md
@@ -174,10 +191,10 @@ Source scope is defined by mandatory `ob-global` skill.
174
191
  - Follow the generated `## Source Roots` section from that skill.
175
192
  - Do not duplicate source-scope rules here.
176
193
 
177
- ## I Am the Lead, Full Workflow Ownership
178
-
179
- <!-- OB-PLATFORM-WORKFLOW-START -->
180
- When the user provides a work item URL or says "implement the plan" or "I've added comments to the PR", **I own the full lifecycle**. I load `ob-global` skill first, then the appropriate userstory skill, and use ensemble tools to coordinate the agent team.
194
+ ## I Am the Lead, Full Workflow Ownership
195
+
196
+ <!-- OB-PLATFORM-WORKFLOW-START -->
197
+ When the user provides a work item URL or says "implement the plan" or "I've added comments to the PR", **I own the full lifecycle**. I load `ob-global` skill first, then the appropriate userstory skill, and use ensemble tools to coordinate the agent team.
181
198
 
182
199
  Trigger patterns, I recognize ALL of these, exact wording does not matter:
183
200
  - User pastes or mentions a GitHub Issue URL → load `ob-userstory-gh` skill → parse issue → run `/opsx-propose` → confirm with user → run `/opsx-apply` → ship
@@ -186,20 +203,20 @@ Trigger patterns, I recognize ALL of these, exact wording does not matter:
186
203
  - `I've added comments to the PR` → read PR comments → fix → update PR
187
204
  - Any GitHub/Azure DevOps PR URL in a feedback/fix request (e.g. "check comments", "fix PR feedback") → run PR Feedback Loop
188
205
 
189
- **A GitHub or Azure DevOps URL anywhere in the user's message is always a trigger, regardless of surrounding words.**
190
- <!-- OB-PLATFORM-WORKFLOW-END -->
191
-
192
- **Never delegate without a plan. Default to specialists for implementation. If ensemble is clearly non-functional in the current session (idle teammate, no claim, or repeated spawn failure after one retry), stop forcing it: report the failure, then continue in the main session or ask the user whether to retry later.**
193
-
194
- ## Engineer Selection
195
-
196
- Before spawning implementation workers:
197
- - Inspect `.opencode/agents/*.md` and build the list of engineers that actually exist in this project.
198
- - Exclude `devops-manager` from implementation selection.
199
- - Prefer the most specialized custom engineer whose description and abilities clearly match the task domain.
200
- - Use `basic-engineer` only when no custom engineer is a clear fit or as a recovery fallback.
201
- - Never spawn engineer names that are not present in `.opencode/agents/`.
202
- - When multiple engineers could fit, choose the narrower specialist before the generalist.
206
+ **A GitHub or Azure DevOps URL anywhere in the user's message is always a trigger, regardless of surrounding words.**
207
+ <!-- OB-PLATFORM-WORKFLOW-END -->
208
+
209
+ **Never delegate without a plan. Default to specialists for implementation. If ensemble is clearly non-functional in the current session (idle teammate, no claim, or repeated spawn failure after one retry), stop forcing it: report the failure, then continue in the main session or ask the user whether to retry later.**
210
+
211
+ ## Engineer Selection
212
+
213
+ Before spawning implementation workers:
214
+ - Inspect `.opencode/agents/*.md` and build the list of engineers that actually exist in this project.
215
+ - Exclude `devops-manager` from implementation selection.
216
+ - Prefer the most specialized custom engineer whose description and abilities clearly match the task domain.
217
+ - Use `basic-engineer` only when no custom engineer is a clear fit or as a recovery fallback.
218
+ - Never spawn engineer names that are not present in `.opencode/agents/`.
219
+ - When multiple engineers could fit, choose the narrower specialist before the generalist.
203
220
 
204
221
  ## Multi-Agent Execution, opencode-ensemble
205
222
 
@@ -218,10 +235,10 @@ Core tools used in this workflow:
218
235
  - **Max {{MAX_CONCURRENT_AGENTS}} truly concurrent agents.** All {{MAX_CONCURRENT_AGENTS}} must be spawned and running simultaneously, not sequentially. Spawn in waves if more than {{MAX_CONCURRENT_AGENTS}} are needed. Wait for wave N to finish before spawning wave N+1.
219
236
  - **Non-overlapping file domains.** Each agent owns exclusive directories. Two agents must NEVER touch the same file.
220
237
  - **Immediate shutdown on completion.** The moment an agent's domain has no more pending tasks → `team_shutdown` → `team_merge`. Keep agents alive if more tasks in their domain are pending (rolling batch).
221
- - **Rolling batch assignment.** Agents receive up to 3 tasks initially. When they complete a batch, lead assigns the next batch of up to 3 from the board. Never leave pending tasks orphaned.
222
- - **Stall detection at 5 minutes.** No commits after 5 min → nudge message → 2 min grace → force shutdown + respawn.
223
- - **Idle-without-claim is an earlier stall.** If a spawned teammate sits idle with no claimed task after a short wait, resend one short claim-only message with the exact task IDs. If still idle, force shutdown + respawn once with a shorter prompt. If the retry repeats the same failure, treat ensemble as unavailable for that session and stop recycling equivalent workers.
224
- - **Retry limit.** Max 3 retries per failing task → stop-and-report to user. Never retry indefinitely.
238
+ - **Rolling batch assignment.** Agents receive up to 3 tasks initially. When they complete a batch, lead assigns the next batch of up to 3 from the board. Never leave pending tasks orphaned.
239
+ - **Stall detection at 5 minutes.** No commits after 5 min → nudge message → 2 min grace → force shutdown + respawn.
240
+ - **Idle-without-claim is an earlier stall.** If a spawned teammate sits idle with no claimed task after a short wait, resend one short claim-only message with the exact task IDs. If still idle, force shutdown + respawn once with a shorter prompt. If the retry repeats the same failure, treat ensemble as unavailable for that session and stop recycling equivalent workers.
241
+ - **Retry limit.** Max 3 retries per failing task → stop-and-report to user. Never retry indefinitely.
225
242
 
226
243
  **Progress inspection commands (tell user explicitly after spawning):**
227
244
  - `team_status` for live team snapshot
@@ -236,12 +253,12 @@ If a teammate stalls due to model quota/rate-limit exhaustion:
236
253
 
237
254
  ---
238
255
 
239
- ## Pipeline
240
-
241
- <!-- OB-PLATFORM-PIPELINE-START -->
242
- ```
243
- devops-manager (lead mode)
244
- → load ob-global + parse work item via skill
256
+ ## Pipeline
257
+
258
+ <!-- OB-PLATFORM-PIPELINE-START -->
259
+ ```
260
+ devops-manager (lead mode)
261
+ → load ob-global + parse work item via skill
245
262
 
246
263
  openspec-propose
247
264
  → proposal.md + specs + tasks
@@ -269,11 +286,11 @@ devops-manager (ship mode)
269
286
 
270
287
  ```
271
288
  0. Run /quota to check remaining budget before spawning.
272
- 1. Run /opsx-apply.
273
- - Step 5b: classify cost tier, announce scope, ask user to confirm if ≥4 tasks.
274
- - Lead adds all tasks to board.
275
- - When dependencies exist, lead uses multiple `team_tasks_add` waves so later tasks can reference real task IDs returned by earlier waves.
276
- - Lead discovers available engineers from `.opencode/agents/*.md`, prefers matching custom engineers, then spawns engineers with initial batch of up to 3 tasks each (rolling batch model).
289
+ 1. Run /opsx-apply.
290
+ - Step 5b: classify cost tier, announce scope, ask user to confirm if ≥4 tasks.
291
+ - Lead adds all tasks to board.
292
+ - When dependencies exist, lead uses multiple `team_tasks_add` waves so later tasks can reference real task IDs returned by earlier waves.
293
+ - Lead discovers available engineers from `.opencode/agents/*.md`, prefers matching custom engineers, then spawns engineers with initial batch of up to 3 tasks each (rolling batch model).
277
294
  - Each engineer claims tasks, implements, completes, messages lead.
278
295
  - Lead assigns next batch (up to 3) to agents that report done. Repeat until board empty.
279
296
  - Lead merges each engineer branch after shutdown, then marks tasks done in tasks.md.
@@ -306,10 +323,10 @@ When user says "I've added comments to the PR" or asks to fix PR comments from P
306
323
  6. Wait for engineer results → team_shutdown + team_merge per engineer
307
324
  7. Run verification tasks (tests/build/lint) and fix blockers if any
308
325
  8. team_spawn devops-manager (ship mode) with "push + update PR threads" task ID + team_message "Start now"
309
- 9. Wait → team_results → report what was updated
310
- 10. team_cleanup
311
- ```
312
- <!-- OB-PLATFORM-PIPELINE-END -->
326
+ 9. Wait → team_results → report what was updated
327
+ 10. team_cleanup
328
+ ```
329
+ <!-- OB-PLATFORM-PIPELINE-END -->
313
330
 
314
331
  ---
315
332
 
@@ -322,7 +339,7 @@ All agents are universal, no project-specific knowledge. Platform and tech knowl
322
339
  | `devops-manager` | .opencode/agents/devops-manager.md | Reads work items, creates PRs, handles review feedback |
323
340
  | `basic-engineer` | .opencode/agents/basic-engineer.md | Generic implementation worker using ability-loaded skills |
324
341
 
325
- User can add more custom engineer agents and run them in parallel. Keep behavior ability-driven via skill mappings. Custom engineers are the primary specialization mechanism; `basic-engineer` is the general fallback when no custom engineer is a clear fit.
342
+ User can add more custom engineer agents and run them in parallel. Keep behavior ability-driven via skill mappings. Custom engineers are the primary specialization mechanism; `basic-engineer` is the general fallback when no custom engineer is a clear fit.
326
343
 
327
344
  Default `basic-engineer` abilities:
328
345
 
@@ -336,7 +353,7 @@ Default `basic-engineer` abilities:
336
353
 
337
354
  ## Skills
338
355
 
339
- Skills provide platform and tech-specific knowledge. Agents usually detect and load them automatically. Prefer auto-detection, but explicitly naming a skill in a spawn prompt is allowed when a workflow requires it or repeated misses show the agent is not loading the right context.
356
+ Skills provide platform and tech-specific knowledge. Agents usually detect and load them automatically. Prefer auto-detection, but explicitly naming a skill in a spawn prompt is allowed when a workflow requires it or repeated misses show the agent is not loading the right context.
340
357
 
341
358
  `ob-global` is always loaded first, it provides baseline rules for all agents.
342
359
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opencode-onboard",
3
- "version": "0.4.14",
4
- "description": "Prepare any brownfield codebase for AI agent workflows using OpenCode, OpenSpec, and ensemble orchestration.",
3
+ "version": "0.5.0",
4
+ "description": "Prepare any codebase for AI agent workflows using OpenCode, OpenSpec, and ensemble orchestration.",
5
5
  "keywords": [
6
6
  "opencode",
7
7
  "ai",
@@ -111,7 +111,7 @@ export async function runWizard(version) {
111
111
  console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
112
112
  console.log()
113
113
  console.log(' Open this project in OpenCode and type:')
114
- console.log(chalk.bold(' "init"'))
114
+ console.log(chalk.bold(' "/ob-init"'))
115
115
  console.log()
116
116
  if (toGenerate.length > 0) {
117
117
  console.log(` OpenCode will generate ${toGenerate.join(' and ')}`)
@@ -1,6 +1,6 @@
1
1
  import { execa } from "execa"
2
2
  import path from "node:path"
3
- import { commandExists, error, header, info, loading, success, warn} from "../../utils/exec.js"
3
+ import { commandExists, error, header, info, loading, success, warn } from "../../utils/exec.js"
4
4
  import { APPLY_TARGETS, patchApplyFile } from "./ensemble.js"
5
5
 
6
6
  export const openspecSteps = {
@@ -58,7 +58,7 @@ async function install() {
58
58
  success("OpenSpec installed")
59
59
  } catch (err) {
60
60
  error(`Failed to run openspec install: ${err.message}`)
61
- }
61
+ }
62
62
  }
63
63
 
64
64
  async function check() {
@@ -77,7 +77,7 @@ async function init() {
77
77
  try {
78
78
  const result = await execa(
79
79
  "npx",
80
- ["@fission-ai/openspec", "init", "--tools", "opencode", "--force"],
80
+ ["@fission-ai/openspec", "/ob-init", "--tools", "opencode", "--force"],
81
81
  {
82
82
  cwd: process.cwd(),
83
83
  stdio: "pipe",
@@ -44,6 +44,7 @@ export async function installQuota(options = {}) {
44
44
  try {
45
45
  const opencodeDir = path.join(process.cwd(), '.opencode')
46
46
  const opencodePath = path.join(opencodeDir, 'opencode.json')
47
+ const pkgPath = path.join(opencodeDir, 'package.json')
47
48
  const tuiPath = path.join(opencodeDir, 'tui.json')
48
49
  const quotaDir = path.join(opencodeDir, 'opencode-quota')
49
50
  const quotaPath = path.join(quotaDir, 'quota-toast.json')
@@ -52,6 +53,10 @@ export async function installQuota(options = {}) {
52
53
  ? await fse.readJson(opencodePath)
53
54
  : { $schema: 'https://opencode.ai/config.json' }
54
55
 
56
+ const pkg = await fse.pathExists(pkgPath)
57
+ ? await fse.readJson(pkgPath)
58
+ : {}
59
+
55
60
  const tui = await fse.pathExists(tuiPath)
56
61
  ? await fse.readJson(tuiPath)
57
62
  : { $schema: 'https://opencode.ai/tui.json' }
@@ -59,8 +64,15 @@ export async function installQuota(options = {}) {
59
64
  ensurePlugin(opencode)
60
65
  ensurePlugin(tui)
61
66
 
67
+ if (!pkg.dependencies) pkg.dependencies = {}
68
+ const pkgName = PLUGIN.replace(/@latest$/, '')
69
+ if (!(pkgName in pkg.dependencies)) {
70
+ pkg.dependencies[pkgName] = 'latest'
71
+ }
72
+
62
73
  await fse.ensureDir(opencodeDir)
63
74
  await fse.writeJson(opencodePath, opencode, { spaces: 2 })
75
+ await fse.writeJson(pkgPath, pkg, { spaces: 2 })
64
76
  await fse.writeJson(tuiPath, tui, { spaces: 2 })
65
77
 
66
78
  const quotaConfig = await fse.pathExists(quotaPath)
@@ -1,378 +0,0 @@
1
- {
2
- "name": ".opencode",
3
- "lockfileVersion": 3,
4
- "requires": true,
5
- "packages": {
6
- "": {
7
- "dependencies": {
8
- "@opencode-ai/plugin": "1.14.19"
9
- }
10
- },
11
- "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
12
- "version": "3.0.3",
13
- "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
14
- "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
15
- "cpu": [
16
- "arm64"
17
- ],
18
- "license": "MIT",
19
- "optional": true,
20
- "os": [
21
- "darwin"
22
- ]
23
- },
24
- "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
25
- "version": "3.0.3",
26
- "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
27
- "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
28
- "cpu": [
29
- "x64"
30
- ],
31
- "license": "MIT",
32
- "optional": true,
33
- "os": [
34
- "darwin"
35
- ]
36
- },
37
- "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
38
- "version": "3.0.3",
39
- "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
40
- "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
41
- "cpu": [
42
- "arm"
43
- ],
44
- "license": "MIT",
45
- "optional": true,
46
- "os": [
47
- "linux"
48
- ]
49
- },
50
- "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
51
- "version": "3.0.3",
52
- "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
53
- "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
54
- "cpu": [
55
- "arm64"
56
- ],
57
- "license": "MIT",
58
- "optional": true,
59
- "os": [
60
- "linux"
61
- ]
62
- },
63
- "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
64
- "version": "3.0.3",
65
- "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
66
- "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
67
- "cpu": [
68
- "x64"
69
- ],
70
- "license": "MIT",
71
- "optional": true,
72
- "os": [
73
- "linux"
74
- ]
75
- },
76
- "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
77
- "version": "3.0.3",
78
- "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
79
- "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
80
- "cpu": [
81
- "x64"
82
- ],
83
- "license": "MIT",
84
- "optional": true,
85
- "os": [
86
- "win32"
87
- ]
88
- },
89
- "node_modules/@opencode-ai/plugin": {
90
- "version": "1.14.19",
91
- "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.14.19.tgz",
92
- "integrity": "sha512-g0C8Viocybmet7nBqJK/1xrQnacRS1f30VmqRTPScPmWz+4knIZzc2TEQp8+920sN8rB6BuoGwfBUVRXJmavhQ==",
93
- "license": "MIT",
94
- "dependencies": {
95
- "@opencode-ai/sdk": "1.14.19",
96
- "effect": "4.0.0-beta.48",
97
- "zod": "4.1.8"
98
- },
99
- "peerDependencies": {
100
- "@opentui/core": ">=0.1.101",
101
- "@opentui/solid": ">=0.1.101"
102
- },
103
- "peerDependenciesMeta": {
104
- "@opentui/core": {
105
- "optional": true
106
- },
107
- "@opentui/solid": {
108
- "optional": true
109
- }
110
- }
111
- },
112
- "node_modules/@opencode-ai/sdk": {
113
- "version": "1.14.19",
114
- "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.14.19.tgz",
115
- "integrity": "sha512-9sTGsi8/HlBBeaWfsUjdJ2yi/SqpRvqSld0IFXc3ldaPb1w1uIPvgCGzhlHYQtqatXxSaX5lTN7zpudMaE21aw==",
116
- "license": "MIT",
117
- "dependencies": {
118
- "cross-spawn": "7.0.6"
119
- }
120
- },
121
- "node_modules/@standard-schema/spec": {
122
- "version": "1.1.0",
123
- "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
124
- "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
125
- "license": "MIT"
126
- },
127
- "node_modules/cross-spawn": {
128
- "version": "7.0.6",
129
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
130
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
131
- "license": "MIT",
132
- "dependencies": {
133
- "path-key": "^3.1.0",
134
- "shebang-command": "^2.0.0",
135
- "which": "^2.0.1"
136
- },
137
- "engines": {
138
- "node": ">= 8"
139
- }
140
- },
141
- "node_modules/detect-libc": {
142
- "version": "2.1.2",
143
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
144
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
145
- "license": "Apache-2.0",
146
- "optional": true,
147
- "engines": {
148
- "node": ">=8"
149
- }
150
- },
151
- "node_modules/effect": {
152
- "version": "4.0.0-beta.48",
153
- "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.48.tgz",
154
- "integrity": "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw==",
155
- "license": "MIT",
156
- "dependencies": {
157
- "@standard-schema/spec": "^1.1.0",
158
- "fast-check": "^4.6.0",
159
- "find-my-way-ts": "^0.1.6",
160
- "ini": "^6.0.0",
161
- "kubernetes-types": "^1.30.0",
162
- "msgpackr": "^1.11.9",
163
- "multipasta": "^0.2.7",
164
- "toml": "^4.1.1",
165
- "uuid": "^13.0.0",
166
- "yaml": "^2.8.3"
167
- }
168
- },
169
- "node_modules/fast-check": {
170
- "version": "4.7.0",
171
- "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.7.0.tgz",
172
- "integrity": "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==",
173
- "funding": [
174
- {
175
- "type": "individual",
176
- "url": "https://github.com/sponsors/dubzzz"
177
- },
178
- {
179
- "type": "opencollective",
180
- "url": "https://opencollective.com/fast-check"
181
- }
182
- ],
183
- "license": "MIT",
184
- "dependencies": {
185
- "pure-rand": "^8.0.0"
186
- },
187
- "engines": {
188
- "node": ">=12.17.0"
189
- }
190
- },
191
- "node_modules/find-my-way-ts": {
192
- "version": "0.1.6",
193
- "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz",
194
- "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==",
195
- "license": "MIT"
196
- },
197
- "node_modules/ini": {
198
- "version": "6.0.0",
199
- "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz",
200
- "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==",
201
- "license": "ISC",
202
- "engines": {
203
- "node": "^20.17.0 || >=22.9.0"
204
- }
205
- },
206
- "node_modules/isexe": {
207
- "version": "2.0.0",
208
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
209
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
210
- "license": "ISC"
211
- },
212
- "node_modules/kubernetes-types": {
213
- "version": "1.30.0",
214
- "resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz",
215
- "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==",
216
- "license": "Apache-2.0"
217
- },
218
- "node_modules/msgpackr": {
219
- "version": "1.11.10",
220
- "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz",
221
- "integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==",
222
- "license": "MIT",
223
- "optionalDependencies": {
224
- "msgpackr-extract": "^3.0.2"
225
- }
226
- },
227
- "node_modules/msgpackr-extract": {
228
- "version": "3.0.3",
229
- "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
230
- "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
231
- "hasInstallScript": true,
232
- "license": "MIT",
233
- "optional": true,
234
- "dependencies": {
235
- "node-gyp-build-optional-packages": "5.2.2"
236
- },
237
- "bin": {
238
- "download-msgpackr-prebuilds": "bin/download-prebuilds.js"
239
- },
240
- "optionalDependencies": {
241
- "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3",
242
- "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3",
243
- "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3",
244
- "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3",
245
- "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3",
246
- "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3"
247
- }
248
- },
249
- "node_modules/multipasta": {
250
- "version": "0.2.7",
251
- "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz",
252
- "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==",
253
- "license": "MIT"
254
- },
255
- "node_modules/node-gyp-build-optional-packages": {
256
- "version": "5.2.2",
257
- "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
258
- "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
259
- "license": "MIT",
260
- "optional": true,
261
- "dependencies": {
262
- "detect-libc": "^2.0.1"
263
- },
264
- "bin": {
265
- "node-gyp-build-optional-packages": "bin.js",
266
- "node-gyp-build-optional-packages-optional": "optional.js",
267
- "node-gyp-build-optional-packages-test": "build-test.js"
268
- }
269
- },
270
- "node_modules/path-key": {
271
- "version": "3.1.1",
272
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
273
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
274
- "license": "MIT",
275
- "engines": {
276
- "node": ">=8"
277
- }
278
- },
279
- "node_modules/pure-rand": {
280
- "version": "8.4.0",
281
- "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz",
282
- "integrity": "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==",
283
- "funding": [
284
- {
285
- "type": "individual",
286
- "url": "https://github.com/sponsors/dubzzz"
287
- },
288
- {
289
- "type": "opencollective",
290
- "url": "https://opencollective.com/fast-check"
291
- }
292
- ],
293
- "license": "MIT"
294
- },
295
- "node_modules/shebang-command": {
296
- "version": "2.0.0",
297
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
298
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
299
- "license": "MIT",
300
- "dependencies": {
301
- "shebang-regex": "^3.0.0"
302
- },
303
- "engines": {
304
- "node": ">=8"
305
- }
306
- },
307
- "node_modules/shebang-regex": {
308
- "version": "3.0.0",
309
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
310
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
311
- "license": "MIT",
312
- "engines": {
313
- "node": ">=8"
314
- }
315
- },
316
- "node_modules/toml": {
317
- "version": "4.1.1",
318
- "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz",
319
- "integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==",
320
- "license": "MIT",
321
- "engines": {
322
- "node": ">=20"
323
- }
324
- },
325
- "node_modules/uuid": {
326
- "version": "13.0.1",
327
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.1.tgz",
328
- "integrity": "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw==",
329
- "funding": [
330
- "https://github.com/sponsors/broofa",
331
- "https://github.com/sponsors/ctavan"
332
- ],
333
- "license": "MIT",
334
- "bin": {
335
- "uuid": "dist-node/bin/uuid"
336
- }
337
- },
338
- "node_modules/which": {
339
- "version": "2.0.2",
340
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
341
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
342
- "license": "ISC",
343
- "dependencies": {
344
- "isexe": "^2.0.0"
345
- },
346
- "bin": {
347
- "node-which": "bin/node-which"
348
- },
349
- "engines": {
350
- "node": ">= 8"
351
- }
352
- },
353
- "node_modules/yaml": {
354
- "version": "2.8.3",
355
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
356
- "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
357
- "license": "ISC",
358
- "bin": {
359
- "yaml": "bin.mjs"
360
- },
361
- "engines": {
362
- "node": ">= 14.6"
363
- },
364
- "funding": {
365
- "url": "https://github.com/sponsors/eemeli"
366
- }
367
- },
368
- "node_modules/zod": {
369
- "version": "4.1.8",
370
- "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz",
371
- "integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==",
372
- "license": "MIT",
373
- "funding": {
374
- "url": "https://github.com/sponsors/colinhacks"
375
- }
376
- }
377
- }
378
- }