@meltstudio/meltctl 4.2.0 → 4.3.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/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +130 -51
- package/dist/index.js +3 -1
- package/package.json +2 -1
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import { checkbox, confirm } from '@inquirer/prompts';
|
|
2
3
|
import fs from 'fs-extra';
|
|
3
4
|
import path from 'path';
|
|
4
5
|
import { authenticatedFetch, isAuthenticated } from '../utils/auth.js';
|
|
@@ -37,12 +38,78 @@ async function fetchTemplates() {
|
|
|
37
38
|
const data = (await response.json());
|
|
38
39
|
return data.files;
|
|
39
40
|
}
|
|
41
|
+
function detectExistingTools(cwd) {
|
|
42
|
+
return {
|
|
43
|
+
claude: fs.pathExistsSync(path.join(cwd, '.claude/settings.json')),
|
|
44
|
+
cursor: fs.pathExistsSync(path.join(cwd, '.cursor/commands')),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function promptToolSelection(existingTools) {
|
|
48
|
+
const choices = [];
|
|
49
|
+
if (!existingTools?.claude) {
|
|
50
|
+
choices.push({ name: 'Claude Code', value: 'claude', checked: true });
|
|
51
|
+
}
|
|
52
|
+
if (!existingTools?.cursor) {
|
|
53
|
+
choices.push({ name: 'Cursor', value: 'cursor', checked: true });
|
|
54
|
+
}
|
|
55
|
+
choices.push({
|
|
56
|
+
name: 'Other — contact us in #dev on Slack to request support',
|
|
57
|
+
value: 'other',
|
|
58
|
+
});
|
|
59
|
+
const selected = await checkbox({
|
|
60
|
+
message: 'Which AI coding tools do you use?',
|
|
61
|
+
choices,
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
claude: selected.includes('claude'),
|
|
65
|
+
cursor: selected.includes('cursor'),
|
|
66
|
+
other: selected.includes('other'),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
40
69
|
export async function initCommand(options) {
|
|
41
70
|
const cwd = process.cwd();
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
71
|
+
const alreadyInitialized = await fs.pathExists(path.join(cwd, 'AGENTS.md'));
|
|
72
|
+
let isReInit = false;
|
|
73
|
+
let tools;
|
|
74
|
+
if (alreadyInitialized && !options.force) {
|
|
75
|
+
// Re-init scenario: project already set up, developer wants to add another tool
|
|
76
|
+
const existing = detectExistingTools(cwd);
|
|
77
|
+
const existingNames = [existing.claude ? 'Claude Code' : '', existing.cursor ? 'Cursor' : '']
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.join(' and ');
|
|
80
|
+
if (existing.claude && existing.cursor) {
|
|
81
|
+
console.log(chalk.yellow('Project already initialized with Claude Code and Cursor. Use --force to overwrite.'));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
console.log(chalk.dim(`Project already initialized${existingNames ? ` with ${existingNames}` : ''}.`));
|
|
85
|
+
isReInit = true;
|
|
86
|
+
if (options.claude || options.cursor) {
|
|
87
|
+
// Non-interactive: use flags directly, skip confirm prompt
|
|
88
|
+
tools = { claude: !!options.claude, cursor: !!options.cursor, other: false };
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const addMore = await confirm({
|
|
92
|
+
message: 'Add configuration for another tool?',
|
|
93
|
+
default: true,
|
|
94
|
+
});
|
|
95
|
+
if (!addMore) {
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
tools = await promptToolSelection(existing);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Fresh init or --force
|
|
103
|
+
if (options.claude || options.cursor) {
|
|
104
|
+
tools = { claude: !!options.claude, cursor: !!options.cursor, other: false };
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
tools = await promptToolSelection();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!tools.claude && !tools.cursor && !tools.other) {
|
|
111
|
+
console.log(chalk.yellow('No tools selected. Nothing to do.'));
|
|
112
|
+
process.exit(0);
|
|
46
113
|
}
|
|
47
114
|
// Require authentication
|
|
48
115
|
if (!(await isAuthenticated())) {
|
|
@@ -67,62 +134,74 @@ export async function initCommand(options) {
|
|
|
67
134
|
}
|
|
68
135
|
console.log(chalk.bold('Initializing Melt development tools...'));
|
|
69
136
|
console.log();
|
|
70
|
-
|
|
71
|
-
const agentsMd = templates['agents-md.md'];
|
|
72
|
-
if (agentsMd) {
|
|
73
|
-
await fs.writeFile(path.join(cwd, 'AGENTS.md'), agentsMd, 'utf-8');
|
|
74
|
-
}
|
|
75
|
-
// Copy .claude/settings.json
|
|
76
|
-
const claudeSettings = templates['claude-settings.json'];
|
|
77
|
-
if (claudeSettings) {
|
|
78
|
-
await fs.ensureDir(path.join(cwd, '.claude'));
|
|
79
|
-
await fs.writeFile(path.join(cwd, '.claude/settings.json'), claudeSettings, 'utf-8');
|
|
80
|
-
}
|
|
81
|
-
// Create Claude skills from workflow templates
|
|
137
|
+
const createdFiles = [];
|
|
82
138
|
const workflows = ['plan', 'review', 'pr', 'debug'];
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
await fs.
|
|
88
|
-
|
|
89
|
-
await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent, 'utf-8');
|
|
139
|
+
// Shared files (skip on re-init)
|
|
140
|
+
if (!isReInit) {
|
|
141
|
+
const agentsMd = templates['agents-md.md'];
|
|
142
|
+
if (agentsMd) {
|
|
143
|
+
await fs.writeFile(path.join(cwd, 'AGENTS.md'), agentsMd, 'utf-8');
|
|
144
|
+
createdFiles.push('AGENTS.md');
|
|
90
145
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const workflowContent = templates[`workflows/${name}.md`];
|
|
96
|
-
if (workflowContent) {
|
|
97
|
-
await fs.writeFile(path.join(cwd, `.cursor/commands/melt-${name}.md`), workflowContent, 'utf-8');
|
|
146
|
+
const mcpConfig = templates['mcp-configs/base.json'];
|
|
147
|
+
if (mcpConfig) {
|
|
148
|
+
await fs.writeFile(path.join(cwd, '.mcp.json'), mcpConfig, 'utf-8');
|
|
149
|
+
createdFiles.push('.mcp.json');
|
|
98
150
|
}
|
|
151
|
+
const envExample = templates['env-melt-example'];
|
|
152
|
+
if (envExample) {
|
|
153
|
+
await fs.writeFile(path.join(cwd, '.env.melt.example'), envExample, 'utf-8');
|
|
154
|
+
createdFiles.push('.env.melt.example');
|
|
155
|
+
}
|
|
156
|
+
await updateGitignore(cwd);
|
|
99
157
|
}
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
158
|
+
// Claude Code files
|
|
159
|
+
if (tools.claude) {
|
|
160
|
+
const claudeSettings = templates['claude-settings.json'];
|
|
161
|
+
if (claudeSettings) {
|
|
162
|
+
await fs.ensureDir(path.join(cwd, '.claude'));
|
|
163
|
+
await fs.writeFile(path.join(cwd, '.claude/settings.json'), claudeSettings, 'utf-8');
|
|
164
|
+
createdFiles.push('.claude/settings.json');
|
|
165
|
+
}
|
|
166
|
+
for (const name of workflows) {
|
|
167
|
+
const workflowContent = templates[`workflows/${name}.md`];
|
|
168
|
+
if (workflowContent) {
|
|
169
|
+
const skillDir = path.join(cwd, `.claude/skills/melt-${name}`);
|
|
170
|
+
await fs.ensureDir(skillDir);
|
|
171
|
+
const skillContent = SKILL_FRONTMATTER[name] + workflowContent;
|
|
172
|
+
await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent, 'utf-8');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
createdFiles.push('.claude/skills/melt-{plan,review,pr,debug}/SKILL.md');
|
|
104
176
|
}
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
177
|
+
// Cursor files
|
|
178
|
+
if (tools.cursor) {
|
|
179
|
+
await fs.ensureDir(path.join(cwd, '.cursor/commands'));
|
|
180
|
+
for (const name of workflows) {
|
|
181
|
+
const workflowContent = templates[`workflows/${name}.md`];
|
|
182
|
+
if (workflowContent) {
|
|
183
|
+
await fs.writeFile(path.join(cwd, `.cursor/commands/melt-${name}.md`), workflowContent, 'utf-8');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
createdFiles.push('.cursor/commands/melt-{plan,review,pr,debug}.md');
|
|
109
187
|
}
|
|
110
|
-
// Update .gitignore
|
|
111
|
-
await updateGitignore(cwd);
|
|
112
188
|
// Print summary
|
|
113
189
|
console.log(chalk.green('Created files:'));
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
console.log(chalk.dim(' .cursor/commands/melt-{plan,review,pr,debug}.md'));
|
|
118
|
-
console.log(chalk.dim(' .mcp.json'));
|
|
119
|
-
console.log(chalk.dim(' .env.melt.example'));
|
|
120
|
-
console.log();
|
|
121
|
-
console.log(chalk.yellow('Next steps:'));
|
|
122
|
-
console.log(chalk.dim(' 1. Run your AI agent — it will automatically fill in project details in AGENTS.md'));
|
|
123
|
-
console.log(chalk.dim(' 2. Copy .env.melt.example to .env.local and fill in credentials'));
|
|
124
|
-
console.log(chalk.dim(' 3. Commit the generated files'));
|
|
190
|
+
for (const file of createdFiles) {
|
|
191
|
+
console.log(chalk.dim(` ${file}`));
|
|
192
|
+
}
|
|
125
193
|
console.log();
|
|
194
|
+
if (tools.other) {
|
|
195
|
+
console.log(chalk.cyan('Want support for your tool? Let us know in #dev on Slack'));
|
|
196
|
+
console.log();
|
|
197
|
+
}
|
|
198
|
+
if (!isReInit) {
|
|
199
|
+
console.log(chalk.yellow('Next steps:'));
|
|
200
|
+
console.log(chalk.dim(' 1. Run your AI agent — it will automatically fill in project details in AGENTS.md'));
|
|
201
|
+
console.log(chalk.dim(' 2. Copy .env.melt.example to .env.local and fill in credentials'));
|
|
202
|
+
console.log(chalk.dim(' 3. Commit the generated files'));
|
|
203
|
+
console.log();
|
|
204
|
+
}
|
|
126
205
|
console.log(chalk.green('Done!'));
|
|
127
206
|
}
|
|
128
207
|
async function updateGitignore(cwd) {
|
package/dist/index.js
CHANGED
|
@@ -42,8 +42,10 @@ project
|
|
|
42
42
|
.command('init')
|
|
43
43
|
.description('scaffold Melt development tools into the current directory (AGENTS.md, .claude/, .cursor/, .mcp.json)')
|
|
44
44
|
.option('--force', 'overwrite existing files if already initialized')
|
|
45
|
+
.option('--claude', 'generate Claude Code configuration')
|
|
46
|
+
.option('--cursor', 'generate Cursor configuration')
|
|
45
47
|
.action(options => {
|
|
46
|
-
return initCommand({ force: options.force });
|
|
48
|
+
return initCommand({ force: options.force, claude: options.claude, cursor: options.cursor });
|
|
47
49
|
});
|
|
48
50
|
program
|
|
49
51
|
.command('version')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meltstudio/meltctl",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "AI-first development tools for teams - set up AGENTS.md, Claude Code, Cursor, and Copilot standards",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"license": "MIT",
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@commander-js/extra-typings": "^12.1.0",
|
|
51
|
+
"@inquirer/prompts": "^8.2.1",
|
|
51
52
|
"chalk": "^5.4.1",
|
|
52
53
|
"commander": "^12.1.0",
|
|
53
54
|
"fs-extra": "^11.2.0",
|