Skip to content

Commit 2f7d2b5

Browse files
committed
feat: add Neovate Code support with slash command integration
1 parent 6d3cfe0 commit 2f7d2b5

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ These tools have built-in OpenSpec commands. Select the OpenSpec integration whe
112112
| **Qwen Code** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.qwen/commands/`) |
113113
| **RooCode** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.roo/commands/`) |
114114
| **Windsurf** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.windsurf/workflows/`) |
115+
| **Neovate Code** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`..neovate/commands/openspec/`) — see [docs](https://neovateai.dev/en) |
115116

116117
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`.
117118

src/core/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@ export const AI_TOOLS: AIToolOption[] = [
3737
{ name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code' },
3838
{ name: 'RooCode', value: 'roocode', available: true, successLabel: 'RooCode' },
3939
{ name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf' },
40+
{ name: 'Neovate Code', value: 'neovate', available: true, successLabel: 'Neovate Code' },
4041
{ name: 'AGENTS.md (works with Amp, VS Code, …)', value: 'agents', available: false, successLabel: 'your AGENTS.md-compatible assistant' }
4142
];
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { SlashCommandConfigurator } from './base.js';
2+
import { SlashCommandId } from '../../templates/index.js';
3+
4+
/**
5+
* File paths for Neovate slash commands
6+
* Maps each OpenSpec workflow stage to its command file location
7+
* Commands are stored in .neovate/commands/openspec/ directory
8+
*/
9+
const FILE_PATHS: Record<SlashCommandId, string> = {
10+
// Create and validate new change proposals
11+
proposal: '.neovate/commands/openspec/proposal.md',
12+
13+
// Implement approved changes with task tracking
14+
apply: '.neovate/commands/openspec/apply.md',
15+
16+
// Archive completed changes and update specs
17+
archive: '.neovate/commands/openspec/archive.md'
18+
};
19+
20+
/**
21+
* YAML frontmatter for Neovate slash commands
22+
* Defines metadata displayed in Neovate's command palette
23+
* Each command is categorized and tagged for easy discovery
24+
*/
25+
const FRONTMATTER: Record<SlashCommandId, string> = {
26+
proposal: `---
27+
name: Proposal
28+
description: Scaffold a new OpenSpec change and validate strictly.
29+
---`,
30+
apply: `---
31+
name: Apply
32+
description: Implement an approved OpenSpec change and keep tasks in sync.
33+
---`,
34+
archive: `---
35+
name: Archive
36+
description: Archive a deployed OpenSpec change and update specs.
37+
---`
38+
};
39+
40+
/**
41+
* Neovate Slash Command Configurator
42+
*
43+
* Manages OpenSpec slash commands for Neovate Code AI assistant.
44+
* Creates three workflow commands: proposal, apply, and archive.
45+
* Uses colon-separated command format (/openspec:proposal).
46+
*
47+
* @extends {SlashCommandConfigurator}
48+
*/
49+
export class NeovateSlashCommandConfigurator extends SlashCommandConfigurator {
50+
/** Unique identifier for Neovate tool */
51+
readonly toolId = 'neovate';
52+
53+
/** Indicates slash commands are available for this tool */
54+
readonly isAvailable = true;
55+
56+
/**
57+
* Get relative file path for a slash command
58+
*
59+
* @param {SlashCommandId} id - Command identifier (proposal, apply, or archive)
60+
* @returns {string} Relative path from project root to command file
61+
*/
62+
protected getRelativePath(id: SlashCommandId): string {
63+
return FILE_PATHS[id];
64+
}
65+
66+
/**
67+
* Get YAML frontmatter for a slash command
68+
*
69+
* Frontmatter defines how the command appears in Neovate's UI,
70+
* including display name, description, and categorization.
71+
*
72+
* @param {SlashCommandId} id - Command identifier (proposal, apply, or archive)
73+
* @returns {string} YAML frontmatter block with command metadata
74+
*/
75+
protected getFrontmatter(id: SlashCommandId): string {
76+
return FRONTMATTER[id];
77+
}
78+
}

src/core/configurators/slash/registry.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { SlashCommandConfigurator } from './base.js';
22
import { ClaudeSlashCommandConfigurator } from './claude.js';
33
import { CodeBuddySlashCommandConfigurator } from './codebuddy.js';
44
import { QoderSlashCommandConfigurator } from './qoder.js';
5+
import { NeovateSlashCommandConfigurator } from './neovate.js';
56
import { CursorSlashCommandConfigurator } from './cursor.js';
67
import { WindsurfSlashCommandConfigurator } from './windsurf.js';
78
import { KiloCodeSlashCommandConfigurator } from './kilocode.js';
@@ -27,6 +28,7 @@ export class SlashCommandRegistry {
2728
const claude = new ClaudeSlashCommandConfigurator();
2829
const codeBuddy = new CodeBuddySlashCommandConfigurator();
2930
const qoder = new QoderSlashCommandConfigurator();
31+
const neovate = new NeovateSlashCommandConfigurator();
3032
const cursor = new CursorSlashCommandConfigurator();
3133
const windsurf = new WindsurfSlashCommandConfigurator();
3234
const kilocode = new KiloCodeSlashCommandConfigurator();
@@ -48,6 +50,7 @@ export class SlashCommandRegistry {
4850
this.configurators.set(claude.toolId, claude);
4951
this.configurators.set(codeBuddy.toolId, codeBuddy);
5052
this.configurators.set(qoder.toolId, qoder);
53+
this.configurators.set(neovate.toolId, neovate);
5154
this.configurators.set(cursor.toolId, cursor);
5255
this.configurators.set(windsurf.toolId, windsurf);
5356
this.configurators.set(kilocode.toolId, kilocode);

0 commit comments

Comments
 (0)