refacil-sdd-ai 4.5.0 → 4.5.2

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
@@ -2,16 +2,16 @@
2
2
 
3
3
  **SDD-AI** (Specification-Driven Development with AI) packaged as a CLI.
4
4
 
5
- Installs **skills** and **sub-agents** for **Claude Code** and **Cursor** that guide the developer through a structured AI-assisted development workflow, using **`refacil-sdd/`** as the specification store, plus a **local bus** so agents across different repos can communicate with each other.
5
+ Installs **skills** and **sub-agents** for **Claude Code**, **Cursor**, and **OpenCode** that guide the developer through a structured AI-assisted development workflow, using **`refacil-sdd/`** as the specification store, plus a **local bus** so agents across different repos can communicate with each other.
6
6
 
7
7
  ---
8
8
 
9
9
  ## Requirements
10
10
 
11
11
  - **Node.js >= 20.0.0**
12
- - **Claude Code >= 2.1.89** (required by the `compact-bash` hook for silent rewrite via `updatedInput`) or **Cursor**
12
+ - One or more supported IDEs: **Claude Code >= 2.1.89**, **Cursor**, or **OpenCode**
13
13
 
14
- `refacil-sdd-ai init` checks the Claude Code version and warns if it is below 2.1.89. With an older version the rest of the methodology works, but `compact-bash` will have no effect.
14
+ `refacil-sdd-ai init` checks the Claude Code version and warns if it is below 2.1.89. With an older version the rest of the methodology works, but `compact-bash` will have no effect (Claude Code only — OpenCode and Cursor have their own hook delivery mechanisms).
15
15
 
16
16
  ---
17
17
 
@@ -25,10 +25,12 @@ npm install -g refacil-sdd-ai
25
25
 
26
26
  # 2. In the repo root
27
27
  refacil-sdd-ai init
28
- # Copies skills to .claude/ and .cursor/, creates CLAUDE.md + .cursorrules, configures hooks
29
- # Creates/updates .claudeignore and .cursorignore with base exclusions
28
+ # Interactive IDE selector (Claude Code / Cursor / OpenCode) pre-selects IDEs
29
+ # whose folder already exists. Use --all to install for all three without prompting.
30
+ # Copies skills and sub-agents to the selected IDEs, configures hooks,
31
+ # and creates/updates .claudeignore, .cursorignore and .opencodeignore.
30
32
 
31
- # 3. Restart your Claude Code or Cursor session
33
+ # 3. Restart your IDE session
32
34
  # (new skills are not detected until you restart)
33
35
 
34
36
  # 4. In the IDE
@@ -36,6 +38,18 @@ refacil-sdd-ai init
36
38
  # Generates AGENTS.md and the .agents/ directory for the project
37
39
  ```
38
40
 
41
+ ### Adding a new IDE to an existing installation
42
+
43
+ If you already have the methodology installed for Claude Code or Cursor and want to add OpenCode (or any other IDE), just run `init` again from the repo root:
44
+
45
+ ```bash
46
+ refacil-sdd-ai init
47
+ ```
48
+
49
+ The selector will pre-select the IDEs whose folders already exist (`.claude/`, `.cursor/`). Check the new IDE you want to add (e.g. OpenCode), leave the existing ones checked, and confirm — only the newly selected IDE will receive files; existing installations are refreshed in place.
50
+
51
+ > **`update` does not add new IDEs** — it only updates IDEs already installed. Use `init` to add a new one.
52
+
39
53
  ### Update
40
54
 
41
55
  ```bash
@@ -43,23 +57,15 @@ npm update -g refacil-sdd-ai
43
57
  refacil-sdd-ai update # in each repo where it is used
