odd-studio 1.0.1 → 2.1.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/bin/odd-studio.js +33 -5
- package/package.json +1 -1
- package/scripts/postinstall.js +10 -7
- package/scripts/setup-mcp.js +68 -0
- package/skill/SKILL.md +36 -11
- package/skill/docs/build/build-protocol.md +47 -469
- package/skill/docs/chapters/chapter-1.md +31 -0
- package/skill/docs/chapters/chapter-10.md +31 -0
- package/skill/docs/chapters/chapter-11.md +35 -0
- package/skill/docs/chapters/chapter-12.md +39 -0
- package/skill/docs/chapters/chapter-13.md +31 -0
- package/skill/docs/chapters/chapter-14.md +31 -0
- package/skill/docs/chapters/chapter-15.md +35 -0
- package/skill/docs/chapters/chapter-16.md +33 -0
- package/skill/docs/chapters/chapter-17.md +35 -0
- package/skill/docs/chapters/chapter-18.md +31 -0
- package/skill/docs/chapters/chapter-2.md +27 -0
- package/skill/docs/chapters/chapter-3.md +27 -0
- package/skill/docs/chapters/chapter-4.md +37 -0
- package/skill/docs/chapters/chapter-5.md +29 -0
- package/skill/docs/chapters/chapter-6.md +31 -0
- package/skill/docs/chapters/chapter-7.md +35 -0
- package/skill/docs/chapters/chapter-8.md +31 -0
- package/skill/docs/chapters/chapter-9.md +33 -0
- package/skill/docs/kb/odd-kb.md +28 -22
package/bin/odd-studio.js
CHANGED
|
@@ -62,7 +62,7 @@ program
|
|
|
62
62
|
console.log(chalk.bold(` Setting up: ${chalk.cyan(resolvedName)}\n`));
|
|
63
63
|
|
|
64
64
|
// 1. Scaffold project structure
|
|
65
|
-
print.step(1,
|
|
65
|
+
print.step(1, 4, 'Creating project structure...');
|
|
66
66
|
const spinner1 = ora({ text: '', indent: 4 }).start();
|
|
67
67
|
try {
|
|
68
68
|
await scaffoldProject(targetDir, resolvedName);
|
|
@@ -76,7 +76,7 @@ program
|
|
|
76
76
|
|
|
77
77
|
// 2. Install /odd skill
|
|
78
78
|
if (!options.skipSkill) {
|
|
79
|
-
print.step(2,
|
|
79
|
+
print.step(2, 4, 'Installing /odd skill into Claude Code...');
|
|
80
80
|
const spinner2 = ora({ text: '', indent: 4 }).start();
|
|
81
81
|
try {
|
|
82
82
|
const result = await installSkill(PACKAGE_ROOT);
|
|
@@ -88,13 +88,13 @@ program
|
|
|
88
88
|
print.info('Manual install: copy ' + chalk.dim('skill/') + ' to ' + chalk.dim('~/.claude/skills/odd/'));
|
|
89
89
|
}
|
|
90
90
|
} else {
|
|
91
|
-
print.step(2,
|
|
91
|
+
print.step(2, 4, 'Skipping skill install (--skip-skill)');
|
|
92
92
|
print.warn('Remember to install the skill manually for /odd to work in Claude Code.');
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// 3. Setup hooks
|
|
96
96
|
if (!options.skipHooks) {
|
|
97
|
-
print.step(3,
|
|
97
|
+
print.step(3, 4, 'Installing safety hooks into Claude Code settings...');
|
|
98
98
|
const spinner3 = ora({ text: '', indent: 4 }).start();
|
|
99
99
|
try {
|
|
100
100
|
const result = await setupHooks(PACKAGE_ROOT);
|
|
@@ -106,10 +106,29 @@ program
|
|
|
106
106
|
print.info('Manual install: add entries from ' + chalk.dim('hooks/') + ' to ~/.claude/settings.json');
|
|
107
107
|
}
|
|
108
108
|
} else {
|
|
109
|
-
print.step(3,
|
|
109
|
+
print.step(3, 4, 'Skipping hooks (--skip-hooks)');
|
|
110
110
|
print.warn('Safety hooks not installed. Git guardrails and quality gates will not run.');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
// 4. Configure ruflo MCP server (cross-session memory)
|
|
114
|
+
print.step(4, 4, 'Configuring ruflo memory server...');
|
|
115
|
+
const spinner4 = ora({ text: '', indent: 4 }).start();
|
|
116
|
+
try {
|
|
117
|
+
const { default: setupMcp } = await import('../scripts/setup-mcp.js');
|
|
118
|
+
const mcpResult = await setupMcp();
|
|
119
|
+
spinner4.stop();
|
|
120
|
+
if (mcpResult.mcpJsonUpdated || mcpResult.settingsUpdated) {
|
|
121
|
+
print.ok('Ruflo MCP server configured — cross-session memory enabled');
|
|
122
|
+
} else {
|
|
123
|
+
print.ok('Ruflo MCP server already configured');
|
|
124
|
+
}
|
|
125
|
+
} catch (e) {
|
|
126
|
+
spinner4.stop();
|
|
127
|
+
print.warn('Could not configure ruflo automatically: ' + e.message);
|
|
128
|
+
print.info('Manual setup: add ruflo to ~/.mcp.json and enable in ~/.claude/settings.json');
|
|
129
|
+
print.info('See: https://github.com/ruvnet/ruflo for installation instructions');
|
|
130
|
+
}
|
|
131
|
+
|
|
113
132
|
// ── Done ──
|
|
114
133
|
print.blank();
|
|
115
134
|
console.log(chalk.bold.green(' ✓ ODD Studio is ready.\n'));
|
|
@@ -188,6 +207,15 @@ program
|
|
|
188
207
|
s2.fail('Hooks update failed: ' + e.message);
|
|
189
208
|
}
|
|
190
209
|
|
|
210
|
+
const s3 = ora({ text: 'Checking ruflo MCP configuration...', indent: 4 }).start();
|
|
211
|
+
try {
|
|
212
|
+
const { default: setupMcp } = await import('../scripts/setup-mcp.js');
|
|
213
|
+
const mcpResult = await setupMcp();
|
|
214
|
+
s3.succeed(mcpResult.mcpJsonUpdated || mcpResult.settingsUpdated ? 'Ruflo MCP configured' : 'Ruflo MCP already configured');
|
|
215
|
+
} catch (e) {
|
|
216
|
+
s3.fail('Ruflo MCP check failed: ' + e.message);
|
|
217
|
+
}
|
|
218
|
+
|
|
191
219
|
print.blank();
|
|
192
220
|
print.ok('Upgrade complete.');
|
|
193
221
|
print.blank();
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -13,16 +13,19 @@ if (!isGlobal && !isNpx) {
|
|
|
13
13
|
process.exit(0);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
})
|
|
16
|
+
const pkg = new URL('..', import.meta.url).pathname.replace(/\/$/, '');
|
|
17
|
+
|
|
18
|
+
Promise.all([
|
|
19
|
+
import('./install-skill.js').then(({ default: installSkill }) => installSkill(pkg)),
|
|
20
|
+
import('./setup-hooks.js').then(({ default: setupHooks }) => setupHooks(pkg)),
|
|
21
|
+
import('./setup-mcp.js').then(({ default: setupMcp }) => setupMcp()),
|
|
22
|
+
])
|
|
21
23
|
.then(() => {
|
|
22
|
-
console.log('✓ ODD Studio: /odd skill installed into Claude Code');
|
|
24
|
+
console.log('✓ ODD Studio: /odd skill, safety hooks, and ruflo memory installed into Claude Code');
|
|
25
|
+
console.log(' Run: npx odd-studio init [project-name] to scaffold your first project.');
|
|
23
26
|
})
|
|
24
27
|
.catch((e) => {
|
|
25
28
|
// Non-fatal — user can run odd-studio init manually
|
|
26
|
-
console.log('⚠ ODD Studio: Could not
|
|
29
|
+
console.log('⚠ ODD Studio: Could not complete setup (' + e.message + ')');
|
|
27
30
|
console.log(' Run: npx odd-studio init to complete setup.');
|
|
28
31
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
|
|
6
|
+
const MCP_JSON_PATH = path.join(os.homedir(), '.mcp.json');
|
|
7
|
+
const SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json');
|
|
8
|
+
|
|
9
|
+
const RUFLO_SERVER_ENTRY = {
|
|
10
|
+
type: 'stdio',
|
|
11
|
+
command: 'npx',
|
|
12
|
+
args: ['ruflo@latest', 'mcp', 'start'],
|
|
13
|
+
env: {},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Configures the ruflo MCP server so that cross-session memory works.
|
|
18
|
+
*
|
|
19
|
+
* Two writes required:
|
|
20
|
+
* 1. ~/.mcp.json — defines the server (npx ruflo@latest mcp start)
|
|
21
|
+
* 2. ~/.claude/settings.json — adds "ruflo" to enabledMcpjsonServers
|
|
22
|
+
*
|
|
23
|
+
* Both are idempotent: existing entries are left untouched.
|
|
24
|
+
*/
|
|
25
|
+
export default async function setupMcp() {
|
|
26
|
+
const result = { mcpJsonUpdated: false, settingsUpdated: false };
|
|
27
|
+
|
|
28
|
+
// ── 1. Add ruflo to ~/.mcp.json ────────────────────────────────────────────
|
|
29
|
+
let mcpConfig = { mcpServers: {} };
|
|
30
|
+
if (fs.existsSync(MCP_JSON_PATH)) {
|
|
31
|
+
try {
|
|
32
|
+
mcpConfig = await fs.readJson(MCP_JSON_PATH);
|
|
33
|
+
} catch {
|
|
34
|
+
// Corrupt file — start fresh but preserve any valid content
|
|
35
|
+
mcpConfig = { mcpServers: {} };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
39
|
+
|
|
40
|
+
if (!mcpConfig.mcpServers.ruflo) {
|
|
41
|
+
mcpConfig.mcpServers.ruflo = RUFLO_SERVER_ENTRY;
|
|
42
|
+
await fs.writeJson(MCP_JSON_PATH, mcpConfig, { spaces: 2 });
|
|
43
|
+
result.mcpJsonUpdated = true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ── 2. Enable ruflo in ~/.claude/settings.json ─────────────────────────────
|
|
47
|
+
await fs.ensureDir(path.join(os.homedir(), '.claude'));
|
|
48
|
+
let settings = {};
|
|
49
|
+
if (fs.existsSync(SETTINGS_PATH)) {
|
|
50
|
+
try {
|
|
51
|
+
settings = await fs.readJson(SETTINGS_PATH);
|
|
52
|
+
} catch {
|
|
53
|
+
settings = {};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!Array.isArray(settings.enabledMcpjsonServers)) {
|
|
58
|
+
settings.enabledMcpjsonServers = [];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!settings.enabledMcpjsonServers.includes('ruflo')) {
|
|
62
|
+
settings.enabledMcpjsonServers.push('ruflo');
|
|
63
|
+
await fs.writeJson(SETTINGS_PATH, settings, { spaces: 2 });
|
|
64
|
+
result.settingsUpdated = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return result;
|
|
68
|
+
}
|
package/skill/SKILL.md
CHANGED
|
@@ -176,6 +176,22 @@ Initialise the ruflo swarm for parallel build execution. See the full Ruflo Swar
|
|
|
176
176
|
|
|
177
177
|
---
|
|
178
178
|
|
|
179
|
+
### `*agent`
|
|
180
|
+
|
|
181
|
+
Create a custom agent for a domain-specific concern. The domain expert describes what they need in plain language. ODD Studio configures the agent, assigns it to the swarm, and includes its reports in the verification output alongside the QA agent's report.
|
|
182
|
+
|
|
183
|
+
Common use cases: brand voice (flag text that does not match the platform's tone), compliance (check every outcome against a regulatory standard), accessibility (review every screen against WCAG).
|
|
184
|
+
|
|
185
|
+
The domain expert does not write agent code. They describe the concern:
|
|
186
|
+
|
|
187
|
+
> "Every piece of text a customer sees should sound like it comes from a small, friendly independent bookshop. Flag anything that sounds corporate or uses jargon."
|
|
188
|
+
|
|
189
|
+
ODD Studio creates the agent from that description. It runs on every relevant outcome and reports in domain language.
|
|
190
|
+
|
|
191
|
+
After collecting the description, call `mcp__ruflo__agent_spawn` with the custom role and the domain expert's description as instructions. Confirm the agent is active and will run during the next `*build` or `*swarm` session.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
179
195
|
### `*export`
|
|
180
196
|
|
|
181
197
|
Generate the IDE Session Brief. This is a standalone document that a developer or AI coding agent can use to execute a build session without needing to ask planning questions.
|
|
@@ -199,16 +215,24 @@ After writing the file, display: "Your Session Brief has been written to docs/se
|
|
|
199
215
|
Load coaching content from chapter n of the ODD methodology book. Route to the appropriate file in `docs/chapters/`. If the chapter file does not exist, explain what that chapter covers conceptually and offer to explore it through dialogue.
|
|
200
216
|
|
|
201
217
|
Chapter reference:
|
|
202
|
-
- Chapter 1:
|
|
203
|
-
- Chapter 2:
|
|
204
|
-
- Chapter 3:
|
|
205
|
-
- Chapter 4:
|
|
206
|
-
- Chapter 5:
|
|
207
|
-
- Chapter 6:
|
|
208
|
-
- Chapter 7:
|
|
209
|
-
- Chapter 8:
|
|
210
|
-
- Chapter 9:
|
|
211
|
-
- Chapter 10:
|
|
218
|
+
- Chapter 1: It's All About Clarity
|
|
219
|
+
- Chapter 2: The Right Division of Labour
|
|
220
|
+
- Chapter 3: Features Aren't Enough
|
|
221
|
+
- Chapter 4: Outcomes Should Be Specific
|
|
222
|
+
- Chapter 5: Personas Are Load-Bearing
|
|
223
|
+
- Chapter 6: Every Outcome Has a Contract
|
|
224
|
+
- Chapter 7: Design the Outcome Twice
|
|
225
|
+
- Chapter 8: The Master Implementation Plan
|
|
226
|
+
- Chapter 9: Start from Zero
|
|
227
|
+
- Chapter 10: The Build Protocol
|
|
228
|
+
- Chapter 11: Verification Is Your Job
|
|
229
|
+
- Chapter 12: Building One Outcome
|
|
230
|
+
- Chapter 13: Concurrent Outcomes and the Swarm
|
|
231
|
+
- Chapter 14: The Things That Scare You
|
|
232
|
+
- Chapter 15: Good Interfaces Are Specified, Not Designed
|
|
233
|
+
- Chapter 16: Managing Change
|
|
234
|
+
- Chapter 17: The Swarm in Depth
|
|
235
|
+
- Chapter 18: Conclusion
|
|
212
236
|
|
|
213
237
|
---
|
|
214
238
|
|
|
@@ -245,7 +269,8 @@ Display this reference:
|
|
|
245
269
|
| `*contracts` | Map contracts with Theo |
|
|
246
270
|
| `*phase-plan` | Build the Master Implementation Plan with Rachel |
|
|
247
271
|
| `*ui` | Load UI excellence principles |
|
|
248
|
-
| `*swarm` |
|
|
272
|
+
| `*swarm` | Build all independent outcomes in the current phase simultaneously |
|
|
273
|
+
| `*agent` | Create a custom agent for a domain-specific concern |
|
|
249
274
|
| `*export` | Generate IDE Session Brief |
|
|
250
275
|
| `*chapter [n]` | Load methodology coaching for chapter n |
|
|
251
276
|
| `*why` | Explain why the current step matters |
|