@meltstudio/meltctl 4.22.0 → 4.23.1
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/README.md +3 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +127 -26
- package/dist/index.js +9 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,7 +20,8 @@ meltctl project init
|
|
|
20
20
|
# Select specific tools
|
|
21
21
|
meltctl project init --claude # Claude Code only
|
|
22
22
|
meltctl project init --cursor # Cursor only
|
|
23
|
-
meltctl project init --
|
|
23
|
+
meltctl project init --opencode # OpenCode only
|
|
24
|
+
meltctl project init --claude --cursor --opencode # All tools
|
|
24
25
|
|
|
25
26
|
# Re-initialize
|
|
26
27
|
meltctl project init --force
|
|
@@ -49,6 +50,7 @@ meltctl version --check
|
|
|
49
50
|
- `.claude/settings.json` — Claude Code permissions
|
|
50
51
|
- `.claude/skills/melt-{setup,plan,...,update}/SKILL.md` — Claude Code workflow skills
|
|
51
52
|
- `.cursor/commands/melt-{setup,plan,...,update}.md` — Cursor workflow commands
|
|
53
|
+
- `.opencode/commands/melt-{setup,plan,...,update}.md` — OpenCode workflow commands
|
|
52
54
|
- `.mcp.json` — MCP server configuration (Chrome DevTools)
|
|
53
55
|
|
|
54
56
|
## Requirements
|
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -96,6 +96,53 @@ description: >-
|
|
|
96
96
|
This is a reference skill — it explains the process, not executes it.
|
|
97
97
|
---
|
|
98
98
|
|
|
99
|
+
`,
|
|
100
|
+
};
|
|
101
|
+
const OPENCODE_COMMAND_FRONTMATTER = {
|
|
102
|
+
setup: `---
|
|
103
|
+
description: Analyze the project and customize AGENTS.md for this codebase.
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
`,
|
|
107
|
+
plan: `---
|
|
108
|
+
description: Design an implementation approach before writing code.
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
`,
|
|
112
|
+
review: `---
|
|
113
|
+
description: Review code changes against project standards and address PR feedback.
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
`,
|
|
117
|
+
pr: `---
|
|
118
|
+
description: Create a well-structured pull request from current changes.
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
`,
|
|
122
|
+
debug: `---
|
|
123
|
+
description: Systematically investigate and fix bugs.
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
`,
|
|
127
|
+
audit: `---
|
|
128
|
+
description: Run a comprehensive project compliance audit against team standards.
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
`,
|
|
132
|
+
validate: `---
|
|
133
|
+
description: Run the validation plan from the plan document after implementation.
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
`,
|
|
137
|
+
update: `---
|
|
138
|
+
description: Update Melt skills and standards to the latest version.
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
`,
|
|
142
|
+
help: `---
|
|
143
|
+
description: Answer questions about the AI-First Development Playbook and team workflow.
|
|
144
|
+
---
|
|
145
|
+
|
|
99
146
|
`,
|
|
100
147
|
};
|
|
101
148
|
const GITIGNORE_ENTRIES = ['.env.local', '.claude/settings.local.json'];
|
|
@@ -103,6 +150,7 @@ function detectExistingTools(cwd) {
|
|
|
103
150
|
return {
|
|
104
151
|
claude: fs.pathExistsSync(path.join(cwd, '.claude/settings.json')),
|
|
105
152
|
cursor: fs.pathExistsSync(path.join(cwd, '.cursor/commands')),
|
|
153
|
+
opencode: fs.pathExistsSync(path.join(cwd, '.opencode/commands')),
|
|
106
154
|
};
|
|
107
155
|
}
|
|
108
156
|
async function promptToolSelection(existingTools) {
|
|
@@ -113,6 +161,9 @@ async function promptToolSelection(existingTools) {
|
|
|
113
161
|
if (!existingTools?.cursor) {
|
|
114
162
|
choices.push({ name: 'Cursor', value: 'cursor', checked: true });
|
|
115
163
|
}
|
|
164
|
+
if (!existingTools?.opencode) {
|
|
165
|
+
choices.push({ name: 'OpenCode', value: 'opencode', checked: true });
|
|
166
|
+
}
|
|
116
167
|
choices.push({
|
|
117
168
|
name: 'Other — contact us in #dev on Slack to request support',
|
|
118
169
|
value: 'other',
|
|
@@ -124,6 +175,7 @@ async function promptToolSelection(existingTools) {
|
|
|
124
175
|
return {
|
|
125
176
|
claude: selected.includes('claude'),
|
|
126
177
|
cursor: selected.includes('cursor'),
|
|
178
|
+
opencode: selected.includes('opencode'),
|
|
127
179
|
other: selected.includes('other'),
|
|
128
180
|
};
|
|
129
181
|
}
|
|
@@ -156,18 +208,27 @@ export async function initCommand(options) {
|
|
|
156
208
|
if (alreadyInitialized && !options.force) {
|
|
157
209
|
// Re-init scenario: project already set up, developer wants to add another tool
|
|
158
210
|
const existing = detectExistingTools(cwd);
|
|
159
|
-
const existingNames = [
|
|
211
|
+
const existingNames = [
|
|
212
|
+
existing.claude ? 'Claude Code' : '',
|
|
213
|
+
existing.cursor ? 'Cursor' : '',
|
|
214
|
+
existing.opencode ? 'OpenCode' : '',
|
|
215
|
+
]
|
|
160
216
|
.filter(Boolean)
|
|
161
|
-
.join('
|
|
162
|
-
if (existing.claude && existing.cursor) {
|
|
163
|
-
console.log(chalk.yellow('Project already initialized with
|
|
217
|
+
.join(', ');
|
|
218
|
+
if (existing.claude && existing.cursor && existing.opencode) {
|
|
219
|
+
console.log(chalk.yellow('Project already initialized with all tools. Use --force to overwrite.'));
|
|
164
220
|
process.exit(1);
|
|
165
221
|
}
|
|
166
222
|
console.log(chalk.dim(`Project already initialized${existingNames ? ` with ${existingNames}` : ''}.`));
|
|
167
223
|
isReInit = true;
|
|
168
|
-
if (options.claude || options.cursor) {
|
|
224
|
+
if (options.claude || options.cursor || options.opencode) {
|
|
169
225
|
// Non-interactive: use flags directly, skip confirm prompt
|
|
170
|
-
tools = {
|
|
226
|
+
tools = {
|
|
227
|
+
claude: !!options.claude,
|
|
228
|
+
cursor: !!options.cursor,
|
|
229
|
+
opencode: !!options.opencode,
|
|
230
|
+
other: false,
|
|
231
|
+
};
|
|
171
232
|
}
|
|
172
233
|
else {
|
|
173
234
|
const addMore = await confirm({
|
|
@@ -182,14 +243,19 @@ export async function initCommand(options) {
|
|
|
182
243
|
}
|
|
183
244
|
else {
|
|
184
245
|
// Fresh init or --force
|
|
185
|
-
if (options.claude || options.cursor) {
|
|
186
|
-
tools = {
|
|
246
|
+
if (options.claude || options.cursor || options.opencode) {
|
|
247
|
+
tools = {
|
|
248
|
+
claude: !!options.claude,
|
|
249
|
+
cursor: !!options.cursor,
|
|
250
|
+
opencode: !!options.opencode,
|
|
251
|
+
other: false,
|
|
252
|
+
};
|
|
187
253
|
}
|
|
188
254
|
else {
|
|
189
255
|
tools = await promptToolSelection();
|
|
190
256
|
}
|
|
191
257
|
}
|
|
192
|
-
if (!tools.claude && !tools.cursor && !tools.other) {
|
|
258
|
+
if (!tools.claude && !tools.cursor && !tools.opencode && !tools.other) {
|
|
193
259
|
console.log(chalk.yellow('No tools selected. Nothing to do.'));
|
|
194
260
|
process.exit(0);
|
|
195
261
|
}
|
|
@@ -267,6 +333,18 @@ export async function initCommand(options) {
|
|
|
267
333
|
}
|
|
268
334
|
createdFiles.push('.cursor/commands/melt-{setup,plan,validate,review,pr,debug,audit,update,help}.md');
|
|
269
335
|
}
|
|
336
|
+
// OpenCode files
|
|
337
|
+
if (tools.opencode) {
|
|
338
|
+
await fs.ensureDir(path.join(cwd, '.opencode/commands'));
|
|
339
|
+
for (const name of workflows) {
|
|
340
|
+
const workflowContent = templates[`workflows/${name}.md`];
|
|
341
|
+
if (workflowContent) {
|
|
342
|
+
const commandContent = OPENCODE_COMMAND_FRONTMATTER[name] + workflowContent;
|
|
343
|
+
await fs.writeFile(path.join(cwd, `.opencode/commands/melt-${name}.md`), commandContent, 'utf-8');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
createdFiles.push('.opencode/commands/melt-{setup,plan,validate,review,pr,debug,audit,update,help}.md');
|
|
347
|
+
}
|
|
270
348
|
// Print summary
|
|
271
349
|
console.log(chalk.green('Created files:'));
|
|
272
350
|
for (const file of createdFiles) {
|
|
@@ -277,35 +355,58 @@ export async function initCommand(options) {
|
|
|
277
355
|
console.log(chalk.cyan('Want support for your tool? Let us know in #dev on Slack'));
|
|
278
356
|
console.log();
|
|
279
357
|
}
|
|
358
|
+
const commandNames = 'melt-setup, melt-plan, melt-validate, melt-review, melt-pr, melt-debug, melt-audit, melt-update, melt-help';
|
|
280
359
|
if (tools.claude) {
|
|
281
|
-
|
|
282
|
-
console.log(chalk.dim(`Available skills: ${skills}`));
|
|
360
|
+
console.log(chalk.dim(`Available skills: /${commandNames.replace(/, /g, ', /')}`));
|
|
283
361
|
}
|
|
284
362
|
if (tools.cursor) {
|
|
285
|
-
console.log(chalk.dim(
|
|
363
|
+
console.log(chalk.dim(`Available Cursor commands: ${commandNames}`));
|
|
364
|
+
}
|
|
365
|
+
if (tools.opencode) {
|
|
366
|
+
console.log(chalk.dim(`Available OpenCode commands: /${commandNames.replace(/, /g, ', /')}`));
|
|
286
367
|
}
|
|
287
|
-
if (tools.claude || tools.cursor) {
|
|
368
|
+
if (tools.claude || tools.cursor || tools.opencode) {
|
|
288
369
|
console.log();
|
|
289
370
|
}
|
|
290
371
|
if (!isReInit) {
|
|
291
372
|
console.log(chalk.bold.cyan(' Next step: run /melt-setup to customize AGENTS.md for your project'));
|
|
292
373
|
console.log();
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
374
|
+
const toolInstructions = [];
|
|
375
|
+
if (tools.claude) {
|
|
376
|
+
toolInstructions.push({
|
|
377
|
+
name: 'Claude Code',
|
|
378
|
+
steps: [
|
|
379
|
+
'Type /melt-setup in the chat prompt, or',
|
|
380
|
+
'Open the skills menu and select melt-setup',
|
|
381
|
+
],
|
|
382
|
+
});
|
|
300
383
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
384
|
+
if (tools.cursor) {
|
|
385
|
+
toolInstructions.push({
|
|
386
|
+
name: 'Cursor',
|
|
387
|
+
steps: ['Open the command menu (Cmd+K) and search for melt-setup'],
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
if (tools.opencode) {
|
|
391
|
+
toolInstructions.push({
|
|
392
|
+
name: 'OpenCode',
|
|
393
|
+
steps: ['Type /melt-setup in the chat prompt'],
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
if (toolInstructions.length === 1 && toolInstructions[0]) {
|
|
397
|
+
console.log(chalk.dim(` In ${toolInstructions[0].name}:`));
|
|
398
|
+
for (const step of toolInstructions[0].steps) {
|
|
399
|
+
console.log(chalk.dim(` - ${step}`));
|
|
400
|
+
}
|
|
305
401
|
}
|
|
306
402
|
else {
|
|
307
|
-
|
|
308
|
-
|
|
403
|
+
for (const tool of toolInstructions) {
|
|
404
|
+
console.log(chalk.dim(` ${tool.name}:`));
|
|
405
|
+
for (const step of tool.steps) {
|
|
406
|
+
console.log(chalk.dim(` - ${step}`));
|
|
407
|
+
}
|
|
408
|
+
console.log();
|
|
409
|
+
}
|
|
309
410
|
}
|
|
310
411
|
console.log();
|
|
311
412
|
console.log(chalk.dim(' The setup skill will analyze your project and fill in AGENTS.md.'));
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'),
|
|
|
21
21
|
const program = new Command();
|
|
22
22
|
program
|
|
23
23
|
.name('meltctl')
|
|
24
|
-
.description('Set up AI-first development standards (AGENTS.md, Claude skills, Cursor commands, MCP config) in your project.\n\nRequires a @meltstudio.co Google Workspace account. Run `npx @meltstudio/meltctl@latest login` first, then `npx @meltstudio/meltctl@latest project init` in your repo.')
|
|
24
|
+
.description('Set up AI-first development standards (AGENTS.md, Claude skills, Cursor commands, OpenCode commands, MCP config) in your project.\n\nRequires a @meltstudio.co Google Workspace account. Run `npx @meltstudio/meltctl@latest login` first, then `npx @meltstudio/meltctl@latest project init` in your repo.')
|
|
25
25
|
.version(packageJson.version)
|
|
26
26
|
.addHelpText('beforeAll', () => {
|
|
27
27
|
printBanner();
|
|
@@ -45,12 +45,18 @@ program
|
|
|
45
45
|
const project = program.command('project').description('manage project configuration');
|
|
46
46
|
project
|
|
47
47
|
.command('init')
|
|
48
|
-
.description('scaffold Melt development tools into the current directory (AGENTS.md, .claude/, .cursor/, .mcp.json)')
|
|
48
|
+
.description('scaffold Melt development tools into the current directory (AGENTS.md, .claude/, .cursor/, .opencode/, .mcp.json)')
|
|
49
49
|
.option('--force', 'overwrite existing files if already initialized')
|
|
50
50
|
.option('--claude', 'generate Claude Code configuration')
|
|
51
51
|
.option('--cursor', 'generate Cursor configuration')
|
|
52
|
+
.option('--opencode', 'generate OpenCode configuration')
|
|
52
53
|
.action(options => {
|
|
53
|
-
return initCommand({
|
|
54
|
+
return initCommand({
|
|
55
|
+
force: options.force,
|
|
56
|
+
claude: options.claude,
|
|
57
|
+
cursor: options.cursor,
|
|
58
|
+
opencode: options.opencode,
|
|
59
|
+
});
|
|
54
60
|
});
|
|
55
61
|
project
|
|
56
62
|
.command('templates')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meltstudio/meltctl",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "AI-first development tools for teams - set up AGENTS.md, Claude Code, Cursor, and
|
|
3
|
+
"version": "4.23.1",
|
|
4
|
+
"description": "AI-first development tools for teams - set up AGENTS.md, Claude Code, Cursor, and OpenCode standards",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|