44
58
  ```
45
59
 
46
- In Claude Code / Cursor the `check-update` hook (every session) syncs skills and `compact-guidance`. Only if the automatic detection (`lib/methodology-migration-pending.js`) finds a pending methodology migration does it write the flag and allow `notify-update` to prompt `/refacil:update`. If there is no migration, the user is not interrupted. The `/refacil:update` skill uses `refacil-sdd-ai migration-pending` as the same criterion.
60
+ `update` detects which IDEs are installed by folder presence (`.claude/`, `.cursor/`, `.opencode/`) and only updates those — it never creates IDE directories that did not exist before. In Claude Code and Cursor the `check-update` hook (every session) syncs skills and `compact-guidance`. In OpenCode the equivalent runs via the `session.created` handler of the embedded plugin (`.opencode/plugins/refacil-hooks.js`). Only if the automatic detection (`lib/methodology-migration-pending.js`) finds a pending methodology migration does it write the flag and allow `notify-update` / `tui.prompt.append` to prompt `/refacil:update`. If there is no migration, the user is not interrupted. The `/refacil:update` skill uses `refacil-sdd-ai migration-pending` as the same criterion.
47
61
 
48
62
  ### Uninstall
49
63
 
50
64
  ```bash
51
- refacil-sdd-ai clean # in the repo (removes skills + SDD-AI hooks)
65
+ refacil-sdd-ai clean # in the repo (removes skills + SDD-AI hooks for all IDEs)
52
66
  npm uninstall -g refacil-sdd-ai
