Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ These tools have built-in OpenSpec commands. Select the OpenSpec integration whe
| **Qwen Code** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.qwen/commands/`) |
| **RooCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.roo/commands/`) |
| **Windsurf** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.windsurf/workflows/`) |
| **Neovate Code** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`..neovate/commands/openspec/`) — see [docs](https://neovateai.dev/en) |

Kilo Code discovers team workflows automatically. Save the generated files under `.kilocode/workflows/` and trigger them from the command palette with `/openspec-proposal.md`, `/openspec-apply.md`, or `/openspec-archive.md`.

Expand Down
1 change: 1 addition & 0 deletions src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ export const AI_TOOLS: AIToolOption[] = [
{ name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code' },
{ name: 'RooCode', value: 'roocode', available: true, successLabel: 'RooCode' },
{ name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf' },
{ name: 'Neovate Code', value: 'neovate', available: true, successLabel: 'Neovate Code' },
{ name: 'AGENTS.md (works with Amp, VS Code, …)', value: 'agents', available: false, successLabel: 'your AGENTS.md-compatible assistant' }
];
78 changes: 78 additions & 0 deletions src/core/configurators/slash/neovate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { SlashCommandConfigurator } from './base.js';
import { SlashCommandId } from '../../templates/index.js';

/**
* File paths for Neovate slash commands
* Maps each OpenSpec workflow stage to its command file location
* Commands are stored in .neovate/commands/openspec/ directory
*/
const FILE_PATHS: Record<SlashCommandId, string> = {
// Create and validate new change proposals
proposal: '.neovate/commands/openspec/proposal.md',

// Implement approved changes with task tracking
apply: '.neovate/commands/openspec/apply.md',

// Archive completed changes and update specs
archive: '.neovate/commands/openspec/archive.md'
};

/**
* YAML frontmatter for Neovate slash commands
* Defines metadata displayed in Neovate's command palette
* Each command is categorized and tagged for easy discovery
*/
const FRONTMATTER: Record<SlashCommandId, string> = {
proposal: `---
name: Proposal
description: Scaffold a new OpenSpec change and validate strictly.
---`,
apply: `---
name: Apply
description: Implement an approved OpenSpec change and keep tasks in sync.
---`,
archive: `---
name: Archive
description: Archive a deployed OpenSpec change and update specs.
---`
};

/**
* Neovate Slash Command Configurator
*
* Manages OpenSpec slash commands for Neovate Code AI assistant.
* Creates three workflow commands: proposal, apply, and archive.
* Uses colon-separated command format (/openspec:proposal).
*
* @extends {SlashCommandConfigurator}
*/
export class NeovateSlashCommandConfigurator extends SlashCommandConfigurator {
/** Unique identifier for Neovate tool */
readonly toolId = 'neovate';

/** Indicates slash commands are available for this tool */
readonly isAvailable = true;

/**
* Get relative file path for a slash command
*
* @param {SlashCommandId} id - Command identifier (proposal, apply, or archive)
* @returns {string} Relative path from project root to command file
*/
protected getRelativePath(id: SlashCommandId): string {
return FILE_PATHS[id];
}

/**
* Get YAML frontmatter for a slash command
*
* Frontmatter defines how the command appears in Neovate's UI,
* including display name, description, and categorization.
*
* @param {SlashCommandId} id - Command identifier (proposal, apply, or archive)
* @returns {string} YAML frontmatter block with command metadata
*/
protected getFrontmatter(id: SlashCommandId): string {
return FRONTMATTER[id];
}
}
3 changes: 3 additions & 0 deletions src/core/configurators/slash/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SlashCommandConfigurator } from './base.js';
import { ClaudeSlashCommandConfigurator } from './claude.js';
import { CodeBuddySlashCommandConfigurator } from './codebuddy.js';
import { QoderSlashCommandConfigurator } from './qoder.js';
import { NeovateSlashCommandConfigurator } from './neovate.js';
import { CursorSlashCommandConfigurator } from './cursor.js';
import { WindsurfSlashCommandConfigurator } from './windsurf.js';
import { KiloCodeSlashCommandConfigurator } from './kilocode.js';
Expand All @@ -27,6 +28,7 @@ export class SlashCommandRegistry {
const claude = new ClaudeSlashCommandConfigurator();
const codeBuddy = new CodeBuddySlashCommandConfigurator();
const qoder = new QoderSlashCommandConfigurator();
const neovate = new NeovateSlashCommandConfigurator();
const cursor = new CursorSlashCommandConfigurator();
const windsurf = new WindsurfSlashCommandConfigurator();
const kilocode = new KiloCodeSlashCommandConfigurator();
Expand All @@ -48,6 +50,7 @@ export class SlashCommandRegistry {
this.configurators.set(claude.toolId, claude);
this.configurators.set(codeBuddy.toolId, codeBuddy);
this.configurators.set(qoder.toolId, qoder);
this.configurators.set(neovate.toolId, neovate);
this.configurators.set(cursor.toolId, cursor);
this.configurators.set(windsurf.toolId, windsurf);
this.configurators.set(kilocode.toolId, kilocode);
Expand Down