claude-flow-guidance-implementation 0.1.1 → 0.1.3

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
@@ -24,6 +24,19 @@ npm i -D claude-flow-guidance-implementation
24
24
  npx cf-guidance-impl init --target ~/source/my-project --install-deps
25
25
  ```
26
26
 
27
+ Choose integration target mode explicitly when needed:
28
+
29
+ ```bash
30
+ # default: both Claude + Codex wiring
31
+ npx cf-guidance-impl init --target ~/source/my-project --target-mode both
32
+
33
+ # Claude-only wiring (.claude hooks + settings merge)
34
+ npx cf-guidance-impl init --target ~/source/my-project --target-mode claude
35
+
36
+ # Codex-only wiring (.agents bridge + codex scripts)
37
+ npx cf-guidance-impl init --target ~/source/my-project --target-mode codex
38
+ ```
39
+
27
40
  ## Quickstart
28
41
 
29
42
  ```bash
@@ -34,24 +47,47 @@ npx --yes -p claude-flow-guidance-implementation cf-guidance-impl init --target
34
47
  npx --yes -p claude-flow-guidance-implementation cf-guidance-impl verify --target ~/source/my-project
35
48
  ```
36
49
 
50
+ ## Package Runtime Mode (No Local Guidance Code)
51
+
52
+ You can run guidance directly from `node_modules` and avoid committing copied guidance runtime files.
53
+
54
+ Example `package.json` scripts in a target repo:
55
+
56
+ ```bash
57
+ "guidance:analyze": "node ./node_modules/claude-flow-guidance-implementation/scaffold/scripts/analyze-guidance.js",
58
+ "guidance:optimize": "node ./node_modules/claude-flow-guidance-implementation/scaffold/scripts/guidance-autopilot.js --once --apply --source manual",
59
+ "guidance:ab-benchmark": "node ./node_modules/claude-flow-guidance-implementation/scaffold/scripts/guidance-ab-benchmark.js",
60
+ "guidance:codex:status": "node ./node_modules/claude-flow-guidance-implementation/scaffold/scripts/guidance-codex-bridge.js status"
61
+ ```
62
+
63
+ Project root resolution for scaffold scripts:
64
+ - `GUIDANCE_PROJECT_DIR` (if set)
65
+ - else `CLAUDE_PROJECT_DIR` (if set)
66
+ - else current working directory (`process.cwd()`)
67
+
37
68
  ## CLI commands
38
69
 
39
70
  ```bash
40
- cf-guidance-impl init --target <repoPath> [--force] [--install-deps] [--no-dual] [--skip-cf-init] [--no-verify]
41
- cf-guidance-impl install --target <repoPath> [--force] [--install-deps]
42
- cf-guidance-impl verify --target <repoPath>
71
+ cf-guidance-impl init --target <repoPath> [--target-mode both|claude|codex] [--force] [--install-deps] [--no-dual] [--skip-cf-init] [--no-verify]
72
+ cf-guidance-impl install --target <repoPath> [--target-mode both|claude|codex] [--force] [--install-deps]
73
+ cf-guidance-impl verify --target <repoPath> [--target-mode both|claude|codex]
43
74
  ```
44
75
 
45
76
  ## What `init` does
46
77
 
47
78
  `cf-guidance-impl init` performs:
48
- 1. `npx @claude-flow/cli@latest init --dual` in target repo (unless `--skip-cf-init`)
49
- 2. installs scaffold runtime files (`scripts/`, `src/guidance/`, `.claude/helpers/hook-handler.cjs`, docs)
50
- 3. merges target `package.json` scripts + guidance deps
51
- 4. merges `.claude/settings.json` env and hook blocks
52
- 5. appends Codex bridge sections to `.agents/config.toml` and `AGENTS.md`
53
- 6. creates `CLAUDE.local.md` stub and updates `.gitignore`
54
- 7. verifies wiring (unless `--no-verify`)
79
+ 1. runs `npx @claude-flow/cli@latest init` in target repo (unless `--skip-cf-init`)
80
+ 2. adds init flags by mode:
81
+ - `--target-mode both` + default dual -> `--dual`
82
+ - `--target-mode codex` -> `--codex`
83
+ - `--target-mode claude` -> no codex flag
84
+ - `--no-dual` only affects `both` mode (skips `--dual`)
85
+ 3. installs scaffold runtime files (`scripts/`, `src/guidance/`, `.claude/helpers/hook-handler.cjs`, docs)
86
+ 4. merges target `package.json` scripts + guidance deps (Codex scripts only for `both|codex`)
87
+ 5. merges `.claude/settings.json` env and hook blocks (only for `both|claude`)
88
+ 6. appends Codex bridge sections to `.agents/config.toml` and `AGENTS.md` (only for `both|codex`)
89
+ 7. creates `CLAUDE.local.md` stub and updates `.gitignore`
90
+ 8. verifies wiring for selected mode (unless `--no-verify`)
55
91
 
56
92
  ## Codex lifecycle integration
57
93
 
@@ -9,9 +9,9 @@ const toolkitRoot = resolve(__dirname, '..');
9
9
 
10
10
  function usage() {
11
11
  console.log(`Usage:
12
- cf-guidance-impl init --target <repoPath> [--force] [--install-deps] [--no-dual] [--skip-cf-init] [--no-verify]
13
- cf-guidance-impl install --target <repoPath> [--force] [--install-deps]
14
- cf-guidance-impl verify --target <repoPath>
12
+ cf-guidance-impl init --target <repoPath> [--target-mode both|claude|codex] [--force] [--install-deps] [--no-dual] [--skip-cf-init] [--no-verify]
13
+ cf-guidance-impl install --target <repoPath> [--target-mode both|claude|codex] [--force] [--install-deps]
14
+ cf-guidance-impl verify --target <repoPath> [--target-mode both|claude|codex]
15
15
  `);
16
16
  }
17
17
 
@@ -34,6 +34,7 @@ async function main() {
34
34
  }
35
35
 
36
36
  const target = getFlagValue(args, '--target', process.cwd());
37
+ const targetMode = getFlagValue(args, '--target-mode', 'both');
37
38
  const force = hasFlag(args, '--force');
38
39
  const installDeps = hasFlag(args, '--install-deps');
39
40
 
@@ -41,6 +42,7 @@ async function main() {
41
42
  const result = initRepo({
42
43
  toolkitRoot,
43
44
  targetRepo: target,
45
+ targetMode,
44
46
  force,
45
47
  installDeps,
46
48
  dual: !hasFlag(args, '--no-dual'),
@@ -52,13 +54,19 @@ async function main() {
52
54
  }
53
55
 
54
56
  if (command === 'install') {
55
- const result = installIntoRepo({ toolkitRoot, targetRepo: target, force, installDeps });
57
+ const result = installIntoRepo({
58
+ toolkitRoot,
59
+ targetRepo: target,
60
+ targetMode,
61
+ force,
62
+ installDeps,
63
+ });
56
64
  console.log(JSON.stringify(result, null, 2));
57
65
  return;
58
66
  }
59
67
 
60
68
  if (command === 'verify') {
61
- const report = verifyRepo({ targetRepo: target });
69
+ const report = verifyRepo({ targetRepo: target, targetMode });
62
70
  console.log(JSON.stringify(report, null, 2));
63
71
  process.exit(report.passed ? 0 : 2);
64
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow-guidance-implementation",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Reusable guidance control-plane implementation kit for wiring @claude-flow/guidance into any repo",
5
5
  "type": "module",
6
6
  "private": false,
@@ -12,7 +12,7 @@ import { resolve, dirname } from 'node:path';
12
12
  import { fileURLToPath } from 'node:url';
13
13
 
14
14
  const __dirname = dirname(fileURLToPath(import.meta.url));
15
- const root = resolve(__dirname, '..');
15
+ const root = resolve(process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd());
16
16
 
17
17
  // Import guidance modules
18
18
  const { analyze, autoOptimize, formatReport, formatBenchmark } = await import('@claude-flow/guidance/analyzer');
@@ -7,7 +7,9 @@ import { abBenchmark } from '@claude-flow/guidance/analyzer';
7
7
  import { createSyntheticContentAwareExecutor } from '../src/guidance/content-aware-executor.js';
8
8
 
9
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
10
- const rootDir = resolve(__dirname, '..');
10
+ const rootDir = resolve(
11
+ process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd()
12
+ );
11
13
  const guidanceDir = resolve(rootDir, '.claude-flow', 'guidance');
12
14
  const reportPath = resolve(guidanceDir, 'ab-benchmark-report.json');
13
15
 
@@ -19,7 +19,9 @@ import { createCompiler } from '@claude-flow/guidance/compiler';
19
19
  import { createSyntheticContentAwareExecutor } from '../src/guidance/content-aware-executor.js';
20
20
 
21
21
  const __dirname = dirname(fileURLToPath(import.meta.url));
22
- const rootDir = resolve(__dirname, '..');
22
+ const rootDir = resolve(
23
+ process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd()
24
+ );
23
25
 
24
26
  const DEFAULTS = {
25
27
  mode: 'once',
@@ -5,7 +5,9 @@ import { dirname, resolve } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
 
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
- const rootDir = resolve(__dirname, '..');
8
+ const rootDir = resolve(
9
+ process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd()
10
+ );
9
11
 
10
12
  const SUPPORTED_EVENTS = new Set([
11
13
  'pre-command',
@@ -6,7 +6,9 @@ import { fileURLToPath } from 'node:url';
6
6
  import { createGuidanceAdvancedRuntime } from '../src/guidance/advanced-runtime.js';
7
7
 
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const rootDir = resolve(__dirname, '..');
9
+ const rootDir = resolve(
10
+ process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd()
11
+ );
10
12
 
11
13
  function usage() {
12
14
  console.log(`Usage:
@@ -5,7 +5,9 @@ import { fileURLToPath } from 'node:url';
5
5
  import { createGuidancePhase1Runtime } from '../src/guidance/phase1-runtime.js';
6
6
 
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
- const rootDir = resolve(__dirname, '..');
8
+ const rootDir = resolve(
9
+ process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd()
10
+ );
9
11
 
10
12
  function usage() {
11
13
  console.log(`Usage:
@@ -6,7 +6,9 @@ import { fileURLToPath } from 'node:url';
6
6
  import { scaffold } from '@claude-flow/guidance/generators';
7
7
 
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const rootDir = resolve(__dirname, '..');
9
+ const rootDir = resolve(
10
+ process.env.GUIDANCE_PROJECT_DIR || process.env.CLAUDE_PROJECT_DIR || process.cwd()
11
+ );
10
12
  const defaultOutputDir = resolve(rootDir, '.claude-flow', 'guidance', 'scaffold');
11
13
 
12
14
  function parseArg(flag) {
package/src/installer.mjs CHANGED
@@ -64,6 +64,22 @@ function ensureDir(path) {
64
64
  mkdirSync(path, { recursive: true });
65
65
  }
66
66
 
67
+ function normalizeTargetMode(value = 'both') {
68
+ const mode = String(value || 'both').trim().toLowerCase();
69
+ if (!['both', 'claude', 'codex'].includes(mode)) {
70
+ throw new Error(`Invalid target mode: ${value}. Use one of: both, claude, codex.`);
71
+ }
72
+ return mode;
73
+ }
74
+
75
+ function usesClaudeMode(mode) {
76
+ return mode === 'both' || mode === 'claude';
77
+ }
78
+
79
+ function usesCodexMode(mode) {
80
+ return mode === 'both' || mode === 'codex';
81
+ }
82
+
67
83
  function readJson(path, fallback = {}) {
68
84
  if (!existsSync(path)) return fallback;
69
85
  try {
@@ -138,9 +154,16 @@ function appendBlockIfMissing(path, marker, block, fallback = '') {
138
154
  return true;
139
155
  }
140
156
 
141
- export function installIntoRepo({ toolkitRoot, targetRepo, force = false, installDeps = false }) {
157
+ export function installIntoRepo({
158
+ toolkitRoot,
159
+ targetRepo,
160
+ force = false,
161
+ installDeps = false,
162
+ targetMode = 'both',
163
+ }) {
142
164
  const target = resolve(targetRepo);
143
165
  const scaffold = resolve(toolkitRoot, 'scaffold');
166
+ const mode = normalizeTargetMode(targetMode);
144
167
 
145
168
  if (!existsSync(target)) {
146
169
  throw new Error(`Target repo does not exist: ${target}`);
@@ -171,6 +194,8 @@ export function installIntoRepo({ toolkitRoot, targetRepo, force = false, instal
171
194
  packageJson.type = packageJson.type || 'module';
172
195
  packageJson.scripts = packageJson.scripts || {};
173
196
  for (const [name, cmd] of Object.entries(GUIDANCE_PACKAGE_SCRIPTS)) {
197
+ const isCodexScript = name.startsWith('guidance:codex:');
198
+ if (isCodexScript && !usesCodexMode(mode)) continue;
174
199
  if (!(name in packageJson.scripts)) {
175
200
  packageJson.scripts[name] = cmd;
176
201
  }
@@ -185,35 +210,45 @@ export function installIntoRepo({ toolkitRoot, targetRepo, force = false, instal
185
210
 
186
211
  writeJson(packagePath, packageJson);
187
212
 
188
- // Merge .claude/settings.json hooks and env.
189
- const settingsPath = resolve(target, '.claude/settings.json');
190
- const settings = readJson(settingsPath, {});
191
- settings.env = settings.env || {};
192
- for (const [key, value] of Object.entries(GUIDANCE_ENV_DEFAULTS)) {
193
- if (!(key in settings.env)) settings.env[key] = value;
194
- }
195
-
196
- settings.hooks = settings.hooks || {};
197
- for (const [event, blocks] of Object.entries(GUIDANCE_HOOKS_DEFAULTS)) {
198
- settings.hooks[event] = mergeHookBlocks(settings.hooks[event], blocks);
199
- }
213
+ let settingsPath = null;
214
+ if (usesClaudeMode(mode)) {
215
+ // Merge .claude/settings.json hooks and env.
216
+ settingsPath = resolve(target, '.claude/settings.json');
217
+ const settings = readJson(settingsPath, {});
218
+ settings.env = settings.env || {};
219
+ for (const [key, value] of Object.entries(GUIDANCE_ENV_DEFAULTS)) {
220
+ if (!(key in settings.env)) settings.env[key] = value;
221
+ }
200
222
 
201
- writeJson(settingsPath, settings);
223
+ settings.hooks = settings.hooks || {};
224
+ for (const [event, blocks] of Object.entries(GUIDANCE_HOOKS_DEFAULTS)) {
225
+ settings.hooks[event] = mergeHookBlocks(settings.hooks[event], blocks);
226
+ }
202
227
 
203
- const agentsConfigPath = resolve(target, '.agents/config.toml');
204
- const codexConfigAdded = appendBlockIfMissing(
205
- agentsConfigPath,
206
- '[guidance_codex]',
207
- GUIDANCE_CODEX_CONFIG_BLOCK
208
- );
228
+ writeJson(settingsPath, settings);
229
+ }
209
230
 
210
- const agentsDocPath = resolve(target, 'AGENTS.md');
211
- const codexAgentsDocAdded = appendBlockIfMissing(
212
- agentsDocPath,
213
- '## Guidance Lifecycle Wiring (Codex)',
214
- GUIDANCE_CODEX_AGENTS_BLOCK,
215
- '# Project\n\n'
216
- );
231
+ let agentsConfigPath = null;
232
+ let agentsDocPath = null;
233
+ let codexConfigAdded = false;
234
+ let codexAgentsDocAdded = false;
235
+
236
+ if (usesCodexMode(mode)) {
237
+ agentsConfigPath = resolve(target, '.agents/config.toml');
238
+ codexConfigAdded = appendBlockIfMissing(
239
+ agentsConfigPath,
240
+ '[guidance_codex]',
241
+ GUIDANCE_CODEX_CONFIG_BLOCK
242
+ );
243
+
244
+ agentsDocPath = resolve(target, 'AGENTS.md');
245
+ codexAgentsDocAdded = appendBlockIfMissing(
246
+ agentsDocPath,
247
+ '## Guidance Lifecycle Wiring (Codex)',
248
+ GUIDANCE_CODEX_AGENTS_BLOCK,
249
+ '# Project\n\n'
250
+ );
251
+ }
217
252
 
218
253
  // Ensure local guidance file and gitignore entries.
219
254
  writeMissingStub(
@@ -232,6 +267,7 @@ export function installIntoRepo({ toolkitRoot, targetRepo, force = false, instal
232
267
 
233
268
  const summary = {
234
269
  target,
270
+ targetMode: mode,
235
271
  copiedFrom: relative(target, scaffold),
236
272
  filesInstalled: [
237
273
  '.claude/helpers/hook-handler.cjs',
@@ -270,18 +306,24 @@ export function installIntoRepo({ toolkitRoot, targetRepo, force = false, instal
270
306
  return summary;
271
307
  }
272
308
 
273
- export function verifyRepo({ targetRepo }) {
309
+ export function verifyRepo({ targetRepo, targetMode = 'both' }) {
274
310
  const target = resolve(targetRepo);
311
+ const mode = normalizeTargetMode(targetMode);
275
312
  const requiredFiles = [
276
313
  '.claude/helpers/hook-handler.cjs',
277
314
  'scripts/guidance-integrations.js',
278
315
  'scripts/guidance-runtime.js',
279
- 'scripts/guidance-codex-bridge.js',
280
316
  'src/guidance/phase1-runtime.js',
281
- '.claude/settings.json',
282
317
  'package.json',
283
318
  ];
284
319
 
320
+ if (usesCodexMode(mode)) {
321
+ requiredFiles.push('scripts/guidance-codex-bridge.js');
322
+ requiredFiles.push('.agents/config.toml');
323
+ requiredFiles.push('AGENTS.md');
324
+ }
325
+ if (usesClaudeMode(mode)) requiredFiles.push('.claude/settings.json');
326
+
285
327
  const checks = [];
286
328
  for (const relPath of requiredFiles) {
287
329
  const full = resolve(target, relPath);
@@ -293,9 +335,10 @@ export function verifyRepo({ targetRepo }) {
293
335
  '.claude/helpers/hook-handler.cjs',
294
336
  'scripts/guidance-integrations.js',
295
337
  'scripts/guidance-runtime.js',
296
- 'scripts/guidance-codex-bridge.js',
297
338
  ];
298
339
 
340
+ if (usesCodexMode(mode)) checkFiles.push('scripts/guidance-codex-bridge.js');
341
+
299
342
  for (const relPath of checkFiles) {
300
343
  const full = resolve(target, relPath);
301
344
  if (!existsSync(full)) {
@@ -311,29 +354,36 @@ export function verifyRepo({ targetRepo }) {
311
354
  }
312
355
 
313
356
  const smokeInput = '{"tool_input":{"command":"git status"}}';
314
- const smoke = run(
315
- 'bash',
316
- [
317
- '-lc',
318
- `printf '%s' '${smokeInput}' | node .claude/helpers/hook-handler.cjs pre-bash`,
319
- ],
320
- target
321
- );
357
+ let smoke = { status: 0, stdout: '', stderr: '' };
358
+ if (usesClaudeMode(mode)) {
359
+ smoke = run(
360
+ 'bash',
361
+ [
362
+ '-lc',
363
+ `printf '%s' '${smokeInput}' | node .claude/helpers/hook-handler.cjs pre-bash`,
364
+ ],
365
+ target
366
+ );
367
+ }
322
368
 
323
- const smokeCodex = run(
324
- 'node',
325
- ['scripts/guidance-codex-bridge.js', 'status', '--skip-cf-hooks'],
326
- target
327
- );
369
+ let smokeCodex = { status: 0, stdout: '', stderr: '' };
370
+ if (usesCodexMode(mode)) {
371
+ smokeCodex = run(
372
+ 'node',
373
+ ['scripts/guidance-codex-bridge.js', 'status', '--skip-cf-hooks'],
374
+ target
375
+ );
376
+ }
328
377
 
329
378
  const passed =
330
379
  checks.every((check) => check.exists) &&
331
380
  syntaxChecks.every((check) => check.ok) &&
332
- smoke.status === 0 &&
333
- smokeCodex.status === 0;
381
+ (!usesClaudeMode(mode) || smoke.status === 0) &&
382
+ (!usesCodexMode(mode) || smokeCodex.status === 0);
334
383
 
335
384
  return {
336
385
  target,
386
+ targetMode: mode,
337
387
  passed,
338
388
  files: checks,
339
389
  syntaxChecks,
@@ -355,11 +405,13 @@ export function initRepo({
355
405
  targetRepo,
356
406
  force = false,
357
407
  installDeps = false,
408
+ targetMode = 'both',
358
409
  dual = true,
359
410
  skipCfInit = false,
360
411
  verify = true,
361
412
  }) {
362
413
  const target = resolve(targetRepo);
414
+ const mode = normalizeTargetMode(targetMode);
363
415
  if (!existsSync(target)) {
364
416
  throw new Error(`Target repo does not exist: ${target}`);
365
417
  }
@@ -371,7 +423,11 @@ export function initRepo({
371
423
 
372
424
  if (!skipCfInit) {
373
425
  const initArgs = ['@claude-flow/cli@latest', 'init'];
374
- if (dual) initArgs.push('--dual');
426
+ if (mode === 'both') {
427
+ if (dual) initArgs.push('--dual');
428
+ } else if (mode === 'codex') {
429
+ initArgs.push('--codex');
430
+ }
375
431
 
376
432
  const initResult = run('npx', initArgs, target);
377
433
  claudeFlowInit = {
@@ -394,11 +450,12 @@ export function initRepo({
394
450
  targetRepo: target,
395
451
  force,
396
452
  installDeps,
453
+ targetMode: mode,
397
454
  });
398
455
 
399
456
  let verifyReport = null;
400
457
  if (verify) {
401
- verifyReport = verifyRepo({ targetRepo: target });
458
+ verifyReport = verifyRepo({ targetRepo: target, targetMode: mode });
402
459
  if (!verifyReport.passed) {
403
460
  throw new Error(
404
461
  `Guidance wiring verification failed in ${target}. Run cf-guidance-impl verify --target ${target} for details.`
@@ -408,6 +465,7 @@ export function initRepo({
408
465
 
409
466
  return {
410
467
  target,
468
+ targetMode: mode,
411
469
  claudeFlowInit,
412
470
  install,
413
471
  verify: verifyReport,