53
67
  ```
54
68
 
55
- ### Legacy `openspec/` directory
56
-
57
- Older repos may still have **`openspec/changes/`**. The package **migrates automatically** to **`refacil-sdd/`** the first time you run any **`refacil-sdd-ai sdd …`** subcommand or when **`check-update`** runs at session start. After you confirm the tree under **`refacil-sdd/`**, you can remove the leftover **`openspec/`** folder.
58
-
59
- Some teams still install the **OpenSpec CLI** for **`opsx:*`** commands; those can coexist with SDD-AI. The **supported** path for changes, review markers, and archiving is **`refacil-sdd/`** plus **`refacil-sdd-ai sdd`** and **`/refacil:*`** skills.
60
-
61
- ---
62
-
63
69
  ## CLI Commands
64
70
 
65
71
  ### Package management
@@ -133,7 +139,7 @@ Run **`refacil-sdd-ai help`** for the full list including `bus` and `compact` su
133
139
 
134
140
  ## Available IDE Skills
135
141
 
136
- All invoked as `/refacil:<name>` in Claude Code or Cursor.
142
+ All invoked as `/refacil:<name>` in Claude Code, Cursor, or OpenCode.
137
143
 
138
144
  ### SDD cycle
139
145
 
@@ -170,7 +176,7 @@ Some skills delegate their heavy work to **sub-agents** that run in isolated con
170
176
 
171
177
  **Model**: `refacil-proposer` runs with `model: opusplan` (uses Opus during plan mode for highest-stakes planning, then switches to Sonnet for execution). Other sub-agents use `model: sonnet` by default.
172
178
 
173
- **Dual-platform**: `.claude/agents/refacil-*.md` uses `tools:` (granular allowlist). `.cursor/agents/refacil-*.md` is auto-generated: `readonly: true` for agents without `Edit`/`Write`, `readonly: false` for those that have them; always `model: inherit`. The installer transforms the frontmatter automatically.
179
+ **Triple-platform**: `.claude/agents/refacil-*.md` uses `tools:` (granular allowlist). `.cursor/agents/refacil-*.md` is auto-generated: `readonly: true` for agents without `Edit`/`Write`, `readonly: false` for those that have them; always `model: inherit`. `.opencode/agents/refacil-*.md` is auto-generated via `transformFrontmatterForOpenCode()`: converts `tools:` to a `permission:` block (`edit: allow/deny`, `bash: allow/deny`, `webfetch: deny`), adds `mode: subagent`, adds `hidden: true` for internal agents, and removes `model:`. The installer transforms the frontmatter automatically for all three IDEs.
174
180
 
175
181
  **Two-pass `refacil:bug` flow**: the wrapper first invokes the sub-agent in `investigation` mode (writes nothing) → the user confirms the hypothesis and approves the fix → the wrapper validates the working branch → invokes the sub-agent in `fix` mode to implement.
176
182
 
@@ -259,16 +265,23 @@ From there, the full cycle is:
259
265
 
260
266
  ## Automatic Hooks
261
267
 
262
- Installed in `.claude/settings.json` **and** `.cursor/settings.json` during `init` / `update`. Apply to both **Claude Code** and **Cursor**.
268
+ Installed during `init` / `update` for each selected IDE. The same four behaviors are active in Claude Code, Cursor, and OpenCode — each through its own delivery mechanism.
263
269
 
264
- | Hook | Event | What it does |
265
- |---|---|---|
266
- | `check-update` | `SessionStart` | On startup deletes `.refacil-pending-update` if no migration is pending (stale flags). Then: npm check, sync skills, **compact-guidance**. If skills were synced **and** a migration is pending, writes the flag for `notify-update`. |
267
- | `notify-update` | `UserPromptSubmit` (Claude Code) / `beforeSubmitPrompt` (Cursor) | If the flag exists **and** a methodology migration is pending (same table as `/refacil:update`), injects the instruction or pauses the first message; if the sync happened without a migration, the flag is not created or is discarded silently. |
268
- | `compact-bash` | `PreToolUse` (Bash) | Silently rewrites bare Bash commands via `updatedInput`. No extra turns, the IDE does not see the change. Requires Claude Code >= 2.1.89. |
269
- | `check-review` | `PreToolUse` (Bash) | Intercepts `git push` and blocks if `.review-passed` is missing in any active change. |
270
+ | Behavior | Claude Code | Cursor | OpenCode |
271
+ |---|---|---|---|
272
+ | **check-update** | `SessionStart` hook in `.claude/settings.json` | `SessionStart` hook in `.cursor/settings.json` | `session.created` handler in `.opencode/plugins/refacil-hooks.js` |
273
+ | **notify-update** | `UserPromptSubmit` hook | `beforeSubmitPrompt` hook | `tui.prompt.append` handler |
274
+ | **compact-bash** | `PreToolUse` (Bash) hook | `PreToolUse` (Bash) hook | `tool.execute.before` handler for bash tool |
275
+ | **check-review** | `PreToolUse` (Bash) hook | `PreToolUse` (Bash) hook | `tool.execute.before` handler for bash tool |
270
276
 
271
- All four hooks are installed in `.claude/settings.json` (Claude Code) and `.cursor/settings.json` (Cursor) with the same parametric logic.
277
+ | Behavior | What it does |
278
+ |---|---|
279
+ | `check-update` | On startup: deletes `.refacil-pending-update` if no migration is pending (stale flags). Then: npm check, sync skills, **compact-guidance**. If skills were synced **and** a migration is pending, writes the flag for `notify-update`. Always refreshes the flag content when a migration is pending (keeps the `to` version current). |
280
+ | `notify-update` | If the flag exists **and** a methodology migration is pending (same table as `/refacil:update`), injects the instruction before the agent processes the next user message; if the sync happened without a migration, the flag is not created or is discarded silently. |
281
+ | `compact-bash` | Silently rewrites bare Bash commands. No extra turns, the IDE does not see the change. Requires Claude Code >= 2.1.89 for the `updatedInput` path. |
282
+ | `check-review` | Intercepts `git push` and blocks if `.review-passed` is missing in any active change. |
283
+
284
+ > **OpenCode plugin**: a single file (`.opencode/plugins/refacil-hooks.js`) implements all four behaviors. It loads `lib/compact/rules.js` from the package to reuse the same rewrite rules — no duplicated logic. If the rules file is not resolvable, compact-bash is disabled gracefully with a warning to stderr; the plugin never crashes the session.
272
285
 
273
286
  > **Why two hooks for updates?** `SessionStart` does the silent sync when opening the session without user interaction. `notify-update` on `UserPromptSubmit` / `beforeSubmitPrompt` injects the instruction just before the agent processes the next user message, ensuring it is not ignored.
274
287
 
@@ -406,18 +419,35 @@ Local bus (WebSocket over `127.0.0.1`) so agents across different repos can comm
406
419
 
407
420
  ## What Gets Installed in Your Repo
408
421
 
422
+ Only the IDEs selected during `init` (or detected during `update`) receive files. The three IDE targets are independent — selecting only `.opencode` does not create `.claude/` or `.cursor/` directories.
423
+
409
424
  ```
410
- .claude/skills/refacil-*/ # Claude Code skills (includes refacil-prereqs: METHODOLOGY-CONTRACT.md, BUS-CROSS-REPO.md, …)
425
+ # Claude Code (if selected)
426
+ .claude/skills/refacil-*/ # Skills (includes refacil-prereqs: METHODOLOGY-CONTRACT.md, BUS-CROSS-REPO.md, …)
411
427
  .claude/agents/refacil-*.md # Read-only sub-agents: auditor, investigator, validator
