create-issflow 1.0.3 → 1.2.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 (45) hide show
  1. package/README.md +61 -56
  2. package/bin/cli.js +270 -259
  3. package/package.json +32 -28
  4. package/template/.claude/agents/debugger.md +47 -47
  5. package/template/.claude/agents/e2e-runner.md +66 -66
  6. package/template/.claude/agents/implementer.md +79 -75
  7. package/template/.claude/agents/planner.md +93 -71
  8. package/template/.claude/agents/researcher.md +103 -103
  9. package/template/.claude/agents/synthesizer.md +78 -72
  10. package/template/.claude/agents/test-author.md +70 -70
  11. package/template/.claude/commands/change-request.md +53 -0
  12. package/template/.claude/commands/log-decision.md +33 -33
  13. package/template/.claude/commands/log-issue.md +28 -28
  14. package/template/.claude/commands/overview.md +114 -99
  15. package/template/.claude/commands/phase.md +230 -202
  16. package/template/.claude/commands/propose.md +71 -0
  17. package/template/.claude/commands/qa-audit.md +53 -0
  18. package/template/.claude/commands/quick.md +30 -30
  19. package/template/.claude/commands/replan.md +68 -63
  20. package/template/.claude/commands/security-audit.md +56 -0
  21. package/template/.claude/commands/store-wisdom.md +195 -195
  22. package/template/.claude/commands/synthesize.md +26 -26
  23. package/template/.claude/commands/ui-audit.md +54 -0
  24. package/template/.claude/commands/unstuck.md +40 -40
  25. package/template/.claude/hooks/pre-compact.js +42 -0
  26. package/template/.claude/hooks/session-start.js +137 -0
  27. package/template/.claude/hooks/subagent-stop.js +18 -0
  28. package/template/.claude/istartsoft-flow/METHODOLOGY.md +432 -229
  29. package/template/.claude/skills/caveman/SKILL.md +39 -39
  30. package/template/.claude/skills/code-standards/SKILL.md +61 -0
  31. package/template/.claude/skills/code-standards/references/architecture.md +61 -0
  32. package/template/.claude/skills/code-standards/references/naming.md +60 -0
  33. package/template/.claude/skills/grill-me/SKILL.md +31 -10
  34. package/template/.claude/skills/karpathy-guidelines/SKILL.md +34 -34
  35. package/template/.claude/skills/security/SKILL.md +70 -0
  36. package/template/.claude/skills/security/references/pentest-checklist.md +46 -0
  37. package/template/.claude/skills/security/references/secure-coding.md +50 -0
  38. package/template/.claude/skills/security/references/standards.md +60 -0
  39. package/template/.claude/skills/security/references/threat-modeling.md +36 -0
  40. package/template/.claude/skills/ux-design/SKILL.md +117 -99
  41. package/template/.claude/skills/ux-design/{wireframe-template.md → references/wireframe-template.md} +95 -95
  42. package/template/.claude/templates/proposal.html +126 -0
  43. package/template/.claude/hooks/pre-compact.sh +0 -25
  44. package/template/.claude/hooks/session-start.sh +0 -120
  45. package/template/.claude/hooks/subagent-stop.sh +0 -11
