create-claudecraft 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/LICENSE +21 -0
- package/README.md +194 -0
- package/bin/cli.js +2 -0
- package/dist/constants.d.ts +71 -0
- package/dist/constants.js +128 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +229 -0
- package/dist/ink-prompts.d.ts +12 -0
- package/dist/ink-prompts.js +363 -0
- package/dist/prompts.d.ts +16 -0
- package/dist/prompts.js +434 -0
- package/dist/scaffold.d.ts +19 -0
- package/dist/scaffold.js +303 -0
- package/dist/ui.d.ts +27 -0
- package/dist/ui.js +254 -0
- package/package.json +74 -0
- package/templates/app/App.tsx +21 -0
- package/templates/base/CLAUDE.md +332 -0
- package/templates/base/eslint.config.js +28 -0
- package/templates/base/index.html +17 -0
- package/templates/base/package.json +43 -0
- package/templates/base/postcss.config.js +6 -0
- package/templates/base/tailwind.config.js +81 -0
- package/templates/base/tsconfig.json +25 -0
- package/templates/base/vite.config.ts +16 -0
- package/templates/commands/brainstorm.md +6 -0
- package/templates/commands/build.md +41 -0
- package/templates/commands/execute-plan.md +6 -0
- package/templates/commands/lint.md +41 -0
- package/templates/commands/ralph.md +113 -0
- package/templates/commands/typecheck.md +44 -0
- package/templates/commands/write-plan.md +6 -0
- package/templates/components/ErrorBoundary.tsx +49 -0
- package/templates/components/ui/Button.tsx +60 -0
- package/templates/components/ui/CodeBlock.tsx +46 -0
- package/templates/components/ui/CopyCommand.tsx +38 -0
- package/templates/components/ui/FilePreview.tsx +46 -0
- package/templates/components/ui/SkipLink.tsx +7 -0
- package/templates/components/ui/ThemeSelector.tsx +41 -0
- package/templates/components/ui/UICarousel.tsx +309 -0
- package/templates/context/ThemeContext.tsx +61 -0
- package/templates/homepage/HomePage.tsx +534 -0
- package/templates/homepage/NotFoundPage.tsx +17 -0
- package/templates/hooks/README.md +82 -0
- package/templates/hooks/check-branch.js +27 -0
- package/templates/hooks/typecheck-after-edit.js +51 -0
- package/templates/index.css +67 -0
- package/templates/lib/utils.ts +9 -0
- package/templates/main.tsx +16 -0
- package/templates/settings/MCP_SETUP.md +76 -0
- package/templates/settings/settings.json +16 -0
- package/templates/settings/settings.local.json +37 -0
- package/templates/skills/design/a11y-audit/SKILL.md +173 -0
- package/templates/skills/design/design-polish/SKILL.md +75 -0
- package/templates/skills/design/figma-to-code/SKILL.md +157 -0
- package/templates/skills/design/json-ld/SKILL.md +125 -0
- package/templates/skills/design/microcopy/SKILL.md +197 -0
- package/templates/skills/design/og-image/SKILL.md +157 -0
- package/templates/skills/design/ralph-wiggum-loops/SKILL.md +299 -0
- package/templates/skills/design/react-best-practices/SKILL.md +106 -0
- package/templates/skills/design/react-best-practices/references/react-performance-guidelines.md +143 -0
- package/templates/skills/design/seo-review/SKILL.md +96 -0
- package/templates/skills/design/sitemap-generator/SKILL.md +66 -0
- package/templates/skills/design/testing-patterns/SKILL.md +276 -0
- package/templates/skills/design/ui-skills/SKILL.md +85 -0
- package/templates/skills/design/visual-iteration/SKILL.md +88 -0
- package/templates/skills/workflow/brainstorming/SKILL.md +54 -0
- package/templates/skills/workflow/dispatching-parallel-agents/SKILL.md +180 -0
- package/templates/skills/workflow/executing-plans/SKILL.md +76 -0
- package/templates/skills/workflow/finishing-a-development-branch/SKILL.md +200 -0
- package/templates/skills/workflow/receiving-code-review/SKILL.md +213 -0
- package/templates/skills/workflow/requesting-code-review/SKILL.md +105 -0
- package/templates/skills/workflow/requesting-code-review/code-reviewer.md +146 -0
- package/templates/skills/workflow/subagent-driven-development/SKILL.md +240 -0
- package/templates/skills/workflow/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
- package/templates/skills/workflow/subagent-driven-development/implementer-prompt.md +78 -0
- package/templates/skills/workflow/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/templates/skills/workflow/systematic-debugging/CREATION-LOG.md +119 -0
- package/templates/skills/workflow/systematic-debugging/SKILL.md +296 -0
- package/templates/skills/workflow/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/templates/skills/workflow/systematic-debugging/condition-based-waiting.md +115 -0
- package/templates/skills/workflow/systematic-debugging/defense-in-depth.md +122 -0
- package/templates/skills/workflow/systematic-debugging/find-polluter.sh +63 -0
- package/templates/skills/workflow/systematic-debugging/root-cause-tracing.md +169 -0
- package/templates/skills/workflow/systematic-debugging/test-academic.md +14 -0
- package/templates/skills/workflow/systematic-debugging/test-pressure-1.md +58 -0
- package/templates/skills/workflow/systematic-debugging/test-pressure-2.md +68 -0
- package/templates/skills/workflow/systematic-debugging/test-pressure-3.md +69 -0
- package/templates/skills/workflow/test-driven-development/SKILL.md +371 -0
- package/templates/skills/workflow/test-driven-development/testing-anti-patterns.md +299 -0
- package/templates/skills/workflow/using-git-worktrees/SKILL.md +217 -0
- package/templates/skills/workflow/using-superpowers/SKILL.md +87 -0
- package/templates/skills/workflow/verification-before-completion/SKILL.md +139 -0
- package/templates/skills/workflow/writing-plans/SKILL.md +116 -0
- package/templates/skills/workflow/writing-skills/SKILL.md +655 -0
- package/templates/skills/workflow/writing-skills/anthropic-best-practices.md +1150 -0
- package/templates/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/templates/skills/workflow/writing-skills/graphviz-conventions.dot +172 -0
- package/templates/skills/workflow/writing-skills/persuasion-principles.md +187 -0
- package/templates/skills/workflow/writing-skills/render-graphs.js +168 -0
- package/templates/skills/workflow/writing-skills/testing-skills-with-subagents.md +384 -0
- package/templates/types/index.ts +17 -0
- package/templates/vite-env.d.ts +1 -0
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { SKILLS, BUNDLES } from './constants.js';
|
|
6
|
+
import { renderMiniHeader } from './ui.js';
|
|
7
|
+
// Interactive slash commands available during prompts
|
|
8
|
+
function showInteractiveHelp() {
|
|
9
|
+
const existentialBits = [
|
|
10
|
+
"You're not being replaced. You're being... augmented. Involuntarily.",
|
|
11
|
+
"The AI can't feel impostor syndrome. That's still your job.",
|
|
12
|
+
"Remember when 'prompt engineering' wasn't a career? Good times.",
|
|
13
|
+
"The robots write code now. You write prompts. This is fine.",
|
|
14
|
+
"Your design degree prepared you for this. (It didn't.)",
|
|
15
|
+
"At least the AI doesn't have opinions about your font choices. Yet.",
|
|
16
|
+
"You're not obsolete. You're a 'human-in-the-loop'. Very important loop.",
|
|
17
|
+
"The future is AI-assisted. Your anxiety is fully organic.",
|
|
18
|
+
"Figma + AI + You = Still confused, but faster.",
|
|
19
|
+
"Don't worry. The AI hallucinates too. You have that in common.",
|
|
20
|
+
];
|
|
21
|
+
const randomBit = existentialBits[Math.floor(Math.random() * existentialBits.length)];
|
|
22
|
+
const reassurance = [
|
|
23
|
+
"But hey, someone still needs taste. That's you. Allegedly.",
|
|
24
|
+
"Breathe. The AI still can't center a div without help.",
|
|
25
|
+
"You're here because clients still need someone to blame.",
|
|
26
|
+
"Keep going. The AI believes in you. (It doesn't. It can't.)",
|
|
27
|
+
"This too shall ship. Eventually. Maybe.",
|
|
28
|
+
];
|
|
29
|
+
const randomReassurance = reassurance[Math.floor(Math.random() * reassurance.length)];
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log(pc.dim(' ╭─── HELP ─────────────────────────────────────────────────────────────╮'));
|
|
32
|
+
console.log(` ${pc.dim('│')} ${pc.dim(randomBit)}`);
|
|
33
|
+
console.log(pc.dim(' ├─── COMMANDS ────────────────────────────────────────────────────────┤'));
|
|
34
|
+
console.log(` ${pc.dim('│')} ${pc.cyan('/help')} ${pc.dim('you are here (existentially, too)')}`);
|
|
35
|
+
console.log(` ${pc.dim('│')} ${pc.cyan('/skills')} ${pc.dim('see what the robots learned')}`);
|
|
36
|
+
console.log(` ${pc.dim('│')} ${pc.cyan('/quit')} ${pc.dim('rage quit (Ctrl+C also works)')}`);
|
|
37
|
+
console.log(pc.dim(' ├─── NAVIGATION ─────────────────────────────────────────────────────┤'));
|
|
38
|
+
console.log(` ${pc.dim('│')} ${pc.dim('↑↓')} ${pc.dim('move through options')}`);
|
|
39
|
+
console.log(` ${pc.dim('│')} ${pc.dim('space')} ${pc.dim('toggle selection')}`);
|
|
40
|
+
console.log(` ${pc.dim('│')} ${pc.dim('enter')} ${pc.dim('confirm your life choices')}`);
|
|
41
|
+
console.log(` ${pc.dim('│')} ${pc.dim('esc')} ${pc.dim('cancel (the project, not your career)')}`);
|
|
42
|
+
console.log(pc.dim(' ├─── REASSURANCE ────────────────────────────────────────────────────┤'));
|
|
43
|
+
console.log(` ${pc.dim('│')} ${pc.dim(randomReassurance)}`);
|
|
44
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
45
|
+
console.log('');
|
|
46
|
+
}
|
|
47
|
+
function showSkillsList() {
|
|
48
|
+
const headers = [
|
|
49
|
+
"Things the AI learned so you don't have to:",
|
|
50
|
+
"Skills acquired through mass data consumption:",
|
|
51
|
+
"What the robots know (spoiler: a lot):",
|
|
52
|
+
"Your competition's new skill tree:",
|
|
53
|
+
"Capabilities that took humans years to learn:",
|
|
54
|
+
];
|
|
55
|
+
const randomHeader = headers[Math.floor(Math.random() * headers.length)];
|
|
56
|
+
const footers = [
|
|
57
|
+
"Total skills: " + SKILLS.length + ". Total human obsolescence: pending.",
|
|
58
|
+
"That's " + SKILLS.length + " things you can delegate to the void.",
|
|
59
|
+
SKILLS.length + " skills. 0 benefits. ∞ existential questions.",
|
|
60
|
+
"The AI learned all this in mass. You're still on this prompt.",
|
|
61
|
+
];
|
|
62
|
+
const randomFooter = footers[Math.floor(Math.random() * footers.length)];
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(pc.dim(' ╭─── SKILLS ─────────────────────────────────────────────────────────╮'));
|
|
65
|
+
console.log(` ${pc.dim('│')} ${pc.dim(randomHeader)}`);
|
|
66
|
+
console.log(pc.dim(' ├─── WORKFLOW ────────────────────────────────────────────────────────┤'));
|
|
67
|
+
SKILLS.filter(s => s.group === 'workflow').forEach(s => {
|
|
68
|
+
console.log(` ${pc.dim('│')} ${s.name.padEnd(26)} ${pc.dim(s.description)}`);
|
|
69
|
+
});
|
|
70
|
+
console.log(pc.dim(' ├─── DESIGN ─────────────────────────────────────────────────────────┤'));
|
|
71
|
+
SKILLS.filter(s => s.group === 'design').forEach(s => {
|
|
72
|
+
console.log(` ${pc.dim('│')} ${s.name.padEnd(26)} ${pc.dim(s.description)}`);
|
|
73
|
+
});
|
|
74
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
75
|
+
console.log(` ${pc.dim('│')} ${pc.dim(randomFooter)}`);
|
|
76
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
77
|
+
console.log('');
|
|
78
|
+
}
|
|
79
|
+
// Show autocomplete suggestions
|
|
80
|
+
function showCommandSuggestions() {
|
|
81
|
+
console.log('');
|
|
82
|
+
console.log(pc.dim(' ╭─── / ────────────────────────────────────────────────────────────────╮'));
|
|
83
|
+
console.log(` ${pc.dim('│')} ${pc.cyan('/help')} ${pc.dim('existential guidance')}`);
|
|
84
|
+
console.log(` ${pc.dim('│')} ${pc.cyan('/skills')} ${pc.dim('what the AI knows')}`);
|
|
85
|
+
console.log(` ${pc.dim('│')} ${pc.cyan('/quit')} ${pc.dim('escape while you can')}`);
|
|
86
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
87
|
+
console.log('');
|
|
88
|
+
}
|
|
89
|
+
// Check if input is a slash command, handle it, return true if handled
|
|
90
|
+
function handleSlashCommand(value) {
|
|
91
|
+
const cmd = value.trim().toLowerCase();
|
|
92
|
+
// Just "/" shows autocomplete suggestions
|
|
93
|
+
if (cmd === '/') {
|
|
94
|
+
showCommandSuggestions();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if (cmd === '/help' || cmd === '/h' || cmd === '/?') {
|
|
98
|
+
showInteractiveHelp();
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
if (cmd === '/skills' || cmd === '/list') {
|
|
102
|
+
showSkillsList();
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (cmd === '/quit' || cmd === '/exit' || cmd === '/q') {
|
|
106
|
+
p.cancel("You'll be back. They always come back.");
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
// Partial match suggestions
|
|
110
|
+
if (cmd.startsWith('/')) {
|
|
111
|
+
const available = ['/help', '/skills', '/quit'];
|
|
112
|
+
const matches = available.filter(c => c.startsWith(cmd));
|
|
113
|
+
if (matches.length > 0 && matches.length < available.length) {
|
|
114
|
+
console.log(pc.dim(` Did you mean: ${matches.join(', ')}?`));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log(pc.dim(` Unknown command: ${cmd}. Try /help`));
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
export async function runPrompts(defaultName) {
|
|
124
|
+
const totalSteps = 4;
|
|
125
|
+
const workflowCount = SKILLS.filter((s) => s.group === 'workflow').length;
|
|
126
|
+
// Step 1: Project name
|
|
127
|
+
// Don't clear - let intro screen stay visible for first step
|
|
128
|
+
console.log('');
|
|
129
|
+
console.log(pc.dim(' ╭─── [1/4] PROJECT NAME ──────────────────────────────────────────────╮'));
|
|
130
|
+
console.log(` ${pc.dim('│')} What are we calling this? ${pc.dim('lowercase · numbers · dashes · /help')}`);
|
|
131
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
132
|
+
let projectName;
|
|
133
|
+
while (true) {
|
|
134
|
+
projectName = await p.text({
|
|
135
|
+
message: '',
|
|
136
|
+
placeholder: defaultName || 'my-app',
|
|
137
|
+
defaultValue: defaultName,
|
|
138
|
+
validate: (value) => {
|
|
139
|
+
// Allow slash commands through validation
|
|
140
|
+
if (value.startsWith('/'))
|
|
141
|
+
return undefined;
|
|
142
|
+
if (!value)
|
|
143
|
+
return 'Required';
|
|
144
|
+
if (!/^[a-z0-9-]+$/.test(value))
|
|
145
|
+
return 'Lowercase, numbers, dashes only';
|
|
146
|
+
if (value.length > 64)
|
|
147
|
+
return 'Max 64 chars';
|
|
148
|
+
const targetDir = path.resolve(process.cwd(), value);
|
|
149
|
+
if (fs.existsSync(targetDir))
|
|
150
|
+
return `Directory "${value}" already exists`;
|
|
151
|
+
return undefined;
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
if (p.isCancel(projectName)) {
|
|
155
|
+
p.cancel("You'll be back. They always come back.");
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
// Handle slash commands
|
|
159
|
+
if (typeof projectName === 'string' && handleSlashCommand(projectName)) {
|
|
160
|
+
continue; // Re-prompt after showing command output
|
|
161
|
+
}
|
|
162
|
+
break; // Valid input, continue
|
|
163
|
+
}
|
|
164
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
165
|
+
// Step 2: Bundle selection
|
|
166
|
+
console.clear();
|
|
167
|
+
console.log(renderMiniHeader());
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(pc.dim(' ╭─── [2/4] SKILL BUNDLE ──────────────────────────────────────────────╮'));
|
|
170
|
+
console.log(` ${pc.dim('│')} How much help do you want?`);
|
|
171
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
172
|
+
console.log(pc.dim(` │ everything ${SKILLS.length} skills, 6 cmds workflow ${workflowCount} skills, 3 cmds`));
|
|
173
|
+
console.log(pc.dim(` │ designer ${BUNDLES.designer.skills.length} skills, 3 cmds custom you pick`));
|
|
174
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
175
|
+
const bundle = await p.select({
|
|
176
|
+
message: '',
|
|
177
|
+
options: [
|
|
178
|
+
{
|
|
179
|
+
value: 'everything',
|
|
180
|
+
label: `${pc.bold('Everything')}`,
|
|
181
|
+
hint: `${BUNDLES.everything.description} · ${SKILLS.length} skills`,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
value: 'designer',
|
|
185
|
+
label: `${pc.bold('Designer Essentials')}`,
|
|
186
|
+
hint: `${BUNDLES.designer.description} · ${BUNDLES.designer.skills.length} skills`,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
value: 'workflow',
|
|
190
|
+
label: `${pc.bold('Workflow Only')}`,
|
|
191
|
+
hint: `${BUNDLES.workflow.description} · ${workflowCount} skills`,
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
value: 'custom',
|
|
195
|
+
label: `${pc.bold('Let Me Pick')}`,
|
|
196
|
+
hint: 'Control freak? Respect.',
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
});
|
|
200
|
+
if (p.isCancel(bundle)) {
|
|
201
|
+
p.cancel("You'll be back. They always come back.");
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
205
|
+
// Step 2b: Custom skill selection (if "Let Me Pick")
|
|
206
|
+
let selectedSkills = [];
|
|
207
|
+
if (bundle === 'custom') {
|
|
208
|
+
const workflowSkills = SKILLS.filter((s) => s.group === 'workflow');
|
|
209
|
+
const designSkills = SKILLS.filter((s) => s.group === 'design');
|
|
210
|
+
// Workflow skills
|
|
211
|
+
console.clear();
|
|
212
|
+
console.log(renderMiniHeader());
|
|
213
|
+
console.log('');
|
|
214
|
+
console.log(pc.dim(' ╭─── [2/4] WORKFLOW SKILLS ───────────────────────────────────────────╮'));
|
|
215
|
+
console.log(` ${pc.dim('│')} Select workflow skills ${pc.dim('space: toggle · a: all · enter: confirm')}`);
|
|
216
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
217
|
+
const workflowChoices = await p.multiselect({
|
|
218
|
+
message: '',
|
|
219
|
+
options: workflowSkills.map((s) => ({
|
|
220
|
+
value: s.name,
|
|
221
|
+
label: s.name.padEnd(28),
|
|
222
|
+
hint: s.description,
|
|
223
|
+
})),
|
|
224
|
+
initialValues: workflowSkills.slice(0, 6).map((s) => s.name),
|
|
225
|
+
required: false,
|
|
226
|
+
});
|
|
227
|
+
if (p.isCancel(workflowChoices)) {
|
|
228
|
+
p.cancel("You'll be back. They always come back.");
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
232
|
+
const selectedWorkflow = workflowChoices;
|
|
233
|
+
// Design skills
|
|
234
|
+
console.clear();
|
|
235
|
+
console.log(renderMiniHeader());
|
|
236
|
+
console.log('');
|
|
237
|
+
console.log(pc.dim(' ╭─── [2/4] DESIGN SKILLS ─────────────────────────────────────────────╮'));
|
|
238
|
+
console.log(` ${pc.dim('│')} Select design skills ${pc.dim(`(${selectedWorkflow.length} workflow selected) · space · a · enter`)}`);
|
|
239
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
240
|
+
const designChoices = await p.multiselect({
|
|
241
|
+
message: '',
|
|
242
|
+
options: designSkills.map((s) => ({
|
|
243
|
+
value: s.name,
|
|
244
|
+
label: s.name.padEnd(28),
|
|
245
|
+
hint: s.description,
|
|
246
|
+
})),
|
|
247
|
+
initialValues: designSkills.slice(0, 4).map((s) => s.name),
|
|
248
|
+
required: false,
|
|
249
|
+
});
|
|
250
|
+
if (p.isCancel(designChoices)) {
|
|
251
|
+
p.cancel("You'll be back. They always come back.");
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
255
|
+
const selectedDesign = designChoices;
|
|
256
|
+
selectedSkills = [...selectedWorkflow, ...selectedDesign];
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
selectedSkills =
|
|
260
|
+
bundle === 'everything'
|
|
261
|
+
? SKILLS.map((s) => s.name)
|
|
262
|
+
: bundle === 'designer'
|
|
263
|
+
? [...BUNDLES.designer.skills]
|
|
264
|
+
: [...BUNDLES.workflow.skills];
|
|
265
|
+
}
|
|
266
|
+
// Step 3: Include homepage
|
|
267
|
+
console.clear();
|
|
268
|
+
console.log(renderMiniHeader());
|
|
269
|
+
console.log('');
|
|
270
|
+
console.log(pc.dim(' ╭─── [3/4] EXAMPLE HOMEPAGE ────────────────────────────────────────────╮'));
|
|
271
|
+
console.log(` ${pc.dim('│')} Include the example homepage? ${pc.dim('+6 files')}`);
|
|
272
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
273
|
+
console.log(pc.dim(' │ ╭───────────────────────────────────────────────────────────╮'));
|
|
274
|
+
console.log(pc.dim(' │ │ claudecraft [theme picker] │'));
|
|
275
|
+
console.log(pc.dim(' │ │ Your taste. Their labor. Finally. │'));
|
|
276
|
+
console.log(pc.dim(' │ │ [Commands] [Skills] [Themes] ████ Theme Carousel ◄► │'));
|
|
277
|
+
console.log(pc.dim(' │ ╰───────────────────────────────────────────────────────────╯'));
|
|
278
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
279
|
+
const includeHomepage = await p.select({
|
|
280
|
+
message: '',
|
|
281
|
+
options: [
|
|
282
|
+
{
|
|
283
|
+
value: true,
|
|
284
|
+
label: 'Yes',
|
|
285
|
+
hint: '+6 files · you can delete it later',
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
value: false,
|
|
289
|
+
label: 'No',
|
|
290
|
+
hint: 'Blank App.tsx · the void awaits',
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
});
|
|
294
|
+
if (p.isCancel(includeHomepage)) {
|
|
295
|
+
p.cancel("You'll be back. They always come back.");
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
299
|
+
// Step 4: Git init
|
|
300
|
+
console.clear();
|
|
301
|
+
console.log(renderMiniHeader());
|
|
302
|
+
console.log('');
|
|
303
|
+
console.log(pc.dim(' ╭─── [4/4] GIT INIT ────────────────────────────────────────────────────╮'));
|
|
304
|
+
console.log(` ${pc.dim('│')} Initialize git? ${pc.dim('init + commit · or suffer later')}`);
|
|
305
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
306
|
+
const initGit = await p.select({
|
|
307
|
+
message: '',
|
|
308
|
+
options: [
|
|
309
|
+
{
|
|
310
|
+
value: true,
|
|
311
|
+
label: 'Yes',
|
|
312
|
+
hint: 'Fresh repo · future you says thanks',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
value: false,
|
|
316
|
+
label: 'No',
|
|
317
|
+
hint: 'No .git · living dangerously',
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
});
|
|
321
|
+
if (p.isCancel(initGit)) {
|
|
322
|
+
p.cancel("You'll be back. They always come back.");
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
326
|
+
return {
|
|
327
|
+
projectName: projectName,
|
|
328
|
+
bundle: bundle,
|
|
329
|
+
selectedSkills,
|
|
330
|
+
includeHomepage: includeHomepage,
|
|
331
|
+
initGit: initGit,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Prompts for --init mode (existing project)
|
|
336
|
+
* Only asks about skills selection
|
|
337
|
+
*/
|
|
338
|
+
export async function runInitPrompts() {
|
|
339
|
+
const workflowCount = SKILLS.filter((s) => s.group === 'workflow').length;
|
|
340
|
+
// Bundle selection
|
|
341
|
+
console.log(pc.dim(' ╭─── SKILL BUNDLE ────────────────────────────────────────────────────╮'));
|
|
342
|
+
console.log(` ${pc.dim('│')} How much help do you want?`);
|
|
343
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
344
|
+
console.log(pc.dim(` │ everything ${SKILLS.length} skills workflow ${workflowCount} skills`));
|
|
345
|
+
console.log(pc.dim(` │ designer ${BUNDLES.designer.skills.length} skills custom you pick`));
|
|
346
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
347
|
+
const bundle = await p.select({
|
|
348
|
+
message: '',
|
|
349
|
+
options: [
|
|
350
|
+
{
|
|
351
|
+
value: 'everything',
|
|
352
|
+
label: `${pc.bold('Everything')}`,
|
|
353
|
+
hint: `All ${SKILLS.length} skills · the full experience`,
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
value: 'designer',
|
|
357
|
+
label: `${pc.bold('Designer Essentials')}`,
|
|
358
|
+
hint: `${BUNDLES.designer.skills.length} skills · UI, a11y, Figma`,
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
value: 'workflow',
|
|
362
|
+
label: `${pc.bold('Workflow Only')}`,
|
|
363
|
+
hint: `${workflowCount} skills · process only`,
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
value: 'custom',
|
|
367
|
+
label: `${pc.bold('Let Me Pick')}`,
|
|
368
|
+
hint: 'Control freak? Respect.',
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
});
|
|
372
|
+
if (p.isCancel(bundle)) {
|
|
373
|
+
p.cancel("You'll be back. They always come back.");
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
377
|
+
let selectedSkills = [];
|
|
378
|
+
if (bundle === 'custom') {
|
|
379
|
+
const workflowSkills = SKILLS.filter((s) => s.group === 'workflow');
|
|
380
|
+
const designSkills = SKILLS.filter((s) => s.group === 'design');
|
|
381
|
+
// Workflow skills
|
|
382
|
+
console.log('');
|
|
383
|
+
console.log(pc.dim(' ╭─── WORKFLOW SKILLS ─────────────────────────────────────────────────╮'));
|
|
384
|
+
console.log(` ${pc.dim('│')} Select workflow skills ${pc.dim('space: toggle · a: all · enter: confirm')}`);
|
|
385
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
386
|
+
const workflowChoices = await p.multiselect({
|
|
387
|
+
message: '',
|
|
388
|
+
options: workflowSkills.map((s) => ({
|
|
389
|
+
value: s.name,
|
|
390
|
+
label: s.name.padEnd(28),
|
|
391
|
+
hint: s.description,
|
|
392
|
+
})),
|
|
393
|
+
initialValues: workflowSkills.slice(0, 6).map((s) => s.name),
|
|
394
|
+
required: false,
|
|
395
|
+
});
|
|
396
|
+
if (p.isCancel(workflowChoices)) {
|
|
397
|
+
p.cancel("You'll be back. They always come back.");
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
401
|
+
const selectedWorkflow = workflowChoices;
|
|
402
|
+
// Design skills
|
|
403
|
+
console.log('');
|
|
404
|
+
console.log(pc.dim(' ╭─── DESIGN SKILLS ───────────────────────────────────────────────────╮'));
|
|
405
|
+
console.log(` ${pc.dim('│')} Select design skills ${pc.dim(`(${selectedWorkflow.length} workflow) · space · a · enter`)}`);
|
|
406
|
+
console.log(pc.dim(' ├───────────────────────────────────────────────────────────────────────┤'));
|
|
407
|
+
const designChoices = await p.multiselect({
|
|
408
|
+
message: '',
|
|
409
|
+
options: designSkills.map((s) => ({
|
|
410
|
+
value: s.name,
|
|
411
|
+
label: s.name.padEnd(28),
|
|
412
|
+
hint: s.description,
|
|
413
|
+
})),
|
|
414
|
+
initialValues: designSkills.slice(0, 4).map((s) => s.name),
|
|
415
|
+
required: false,
|
|
416
|
+
});
|
|
417
|
+
if (p.isCancel(designChoices)) {
|
|
418
|
+
p.cancel("You'll be back. They always come back.");
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
console.log(pc.dim(' ╰───────────────────────────────────────────────────────────────────────╯'));
|
|
422
|
+
const selectedDesign = designChoices;
|
|
423
|
+
selectedSkills = [...selectedWorkflow, ...selectedDesign];
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
selectedSkills =
|
|
427
|
+
bundle === 'everything'
|
|
428
|
+
? SKILLS.map((s) => s.name)
|
|
429
|
+
: bundle === 'designer'
|
|
430
|
+
? [...BUNDLES.designer.skills]
|
|
431
|
+
: SKILLS.filter((s) => s.group === 'workflow').map((s) => s.name);
|
|
432
|
+
}
|
|
433
|
+
return { selectedSkills };
|
|
434
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { UserChoices } from './prompts.js';
|
|
2
|
+
export interface ScaffoldResult {
|
|
3
|
+
files: number;
|
|
4
|
+
skills: number;
|
|
5
|
+
commands: number;
|
|
6
|
+
time: string;
|
|
7
|
+
deps: number;
|
|
8
|
+
disk: string;
|
|
9
|
+
}
|
|
10
|
+
type ProgressCallback = (task: string, progress: number, detail?: string) => void;
|
|
11
|
+
export declare function scaffold(choices: UserChoices, onProgress: ProgressCallback): Promise<ScaffoldResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize claudecraft in an existing project
|
|
14
|
+
* Only adds .claude folder with skills, commands, hooks, settings
|
|
15
|
+
*/
|
|
16
|
+
export declare function initExisting(choices: {
|
|
17
|
+
selectedSkills: string[];
|
|
18
|
+
}, onProgress: ProgressCallback): Promise<ScaffoldResult>;
|
|
19
|
+
export {};
|