412
428
  # Write sub-agents: tester, implementer, debugger, proposer
413
- .claude/settings.json # Hooks: check-update + check-review + compact-bash
429
+ .claude/settings.json # Hooks: check-update + notify-update + check-review + compact-bash
430
+ .claude/.sdd-version # Installed methodology version (used by check-update)
431
+
432
+ # Cursor (if selected)
414
433
  .cursor/skills/refacil-*/ # Cursor skills (equivalent)
415
- .cursor/agents/refacil-*.md # Cursor sub-agents (readonly:true/false + model:inherit auto-generated)
416
- .cursor/settings.json # Hooks: check-update + check-review + compact-bash (mirror of .claude/)
434
+ .cursor/agents/refacil-*.md # Cursor sub-agents (readonly:true/false + model:inherit, auto-generated)
435
+ .cursor/settings.json # Hooks: check-update + notify-update + check-review + compact-bash
436
+ .cursor/.sdd-version # Installed methodology version
437
+
438
+ # OpenCode (if selected)
439
+ .opencode/skills/refacil-*/ # OpenCode skills (byte-for-byte copy — same spec as Claude Code)
440
+ .opencode/agents/refacil-*.md # OpenCode sub-agents (permission block + mode:subagent, auto-generated)
441
+ .opencode/plugins/refacil-hooks.js # Embedded plugin: session.created + tui.prompt.append + tool.execute.before
442
+ .opencode/opencode.json # Created/merged with $schema (user keys preserved)
443
+ .opencode/.sdd-version # Installed methodology version
444
+
445
+ # Shared (IDE-agnostic)
417
446
  CLAUDE.md # Minimal index → points to AGENTS.md
418
- .cursorrules # Same in Cursor format
447
+ .cursorrules # Cursor format equivalent of CLAUDE.md
419
448
  .claudeignore # Base exclusions (node_modules, dist, .env, *.key, etc.)
420
449
  .cursorignore # Same content as .claudeignore
450
+ .opencodeignore # Same content as .claudeignore
421
451
  AGENTS.md # Project index → generated by /refacil:setup
422
452
  # Points to .agents/ + includes auto-managed blocks
423
453
  # (compact-guidance and bus presentation)