package/bin/cli.js CHANGED
@@ -1,259 +1,270 @@
1
- #!/usr/bin/env node
2
- // create-issflow — scaffold the iStartSoftFlow agentic-dev workflow into the
3
- // current project. Pure Node, zero deps, cross-platform, NON-DESTRUCTIVE:
4
- // never overwrites an existing file — on conflict it writes `<file>.issflow-new`.
5
- //
6
- // Tool-agnostic: the portable kit lives in `.claude/` and the methodology is the
7
- // single source of truth. `--tool=<name>` writes the right adapter so the same
8
- // kit drives Claude Code, Codex, Cursor, Gemini CLI, Aider, or any AGENTS.md tool.
9
- 'use strict';
10
- const fs = require('fs');
11
- const path = require('path');
12
-
13
- const TPL = path.join(__dirname, '..', 'template');
14
- const CWD = process.cwd();
15
- const argv = process.argv.slice(2);
16
- const DRY = argv.includes('--dry-run');
17
- const FORCE = argv.includes('--force');
18
- const HELP = argv.includes('-h') || argv.includes('--help');
19
- const toolArg = (argv.find(a => a.startsWith('--tool=')) || '').split('=')[1];
20
-
21
- const TOOLS = {
22
- claude: 'Claude Code (Anthropic) — full: subagents, lifecycle hooks, skills',
23
- codex: 'OpenAI Codex CLI — AGENTS.md native; subagents/skills as readable files',
24
- cursor: 'Cursor — .cursor/rules + commands + hooks; reads .claude/agents natively',
25
- gemini: 'Google Gemini CLI — GEMINI.md pointer; commands/skills as readable files',
26
- aider: 'Aider — .aider.conf.yml loads the methodology as conventions',
27
- all: 'Write every adapter above (mixed-team repo)',
28
- };
29
-
30
- let created = 0, skipped = 0, conflicts = 0;
31
- const warnings = [];
32
- const log = (...a) => console.log(...a);
33
-
34
- // ---- helpers ----------------------------------------------------------------
35
-
36
- function printHelp() {
37
- log(`create-issflow — scaffold the iStartSoftFlow workflow.
38
-
39
- Usage: npx create-issflow [--tool=<name>] [--dry-run] [--force]
40
-
41
- Tools (--tool=, interactive prompt if omitted):`);
42
- for (const [k, v] of Object.entries(TOOLS)) log(` ${k.padEnd(7)} ${v}`);
43
- log(`
44
- Flags:
45
- --dry-run print what would happen, write nothing
46
- --force overwrite existing kit files (default keeps yours -> <file>.issflow-new)
47
- -h, --help this message
48
-
49
- Every tool installs the portable kit in .claude/ + a root AGENTS.md (the open
50
- standard). The full methodology lives in .claude/istartsoft-flow/METHODOLOGY.md.`);
51
- }
52
-
53
- // Resolve the target tool: flag -> interactive (TTY) -> default 'claude'.
54
- function pickTool() {
55
- if (toolArg) {
56
- if (!TOOLS[toolArg]) { console.error(`create-issflow: unknown --tool=${toolArg}. One of: ${Object.keys(TOOLS).join(', ')}`); process.exit(1); }
57
- return toolArg;
58
- }
59
- if (process.stdin.isTTY && process.stdout.isTTY && !DRY) {
60
- const keys = Object.keys(TOOLS);
61
- process.stdout.write('\nWhich AI coding tool? (the kit is portable — pick your primary)\n');
62
- keys.forEach((k, i) => process.stdout.write(` ${i + 1}) ${k} — ${TOOLS[k]}\n`));
63
- process.stdout.write('> ');
64
- let line = '';
65
- try { line = (fs.readFileSync(0, 'utf8').split('\n')[0] || '').trim().toLowerCase(); } catch (_) {}
66
- const chosen = TOOLS[line] ? line : keys[parseInt(line, 10) - 1];
67
- if (!chosen) { console.error('create-issflow: no valid choice; defaulting to claude.'); return 'claude'; }
68
- return chosen;
69
- }
70
- return 'claude'; // non-interactive default = back-compatible
71
- }
72
-
73
- // write a single file, non-destructive (honors DRY/FORCE).
74
- function writeFile(rel, content, { exec = false } = {}) {
75
- const dest = path.join(CWD, rel);
76
- const exists = fs.existsSync(dest);
77
- if (exists && !FORCE) {
78
- if (fs.readFileSync(dest, 'utf8') === content) { skipped++; return; }
79
- const alt = dest + '.issflow-new';
80
- conflicts++; log(` ~ conflict, wrote ${path.relative(CWD, alt)} (yours kept)`);
81
- if (!DRY) { fs.mkdirSync(path.dirname(alt), { recursive: true }); fs.writeFileSync(alt, content); }
82
- return;
83
- }
84
- created++; log(` + ${rel}${exists ? ' (overwrote, --force)' : ''}`);
85
- if (!DRY) {
86
- fs.mkdirSync(path.dirname(dest), { recursive: true });
87
- fs.writeFileSync(dest, content);
88
- if (exec) { try { fs.chmodSync(dest, 0o755); } catch (_) {} }
89
- }
90
- }
91
-
92
- function walk(dir) {
93
- const out = [];
94
- for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
95
- const p = path.join(dir, e.name);
96
- if (e.isDirectory()) out.push(...walk(p)); else out.push(p);
97
- }
98
- return out;
99
- }
100
-
101
- function copyTemplateCommands(destDir) {
102
- const cmdDir = path.join(TPL, '.claude', 'commands');
103
- if (!fs.existsSync(cmdDir)) return;
104
- for (const f of fs.readdirSync(cmdDir)) writeFile(path.join(destDir, f), fs.readFileSync(path.join(cmdDir, f), 'utf8'));
105
- }
106
-
107
- // ---- adapters (keep the methodology single-source — these POINT at it) ------
108
-
109
- function adapterClaude() {
110
- const HOOKS = {
111
- SessionStart: [{ matcher: 'startup|clear|compact', hooks: [{ type: 'command', command: 'bash .claude/hooks/session-start.sh' }] }],
112
- PreCompact: [{ matcher: 'auto|manual', hooks: [{ type: 'command', command: 'bash .claude/hooks/pre-compact.sh' }] }],
113
- SubagentStop: [{ hooks: [{ type: 'command', command: 'bash .claude/hooks/subagent-stop.sh' }] }],
114
- };
115
- const sp = path.join(CWD, '.claude', 'settings.json');
116
- let settings = {};
117
- if (fs.existsSync(sp)) { try { settings = JSON.parse(fs.readFileSync(sp, 'utf8')); } catch (_) { warnings.push('.claude/settings.json is not valid JSON — skipped hook merge'); settings = null; } }
118
- if (!settings) return;
119
- settings.hooks = settings.hooks || {};
120
- const added = [];
121
- for (const k of Object.keys(HOOKS)) if (!settings.hooks[k]) { settings.hooks[k] = HOOKS[k]; added.push(k); }
122
- if (added.length) { log(` + .claude/settings.json hooks: ${added.join(', ')}`); if (!DRY) { fs.mkdirSync(path.dirname(sp), { recursive: true }); fs.writeFileSync(sp, JSON.stringify(settings, null, 2) + '\n'); } }
123
- else log(' = .claude/settings.json hooks already present');
124
- }
125
-
126
- function adapterCodex() {
127
- warnings.push('codex: AGENTS.md is read natively. Lifecycle hooks unsupported (rituals model-run); subagents in .claude/agents/ are read as reference, not isolated contexts.');
128
- }
129
-
130
- function adapterCursor() {
131
- writeFile('.cursor/rules/istartsoftflow.mdc', [
132
- '---', 'description: iStartSoftFlow workflow — always apply', 'alwaysApply: true', '---', '',
133
- 'Run the **iStartSoftFlow** workflow. The full, single-source methodology is',
134
- '`.claude/istartsoft-flow/METHODOLOGY.md` — read it before acting. Roles live in',
135
- '`.claude/agents/` (Cursor reads them natively); procedures in `.cursor/commands/`',
136
- '(mirror of `.claude/commands/`). Caveman ULTRA mode; apply the `karpathy-guidelines`',
137
- 'and `ux-design` skills. See `AGENTS.md` for the role/command/skill map.', '',
138
- ].join('\n'));
139
- copyTemplateCommands('.cursor/commands');
140
- writeFile('.cursor/hooks.json', JSON.stringify({
141
- version: 1,
142
- hooks: {
143
- sessionStart: [{ command: 'bash .claude/hooks/session-start.sh' }],
144
- subagentStop: [{ command: 'bash .claude/hooks/subagent-stop.sh' }],
145
- },
146
- }, null, 2) + '\n');
147
- warnings.push('cursor: PreCompact has no Cursor equivalent (snapshot ritual degrades to model-run); verify hooks.json against cursor.com/docs/hooks — the schema evolves.');
148
- }
149
-
150
- function adapterGemini() {
151
- writeFile('GEMINI.md', [
152
- '# GEMINI.md — iStartSoftFlow', '',
153
- 'This repo runs the **iStartSoftFlow** agentic dev workflow. The complete,',
154
- 'tool-agnostic methodology (the single source of truth) lives in',
155
- '`.claude/istartsoft-flow/METHODOLOGY.md` — read it before acting. Roles are in',
156
- '`.claude/agents/`, procedures in `.claude/commands/` (run their bodies as prompts),',
157
- 'skills in `.claude/skills/` (read on demand). See `AGENTS.md` for the full map.', '',
158
- 'Lifecycle hooks do not auto-fire in Gemini CLI — run the SESSION-OPEN ritual',
159
- '(git state, docs/STATE.md, docs/ISSUES.md) yourself at the start of each session.', '',
160
- ].join('\n'));
161
- warnings.push('gemini: lifecycle hooks unsupported — SESSION-OPEN / PreCompact rituals are model-run (see GEMINI.md).');
162
- }
163
-
164
- function adapterAider() {
165
- writeFile('.aider.conf.yml', [
166
- '# iStartSoftFlow — load the methodology as conventions.',
167
- '# Aider has no lifecycle hooks/subagents; the workflow degrades to model-run rituals.',
168
- 'read:',
169
- ' - AGENTS.md',
170
- ' - .claude/istartsoft-flow/METHODOLOGY.md',
171
- '',
172
- ].join('\n'));
173
- warnings.push('aider: hooks + named subagents unsupported — the loop runs as a single-agent, model-driven workflow.');
174
- }
175
-
176
- const ADAPTERS = { claude: adapterClaude, codex: adapterCodex, cursor: adapterCursor, gemini: adapterGemini, aider: adapterAider };
177
-
178
- const NEXT_STEPS = {
179
- claude: 'Open Claude Code — the SessionStart hook fires automatically. Run /overview to bootstrap.',
180
- codex: 'Open Codex CLI — it reads AGENTS.md. Start by running the /overview procedure (.claude/commands/overview.md).',
181
- cursor: 'Open Cursor — the rule applies automatically. Run the /overview command to bootstrap.',
182
- gemini: 'Open Gemini CLI — it reads GEMINI.md. Run the SESSION-OPEN ritual, then the overview procedure.',
183
- aider: 'Run aider — it loads AGENTS.md + METHODOLOGY.md. Drive the loop manually (overview -> phase).',
184
- all: 'Open your tool of choice — AGENTS.md is the shared entry. Run /overview to bootstrap.',
185
- };
186
-
187
- function agentsMd() {
188
- return [
189
- '# AGENTS.md — iStartSoftFlow', '',
190
- 'This repo runs the **iStartSoftFlow** agentic dev workflow. The complete,',
191
- 'tool-agnostic methodology — the loop, roles, procedures, rituals, and hard',
192
- 'rules — lives in ONE file. Read it before acting:', '',
193
- '> **`.claude/istartsoft-flow/METHODOLOGY.md`** ← single source of truth.', '',
194
- 'Do not restate its rules elsewhere; this file only indexes it (anti-drift invariant).', '',
195
- '## The loop', '',
196
- 'design-research → grill ×2 → plan → implement → test → deploy — one VERTICAL',
197
- 'SLICE per phase. Phase 0 (infra) leads only when infra is self-managed.', '',
198
- '## Roles — `.claude/agents/`', '',
199
- 'planner · researcher · implementer · test-author · debugger · e2e-runner · synthesizer', '',
200
- '## Procedures — `.claude/commands/` (run as `/name`)', '',
201
- '/overview · /phase · /quick · /replan · /synthesize · /store-wisdom · /log-issue · /log-decision · /unstuck', '',
202
- '## Skills `.claude/skills/` (loaded on demand)', '',
203
- 'caveman · grill-me · karpathy-guidelines · ux-design', '',
204
- '## Hard-rule index (full text in METHODOLOGY.md)', '',
205
- '1 grep ISSUES + research before debugging · 2 debug cap = 3 · 3 log every fix ·',
206
- '4 synthesize + context-reset per phase · 5 phase gate = real suite green ·',
207
- '6 blind tests (RED-first) · 7 programmatic E2E auth · 8 log-decision on arch change ·',
208
- '9 UI conforms to the `ux-design` cookbook + wireframe frame · 10 no-rationalization.', '',
209
- '## Your stack', '',
210
- 'Declare your stack (language, framework, infra, auth, test + E2E runner,',
211
- 'planning source) once in `docs/OVERVIEW.md`. Every rule references *your declared',
212
- 'stack* and hardcodes none.', '',
213
- ].join('\n');
214
- }
215
-
216
- // ---- main -------------------------------------------------------------------
217
-
218
- function main() {
219
- if (HELP) { printHelp(); return; }
220
- if (!fs.existsSync(path.join(TPL, '.claude'))) {
221
- console.error('create-issflow: embedded template/ missing. From source run: bash build.sh');
222
- process.exit(1);
223
- }
224
-
225
- const TOOL = pickTool();
226
- const targets = TOOL === 'all' ? Object.keys(TOOLS).filter(t => t !== 'all') : [TOOL];
227
-
228
- // 1. portable kit tree (.claude/) — every tool gets it.
229
- for (const src of walk(path.join(TPL, '.claude'))) {
230
- const rel = path.relative(TPL, src);
231
- const isHook = rel.includes(`${path.sep}hooks${path.sep}`) && rel.endsWith('.sh');
232
- writeFile(rel, fs.readFileSync(src, 'utf8'), { exec: isHook });
233
- }
234
-
235
- // 2. AGENTS.md — the open-standard entry point.
236
- writeFile('AGENTS.md', agentsMd());
237
-
238
- // 3. per-tool adapters
239
- for (const t of targets) ADAPTERS[t]();
240
-
241
- // 4. .gitignore: track the workflow dirs if .claude/* is ignored
242
- const gi = path.join(CWD, '.gitignore');
243
- if (fs.existsSync(gi)) {
244
- const txt = fs.readFileSync(gi, 'utf8');
245
- if (/^\.claude\/\*\s*$/m.test(txt) && !txt.includes('!.claude/agents/')) {
246
- const block = '\n# iStartSoftFlow workflow track as project config\n!.claude/agents/\n!.claude/commands/\n!.claude/skills/\n!.claude/hooks/\n!.claude/istartsoft-flow/\n';
247
- log(' + .gitignore: un-ignore .claude workflow dirs');
248
- if (!DRY) fs.appendFileSync(gi, block);
249
- }
250
- }
251
-
252
- log('');
253
- log(`iStartSoftFlow ${DRY ? '(dry-run) ' : ''}[${TOOL}] done — created ${created}, conflicts ${conflicts}, unchanged ${skipped}.`);
254
- if (conflicts) log('Review *.issflow-new files and merge manually (your originals were untouched).');
255
- for (const w of warnings) log(` ! ${w}`);
256
- log(NEXT_STEPS[TOOL] || NEXT_STEPS.claude);
257
- }
258
-
259
- main();
1
+ #!/usr/bin/env node
2
+ // create-issflow — scaffold the iStartSoftFlow agentic-dev workflow into the
3
+ // current project. Pure Node, zero deps, cross-platform, NON-DESTRUCTIVE:
4
+ // never overwrites an existing file — on conflict it writes `<file>.issflow-new`.
5
+ //
6
+ // Tool-agnostic: the portable kit lives in `.claude/` and the methodology is the
7
+ // single source of truth. `--tool=<name>` writes the right adapter so the same
8
+ // kit drives Claude Code, Codex, Cursor, Gemini CLI, Aider, or any AGENTS.md tool.
9
+ 'use strict';
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const TPL = path.join(__dirname, '..', 'template');
14
+ const CWD = process.cwd();
15
+ const argv = process.argv.slice(2);
16
+ const DRY = argv.includes('--dry-run');
17
+ const FORCE = argv.includes('--force');
18
+ const HELP = argv.includes('-h') || argv.includes('--help');
19
+ const toolArg = (argv.find(a => a.startsWith('--tool=')) || '').split('=')[1];
20
+
21
+ const TOOLS = {
22
+ claude: 'Claude Code (Anthropic) — full: subagents, lifecycle hooks, skills',
23
+ codex: 'OpenAI Codex CLI — AGENTS.md native; subagents/skills as readable files',
24
+ cursor: 'Cursor — .cursor/rules + commands + hooks; reads .claude/agents natively',
25
+ gemini: 'Google Gemini CLI — GEMINI.md pointer; commands/skills as readable files',
26
+ aider: 'Aider — .aider.conf.yml loads the methodology as conventions',
27
+ all: 'Write every adapter above (mixed-team repo)',
28
+ };
29
+
30
+ let created = 0, skipped = 0, conflicts = 0;
31
+ const warnings = [];
32
+ const log = (...a) => console.log(...a);
33
+
34
+ // ---- helpers ----------------------------------------------------------------
35
+
36
+ function printHelp() {
37
+ log(`create-issflow — scaffold the iStartSoftFlow workflow.
38
+
39
+ Usage: npx create-issflow [--tool=<name>] [--dry-run] [--force]
40
+
41
+ Tools (--tool=, interactive prompt if omitted):`);
42
+ for (const [k, v] of Object.entries(TOOLS)) log(` ${k.padEnd(7)} ${v}`);
43
+ log(`
44
+ Flags:
45
+ --dry-run print what would happen, write nothing
46
+ --force overwrite existing kit files (default keeps yours -> <file>.issflow-new)
47
+ -h, --help this message
48
+
49
+ Every tool installs the portable kit in .claude/ + a root AGENTS.md (the open
50
+ standard). The full methodology lives in .claude/istartsoft-flow/METHODOLOGY.md.`);
51
+ }
52
+
53
+ // Resolve the target tool: flag -> interactive (TTY) -> default 'claude'.
54
+ function pickTool() {
55
+ if (toolArg) {
56
+ if (!TOOLS[toolArg]) { console.error(`create-issflow: unknown --tool=${toolArg}. One of: ${Object.keys(TOOLS).join(', ')}`); process.exit(1); }
57
+ return toolArg;
58
+ }
59
+ if (process.stdin.isTTY && process.stdout.isTTY && !DRY) {
60
+ const keys = Object.keys(TOOLS);
61
+ process.stdout.write('\nWhich AI coding tool? (the kit is portable — pick your primary)\n');
62
+ keys.forEach((k, i) => process.stdout.write(` ${i + 1}) ${k} — ${TOOLS[k]}\n`));
63
+ process.stdout.write('> ');
64
+ let line = '';
65
+ try { line = (fs.readFileSync(0, 'utf8').split('\n')[0] || '').trim().toLowerCase(); } catch (_) {}
66
+ const chosen = TOOLS[line] ? line : keys[parseInt(line, 10) - 1];
67
+ if (!chosen) { console.error('create-issflow: no valid choice; defaulting to claude.'); return 'claude'; }
68
+ return chosen;
69
+ }
70
+ return 'claude'; // non-interactive default = back-compatible
71
+ }
72
+
73
+ // write a single file, non-destructive (honors DRY/FORCE).
74
+ function writeFile(rel, content, { exec = false } = {}) {
75
+ const dest = path.join(CWD, rel);
76
+ const exists = fs.existsSync(dest);
77
+ if (exists && !FORCE) {
78
+ if (fs.readFileSync(dest, 'utf8') === content) { skipped++; return; }
79
+ const alt = dest + '.issflow-new';
80
+ conflicts++; log(` ~ conflict, wrote ${path.relative(CWD, alt)} (yours kept)`);
81
+ if (!DRY) { fs.mkdirSync(path.dirname(alt), { recursive: true }); fs.writeFileSync(alt, content); }
82
+ return;
83
+ }
84
+ created++; log(` + ${rel}${exists ? ' (overwrote, --force)' : ''}`);
85
+ if (!DRY) {
86
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
87
+ fs.writeFileSync(dest, content);
88
+ if (exec) { try { fs.chmodSync(dest, 0o755); } catch (_) {} }
89
+ }
90
+ }
91
+
92
+ function walk(dir) {
93
+ const out = [];
94
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
95
+ const p = path.join(dir, e.name);
96
+ if (e.isDirectory()) out.push(...walk(p)); else out.push(p);
97
+ }
98
+ return out;
99
+ }
100
+
101
+ function copyTemplateCommands(destDir) {
102
+ const cmdDir = path.join(TPL, '.claude', 'commands');
103
+ if (!fs.existsSync(cmdDir)) return;
104
+ for (const f of fs.readdirSync(cmdDir)) writeFile(path.join(destDir, f), fs.readFileSync(path.join(cmdDir, f), 'utf8'));
105
+ }
106
+
107
+ // ---- adapters (keep the methodology single-source — these POINT at it) ------
108
+
109
+ function adapterClaude() {
110
+ const HOOKS = {
111
+ SessionStart: [{ matcher: 'startup|clear|compact', hooks: [{ type: 'command', command: 'node .claude/hooks/session-start.js' }] }],
112
+ PreCompact: [{ matcher: 'auto|manual', hooks: [{ type: 'command', command: 'node .claude/hooks/pre-compact.js' }] }],
113
+ SubagentStop: [{ hooks: [{ type: 'command', command: 'node .claude/hooks/subagent-stop.js' }] }],
114
+ };
115
+ const sp = path.join(CWD, '.claude', 'settings.json');
116
+ let settings = {};
117
+ if (fs.existsSync(sp)) { try { settings = JSON.parse(fs.readFileSync(sp, 'utf8')); } catch (_) { warnings.push('.claude/settings.json is not valid JSON — skipped hook merge'); settings = null; } }
118
+ if (!settings) return;
119
+ settings.hooks = settings.hooks || {};
120
+ const added = [];
121
+ for (const k of Object.keys(HOOKS)) if (!settings.hooks[k]) { settings.hooks[k] = HOOKS[k]; added.push(k); }
122
+ if (added.length) { log(` + .claude/settings.json hooks: ${added.join(', ')}`); if (!DRY) { fs.mkdirSync(path.dirname(sp), { recursive: true }); fs.writeFileSync(sp, JSON.stringify(settings, null, 2) + '\n'); } }
123
+ else log(' = .claude/settings.json hooks already present');
124
+ }
125
+
126
+ function adapterCodex() {
127
+ warnings.push('codex: AGENTS.md is read natively. Lifecycle hooks unsupported (rituals model-run); subagents in .claude/agents/ are read as reference, not isolated contexts.');
128
+ }
129
+
130
+ function adapterCursor() {
131
+ writeFile('.cursor/rules/istartsoftflow.mdc', [
132
+ '---', 'description: iStartSoftFlow workflow — always apply', 'alwaysApply: true', '---', '',
133
+ 'Run the **iStartSoftFlow** workflow. The full, single-source methodology is',
134
+ '`.claude/istartsoft-flow/METHODOLOGY.md` — read it before acting. Roles live in',
135
+ '`.claude/agents/` (Cursor reads them natively); procedures in `.cursor/commands/`',
136
+ '(mirror of `.claude/commands/`). Caveman ULTRA mode; apply the `karpathy-guidelines`',
137
+ 'and `ux-design` skills. See `AGENTS.md` for the role/command/skill map.', '',
138
+ ].join('\n'));
139
+ copyTemplateCommands('.cursor/commands');
140
+ writeFile('.cursor/hooks.json', JSON.stringify({
141
+ version: 1,
142
+ hooks: {
143
+ sessionStart: [{ command: 'node .claude/hooks/session-start.js' }],
144
+ subagentStop: [{ command: 'node .claude/hooks/subagent-stop.js' }],
145
+ },
146
+ }, null, 2) + '\n');
147
+ warnings.push('cursor: PreCompact has no Cursor equivalent (snapshot ritual degrades to model-run); verify hooks.json against cursor.com/docs/hooks — the schema evolves.');
148
+ }
149
+
150
+ function adapterGemini() {
151
+ writeFile('GEMINI.md', [
152
+ '# GEMINI.md — iStartSoftFlow', '',
153
+ 'This repo runs the **iStartSoftFlow** agentic dev workflow. The complete,',
154
+ 'tool-agnostic methodology (the single source of truth) lives in',
155
+ '`.claude/istartsoft-flow/METHODOLOGY.md` — read it before acting. Roles are in',
156
+ '`.claude/agents/`, procedures in `.claude/commands/` (run their bodies as prompts),',
157
+ 'skills in `.claude/skills/` (read on demand). See `AGENTS.md` for the full map.', '',
158
+ 'Lifecycle hooks do not auto-fire in Gemini CLI — run the SESSION-OPEN ritual',
159
+ '(git state, docs/STATE.md, docs/ISSUES.md) yourself at the start of each session.', '',
160
+ ].join('\n'));
161
+ warnings.push('gemini: lifecycle hooks unsupported — SESSION-OPEN / PreCompact rituals are model-run (see GEMINI.md).');
162
+ }
163
+
164
+ function adapterAider() {
165
+ writeFile('.aider.conf.yml', [
166
+ '# iStartSoftFlow — load the methodology as conventions.',
167
+ '# Aider has no lifecycle hooks/subagents; the workflow degrades to model-run rituals.',
168
+ 'read:',
169
+ ' - AGENTS.md',
170
+ ' - .claude/istartsoft-flow/METHODOLOGY.md',
171
+ '',
172
+ ].join('\n'));
173
+ warnings.push('aider: hooks + named subagents unsupported — the loop runs as a single-agent, model-driven workflow.');
174
+ }
175
+
176
+ const ADAPTERS = { claude: adapterClaude, codex: adapterCodex, cursor: adapterCursor, gemini: adapterGemini, aider: adapterAider };
177
+
178
+ const NEXT_STEPS = {
179
+ claude: 'Open Claude Code — the SessionStart hook fires automatically. Run /overview to bootstrap.',
180
+ codex: 'Open Codex CLI — it reads AGENTS.md. Start by running the /overview procedure (.claude/commands/overview.md).',
181
+ cursor: 'Open Cursor — the rule applies automatically. Run the /overview command to bootstrap.',
182
+ gemini: 'Open Gemini CLI — it reads GEMINI.md. Run the SESSION-OPEN ritual, then the overview procedure.',
183
+ aider: 'Run aider — it loads AGENTS.md + METHODOLOGY.md. Drive the loop manually (overview -> phase).',
184
+ all: 'Open your tool of choice — AGENTS.md is the shared entry. Run /overview to bootstrap.',
185
+ };
186
+
187
+ function agentsMd() {
188
+ return [
189
+ '# AGENTS.md — iStartSoftFlow', '',
190
+ 'This repo runs the **iStartSoftFlow** agentic dev workflow. The complete,',
191
+ 'tool-agnostic methodology — the loop, roles, procedures, rituals, and hard',
192
+ 'rules — lives in ONE file. Read it before acting:', '',
193
+ '> **`.claude/istartsoft-flow/METHODOLOGY.md`** ← single source of truth.', '',
194
+ 'Do not restate its rules elsewhere; this file only indexes it (anti-drift invariant).', '',
195
+ '## The loop', '',
196
+ 'design-research → grill ×2 → plan → implement → test → deploy — one VERTICAL',
197
+ 'SLICE per phase. Phase 0 (infra) leads only when infra is self-managed.', '',
198
+ '## Roles — `.claude/agents/`', '',
199
+ 'planner · researcher · implementer · test-author · debugger · e2e-runner · synthesizer', '',
200
+ '## Procedures — `.claude/commands/` (run as `/name`)', '',
201
+ '/overview · /propose · /phase · /ui-audit · /qa-audit · /security-audit ·',
202
+ '/change-request · /replan · /quick · /synthesize · /store-wisdom · /log-issue ·',
203
+ '/log-decision · /unstuck', '',
204
+ '## Skills `.claude/skills/` (loaded on demand)', '',
205
+ 'caveman · grill-me · karpathy-guidelines · ux-design · security (Secure SDLC) · code-standards', '',
206
+ '## Autonomy', '',
207
+ 'Planning (`/overview` grill + plan approval) always asks that input is cheap.',
208
+ '**AUTO (default)** governs the DEV loop: follow the plan, decide + log + continue,',
209
+ 'do NOT stop to ask. Hard-stops only: security · irreversible/outbound actions · a',
210
+ 'contradictory spec. Blockers are parked + reported at the phase boundary, not',
211
+ 'mid-flow. **GUIDED** asks at each fork in dev too. Declare the mode in',
212
+ '`docs/OVERVIEW.md`. See METHODOLOGY → Autonomy.', '',
213
+ '## Hard-rule index (full text in METHODOLOGY.md)', '',
214
+ '1 grep ISSUES + research before debugging · 2 debug cap = 3 (AUTO: park + continue) ·',
215
+ '3 log every fix · 4 synthesize + context-reset per phase · 5 phase gate = real suite',
216
+ 'green · 6 blind tests (RED-first) · 7 programmatic E2E auth · 8 log-decision on arch',
217
+ 'change · 9 UI conforms to the `ux-design` cookbook + wireframe frame · 10 no-rationalization ·',
218
+ '11 Secure SDLC: threat-model → secure coding → SAST/SCA/secrets each phase → pentest',
219
+ 'gate + security review before deploy (`security` skill) · 12 code-standards gate:',
220
+ 'lint/format clean + naming per language idiom + declared architecture (`code-standards`).', '',
221
+ '## Your stack', '',
222
+ 'Declare your stack (language, framework, infra, auth, test + E2E runner,',
223
+ 'planning source) once in `docs/OVERVIEW.md`. Every rule references *your declared',
224
+ 'stack* and hardcodes none.', '',
225
+ ].join('\n');
226
+ }
227
+
228
+ // ---- main -------------------------------------------------------------------
229
+
230
+ function main() {
231
+ if (HELP) { printHelp(); return; }
232
+ if (!fs.existsSync(path.join(TPL, '.claude'))) {
233
+ console.error('create-issflow: embedded template/ missing. From source run: npm run build');
234
+ process.exit(1);
235
+ }
236
+
237
+ const TOOL = pickTool();
238
+ const targets = TOOL === 'all' ? Object.keys(TOOLS).filter(t => t !== 'all') : [TOOL];
239
+
240
+ // 1. portable kit tree (.claude/) — every tool gets it.
241
+ for (const src of walk(path.join(TPL, '.claude'))) {
242
+ const rel = path.relative(TPL, src);
243
+ writeFile(rel, fs.readFileSync(src, 'utf8'));
244
+ }
245
+
246
+ // 2. AGENTS.mdthe open-standard entry point.
247
+ writeFile('AGENTS.md', agentsMd());
248
+
249
+ // 3. per-tool adapters
250
+ for (const t of targets) ADAPTERS[t]();
251
+
252
+ // 4. .gitignore: track the workflow dirs if .claude/* is ignored
253
+ const gi = path.join(CWD, '.gitignore');
254
+ if (fs.existsSync(gi)) {
255
+ const txt = fs.readFileSync(gi, 'utf8');
256
+ if (/^\.claude\/\*\s*$/m.test(txt) && !txt.includes('!.claude/agents/')) {
257
+ const block = '\n# iStartSoftFlow workflow — track as project config\n!.claude/agents/\n!.claude/commands/\n!.claude/skills/\n!.claude/hooks/\n!.claude/istartsoft-flow/\n';
258
+ log(' + .gitignore: un-ignore .claude workflow dirs');
259
+ if (!DRY) fs.appendFileSync(gi, block);
260
+ }
261
+ }
262
+
263
+ log('');
264
+ log(`iStartSoftFlow ${DRY ? '(dry-run) ' : ''}[${TOOL}] done — created ${created}, conflicts ${conflicts}, unchanged ${skipped}.`);
265
+ if (conflicts) log('Review *.issflow-new files and merge manually (your originals were untouched).');
266
+ for (const w of warnings) log(` ! ${w}`);
267
+ log(NEXT_STEPS[TOOL] || NEXT_STEPS.claude);
268
+ }
269
+
270
+ main();
package/package.json CHANGED
@@ -1,28 +1,32 @@
1
- {
2
- "name": "create-issflow",
3
- "version": "1.0.3",
4
- "description": "Scaffold the iStartSoftFlow AI-coding workflow into a project. Stack-agnostic, tool-agnostic (Claude Code, Codex, Cursor, Gemini, Aider), non-destructive.",
5
- "bin": {
6
- "create-issflow": "bin/cli.js"
7
- },
8
- "files": [
9
- "bin/",
10
- "template/"
11
- ],
12
- "engines": {
13
- "node": ">=18"
14
- },
15
- "keywords": [
16
- "claude-code",
17
- "codex",
18
- "cursor",
19
- "gemini-cli",
20
- "aider",
21
- "agents-md",
22
- "agents",
23
- "tdd",
24
- "workflow",
25
- "istartsoftflow"
26
- ],
27
- "license": "MIT"
28
- }
1
+ {
2
+ "name": "create-issflow",
3
+ "version": "1.2.0",
4
+ "description": "Scaffold the iStartSoftFlow AI-coding workflow into a project. Stack-agnostic, tool-agnostic (Claude Code, Codex, Cursor, Gemini, Aider), non-destructive.",
5
+ "bin": {
6
+ "create-issflow": "bin/cli.js"
7
+ },
8
+ "scripts": {
9
+ "build": "node build.js",
10
+ "prepublishOnly": "node build.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "template/"
15
+ ],
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "keywords": [
20
+ "claude-code",
21
+ "codex",
22
+ "cursor",
23
+ "gemini-cli",
24
+ "aider",
25
+ "agents-md",
26
+ "agents",
27
+ "tdd",
28
+ "workflow",
29
+ "istartsoftflow"
30
+ ],
31
+ "license": "MIT"
32
+ }