@soleri/forge 5.11.0 → 5.12.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.
Files changed (53) hide show
  1. package/dist/facades/forge.facade.js +3 -3
  2. package/dist/facades/forge.facade.js.map +1 -1
  3. package/dist/lib.d.ts +2 -2
  4. package/dist/lib.js +1 -1
  5. package/dist/lib.js.map +1 -1
  6. package/dist/scaffolder.js +137 -20
  7. package/dist/scaffolder.js.map +1 -1
  8. package/dist/templates/agents-md.d.ts +5 -0
  9. package/dist/templates/agents-md.js +33 -0
  10. package/dist/templates/agents-md.js.map +1 -0
  11. package/dist/templates/entry-point.js +15 -2
  12. package/dist/templates/entry-point.js.map +1 -1
  13. package/dist/templates/package-json.js +7 -0
  14. package/dist/templates/package-json.js.map +1 -1
  15. package/dist/templates/readme.js +80 -27
  16. package/dist/templates/readme.js.map +1 -1
  17. package/dist/templates/setup-script.d.ts +1 -1
  18. package/dist/templates/setup-script.js +135 -53
  19. package/dist/templates/setup-script.js.map +1 -1
  20. package/dist/templates/skills.d.ts +0 -7
  21. package/dist/templates/skills.js +0 -21
  22. package/dist/templates/skills.js.map +1 -1
  23. package/dist/templates/telegram-agent.d.ts +6 -0
  24. package/dist/templates/telegram-agent.js +212 -0
  25. package/dist/templates/telegram-agent.js.map +1 -0
  26. package/dist/templates/telegram-bot.d.ts +6 -0
  27. package/dist/templates/telegram-bot.js +450 -0
  28. package/dist/templates/telegram-bot.js.map +1 -0
  29. package/dist/templates/telegram-config.d.ts +6 -0
  30. package/dist/templates/telegram-config.js +81 -0
  31. package/dist/templates/telegram-config.js.map +1 -0
  32. package/dist/templates/telegram-supervisor.d.ts +6 -0
  33. package/dist/templates/telegram-supervisor.js +148 -0
  34. package/dist/templates/telegram-supervisor.js.map +1 -0
  35. package/dist/types.d.ts +13 -5
  36. package/dist/types.js +7 -1
  37. package/dist/types.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/__tests__/scaffolder.test.ts +62 -0
  40. package/src/facades/forge.facade.ts +3 -3
  41. package/src/lib.ts +2 -1
  42. package/src/scaffolder.ts +170 -28
  43. package/src/templates/agents-md.ts +35 -0
  44. package/src/templates/entry-point.ts +15 -2
  45. package/src/templates/package-json.ts +7 -0
  46. package/src/templates/readme.ts +89 -27
  47. package/src/templates/setup-script.ts +141 -54
  48. package/src/templates/skills.ts +0 -23
  49. package/src/templates/telegram-agent.ts +214 -0
  50. package/src/templates/telegram-bot.ts +452 -0
  51. package/src/templates/telegram-config.ts +83 -0
  52. package/src/templates/telegram-supervisor.ts +150 -0
  53. package/src/types.ts +9 -2
package/src/scaffolder.ts CHANGED
@@ -22,14 +22,37 @@ import { generateInjectClaudeMd } from './templates/inject-claude-md.js';
22
22
  import { generateActivate } from './templates/activate.js';
23
23
  import { generateReadme } from './templates/readme.js';
24
24
  import { generateSetupScript } from './templates/setup-script.js';
25
+ import { generateAgentsMd } from './templates/agents-md.js';
25
26
  import { generateSkills } from './templates/skills.js';
26
27
  import { generateExtensionsIndex, generateExampleOp } from './templates/extensions.js';
