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 +62 -31
- package/bin/cli.js +22 -17
- package/lib/ignore-files.js +13 -5
- package/package.json +2 -1
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 **
|
|
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**
|
|
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
|
-
#
|
|
29
|
-
#
|
|
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
|
|
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
|
|
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
|
|
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
|
-
**
|
|
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
|
|
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
|
-
|
|
|
265
|
-
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 #
|
|
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
|
|
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
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
console.log(`
|
|
475
|
-
} else {
|
|
476
|
-
console.log(
|
|
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
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
console.log(`
|
|
571
|
-
} else {
|
|
572
|
-
console.log(
|
|
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}`);
|
package/lib/ignore-files.js
CHANGED
|
@@ -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
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
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.
|
|
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",
|