ccraft 1.0.8 → 1.0.9
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/package.json +1 -1
- package/src/commands/create.js +5 -7
- package/src/commands/install.js +1 -1
- package/src/constants.js +1 -45
- package/src/generators/metadata.js +0 -1
- package/src/prompts/gather.js +2 -49
- package/src/utils/analysis-cache.js +1 -1
- package/src/utils/api-client.js +2 -2
- package/src/utils/description-analyzer.js +1 -3
package/package.json
CHANGED
package/src/commands/create.js
CHANGED
|
@@ -69,7 +69,7 @@ function countTotalItems(summary, selectedCandidateIds) {
|
|
|
69
69
|
* Create command — build a new project from scratch.
|
|
70
70
|
*
|
|
71
71
|
* Step 1: Welcome & Setup (env check + API key)
|
|
72
|
-
* Step 2: Project Setup (name, description,
|
|
72
|
+
* Step 2: Project Setup (name, description, mkdir, git init)
|
|
73
73
|
* Step 3: Configuration & Install (synthetic analysis → server → write .claude/)
|
|
74
74
|
* Step 4: Bootstrap (hand off to Claude CLI /bootstrap:auto)
|
|
75
75
|
* Step 5: Post-bootstrap Sync (re-analyze, rewrite CLAUDE.md, finalize)
|
|
@@ -101,15 +101,14 @@ export async function runCreate(options = {}) {
|
|
|
101
101
|
createProfile = {
|
|
102
102
|
name: options.name || 'my-project',
|
|
103
103
|
description: options.description || 'A new project',
|
|
104
|
-
role: 'web',
|
|
105
104
|
projectType: 'monolith',
|
|
106
105
|
};
|
|
107
|
-
logger.info(`Non-interactive mode — creating ${chalk.bold(createProfile.name)} (
|
|
106
|
+
logger.info(`Non-interactive mode — creating ${chalk.bold(createProfile.name)} (monolith).`);
|
|
108
107
|
} else {
|
|
109
108
|
createProfile = await gatherCreateProfile();
|
|
110
109
|
}
|
|
111
110
|
|
|
112
|
-
let { name, description,
|
|
111
|
+
let { name, description, projectType } = createProfile;
|
|
113
112
|
|
|
114
113
|
// Resolve target directory
|
|
115
114
|
const parentDir = resolve(options.dir || process.cwd());
|
|
@@ -171,9 +170,8 @@ export async function runCreate(options = {}) {
|
|
|
171
170
|
: `Created ${chalk.bold(name)}/ (git init skipped — git not available).`);
|
|
172
171
|
}
|
|
173
172
|
|
|
174
|
-
// Build user profile
|
|
173
|
+
// Build user profile
|
|
175
174
|
const userProfile = {
|
|
176
|
-
role,
|
|
177
175
|
intents: ['implementing', 'debugging', 'refactoring', 'testing', 'reviewing'],
|
|
178
176
|
sourceControl: 'github',
|
|
179
177
|
documentTools: [],
|
|
@@ -188,7 +186,7 @@ export async function runCreate(options = {}) {
|
|
|
188
186
|
let descAnalysis = null;
|
|
189
187
|
{
|
|
190
188
|
const spinnerAnalyze = ora('Analyzing your requirements...').start();
|
|
191
|
-
const { analysis, failReason } = await analyzeDescription(description,
|
|
189
|
+
const { analysis, failReason } = await analyzeDescription(description, projectType);
|
|
192
190
|
if (analysis) {
|
|
193
191
|
descAnalysis = analysis;
|
|
194
192
|
const parts = [];
|
package/src/commands/install.js
CHANGED
|
@@ -77,7 +77,7 @@ export async function runInstall(options = {}) {
|
|
|
77
77
|
|
|
78
78
|
let userProfile;
|
|
79
79
|
if (options.yes) {
|
|
80
|
-
userProfile = {
|
|
80
|
+
userProfile = { intents: ['implementing', 'debugging', 'refactoring', 'testing', 'reviewing'], sourceControl: 'github', documentTools: [] };
|
|
81
81
|
logger.info('Non-interactive mode — using default profile (web, all intents, github).');
|
|
82
82
|
} else {
|
|
83
83
|
userProfile = await gatherUserProfile();
|
package/src/constants.js
CHANGED
|
@@ -9,51 +9,7 @@ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8
|
|
|
9
9
|
export const VERSION = pkg.version;
|
|
10
10
|
export const TOOL_NAME = 'claude-craft';
|
|
11
11
|
|
|
12
|
-
// ── Step 1: User
|
|
13
|
-
|
|
14
|
-
export const ROLES = [
|
|
15
|
-
{
|
|
16
|
-
name: 'Developer',
|
|
17
|
-
value: 'developer',
|
|
18
|
-
description: 'Build and ship software across the stack',
|
|
19
|
-
children: [
|
|
20
|
-
{ name: 'Web', value: 'web', description: 'Frontend and backend development' },
|
|
21
|
-
{ name: 'Mobile', value: 'mobile', description: 'iOS, Android, and cross-platform apps' },
|
|
22
|
-
{ name: 'Game', value: 'game', description: 'Game engines, rendering, and gameplay' },
|
|
23
|
-
{ name: 'Blockchain', value: 'blockchain', description: 'Smart contracts, DApps, and Web3' },
|
|
24
|
-
{ name: 'Embedded', value: 'embedded', description: 'Firmware, IoT, and low-level systems' },
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
{ name: 'DevOps', value: 'devops', description: 'Infrastructure, CI/CD, and deployment pipelines' },
|
|
28
|
-
{
|
|
29
|
-
name: 'Data & Analytics',
|
|
30
|
-
value: 'data-analytics',
|
|
31
|
-
description: 'Data pipelines, analysis, ML, and visualization',
|
|
32
|
-
children: [
|
|
33
|
-
{ name: 'Data Scientist', value: 'data-scientist', description: 'ML models, experiments, and research' },
|
|
34
|
-
{ name: 'Data Engineer', value: 'data-engineer', description: 'Pipelines, ETL, and data infrastructure' },
|
|
35
|
-
{ name: 'Data Analyst', value: 'data-analyst', description: 'Queries, dashboards, and reporting' },
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
{ name: 'Quality Assurance', value: 'qa', description: 'Testing strategy, automation, and quality gates' },
|
|
39
|
-
{ name: 'Cybersecurity', value: 'cybersecurity', description: 'Security audits, vulnerability analysis, hardening' },
|
|
40
|
-
{ name: 'Product & Design', value: 'product-design', description: 'Product specs, design systems, UX workflows' },
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
export const ROLE_DISPLAY_NAMES = {
|
|
44
|
-
web: 'Web Developer',
|
|
45
|
-
mobile: 'Mobile Developer',
|
|
46
|
-
game: 'Game Developer',
|
|
47
|
-
blockchain: 'Blockchain Developer',
|
|
48
|
-
embedded: 'Embedded Developer',
|
|
49
|
-
devops: 'DevOps / Infrastructure',
|
|
50
|
-
'data-scientist': 'Data Scientist',
|
|
51
|
-
'data-engineer': 'Data Engineer',
|
|
52
|
-
'data-analyst': 'Data Analyst',
|
|
53
|
-
qa: 'Quality Assurance',
|
|
54
|
-
cybersecurity: 'Cybersecurity',
|
|
55
|
-
'product-design': 'Product & Design',
|
|
56
|
-
};
|
|
12
|
+
// ── Step 1: User intents ──────────────────────────────────────────────
|
|
57
13
|
|
|
58
14
|
export const INTENTS = [
|
|
59
15
|
{ name: 'Implementing new features', value: 'implementing', description: 'Build features from specs, tickets, or ideas' },
|
|
@@ -15,7 +15,6 @@ export async function generate(config, targetDir, opts = {}) {
|
|
|
15
15
|
version: VERSION,
|
|
16
16
|
generatedAt: new Date().toISOString(),
|
|
17
17
|
preset: config._presetAlias || null,
|
|
18
|
-
role: config.role || null,
|
|
19
18
|
intents: config.intents || [],
|
|
20
19
|
components: config.components || [],
|
|
21
20
|
agents: (config._selectedAgents || []).map((a) => a.id),
|
package/src/prompts/gather.js
CHANGED
|
@@ -2,7 +2,6 @@ import { resolve } from 'path';
|
|
|
2
2
|
import { existsSync, statSync } from 'fs';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import {
|
|
5
|
-
ROLES,
|
|
6
5
|
INTENTS,
|
|
7
6
|
COMPONENTS,
|
|
8
7
|
PROJECT_TYPES,
|
|
@@ -55,20 +54,6 @@ export async function gatherCreateProfile() {
|
|
|
55
54
|
validate: (v) => (v.trim().length > 0 ? true : 'Please describe your project.'),
|
|
56
55
|
});
|
|
57
56
|
|
|
58
|
-
// Dev-only role (filtered from ROLES → developer children)
|
|
59
|
-
const devParent = ROLES.find((r) => r.value === 'developer');
|
|
60
|
-
const roleChoices = devParent.children.map((c) => ({
|
|
61
|
-
name: c.name,
|
|
62
|
-
value: c.value,
|
|
63
|
-
description: c.description,
|
|
64
|
-
}));
|
|
65
|
-
|
|
66
|
-
const role = await themedSelect({
|
|
67
|
-
message: 'What type of developer are you?',
|
|
68
|
-
hint: 'This tailors which agents and rules are installed.',
|
|
69
|
-
choices: roleChoices,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
57
|
// Project type
|
|
73
58
|
const projectType = await themedSelect({
|
|
74
59
|
message: 'What kind of project is this?',
|
|
@@ -79,7 +64,7 @@ export async function gatherCreateProfile() {
|
|
|
79
64
|
})),
|
|
80
65
|
});
|
|
81
66
|
|
|
82
|
-
return { name: name.trim(), description: description.trim(),
|
|
67
|
+
return { name: name.trim(), description: description.trim(), projectType };
|
|
83
68
|
}
|
|
84
69
|
|
|
85
70
|
// ── Phase 1: User profile ──────────────────────────────────────────────
|
|
@@ -87,37 +72,6 @@ export async function gatherCreateProfile() {
|
|
|
87
72
|
export async function gatherUserProfile() {
|
|
88
73
|
console.log(colors.muted('\n Let\'s personalize your Claude Code environment.\n'));
|
|
89
74
|
|
|
90
|
-
// Role category
|
|
91
|
-
|
|
92
|
-
const categoryChoices = ROLES.map((r) => ({
|
|
93
|
-
name: r.name,
|
|
94
|
-
value: r.value,
|
|
95
|
-
description: r.description,
|
|
96
|
-
}));
|
|
97
|
-
const category = await themedSelect({
|
|
98
|
-
message: 'What best describes your role?',
|
|
99
|
-
hint: 'A few agents and rules will be tailored to match your specialty.',
|
|
100
|
-
choices: categoryChoices,
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// Sub-role if category has children
|
|
104
|
-
let role;
|
|
105
|
-
const parent = ROLES.find((r) => r.value === category);
|
|
106
|
-
if (parent && parent.children) {
|
|
107
|
-
|
|
108
|
-
role = await themedSelect({
|
|
109
|
-
message: `Which ${parent.name.toLowerCase()} specialty fits best?`,
|
|
110
|
-
hint: 'This fine-tunes which agents and rules are installed.',
|
|
111
|
-
choices: parent.children.map((c) => ({
|
|
112
|
-
name: c.name,
|
|
113
|
-
value: c.value,
|
|
114
|
-
description: c.description,
|
|
115
|
-
})),
|
|
116
|
-
});
|
|
117
|
-
} else {
|
|
118
|
-
role = category;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
75
|
// Intents
|
|
122
76
|
|
|
123
77
|
const intents = await themedCheckbox({
|
|
@@ -166,7 +120,7 @@ export async function gatherUserProfile() {
|
|
|
166
120
|
documentTools[otherIndex] = otherTool.trim();
|
|
167
121
|
}
|
|
168
122
|
|
|
169
|
-
return {
|
|
123
|
+
return { intents, sourceControl, documentTools };
|
|
170
124
|
}
|
|
171
125
|
|
|
172
126
|
// ── MCP selection + credential setup ──────────────────────────────────
|
|
@@ -292,7 +246,6 @@ export async function confirmInstallation(summary) {
|
|
|
292
246
|
|
|
293
247
|
export function getDefaults(detected) {
|
|
294
248
|
return {
|
|
295
|
-
role: 'web',
|
|
296
249
|
intents: ['implementing', 'debugging', 'refactoring', 'testing', 'reviewing'],
|
|
297
250
|
sourceControl: 'github',
|
|
298
251
|
documentTools: [],
|
|
@@ -320,7 +320,7 @@ export function formatRichProjectContext(projectInfo, detected) {
|
|
|
320
320
|
* Called alongside writeAnalysisCache during install.
|
|
321
321
|
*
|
|
322
322
|
* @param {string} targetDir - Project root
|
|
323
|
-
* @param {object} userProfile - {
|
|
323
|
+
* @param {object} userProfile - { intents, sourceControl, documentTools }
|
|
324
324
|
*/
|
|
325
325
|
export function writeUserProfile(targetDir, userProfile) {
|
|
326
326
|
const dir = cachePath(targetDir);
|
package/src/utils/api-client.js
CHANGED
|
@@ -45,7 +45,7 @@ export function saveConfig(config) {
|
|
|
45
45
|
/**
|
|
46
46
|
* Call POST /api/generate on the server.
|
|
47
47
|
*
|
|
48
|
-
* @param {object} profile - {
|
|
48
|
+
* @param {object} profile - { intents, sourceControl, documentTools }
|
|
49
49
|
* @param {object} analysis - Project analysis data
|
|
50
50
|
* @param {object} [options] - { preset }
|
|
51
51
|
* @returns {Promise<{ files, summary, mcpConfigs, serverVersion }>}
|
|
@@ -131,7 +131,7 @@ export async function callGenerate(profile, analysis, options = {}) {
|
|
|
131
131
|
* Call POST /api/update on the server.
|
|
132
132
|
* Returns delta components (new files not already installed) + change summary.
|
|
133
133
|
*
|
|
134
|
-
* @param {object} profile - {
|
|
134
|
+
* @param {object} profile - { intents, sourceControl, documentTools }
|
|
135
135
|
* @param {object} currentAnalysis - Freshly computed project analysis
|
|
136
136
|
* @param {object} previousAnalysis - Previously stored project analysis
|
|
137
137
|
* @param {string[]} installedRelativePaths - Relative file paths already on disk
|
|
@@ -68,11 +68,10 @@ Return ONLY the JSON, nothing else.`;
|
|
|
68
68
|
* so callers can use identical fallback logic.
|
|
69
69
|
*
|
|
70
70
|
* @param {string} description - User's project description (free text)
|
|
71
|
-
* @param {string} role - Developer role (e.g., "web", "backend")
|
|
72
71
|
* @param {string} projectType - Project type the user selected
|
|
73
72
|
* @returns {Promise<{ analysis: object|null, failReason: string|null }>}
|
|
74
73
|
*/
|
|
75
|
-
export async function analyzeDescription(description,
|
|
74
|
+
export async function analyzeDescription(description, projectType) {
|
|
76
75
|
if (!isClaudeAvailable()) {
|
|
77
76
|
return { analysis: null, failReason: 'cli-unavailable' };
|
|
78
77
|
}
|
|
@@ -82,7 +81,6 @@ export async function analyzeDescription(description, role, projectType) {
|
|
|
82
81
|
## Input
|
|
83
82
|
|
|
84
83
|
Description: "${description}"
|
|
85
|
-
Role: ${role}
|
|
86
84
|
Project Type: ${projectType}
|
|
87
85
|
|
|
88
86
|
Analyze the description above and return the JSON.`;
|