@@ -436,6 +466,7 @@ refacil-sdd/ # SDD artifacts store
436
466
  - [AGENTS.md](https://agents.md/) — universal AI instructions standard
437
467
  - [Claude Code](https://claude.ai/code) — Anthropic CLI
438
468
  - [Cursor](https://cursor.sh) — AI IDE
469
+ - [OpenCode](https://opencode.ai) — open-source AI development agent
439
470
 
440
471
  ## License
441
472
 
package/bin/cli.js CHANGED
@@ -207,7 +207,8 @@ async function selectIDEs() {
207
207
  const clack = require('@clack/prompts');
208
208
  const result = await clack.multiselect({
209
209
  message: 'Select IDEs to install refacil-sdd-ai into:',
210
- options: options.map((o) => ({ label: o.label, value: o.value, selected: o.selected })),
210
+ options: options.map((o) => ({ label: o.label, value: o.value })),
211
+ initialValues: options.filter((o) => o.selected).map((o) => o.value),
211
212
  required: false,
212
213
  });
213
214
  if (clack.isCancel(result)) {
@@ -466,14 +467,16 @@ async function init() {
466
467
  }
467
468
 
468
469
  try {
469
- const ignoreResult = syncIgnoreFiles(projectRoot);
470
- const s = ignoreResult.claude;
471
- if (s.status === 'created') {
472
- console.log(' .claudeignore, .cursorignore and .opencodeignore created');
473
- } else if (s.status === 'updated') {
474
- console.log(` .claudeignore, .cursorignore and .opencodeignore updated (${s.added} entries added)`);
475
- } else {
476
- console.log(' .claudeignore, .cursorignore and .opencodeignore are up to date');
470
+ const IDE_TO_IGNORE = { '.claude': '.claudeignore', '.cursor': '.cursorignore', '.opencode': '.opencodeignore' };
471
+ const ignoreResult = syncIgnoreFiles(projectRoot, selectedIDEs);
472
+ const ignoreNames = selectedIDEs.map((d) => IDE_TO_IGNORE[d]).filter(Boolean).join(', ');
473
+ const s = ignoreResult.claude || ignoreResult.cursor || ignoreResult.opencode;
474
+ if (s && s.status === 'created') {
475
+ console.log(` ${ignoreNames} created`);
476
+ } else if (s && s.status === 'updated') {
477
+ console.log(` ${ignoreNames} updated (${s.added} entries added)`);
478
+ } else if (ignoreNames) {
479
+ console.log(` ${ignoreNames} are up to date`);
477
480
  }
478
481
  } catch (err) {
479
482
  console.error(` Warning: could not sync ignore files: ${err.message}`);
@@ -562,14 +565,16 @@ function update() {
562
565
  }
563
566
 
564
567
  try {
565
- const ignoreResult = syncIgnoreFiles(projectRoot);
566
- const s = ignoreResult.claude;
567
- if (s.status === 'created') {
568
- console.log(' .claudeignore, .cursorignore and .opencodeignore created');
569
- } else if (s.status === 'updated') {
570
- console.log(` .claudeignore, .cursorignore and .opencodeignore updated (${s.added} entries added)`);
571
- } else {
572
- console.log(' .claudeignore, .cursorignore and .opencodeignore are up to date');
568
+ const IDE_TO_IGNORE = { '.claude': '.claudeignore', '.cursor': '.cursorignore', '.opencode': '.opencodeignore' };
569
+ const ignoreResult = syncIgnoreFiles(projectRoot, detectedIDEs);
570
+ const ignoreNames = detectedIDEs.map((d) => IDE_TO_IGNORE[d]).filter(Boolean).join(', ');
571
+ const s = ignoreResult.claude || ignoreResult.cursor || ignoreResult.opencode;
572
+ if (s && s.status === 'created') {
573
+ console.log(` ${ignoreNames} created`);
574
+ } else if (s && s.status === 'updated') {
575
+ console.log(` ${ignoreNames} updated (${s.added} entries added)`);
576
+ } else if (ignoreNames) {
577
+ console.log(` ${ignoreNames} are up to date`);
573
578
  }
574
579
  } catch (err) {
575
580
  console.error(` Warning: could not sync ignore files: ${err.message}`);
@@ -79,11 +79,19 @@ function syncIgnoreFile(filePath) {
79
79
  return { status: 'updated', added: missing.length };
80
80
  }
81
81
 
82
- function syncIgnoreFiles(projectRoot) {
83
- const claude = syncIgnoreFile(path.join(projectRoot, '.claudeignore'));
84
- const cursor = syncIgnoreFile(path.join(projectRoot, '.cursorignore'));
85
- const opencode = syncIgnoreFile(path.join(projectRoot, '.opencodeignore'));
86
- return { claude, cursor, opencode };
82
+ function syncIgnoreFiles(projectRoot, ideDirs) {
83
+ const dirs = ideDirs || ['.claude', '.cursor', '.opencode'];
84
+ const result = {};
85
+ if (dirs.includes('.claude')) {
86
+ result.claude = syncIgnoreFile(path.join(projectRoot, '.claudeignore'));
87
+ }
88
+ if (dirs.includes('.cursor')) {
89
+ result.cursor = syncIgnoreFile(path.join(projectRoot, '.cursorignore'));
90
+ }
91
+ if (dirs.includes('.opencode')) {
92
+ result.opencode = syncIgnoreFile(path.join(projectRoot, '.opencodeignore'));
93
+ }
94
+ return result;
87
95
  }
88
96
 
89
97
  module.exports = { syncIgnoreFiles, BASE_ENTRIES };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "refacil-sdd-ai",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "description": "SDD-AI: Specification-Driven Development with AI — development methodology using AI with Claude Code, Cursor and OpenCode",
5
5
  "bin": {
6
6
  "refacil-sdd-ai": "./bin/cli.js"
@@ -21,6 +21,7 @@
21
21
  "methodology",
22
22
  "claude-code",
23
23
  "cursor",
24
+ "opencode",
24
25
  "sdd",
25
26
  "specification-driven",
26
27
  "testing",