ideabox 1.0.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/AGENTS.md +14 -0
- package/CLAUDE.md +14 -0
- package/LICENSE +21 -0
- package/README.md +413 -0
- package/bin/cli.mjs +267 -0
- package/package.json +39 -0
- package/skills/backlog/SKILL.md +101 -0
- package/skills/ideabox/SKILL.md +110 -0
- package/skills/ideabox/phases/01-research.md +173 -0
- package/skills/ideabox/phases/02-brainstorm.md +213 -0
- package/skills/ideabox/phases/03-plan.md +166 -0
- package/skills/ideabox/phases/04-build.md +213 -0
- package/skills/ideabox/phases/05-qa.md +135 -0
- package/skills/ideabox/phases/06-polish.md +111 -0
- package/skills/ideabox/phases/07-ship.md +119 -0
- package/skills/ideabox/phases/08-post-ship.md +83 -0
- package/skills/ideabox/phases/09-learn.md +208 -0
- package/skills/ideabox/references/research-sources.md +247 -0
- package/skills/ideabox/references/revenue-models.md +81 -0
- package/skills/ideabox/references/scoring-rubric.md +245 -0
- package/skills/ideabox/references/self-improvement.md +217 -0
- package/skills/profile/SKILL.md +97 -0
- package/skills/research/SKILL.md +62 -0
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import {
|
|
5
|
+
cpSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
rmSync,
|
|
11
|
+
} from "node:fs";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { dirname, join, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
const ROOT = resolve(__dirname, "..");
|
|
19
|
+
|
|
20
|
+
const SKILLS = ["ideabox", "research", "backlog", "profile"];
|
|
21
|
+
const MARKER_START = "<!-- ideabox:start -->";
|
|
22
|
+
const MARKER_END = "<!-- ideabox:end -->";
|
|
23
|
+
const HOME = homedir();
|
|
24
|
+
const DATA_DIR = join(HOME, ".ideabox");
|
|
25
|
+
|
|
26
|
+
function hasCommand(cmd) {
|
|
27
|
+
try {
|
|
28
|
+
const check = process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`;
|
|
29
|
+
execSync(check, { stdio: "ignore" });
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function autoDetect() {
|
|
37
|
+
const targets = [];
|
|
38
|
+
if (hasCommand("claude")) targets.push("claude");
|
|
39
|
+
if (hasCommand("codex")) targets.push("codex");
|
|
40
|
+
if (targets.length === 0) {
|
|
41
|
+
console.log("No supported CLI detected. Installing to .claude/skills/ (default).");
|
|
42
|
+
targets.push("claude");
|
|
43
|
+
}
|
|
44
|
+
return targets;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getSkillsDir(target) {
|
|
48
|
+
switch (target) {
|
|
49
|
+
case "claude":
|
|
50
|
+
return join(process.cwd(), ".claude", "skills");
|
|
51
|
+
case "codex":
|
|
52
|
+
return join(HOME, ".codex", "skills");
|
|
53
|
+
case "codex-project":
|
|
54
|
+
return join(process.cwd(), ".codex", "skills");
|
|
55
|
+
default:
|
|
56
|
+
return join(process.cwd(), ".claude", "skills");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getInstructionFile(target) {
|
|
61
|
+
if (target === "codex" || target === "codex-project") {
|
|
62
|
+
return join(process.cwd(), "AGENTS.md");
|
|
63
|
+
}
|
|
64
|
+
return join(process.cwd(), "CLAUDE.md");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getInstructionSource(target) {
|
|
68
|
+
if (target === "codex" || target === "codex-project") {
|
|
69
|
+
return join(ROOT, "AGENTS.md");
|
|
70
|
+
}
|
|
71
|
+
return join(ROOT, "CLAUDE.md");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function stripSection(content) {
|
|
75
|
+
const startIdx = content.indexOf(MARKER_START);
|
|
76
|
+
const endIdx = content.indexOf(MARKER_END);
|
|
77
|
+
if (startIdx === -1 || endIdx === -1) return content;
|
|
78
|
+
const before = content.slice(0, startIdx).trimEnd();
|
|
79
|
+
const after = content.slice(endIdx + MARKER_END.length).trimStart();
|
|
80
|
+
return before + (after ? "\n\n" + after : "") + "\n";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function mergeInstructionFile(target) {
|
|
84
|
+
const destPath = getInstructionFile(target);
|
|
85
|
+
const sourcePath = getInstructionSource(target);
|
|
86
|
+
|
|
87
|
+
if (!existsSync(sourcePath)) return;
|
|
88
|
+
|
|
89
|
+
const sourceContent = readFileSync(sourcePath, "utf-8").trim();
|
|
90
|
+
const section = `${MARKER_START}\n${sourceContent}\n${MARKER_END}`;
|
|
91
|
+
|
|
92
|
+
if (existsSync(destPath)) {
|
|
93
|
+
let existing = readFileSync(destPath, "utf-8");
|
|
94
|
+
existing = stripSection(existing);
|
|
95
|
+
writeFileSync(destPath, existing.trimEnd() + "\n\n" + section + "\n");
|
|
96
|
+
} else {
|
|
97
|
+
writeFileSync(destPath, section + "\n");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function installSkills(target) {
|
|
102
|
+
const skillsDir = getSkillsDir(target);
|
|
103
|
+
const srcSkillsDir = join(ROOT, "skills");
|
|
104
|
+
|
|
105
|
+
for (const skill of SKILLS) {
|
|
106
|
+
const src = join(srcSkillsDir, skill);
|
|
107
|
+
const dest = join(skillsDir, skill);
|
|
108
|
+
|
|
109
|
+
if (!existsSync(src)) {
|
|
110
|
+
console.log(` Skipping ${skill} (not found in plugin)`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Copy skill files
|
|
115
|
+
mkdirSync(dest, { recursive: true });
|
|
116
|
+
cpSync(src, dest, { recursive: true });
|
|
117
|
+
|
|
118
|
+
// For skills that reference phases/references, copy them locally
|
|
119
|
+
// so cross-skill references work without depending on sibling paths
|
|
120
|
+
if (skill !== "ideabox" && skill !== "profile") {
|
|
121
|
+
const ideasRefs = join(srcSkillsDir, "ideabox", "references");
|
|
122
|
+
const ideasPhases = join(srcSkillsDir, "ideabox", "phases");
|
|
123
|
+
if (existsSync(ideasRefs)) {
|
|
124
|
+
const destRefs = join(dest, "references");
|
|
125
|
+
mkdirSync(destRefs, { recursive: true });
|
|
126
|
+
cpSync(ideasRefs, destRefs, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
if (existsSync(ideasPhases)) {
|
|
129
|
+
const destPhases = join(dest, "phases");
|
|
130
|
+
mkdirSync(destPhases, { recursive: true });
|
|
131
|
+
cpSync(ideasPhases, destPhases, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log(` Installed ${skill}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function ensureDataDir() {
|
|
140
|
+
if (!existsSync(DATA_DIR)) {
|
|
141
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
142
|
+
console.log(` Created ${DATA_DIR}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function install(targets) {
|
|
147
|
+
console.log("\nIdeaBox -- Installing...\n");
|
|
148
|
+
ensureDataDir();
|
|
149
|
+
|
|
150
|
+
for (const target of targets) {
|
|
151
|
+
console.log(`Target: ${target}`);
|
|
152
|
+
installSkills(target);
|
|
153
|
+
mergeInstructionFile(target);
|
|
154
|
+
console.log(` Merged instruction file for ${target}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
console.log("\nDone! Run /ideabox to get started.\n");
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function uninstall(targets) {
|
|
161
|
+
console.log("\nIdeaBox -- Uninstalling...\n");
|
|
162
|
+
|
|
163
|
+
for (const target of targets) {
|
|
164
|
+
const skillsDir = getSkillsDir(target);
|
|
165
|
+
|
|
166
|
+
for (const skill of SKILLS) {
|
|
167
|
+
const dest = join(skillsDir, skill);
|
|
168
|
+
if (existsSync(dest)) {
|
|
169
|
+
rmSync(dest, { recursive: true });
|
|
170
|
+
console.log(` Removed ${skill}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const instrPath = getInstructionFile(target);
|
|
175
|
+
if (existsSync(instrPath)) {
|
|
176
|
+
const content = readFileSync(instrPath, "utf-8");
|
|
177
|
+
if (content.includes(MARKER_START)) {
|
|
178
|
+
writeFileSync(instrPath, stripSection(content));
|
|
179
|
+
console.log(` Cleaned instruction file for ${target}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(`\nNote: ${DATA_DIR} was kept. Delete it manually if you want to remove all data.\n`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function doctor() {
|
|
188
|
+
console.log("\nIdeaBox -- Health Check\n");
|
|
189
|
+
let ok = true;
|
|
190
|
+
|
|
191
|
+
// Check 1: Node version
|
|
192
|
+
const nodeVersion = parseInt(process.version.slice(1));
|
|
193
|
+
if (nodeVersion >= 18) {
|
|
194
|
+
console.log(` ✓ Node.js ${process.version}`);
|
|
195
|
+
} else {
|
|
196
|
+
console.log(` ✗ Node.js ${process.version} (need >= 18)`);
|
|
197
|
+
ok = false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Check 2: Data directory
|
|
201
|
+
if (existsSync(DATA_DIR)) {
|
|
202
|
+
console.log(` ✓ Data directory exists (${DATA_DIR})`);
|
|
203
|
+
} else {
|
|
204
|
+
console.log(` ✗ Data directory missing (${DATA_DIR})`);
|
|
205
|
+
ok = false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Check 3: Profile
|
|
209
|
+
const profilePath = join(DATA_DIR, "profile.json");
|
|
210
|
+
if (existsSync(profilePath)) {
|
|
211
|
+
console.log(` ✓ Profile configured`);
|
|
212
|
+
} else {
|
|
213
|
+
console.log(` ○ No profile yet (will be created on first /ideas run)`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Check 4: Skills installed (check both Claude and Codex paths)
|
|
217
|
+
const claudeSkills = join(process.cwd(), ".claude", "skills");
|
|
218
|
+
const codexSkills = join(HOME, ".codex", "skills");
|
|
219
|
+
const claudeInstalled = SKILLS.filter((s) => existsSync(join(claudeSkills, s)));
|
|
220
|
+
const codexInstalled = SKILLS.filter((s) => existsSync(join(codexSkills, s)));
|
|
221
|
+
const installed = claudeInstalled.length >= codexInstalled.length ? claudeInstalled : codexInstalled;
|
|
222
|
+
const installTarget = claudeInstalled.length >= codexInstalled.length ? "Claude" : "Codex";
|
|
223
|
+
if (installed.length === SKILLS.length) {
|
|
224
|
+
console.log(` ✓ All ${SKILLS.length} skills installed (${installTarget})`);
|
|
225
|
+
} else if (installed.length > 0) {
|
|
226
|
+
console.log(` △ ${installed.length}/${SKILLS.length} skills installed (${installed.join(", ")})`);
|
|
227
|
+
} else {
|
|
228
|
+
console.log(` ✗ No skills installed in current project`);
|
|
229
|
+
ok = false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check 5: Claude Code / Codex available
|
|
233
|
+
if (hasCommand("claude")) {
|
|
234
|
+
console.log(` ✓ Claude Code CLI detected`);
|
|
235
|
+
} else if (hasCommand("codex")) {
|
|
236
|
+
console.log(` ✓ Codex CLI detected`);
|
|
237
|
+
} else {
|
|
238
|
+
console.log(` ○ No supported CLI found (optional)`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log(ok ? "\n All checks passed!\n" : "\n Some issues found.\n");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// --- Main ---
|
|
245
|
+
function parseTargets(args) {
|
|
246
|
+
const explicit = args.slice(1).filter((a) => !a.startsWith("-") && a !== "--");
|
|
247
|
+
return explicit.length > 0 ? explicit : autoDetect();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const args = process.argv.slice(2);
|
|
251
|
+
const command = args[0] || "init";
|
|
252
|
+
|
|
253
|
+
switch (command) {
|
|
254
|
+
case "init":
|
|
255
|
+
install(parseTargets(args));
|
|
256
|
+
break;
|
|
257
|
+
case "uninstall":
|
|
258
|
+
uninstall(parseTargets(args));
|
|
259
|
+
break;
|
|
260
|
+
case "doctor":
|
|
261
|
+
doctor();
|
|
262
|
+
break;
|
|
263
|
+
default:
|
|
264
|
+
console.log(`Unknown command: ${command}`);
|
|
265
|
+
console.log("Usage: ideabox-agent [init|uninstall|doctor]");
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ideabox",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Data-driven project idea engine for coding agents. Research, brainstorm, plan, and build — all from one command.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ideabox": "bin/cli.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"skills/",
|
|
12
|
+
"CLAUDE.md",
|
|
13
|
+
"AGENTS.md",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ideabox",
|
|
18
|
+
"ideas",
|
|
19
|
+
"project-ideas",
|
|
20
|
+
"claude-code",
|
|
21
|
+
"codex-cli"
|
|
22
|
+
],
|
|
23
|
+
"author": "Pawan Paudel",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/pawanpaudel93/ideabox.git"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"bumpp": "^10.4.1"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"version": "node --input-type=commonjs -e \"const fs=require('fs');const p=JSON.parse(fs.readFileSync('.claude-plugin/plugin.json'));p.version=require('./package.json').version;fs.writeFileSync('.claude-plugin/plugin.json',JSON.stringify(p,null,2)+'\\n');\"",
|
|
37
|
+
"release": "bumpp && pnpm publish"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backlog
|
|
3
|
+
description: >
|
|
4
|
+
View your IdeaBox idea backlog — saved, dismissed, planned, and built ideas.
|
|
5
|
+
Use when asked to "show ideas", "idea backlog", "saved ideas", "what ideas do I have",
|
|
6
|
+
"ideabox backlog", or "list ideas".
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# IdeaBox Backlog
|
|
10
|
+
|
|
11
|
+
Display and manage the user's idea history from `~/.ideabox/ideas.jsonl`.
|
|
12
|
+
|
|
13
|
+
## Reading the Backlog
|
|
14
|
+
|
|
15
|
+
Read `~/.ideabox/ideas.jsonl`. Each line is a JSON object. There are two record types:
|
|
16
|
+
- **Idea records:** have fields `id`, `title`, `problem`, `scores`, `status`, `evidence`, `monetization`, `tech_stack`, `complexity`
|
|
17
|
+
- **Status update records:** have `type: "status_update"`, `idea_id`, `old_status`, `new_status`, `timestamp`
|
|
18
|
+
|
|
19
|
+
To get the current status of an idea: find the latest `status_update` for that `idea_id`. If no status_update exists, use the idea record's `status` field.
|
|
20
|
+
|
|
21
|
+
Parse arguments from the user's command:
|
|
22
|
+
- `/ideas backlog` — show all ideas grouped by status
|
|
23
|
+
- `/ideas backlog saved` — show only saved ideas
|
|
24
|
+
- `/ideas backlog dismissed` — show only dismissed ideas
|
|
25
|
+
- `/ideas backlog built` — show only built ideas
|
|
26
|
+
|
|
27
|
+
## Display Format
|
|
28
|
+
|
|
29
|
+
### If ideas.jsonl does not exist or is empty
|
|
30
|
+
"No ideas in your backlog yet. Run `/ideas` to research your first batch!"
|
|
31
|
+
|
|
32
|
+
### If ideas exist
|
|
33
|
+
|
|
34
|
+
Group by current status and display:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
## IdeaBox Backlog
|
|
38
|
+
|
|
39
|
+
### Saved (ready to build)
|
|
40
|
+
| # | Idea | Score | Monetization | Added |
|
|
41
|
+
|---|------|-------|-------------|-------|
|
|
42
|
+
| 1 | MCP Server Testing Framework | 48/60 | Freemium $29/mo | Mar 26 |
|
|
43
|
+
|
|
44
|
+
### Planned (in progress)
|
|
45
|
+
| # | Idea | Score | Status | Started |
|
|
46
|
+
|---|------|-------|--------|---------|
|
|
47
|
+
|
|
48
|
+
### Built
|
|
49
|
+
| # | Idea | Score | Shipped |
|
|
50
|
+
|---|------|-------|---------|
|
|
51
|
+
|
|
52
|
+
### Dismissed
|
|
53
|
+
Showing {count} dismissed ideas. Use `/ideas backlog dismissed` for details.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Actions
|
|
57
|
+
|
|
58
|
+
After displaying, offer:
|
|
59
|
+
- "Pick a number to brainstorm and build that idea"
|
|
60
|
+
- "Or run `/ideas` for fresh research"
|
|
61
|
+
|
|
62
|
+
If the user picks a saved idea by number:
|
|
63
|
+
1. Read the full idea record from `ideas.jsonl`
|
|
64
|
+
2. Present the complete idea card (problem, evidence, monetization, tech stack, score)
|
|
65
|
+
3. Ask "Ready to brainstorm this one?"
|
|
66
|
+
4. If yes:
|
|
67
|
+
a. Append a status update to `~/.ideabox/ideas.jsonl`:
|
|
68
|
+
```json
|
|
69
|
+
{"type":"status_update","idea_id":"{id}","old_status":"saved","new_status":"planned","timestamp":"{ISO}"}
|
|
70
|
+
```
|
|
71
|
+
b. Create `.ideabox/` and `.ideabox/session/` directories if they don't exist
|
|
72
|
+
c. Initialize `.ideabox/state.json`:
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"session_id": "sess_YYYYMMDD_HHMMSS",
|
|
76
|
+
"current_phase": "02-brainstorm",
|
|
77
|
+
"phases_completed": [],
|
|
78
|
+
"idea": {"id": "{id}", "title": "{title}", "problem": "{problem}"},
|
|
79
|
+
"artifacts": {},
|
|
80
|
+
"started_at": "{ISO}"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
d. Write the idea details to `.ideabox/session/01-research.md` (so phase 02 has context)
|
|
84
|
+
e. Read `${CLAUDE_SKILL_DIR}/phases/02-brainstorm.md` and follow it
|
|
85
|
+
|
|
86
|
+
## Comparison Mode
|
|
87
|
+
|
|
88
|
+
If the user says `/ideas backlog compare N M` (e.g., `compare 1 3`):
|
|
89
|
+
|
|
90
|
+
1. Load both idea records from `ideas.jsonl`
|
|
91
|
+
2. Present using the visual comparison format from `${CLAUDE_SKILL_DIR}/references/scoring-rubric.md` (Head-to-Head section) — with score bars, evidence, and a recommendation
|
|
92
|
+
3. Ask: "Build which one? (N / M / neither)"
|
|
93
|
+
|
|
94
|
+
## Updating Idea Status
|
|
95
|
+
|
|
96
|
+
To update an idea's status, append a NEW line to `~/.ideabox/ideas.jsonl`:
|
|
97
|
+
```json
|
|
98
|
+
{"type":"status_update","idea_id":"idea_20260326_001","old_status":"saved","new_status":"planned","timestamp":"2026-03-26T17:00:00Z"}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Never modify existing lines.** Append-only. The latest status_update for an idea_id is the current status.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ideabox
|
|
3
|
+
description: >
|
|
4
|
+
Full idea-to-code pipeline. Researches real market demand, presents data-backed project ideas,
|
|
5
|
+
then brainstorms, plans, builds, tests, polishes, and ships the one you pick — 9 phases, fully self-contained.
|
|
6
|
+
Use when asked to "give me ideas", "what should I build", "project ideas", "ideabox",
|
|
7
|
+
"find me something to build", "I need a project", "ideas", or "suggest a project".
|
|
8
|
+
argument-hint: "[research|backlog|profile]"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# IdeaBox — Full Pipeline
|
|
12
|
+
|
|
13
|
+
Research -> Present -> Pick -> Brainstorm -> Plan -> Build -> QA -> Polish -> Ship -> Post-Ship -> Learn
|
|
14
|
+
|
|
15
|
+
## Subcommand Routing
|
|
16
|
+
|
|
17
|
+
Check if the user passed a subcommand:
|
|
18
|
+
- `/ideabox research` -> invoke `ideabox:research` skill
|
|
19
|
+
- `/ideabox backlog` -> invoke `ideabox:backlog` skill
|
|
20
|
+
- `/ideabox profile` -> invoke `ideabox:profile` skill
|
|
21
|
+
- `/ideabox` (no subcommand) -> continue with pipeline below
|
|
22
|
+
- `/ideabox [anything else]` -> respond: "Unknown subcommand. Available: `/ideabox`, `/ideabox research`, `/ideabox backlog`, `/ideabox profile`"
|
|
23
|
+
|
|
24
|
+
## Pipeline State
|
|
25
|
+
|
|
26
|
+
Check if `.ideabox/state.json` exists in the current project directory.
|
|
27
|
+
|
|
28
|
+
**If state.json exists and `current_phase` is not null:**
|
|
29
|
+
Ask: "You have an in-progress session (Phase: {current_phase}, Idea: {idea.title}). Resume or start fresh?"
|
|
30
|
+
- Resume: read state, load the current phase file, continue from where you left off
|
|
31
|
+
- Start fresh: delete `.ideabox/state.json` and `.ideabox/session/`, proceed as new
|
|
32
|
+
|
|
33
|
+
**If no state.json or starting fresh:**
|
|
34
|
+
1. Create `.ideabox/` and `.ideabox/session/` directories
|
|
35
|
+
2. Add `.ideabox/` to the project's `.gitignore` if not already present (session state should not be committed)
|
|
36
|
+
3. Check for existing artifacts (phase skipping):
|
|
37
|
+
- If `~/.ideabox/research/` has a file from today -> ask: "You already researched today. Use those results or research fresh?"
|
|
38
|
+
- If `.ideabox/session/02-brainstorm-spec.md` exists -> ask: "Found an existing spec. Resume from planning?"
|
|
39
|
+
- If `.ideabox/session/03-plan.md` exists -> ask: "Found an existing plan. Resume from building?"
|
|
40
|
+
4. Initialize `.ideabox/state.json` with the appropriate starting phase:
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"session_id": "sess_YYYYMMDD_HHMMSS",
|
|
44
|
+
"current_phase": "01-research",
|
|
45
|
+
"phases_completed": [],
|
|
46
|
+
"idea": null,
|
|
47
|
+
"artifacts": {},
|
|
48
|
+
"started_at": "{ISO timestamp}"
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Phase Execution
|
|
53
|
+
|
|
54
|
+
For the current phase, read the corresponding phase file and follow it completely:
|
|
55
|
+
|
|
56
|
+
| Phase | File to Read | Gate Condition |
|
|
57
|
+
|-------|-------------|---------------|
|
|
58
|
+
| 01-research | `phases/01-research.md` | >=3 ideas with >=3 evidence sources each |
|
|
59
|
+
| 02-brainstorm | `phases/02-brainstorm.md` | Spec document written and user-approved |
|
|
60
|
+
| 03-plan | `phases/03-plan.md` | Plan passes self-review (no placeholders) |
|
|
61
|
+
| 04-build | `phases/04-build.md` | All tests pass, two-stage review complete |
|
|
62
|
+
| 05-qa | `phases/05-qa.md` | Health score above threshold, no critical bugs |
|
|
63
|
+
| 06-polish | `phases/06-polish.md` | Before/after evidence, no AI slop detected |
|
|
64
|
+
| 07-ship | `phases/07-ship.md` | PR created, CI passes |
|
|
65
|
+
| 08-post-ship | `phases/08-post-ship.md` | Canary passes or skipped |
|
|
66
|
+
| 09-learn | `phases/09-learn.md` | Preferences updated |
|
|
67
|
+
|
|
68
|
+
**Conditional loading (save tokens):**
|
|
69
|
+
- Phase 06 (polish): If the project has no visual UI (library, API, backend-only), skip directly to phase 07 without reading the phase file
|
|
70
|
+
- Phase 08 (post-ship): If no deployment URL exists and no documentation files exist, skip directly to phase 09
|
|
71
|
+
|
|
72
|
+
**To execute a phase:**
|
|
73
|
+
```
|
|
74
|
+
Read `${CLAUDE_SKILL_DIR}/phases/{phase_file}` and follow it completely.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Phase Transition Protocol
|
|
78
|
+
|
|
79
|
+
After each phase completes and its gate condition is met:
|
|
80
|
+
|
|
81
|
+
1. **Save artifact path** in state.json `artifacts` field
|
|
82
|
+
2. **Move phase** to `phases_completed` array
|
|
83
|
+
3. **Advance** `current_phase` to next phase
|
|
84
|
+
4. **Write state** to `.ideabox/state.json`
|
|
85
|
+
5. **Present summary** to user: "Phase {N} complete. {one-line summary of output}"
|
|
86
|
+
6. **Ask at gate:** "Continue to {next phase name}? (yes / revise / skip remaining / abort)"
|
|
87
|
+
- **yes**: read next phase file and follow it
|
|
88
|
+
- **revise**: stay in current phase, user explains what to change
|
|
89
|
+
- **skip**: jump to phase 09 (learn) to save progress, then end
|
|
90
|
+
- **abort**: save state, end session (can resume later with `/ideas`)
|
|
91
|
+
|
|
92
|
+
## Phase Rules
|
|
93
|
+
|
|
94
|
+
- **Phases 01-04 are MANDATORY** (research, brainstorm, plan, build) — cannot be skipped
|
|
95
|
+
- **Phases 05-08 can be skipped** if user says "skip" — for CLI tools without UI, skip polish; for unpublished tools, skip ship
|
|
96
|
+
- **Phase 09 (learn) always runs** after any end point — tracks what happened for self-improvement
|
|
97
|
+
|
|
98
|
+
## Context Management
|
|
99
|
+
|
|
100
|
+
- **Re-read state** before every phase transition to prevent drift
|
|
101
|
+
- **Each phase writes output** to `.ideabox/session/` (e.g., `01-research.md`, `02-brainstorm-spec.md`, `03-plan.md`, `05-qa-report.md`)
|
|
102
|
+
- **Next phase reads** only its own instructions + the previous phase's output (not all phases)
|
|
103
|
+
- **If context is running low:** save state to `.ideabox/state.json`, tell user: "Context getting full. Run `/ideas` in a new session to resume from phase {current_phase}."
|
|
104
|
+
|
|
105
|
+
## Error Handling
|
|
106
|
+
|
|
107
|
+
- **Phase gate fails:** stay in current phase, explain what's needed to pass
|
|
108
|
+
- **User aborts:** save state, they resume later with `/ideas`
|
|
109
|
+
- **Subagent fails:** note the failure, offer to retry or skip
|
|
110
|
+
- **No profile:** run profile setup inline (don't tell user to run another command)
|