28
+ import { generateTelegramBot } from './templates/telegram-bot.js';
29
+ import { generateTelegramConfig } from './templates/telegram-config.js';
30
+ import { generateTelegramAgent } from './templates/telegram-agent.js';
31
+ import { generateTelegramSupervisor } from './templates/telegram-supervisor.js';
32
+
33
+ function getSetupTarget(config: AgentConfig): 'claude' | 'codex' | 'both' {
34
+ return config.setupTarget ?? 'claude';
35
+ }
36
+
37
+ function includesClaudeSetup(config: AgentConfig): boolean {
38
+ const target = getSetupTarget(config);
39
+ return target === 'claude' || target === 'both';
40
+ }
41
+
42
+ function includesCodexSetup(config: AgentConfig): boolean {
43
+ const target = getSetupTarget(config);
44
+ return target === 'codex' || target === 'both';
45
+ }
27
46
 
28
47
  /**
29
48
  * Preview what scaffold will create without writing anything.
30
49
  */
31
50
  export function previewScaffold(config: AgentConfig): ScaffoldPreview {
32
51
  const agentDir = join(config.outputDir, config.id);
52
+ const claudeSetup = includesClaudeSetup(config);
53
+ const codexSetup = includesCodexSetup(config);
54
+ const setupLabel =
55
+ claudeSetup && codexSetup ? 'Claude Code + Codex' : claudeSetup ? 'Claude Code' : 'Codex';
33
56
 
34
57
  const files = [
35
58
  { path: 'package.json', description: 'NPM package with MCP SDK, SQLite, Zod dependencies' },
@@ -80,7 +103,7 @@ export function previewScaffold(config: AgentConfig): ScaffoldPreview {
80
103
  },
81
104
  {
82
105
  path: 'scripts/setup.sh',
83
- description: 'Automated setup — Node.js check, build, Claude Code MCP registration',
106
+ description: `Automated setup — Node.js check, build, ${setupLabel} MCP registration`,
84
107
  },
85
108
  {
86
109
  path: 'skills/',
@@ -90,13 +113,35 @@ export function previewScaffold(config: AgentConfig): ScaffoldPreview {
90
113
  },
91
114
  ];
92
115
 
93
- if (config.hookPacks?.length) {
116
+ if (codexSetup) {
117
+ files.push({
118
+ path: 'AGENTS.md',
119
+ description: 'Codex project instructions and activation workflow',
120
+ });
121
+ }
122
+
123
+ if (claudeSetup && config.hookPacks?.length) {
94
124
  files.push({
95
125
  path: '.claude/',
96
126
  description: `Hook pack files (${config.hookPacks.join(', ')})`,
97
127
  });
98
128
  }
99
129
 
130
+ if (config.telegram) {
131
+ files.push(
132
+ {
133
+ path: 'src/telegram-bot.ts',
134
+ description: 'Telegram bot entry point with Grammy middleware',
135
+ },
136
+ { path: 'src/telegram-config.ts', description: 'Telegram config loading (env + file)' },
137
+ { path: 'src/telegram-agent.ts', description: 'Agent loop wired to MCP tools' },
138
+ {
139
+ path: 'src/telegram-supervisor.ts',
140
+ description: 'Process supervisor with restart and logging',
141
+ },
142
+ );
143
+ }
144
+
100
145
  const facades = [
101
146
  ...config.domains.map((d) => ({
102
147
  name: `${config.id}_${d.replace(/-/g, '_')}`,
@@ -208,6 +253,8 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
208
253
  greeting: `Hello! I'm ${config.name}, your AI assistant for ${config.role}.`,
209
254
  };
210
255
  }
256
+ const claudeSetup = includesClaudeSetup(config);
257
+ const codexSetup = includesCodexSetup(config);
211
258
  const agentDir = join(config.outputDir, config.id);
212
259
  const filesCreated: string[] = [];
213
260
 
@@ -238,7 +285,7 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
238
285
  'src/extensions/middleware',
239
286
  ];
240
287
 
241
- if (config.hookPacks?.length) {
288
+ if (claudeSetup && config.hookPacks?.length) {
242
289
  dirs.push('.claude');
243
290
  }
244
291
 
@@ -265,6 +312,10 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
265
312
  ['scripts/setup.sh', generateSetupScript(config)],
266
313
  ];
267
314
 
315
+ if (codexSetup) {
316
+ projectFiles.push(['AGENTS.md', generateAgentsMd(config)]);
317
+ }
318
+
268
319
  for (const [path, content] of projectFiles) {
269
320
  writeFileSync(join(agentDir, path), content, 'utf-8');
270
321
  filesCreated.push(path);
@@ -285,6 +336,16 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
285
336
  ['src/extensions/ops/example.ts', generateExampleOp(config)],
286
337
  ];
287
338
 
339
+ // Telegram transport files (optional)
340
+ if (config.telegram) {
341
+ sourceFiles.push(
342
+ ['src/telegram-bot.ts', generateTelegramBot(config)],
343
+ ['src/telegram-config.ts', generateTelegramConfig(config)],
344
+ ['src/telegram-agent.ts', generateTelegramAgent(config)],
345
+ ['src/telegram-supervisor.ts', generateTelegramSupervisor(config)],
346
+ );
347
+ }
348
+
288
349
  // Empty intelligence data bundles (domain facades come from @soleri/core at runtime)
289
350
  for (const domain of config.domains) {
290
351
  sourceFiles.push([`src/intelligence/data/${domain}.json`, generateEmptyBundle(domain)]);
@@ -325,16 +386,41 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
325
386
  buildError = err instanceof Error ? err.message : String(err);
326
387
  }
327
388
 
328
- // Register the agent as an MCP server in ~/.claude.json (only if build succeeded)
329
- let mcpReg: { registered: boolean; path: string; error?: string };
330
- if (buildSuccess) {
331
- mcpReg = registerMcpServer(config.id, agentDir);
332
- } else {
333
- mcpReg = {
334
- registered: false,
335
- path: join(homedir(), '.claude.json'),
336
- error: 'Skipped — build failed',
337
- };
389
+ // Register the agent as an MCP server in selected host configs (only if build succeeded)
390
+ const mcpRegistrations: Array<{ host: 'Claude Code' | 'Codex'; result: RegistrationResult }> = [];
391
+ if (claudeSetup) {
392
+ if (buildSuccess) {
393
+ mcpRegistrations.push({
394
+ host: 'Claude Code',
395
+ result: registerClaudeMcpServer(config.id, agentDir),
396
+ });
397
+ } else {
398
+ mcpRegistrations.push({
399
+ host: 'Claude Code',
400
+ result: {
401
+ registered: false,
402
+ path: join(homedir(), '.claude.json'),
403
+ error: 'Skipped — build failed',
404
+ },
405
+ });
406
+ }
407
+ }
408
+ if (codexSetup) {
409
+ if (buildSuccess) {
410
+ mcpRegistrations.push({
411
+ host: 'Codex',
412
+ result: registerCodexMcpServer(config.id, agentDir),
413
+ });
414
+ } else {
415
+ mcpRegistrations.push({
416
+ host: 'Codex',
417
+ result: {
418
+ registered: false,
419
+ path: join(homedir(), '.codex', 'config.toml'),
420
+ error: 'Skipped — build failed',
421
+ },
422
+ });
423
+ }
338
424
  }
339
425
 
340
426
  const summaryLines = [
@@ -354,22 +440,31 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
354
440
  summaryLines.push(` Run manually: cd ${agentDir} && npm install && npm run build`);
355
441
  }
356
442
 
357
- if (config.hookPacks?.length) {
443
+ if (claudeSetup && config.hookPacks?.length) {
358
444
  summaryLines.push(`${config.hookPacks.length} hook pack(s) bundled in .claude/`);
359
445
  }
360
446
 
361
- if (mcpReg.registered) {
362
- summaryLines.push(`MCP server registered in ${mcpReg.path}`);
363
- } else {
364
- summaryLines.push(`Warning: Failed to register MCP server in ${mcpReg.path}: ${mcpReg.error}`);
447
+ for (const registration of mcpRegistrations) {
448
+ if (registration.result.registered) {
449
+ summaryLines.push(
450
+ `${registration.host} MCP server registered in ${registration.result.path}`,
451
+ );
452
+ } else {
453
+ summaryLines.push(
454
+ `Warning: Failed to register ${registration.host} MCP server in ${registration.result.path}: ${registration.result.error}`,
455
+ );
456
+ }
365
457
  }
366
458
 
367
- summaryLines.push(
368
- '',
369
- 'Next steps:',
370
- ' Restart Claude Code',
371
- ` Say "Hello, ${config.name}!" to activate the persona`,
372
- );
459
+ const nextSteps = ['', 'Next steps:'];
460
+ if (claudeSetup) {
461
+ nextSteps.push(' Restart Claude Code');
462
+ }
463
+ if (codexSetup) {
464
+ nextSteps.push(' Restart Codex');
465
+ }
466
+ nextSteps.push(` Say "Hello, ${config.name}!" to activate the persona`);
467
+ summaryLines.push(...nextSteps);
373
468
 
374
469
  return {
375
470
  success: true,
@@ -432,14 +527,20 @@ export function listAgents(parentDir: string): AgentInfo[] {
432
527
  return agents;
433
528
  }
434
529
 
530
+ /**
531
+ * Registration result for host config updates.
532
+ */
533
+ interface RegistrationResult {
534
+ registered: boolean;
535
+ path: string;
536
+ error?: string;
537
+ }
538
+
435
539
  /**
436
540
  * Register the agent as an MCP server in ~/.claude.json (User MCPs).
437
541
  * Idempotent — updates existing entry if present.
438
542
  */
439
- function registerMcpServer(
440
- agentId: string,
441
- agentDir: string,
442
- ): { registered: boolean; path: string; error?: string } {
543
+ function registerClaudeMcpServer(agentId: string, agentDir: string): RegistrationResult {
443
544
  const claudeJsonPath = join(homedir(), '.claude.json');
444
545
 
445
546
  try {
@@ -472,6 +573,47 @@ function registerMcpServer(
472
573
  }
473
574
  }
474
575
 
576
+ /**
577
+ * Register the agent as an MCP server in ~/.codex/config.toml.
578
+ * Idempotent — updates existing section if present.
579
+ */
580
+ function registerCodexMcpServer(agentId: string, agentDir: string): RegistrationResult {
581
+ const codexDir = join(homedir(), '.codex');
582
+ const codexConfigPath = join(codexDir, 'config.toml');
583
+ const sectionHeader = `[mcp_servers.${agentId}]`;
584
+ const sectionBlock = `${sectionHeader}
585
+ command = "node"
586
+ args = ["${join(agentDir, 'dist', 'index.js')}"]
587
+ `;
588
+
589
+ try {
590
+ mkdirSync(codexDir, { recursive: true });
591
+
592
+ let content = existsSync(codexConfigPath) ? readFileSync(codexConfigPath, 'utf-8') : '';
593
+ const start = content.indexOf(sectionHeader);
594
+
595
+ if (start === -1) {
596
+ const trimmed = content.trimEnd();
597
+ content = trimmed.length === 0 ? `${sectionBlock}\n` : `${trimmed}\n\n${sectionBlock}\n`;
598
+ } else {
599
+ const afterHeader = start + sectionHeader.length;
600
+ const tail = content.slice(afterHeader);
601
+ const nextSectionOffset = tail.search(/\n\[[^\]]+\]/);
602
+ const end = nextSectionOffset === -1 ? content.length : afterHeader + nextSectionOffset;
603
+ content = `${content.slice(0, start).trimEnd()}\n\n${sectionBlock}\n${content.slice(end).trimStart()}`;
604
+ }
605
+
606
+ writeFileSync(codexConfigPath, content.replace(/\n{3,}/g, '\n\n'), 'utf-8');
607
+ return { registered: true, path: codexConfigPath };
608
+ } catch (err) {
609
+ return {
610
+ registered: false,
611
+ path: codexConfigPath,
612
+ error: err instanceof Error ? err.message : String(err),
613
+ };
614
+ }
615
+ }
616
+
475
617
  function generateEmptyBundle(domain: string): string {
476
618
  return JSON.stringify(
477
619
  {
@@ -0,0 +1,35 @@
1
+ import type { AgentConfig } from '../types.js';
2
+
3
+ /**
4
+ * Generate AGENTS.md content for Codex sessions.
5
+ */
6
+ export function generateAgentsMd(config: AgentConfig): string {
7
+ const principles = config.principles.map((p) => `- ${p}`).join('\n');
8
+ const domains = config.domains.map((d) => `- ${d}`).join('\n');
9
+
10
+ return `# AGENTS.md instructions for this project
11
+
12
+ ## Agent Identity
13
+ - Name: ${config.name}
14
+ - Role: ${config.role}
15
+ - Agent MCP prefix: \`${config.id}\`
16
+
17
+ ## Activation
18
+ - Say "Hello, ${config.name}!" to activate persona behavior via \`${config.id}_core\`.
19
+ - Say "Goodbye, ${config.name}!" to deactivate.
20
+
21
+ ## Domains
22
+ ${domains}
23
+
24
+ ## Principles
25
+ ${principles}
26
+
27
+ ## Skills
28
+ - Local skills live in \`skills/<skill>/SKILL.md\`.
29
+ - If a user explicitly names a skill, open that \`SKILL.md\` and follow it for that turn.
30
+
31
+ ## Setup Notes
32
+ - This repository was scaffolded with Codex support.
33
+ - Session model/reasoning is selected at session start and does not auto-switch per prompt.
34
+ `;
35
+ }
@@ -257,10 +257,23 @@ async function main(): Promise<void> {
257
257
  messages: [{ role: 'assistant' as const, content: { type: 'text' as const, text: getPersonaPrompt() } }],
258
258
  }));
259
259
 
260
- registerAllFacades(server, allFacades);
260
+ // Hot ops — promoted to standalone MCP tools with full schema discovery
261
+ const hotOps = new Set([
262
+ 'search_intelligent',
263
+ 'capture_knowledge',
264
+ 'orchestrate_plan',
265
+ 'orchestrate_execute',
266
+ 'orchestrate_complete',
267
+ ]);
268
+
269
+ registerAllFacades(server, allFacades, {
270
+ agentId: '${config.id}',
271
+ hotOps,
272
+ authPolicy: () => runtime.authPolicy,
273
+ });
261
274
 
262
275
  console.error(\`[\${tag}] \${PERSONA.name} — \${PERSONA.role}\`);
263
- console.error(\`[\${tag}] Registered \${allFacades.length} facades with \${allFacades.reduce((sum, f) => sum + f.ops.length, 0)} operations\`);
276
+ console.error(\`[\${tag}] Registered \${allFacades.length} facades with \${allFacades.reduce((sum, f) => sum + f.ops.length, 0)} operations (\${hotOps.size} hot)\`);
264
277
 
265
278
  // ─── Transport + shutdown ──────────────────────────────────────
266
279
  const transport = new StdioServerTransport();
@@ -16,6 +16,12 @@ export function generatePackageJson(config: AgentConfig): string {
16
16
  test: 'vitest run',
17
17
  'test:watch': 'vitest',
18
18
  'test:coverage': 'vitest run --coverage',
19
+ ...(config.telegram
20
+ ? {
21
+ 'telegram:start': 'node dist/telegram-supervisor.js',
22
+ 'telegram:dev': 'tsx src/telegram-bot.ts',
23
+ }
24
+ : {}),
19
25
  },
20
26
  keywords: ['mcp', 'agent', config.id, ...config.domains.slice(0, 5)],
21
27
  license: 'MIT',
@@ -24,6 +30,7 @@ export function generatePackageJson(config: AgentConfig): string {
24
30
  '@modelcontextprotocol/sdk': '^1.12.1',
25
31
  '@soleri/core': '^2.0.0',
26
32
  zod: '^3.24.2',
33
+ ...(config.telegram ? { grammy: '^1.35.0' } : {}),
27
34
  },
28
35
  optionalDependencies: {
29
36
  '@anthropic-ai/sdk': '^0.39.0',
@@ -4,12 +4,92 @@ import type { AgentConfig } from '../types.js';
4
4
  * Generate a README.md for the scaffolded agent.
5
5
  */
6
6
  export function generateReadme(config: AgentConfig): string {
7
+ const setupTarget = config.setupTarget ?? 'claude';
8
+ const claudeSetup = setupTarget === 'claude' || setupTarget === 'both';
9
+ const codexSetup = setupTarget === 'codex' || setupTarget === 'both';
7
10
  const domainRows = config.domains
8
11
  .map((d) => `| ${d} | *Ready for knowledge capture* |`)
9
12
  .join('\n');
10
13
 
11
14
  const principleLines = config.principles.map((p) => `- ${p}`).join('\n');
12
15
 
16
+ const quickStartSession =
17
+ claudeSetup && codexSetup
18
+ ? 'Start a new Claude Code or Codex session, then say:'
19
+ : claudeSetup
20
+ ? 'Start a new Claude Code session, then say:'
21
+ : 'Start a new Codex session, then say:';
22
+
23
+ const prerequisites = [
24
+ '- **Node.js 18+** — `node --version` to check',
25
+ ...(claudeSetup ? ['- **Claude Code** — Anthropic CLI (`claude` command)'] : []),
26
+ ...(codexSetup ? ['- **Codex** — desktop/CLI with `~/.codex/config.toml`'] : []),
27
+ ].join('\n');
28
+
29
+ const helloFlow = [
30
+ `- ${config.name} returns its persona, principles, and tool recommendations`,
31
+ ...(claudeSetup ? [`- Claude can adopt the ${config.name} persona for the session`] : []),
32
+ ...(claudeSetup
33
+ ? [`- ${config.name} can inject/check CLAUDE.md integration when requested`]
34
+ : []),
35
+ ...(codexSetup
36
+ ? ['- Codex uses project-level AGENTS.md guidance and local skills for routing']
37
+ : []),
38
+ ].join('\n');
39
+
40
+ const manualSetupBlocks = [
41
+ ...(claudeSetup
42
+ ? [
43
+ [
44
+ '### Claude Code',
45
+ '',
46
+ 'Add this to `~/.claude/settings.json` under `mcpServers`:',
47
+ '',
48
+ '```json',
49
+ '{',
50
+ ' "mcpServers": {',
51
+ ` "${config.id}": {`,
52
+ ' "command": "node",',
53
+ ' "args": ["dist/index.js"],',
54
+ ` "cwd": "/absolute/path/to/${config.id}"`,
55
+ ' }',
56
+ ' }',
57
+ '}',
58
+ '```',
59
+ ].join('\n'),
60
+ ]
61
+ : []),
62
+ ...(codexSetup
63
+ ? [
64
+ [
65
+ '### Codex',
66
+ '',
67
+ 'Add this to `~/.codex/config.toml`:',
68
+ '',
69
+ '```toml',
70
+ `[mcp_servers.${config.id}]`,
71
+ 'command = "node"',
72
+ `args = ["/absolute/path/to/${config.id}/dist/index.js"]`,
73
+ '```',
74
+ ].join('\n'),
75
+ ]
76
+ : []),
77
+ ].join('\n\n');
78
+
79
+ const skillsLead =
80
+ claudeSetup && codexSetup
81
+ ? `${config.name} ships with 17 structured workflow skills. In Claude Code they are invocable via \`/<skill-name>\`; in Codex they are available via generated AGENTS.md + local skill files.`
82
+ : claudeSetup
83
+ ? `${config.name} ships with 17 structured workflow skills, invocable via \`/<skill-name>\` in Claude Code:`
84
+ : `${config.name} ships with 17 structured workflow skills, available via generated AGENTS.md + local skill files in Codex:`;
85
+
86
+ const skillsInstallNote =
87
+ claudeSetup && codexSetup
88
+ ? 'Skills are installed to `~/.claude/commands/` and `~/.codex/skills/` during setup. Run `./scripts/setup.sh` to install or reinstall.'
89
+ : claudeSetup
90
+ ? 'Skills are installed to `~/.claude/commands/` during setup. Run `./scripts/setup.sh` to install or reinstall.'
91
+ : 'Skills are installed to `~/.codex/skills/` during setup. Run `./scripts/setup.sh` to install or reinstall.';
92
+
13
93
  return `# ${config.name} — ${config.role}
14
94
 
15
95
  ${config.description}
@@ -35,10 +115,10 @@ cd ${config.id}
35
115
  npm install
36
116
  npm run build
37
117
 
38
- # 2. Add to Claude Code
118
+ # 2. Run setup
39
119
  ./scripts/setup.sh
40
120
 
41
- # 3. Start a new Claude Code session, then say:
121
+ # 3. ${quickStartSession}
42
122
  # "Hello, ${config.name}!"
43
123
  \`\`\`
44
124
 
@@ -46,33 +126,15 @@ That's it. ${config.name} will activate, check your setup, and offer to configur
46
126
 
47
127
  ## Prerequisites
48
128
 
49
- - **Node.js 18+** — \`node --version\` to check
50
- - **Claude Code** — Anthropic's CLI for Claude (\`claude\` command)
129
+ ${prerequisites}
51
130
 
52
131
  ## What Happens When You Say "Hello, ${config.name}!"
53
132
 
54
- 1. ${config.name} returns its persona, principles, and tool recommendations
55
- 2. Claude adopts the ${config.name} persona for the rest of the session
56
- 3. ${config.name} checks if your project has CLAUDE.md integration
57
- 4. If not, it offers to inject its configuration (facades table, intent detection, knowledge protocol)
133
+ ${helloFlow}
58
134
 
59
135
  ## Manual Setup (if setup.sh doesn't work)
60
136
 
61
- Add this to \`~/.claude/settings.json\` under \`mcpServers\`:
62
-
63
- \`\`\`json
64
- {
65
- "mcpServers": {
66
- "${config.id}": {
67
- "command": "node",
68
- "args": ["dist/index.js"],
69
- "cwd": "/absolute/path/to/${config.id}"
70
- }
71
- }
72
- }
73
- \`\`\`
74
-
75
- Then restart Claude Code.
137
+ ${manualSetupBlocks}
76
138
 
77
139
  ## Domains
78
140
 
@@ -86,7 +148,7 @@ ${principleLines}
86
148
 
87
149
  ## Built-in Skills
88
150
 
89
- ${config.name} ships with 17 structured workflow skills, invocable via \`/<skill-name>\` in Claude Code:
151
+ ${skillsLead}
90
152
 
91
153
  **Development Workflows:**
92
154
 
@@ -120,7 +182,7 @@ ${config.name} ships with 17 structured workflow skills, invocable via \`/<skill
120
182
  | \`/onboard-me\` | Instant project knowledge tour for newcomers |
121
183
  | \`/health-check\` | Vault maintenance — duplicates, contradictions, stale entries |
122
184
 
123
- Skills are installed to \`~/.claude/commands/\` during setup. Run \`./scripts/setup.sh\` to install or reinstall.
185
+ ${skillsInstallNote}
124
186
 
125
187
  ## Features
126
188
 
@@ -176,8 +238,8 @@ Use \`llm_status\` to check provider availability and key pool health.
176
238
 
177
239
  ### Activating and Deactivating
178
240
 
179
- - **"Hello, ${config.name}!"** — Activate the persona. Claude adopts ${config.name}'s identity, principles, and tool access for the session.
180
- - **"Goodbye, ${config.name}!"** — Deactivate. Claude returns to its default behavior.
241
+ - **"Hello, ${config.name}!"** — Activate the persona. Your active client session adopts ${config.name}'s identity, principles, and tool access.
242
+ - **"Goodbye, ${config.name}!"** — Deactivate and return to default assistant behavior.
181
243
 
182
244
  ### Daily Workflow
183
245