Skip to content
3 changes: 2 additions & 1 deletion docs/supported-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `sync`, `b
| Claude Code (`claude`) | `.claude/skills/openspec-*/SKILL.md` | `.claude/commands/opsx/<id>.md` |
| Cline (`cline`) | `.cline/skills/openspec-*/SKILL.md` | `.clinerules/workflows/opsx-<id>.md` |
| CodeBuddy (`codebuddy`) | `.codebuddy/skills/openspec-*/SKILL.md` | `.codebuddy/commands/opsx/<id>.md` |
| Code Studio (`codestudio`) | `.codestudio/skills/openspec-*/SKILL.md` | `.codestudio/prompts/opsx-<id>.prompt.md` |
| Codex (`codex`) | `.codex/skills/openspec-*/SKILL.md` | `$CODEX_HOME/prompts/opsx-<id>.md`\* |
| ForgeCode (`forgecode`) | `.forge/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
| Continue (`continue`) | `.continue/skills/openspec-*/SKILL.md` | `.continue/prompts/opsx-<id>.prompt` |
Expand Down Expand Up @@ -71,7 +72,7 @@ openspec init --tools none
openspec init --profile core
```

**Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `forgecode`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
**Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `codebuddy`, `codestudio`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `forgecode`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`

## Workflow-Dependent Installation

Expand Down
30 changes: 30 additions & 0 deletions src/core/command-generation/adapters/codestudio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Code Studio Command Adapter
*
* Formats commands for Syncfusion Code Studio following its .prompt.md specification.
*/

import path from 'path';
import type { CommandContent, ToolCommandAdapter } from '../types.js';

/**
* Code Studio adapter for command generation.
* File path: .codestudio/prompts/opsx-<id>.prompt.md
* Frontmatter: description
*/
export const codeStudioAdapter: ToolCommandAdapter = {
toolId: 'codestudio',

getFilePath(commandId: string): string {
return path.join('.codestudio', 'prompts', `opsx-${commandId}.prompt.md`);
},

formatFile(content: CommandContent): string {
return `---
description: ${content.description}
---

${content.body}
`;
},
};
1 change: 1 addition & 0 deletions src/core/command-generation/adapters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { claudeAdapter } from './claude.js';
export { clineAdapter } from './cline.js';
export { codexAdapter } from './codex.js';
export { codebuddyAdapter } from './codebuddy.js';
export { codeStudioAdapter } from './codestudio.js';
export { continueAdapter } from './continue.js';
export { costrictAdapter } from './costrict.js';
export { crushAdapter } from './crush.js';
Expand Down
2 changes: 2 additions & 0 deletions src/core/command-generation/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { claudeAdapter } from './adapters/claude.js';
import { clineAdapter } from './adapters/cline.js';
import { codexAdapter } from './adapters/codex.js';
import { codebuddyAdapter } from './adapters/codebuddy.js';
import { codeStudioAdapter } from './adapters/codestudio.js';
import { continueAdapter } from './adapters/continue.js';
import { costrictAdapter } from './adapters/costrict.js';
import { crushAdapter } from './adapters/crush.js';
Expand Down Expand Up @@ -49,6 +50,7 @@ export class CommandAdapterRegistry {
CommandAdapterRegistry.register(clineAdapter);
CommandAdapterRegistry.register(codexAdapter);
CommandAdapterRegistry.register(codebuddyAdapter);
CommandAdapterRegistry.register(codeStudioAdapter);
CommandAdapterRegistry.register(continueAdapter);
CommandAdapterRegistry.register(costrictAdapter);
CommandAdapterRegistry.register(crushAdapter);
Expand Down
1 change: 1 addition & 0 deletions src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const AI_TOOLS: AIToolOption[] = [
{ name: 'Codex', value: 'codex', available: true, successLabel: 'Codex', skillsDir: '.codex' },
{ name: 'ForgeCode', value: 'forgecode', available: true, successLabel: 'ForgeCode', skillsDir: '.forge' },
{ name: 'CodeBuddy Code (CLI)', value: 'codebuddy', available: true, successLabel: 'CodeBuddy Code', skillsDir: '.codebuddy' },
{ name: 'Code Studio', value: 'codestudio', available: true, successLabel: 'Code Studio', skillsDir: '.codestudio' },
{ name: 'Continue', value: 'continue', available: true, successLabel: 'Continue (VS Code / JetBrains / Cli)', skillsDir: '.continue' },
{ name: 'CoStrict', value: 'costrict', available: true, successLabel: 'CoStrict', skillsDir: '.cospec' },
{ name: 'Crush', value: 'crush', available: true, successLabel: 'Crush', skillsDir: '.crush' },
Expand Down
22 changes: 21 additions & 1 deletion test/core/command-generation/adapters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { claudeAdapter } from '../../../src/core/command-generation/adapters/cla
import { clineAdapter } from '../../../src/core/command-generation/adapters/cline.js';
import { codexAdapter } from '../../../src/core/command-generation/adapters/codex.js';
import { codebuddyAdapter } from '../../../src/core/command-generation/adapters/codebuddy.js';
import { codeStudioAdapter } from '../../../src/core/command-generation/adapters/codestudio.js';
import { continueAdapter } from '../../../src/core/command-generation/adapters/continue.js';
import { costrictAdapter } from '../../../src/core/command-generation/adapters/costrict.js';
import { crushAdapter } from '../../../src/core/command-generation/adapters/crush.js';
Expand Down Expand Up @@ -343,6 +344,25 @@ describe('command-generation/adapters', () => {
});
});

describe('codeStudioAdapter', () => {
it('should have correct toolId', () => {
expect(codeStudioAdapter.toolId).toBe('codestudio');
});

it('should generate correct file path with .prompt.md extension', () => {
const filePath = codeStudioAdapter.getFilePath('explore');
expect(filePath).toBe(path.join('.codestudio', 'prompts', 'opsx-explore.prompt.md'));
});

it('should format file with description frontmatter', () => {
const output = codeStudioAdapter.formatFile(sampleContent);
expect(output).toContain('---\n');
expect(output).toContain('description: Enter explore mode for thinking');
expect(output).toContain('---\n\n');
expect(output).toContain('This is the command body.');
});
});

describe('continueAdapter', () => {
it('should have correct toolId', () => {
expect(continueAdapter.toolId).toBe('continue');
Expand Down Expand Up @@ -695,7 +715,7 @@ describe('command-generation/adapters', () => {
// Verify all adapters produce valid paths
const adapters = [
amazonQAdapter, antigravityAdapter, auggieAdapter, bobAdapter, clineAdapter,
codexAdapter, codebuddyAdapter, continueAdapter, costrictAdapter,
codexAdapter, codebuddyAdapter, codeStudioAdapter, continueAdapter, costrictAdapter,
crushAdapter, factoryAdapter, geminiAdapter, githubCopilotAdapter,
iflowAdapter, kilocodeAdapter, opencodeAdapter, piAdapter, qoderAdapter,
qwenAdapter, roocodeAdapter
Expand Down