Skip to content

Commit 51fb10d

Browse files
authored
feat: add slash commands to artifact-experimental-setup (#442)
Extend the `openspec artifact-experimental-setup` command to also generate slash commands alongside Agent Skills. Changes: - Add CommandTemplate interface and template functions for /opsx:new, /opsx:continue, and /opsx:apply commands - Modify artifactExperimentalSetupCommand() to create slash command files at .claude/commands/opsx/ - Update success message to show both skills and slash commands created The setup command now creates: - 3 Agent Skills (.claude/skills/) - 3 Slash Commands (.claude/commands/opsx/)
1 parent cac5404 commit 51fb10d

File tree

2 files changed

+378
-12
lines changed

2 files changed

+378
-12
lines changed

src/commands/artifact-workflow.ts

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
type ArtifactInstructions,
2727
} from '../core/artifact-graph/index.js';
2828
import { createChange, validateChangeName } from '../utils/change-utils.js';
29-
import { getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate } from '../core/templates/skill-templates.js';
29+
import { getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate } from '../core/templates/skill-templates.js';
3030
import { FileSystemUtils } from '../utils/file-system.js';
3131

3232
// -----------------------------------------------------------------------------
@@ -678,29 +678,36 @@ async function newChangeCommand(name: string | undefined, options: NewChangeOpti
678678
// -----------------------------------------------------------------------------
679679

680680
/**
681-
* Generates Agent Skills for the experimental artifact workflow.
681+
* Generates Agent Skills and slash commands for the experimental artifact workflow.
682682
* Creates .claude/skills/ directory with SKILL.md files following Agent Skills spec.
683+
* Creates .claude/commands/opsx/ directory with slash command files.
683684
*/
684685
async function artifactExperimentalSetupCommand(): Promise<void> {
685-
const spinner = ora('Setting up experimental artifact workflow skills...').start();
686+
const spinner = ora('Setting up experimental artifact workflow...').start();
686687

687688
try {
688689
const projectRoot = process.cwd();
689690
const skillsDir = path.join(projectRoot, '.claude', 'skills');
691+
const commandsDir = path.join(projectRoot, '.claude', 'commands', 'opsx');
690692

691693
// Get skill templates
692694
const newChangeSkill = getNewChangeSkillTemplate();
693695
const continueChangeSkill = getContinueChangeSkillTemplate();
694696
const applyChangeSkill = getApplyChangeSkillTemplate();
695697

698+
// Get command templates
699+
const newCommand = getOpsxNewCommandTemplate();
700+
const continueCommand = getOpsxContinueCommandTemplate();
701+
const applyCommand = getOpsxApplyCommandTemplate();
702+
696703
// Create skill directories and SKILL.md files
697704
const skills = [
698705
{ template: newChangeSkill, dirName: 'openspec-new-change' },
699706
{ template: continueChangeSkill, dirName: 'openspec-continue-change' },
700707
{ template: applyChangeSkill, dirName: 'openspec-apply-change' },
701708
];
702709

703-
const createdFiles: string[] = [];
710+
const createdSkillFiles: string[] = [];
704711

705712
for (const { template, dirName } of skills) {
706713
const skillDir = path.join(skillsDir, dirName);
@@ -717,31 +724,69 @@ ${template.instructions}
717724

718725
// Write the skill file
719726
await FileSystemUtils.writeFile(skillFile, skillContent);
720-
createdFiles.push(path.relative(projectRoot, skillFile));
727+
createdSkillFiles.push(path.relative(projectRoot, skillFile));
728+
}
729+
730+
// Create slash command files
731+
const commands = [
732+
{ template: newCommand, fileName: 'new.md' },
733+
{ template: continueCommand, fileName: 'continue.md' },
734+
{ template: applyCommand, fileName: 'apply.md' },
735+
];
736+
737+
const createdCommandFiles: string[] = [];
738+
739+
for (const { template, fileName } of commands) {
740+
const commandFile = path.join(commandsDir, fileName);
741+
742+
// Generate command content with YAML frontmatter
743+
const commandContent = `---
744+
name: ${template.name}
745+
description: ${template.description}
746+
category: ${template.category}
747+
tags: [${template.tags.join(', ')}]
748+
---
749+
750+
${template.content}
751+
`;
752+
753+
// Write the command file
754+
await FileSystemUtils.writeFile(commandFile, commandContent);
755+
createdCommandFiles.push(path.relative(projectRoot, commandFile));
721756
}
722757

723758
spinner.succeed('Experimental artifact workflow setup complete!');
724759

725760
// Print success message
726761
console.log();
727-
console.log(chalk.bold('🧪 Experimental Artifact Workflow Skills Created'));
762+
console.log(chalk.bold('🧪 Experimental Artifact Workflow Setup Complete'));
763+
console.log();
764+
console.log(chalk.bold('Skills Created:'));
765+
for (const file of createdSkillFiles) {
766+
console.log(chalk.green(' ✓ ' + file));
767+
}
728768
console.log();
729-
for (const file of createdFiles) {
769+
console.log(chalk.bold('Slash Commands Created:'));
770+
for (const file of createdCommandFiles) {
730771
console.log(chalk.green(' ✓ ' + file));
731772
}
732773
console.log();
733774
console.log(chalk.bold('📖 Usage:'));
734775
console.log();
735-
console.log(' Skills work automatically in compatible editors:');
736-
console.log(' • ' + chalk.cyan('Claude Code') + ' - Auto-detected, ready to use');
737-
console.log(' • ' + chalk.cyan('Cursor') + ' - Enable in Settings → Rules → Import Settings');
738-
console.log(' • ' + chalk.cyan('Windsurf') + ' - Auto-imports from .claude directory');
776+
console.log(' ' + chalk.cyan('Skills') + ' work automatically in compatible editors:');
777+
console.log(' • Claude Code - Auto-detected, ready to use');
778+
console.log(' • Cursor - Enable in Settings → Rules → Import Settings');
779+
console.log(' • Windsurf - Auto-imports from .claude directory');
739780
console.log();
740781
console.log(' Ask Claude naturally:');
741782
console.log(' • "I want to start a new OpenSpec change to add <feature>"');
742783
console.log(' • "Continue working on this change"');
784+
console.log(' • "Implement the tasks for this change"');
743785
console.log();
744-
console.log(' Claude will automatically use the appropriate skill.');
786+
console.log(' ' + chalk.cyan('Slash Commands') + ' for explicit invocation:');
787+
console.log(' • /opsx:new - Start a new change');
788+
console.log(' • /opsx:continue - Create the next artifact');
789+
console.log(' • /opsx:apply - Implement tasks');
745790
console.log();
746791
console.log(chalk.yellow('💡 This is an experimental feature.'));
747792
console.log(' Feedback welcome at: https://github.com/Fission-AI/OpenSpec/issues');

0 commit comments

Comments
 (0)