Skip to content

Commit 3f0ca3f

Browse files
jjxyxsjrclaudeTabishB
authored
feat: add Trae command adapter (#1090)
* feat(tools): add Trae command adapter - Added Trae command adapter for generating `.trae/commands/opsx-<id>.md` files - Complete unit tests (9 test cases) and integration tests - Updated documentation and .gitignore - Fixed YAML escaping for carriage returns (\r) Co-Authored-By: Claude Code <noreply@anthropic.com> * fix: handle empty string in YAML escaping - Add explicit check for empty string in escapeYamlValue - Return quoted empty string '""' instead of unquoted empty scalar - Update test to verify empty string is properly quoted Co-Authored-By: Claude Code <noreply@anthropic.com> * fix: address PR review feedback for Trae adapter - Update docs/commands.md Trae entry to reflect generated opsx-* commands - Export traeAdapter from adapters/index.ts Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: align Trae command adapter docs --------- Co-authored-by: jjxyxsjr <jjxyxsjr@users.noreply.github.com> Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: Tabish Bidiwale <30385142+TabishB@users.noreply.github.com> Co-authored-by: TabishB <tabishbidiwale@gmail.com>
1 parent 8ac624b commit 3f0ca3f

14 files changed

Lines changed: 198 additions & 23 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@fission-ai/openspec": minor
3+
---
4+
5+
### New Features
6+
7+
- **TRAE command adapter** — Added command adapter for Trae IDE, enabling generation of `.trae/commands/opsx-<id>.md` files for custom slash commands

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,6 @@ opencode.json
160160

161161
# Bob
162162
.bob/
163+
164+
# Trae
165+
.trae/

docs/commands.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,24 +323,28 @@ AI: Implementing add-dark-mode...
323323
Revise a change's existing planning artifacts and keep them coherent with one another. Planning artifacts only - it never edits code.
324324

325325
**Syntax:**
326-
```
326+
327+
```text
327328
/opsx:update [change-name]
328329
```
329330

330331
**Arguments:**
332+
331333
| Argument | Required | Description |
332334
|----------|----------|-------------|
333335
| `change-name` | No | Which change to update (inferred from context if not provided) |
334336

335337
**What it does:**
338+
336339
- Reads the change's artifacts via `openspec status --change <name> --json`
337340
- Applies your requested revision, or reviews the artifacts for contradictions if you didn't name one
338341
- Reconciles the other existing artifacts in any direction (a design edit may ripple back to the proposal)
339342
- Confirms every edit with you before writing, one artifact at a time
340343
- Ends by recommending the next step: `/opsx:continue` (artifacts missing), `/opsx:apply` (carry a revised plan into code), or `/opsx:archive` (all done)
341344

342345
**Example:**
343-
```
346+
347+
```text
344348
You: /opsx:update add-dark-mode - we're storing the theme in a cookie now, not localStorage
345349
346350
AI: Reading add-dark-mode artifacts...
@@ -356,6 +360,7 @@ AI: Reading add-dark-mode artifacts...
356360
```
357361

358362
**Tips:**
363+
359364
- It won't create missing artifacts - that's `/opsx:continue`
360365
- If the change was already implemented, follow up with `/opsx:apply` so the code matches the revised plan
361366
- If your revision changes the *intent* of the change, start fresh with a new change instead (see [When to Update vs. Start Fresh](opsx.md#when-to-update-vs-start-fresh))
@@ -666,7 +671,7 @@ Different AI tools use slightly different command syntax. Use the format that ma
666671
| Windsurf | `/opsx-propose`, `/opsx-apply` |
667672
| Copilot (IDE) | `/opsx-propose`, `/opsx-apply` |
668673
| Kimi CLI | Skill-based invocations such as `/skill:openspec-propose`, `/skill:openspec-apply-change` (no generated `opsx-*` command files) |
669-
| Trae | Skill-based invocations such as `/openspec-propose`, `/openspec-apply-change` (no generated `opsx-*` command files) |
674+
| Trae | `/opsx-propose`, `/opsx-apply` |
670675

671676
The intent is the same across tools, but how commands are surfaced can differ by integration.
672677

docs/how-commands-work.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ The intent is identical everywhere. The punctuation differs. Use the form that m
8080
| Windsurf | `/opsx-propose`, `/opsx-apply` |
8181
| GitHub Copilot (IDE) | `/opsx-propose`, `/opsx-apply` |
8282
| Kimi CLI | skill-style, e.g. `/skill:openspec-propose` |
83-
| Trae | skill-style, e.g. `/openspec-propose` |
83+
| Trae | `/opsx-propose`, `/opsx-apply` |
8484

8585
Most tools use either the colon form (`/opsx:propose`) or the dash form (`/opsx-propose`). A few tools surface OpenSpec as named skills instead of slash commands; for those you invoke the skill by name. The full per-tool list, including exactly which files get written where, lives in [Supported Tools](supported-tools.md).
8686

docs/supported-tools.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `bulk-arch
5050
| Qoder (`qoder`) | `.qoder/skills/openspec-*/SKILL.md` | `.qoder/commands/opsx/<id>.md` |
5151
| Qwen Code (`qwen`) | `.qwen/skills/openspec-*/SKILL.md` | `.qwen/commands/opsx-<id>.toml` |
5252
| RooCode (`roocode`) | `.roo/skills/openspec-*/SKILL.md` | `.roo/commands/opsx-<id>.md` |
53-
| Trae (`trae`) | `.trae/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
53+
| Trae (`trae`) | `.trae/skills/openspec-*/SKILL.md` | `.trae/commands/opsx-<id>.md` |
5454
| Windsurf (`windsurf`) | `.windsurf/skills/openspec-*/SKILL.md` | `.windsurf/workflows/opsx-<id>.md` |
5555

5656
\* Codex commands are installed in the global Codex home (`$CODEX_HOME/prompts/` if set, otherwise `~/.codex/prompts/`), not your project directory.

docs/troubleshooting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ If `/opsx:propose` (or your tool's equivalent) doesn't appear or doesn't do anyt
5555

5656
5. **Check you initialized this project.** Skills are written per project. If you cloned a repo or switched folders, run `openspec init` (or `openspec update`) there.
5757

58-
6. **Confirm your tool supports command files.** A few tools (Kimi CLI, Trae, ForgeCode, Mistral Vibe) don't get generated `opsx-*` command files; they use skill-based invocations instead. The forms differ per tool: see [Supported Tools](supported-tools.md) and [How Commands Work](how-commands-work.md#slash-command-syntax-by-tool).
58+
6. **Confirm your tool supports command files.** A few tools (Kimi CLI, ForgeCode, Mistral Vibe) don't get generated `opsx-*` command files; they use skill-based invocations instead. The forms differ per tool: see [Supported Tools](supported-tools.md) and [How Commands Work](how-commands-work.md#slash-command-syntax-by-tool).
5959

6060
## Working with changes
6161

openspec/changes/add-tool-command-surface-capabilities/proposal.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
OpenSpec currently assumes command delivery maps directly to command adapters. That assumption does not hold for all tools.
44

5-
Trae is a concrete example: it invokes OpenSpec workflows via skill entries (for example `/openspec-new-change`) rather than adapter-generated command files. In this model, skills are the command surface.
5+
Some tools expose OpenSpec workflows via skill entries rather than adapter-generated command files. Kimi CLI is a concrete example: it invokes skills with forms such as `/skill:openspec-new-change`. In this model, skills are the command surface.
66

77
Today, this creates a behavior gap:
88

99
- `delivery=commands` can remove skills
1010
- tools without adapters skip command generation
11-
- result: selected tools like Trae can end up with no invocable workflow artifacts
11+
- result: selected tools like Kimi CLI, ForgeCode, or Mistral Vibe can end up with no invocable workflow artifacts
1212

1313
This is more than a prompt UX issue because non-interactive and CI flows bypass interactive guidance. We need a capability-aware model in core generation logic.
1414

@@ -25,9 +25,13 @@ Add an optional field in tool metadata to describe how a tool exposes commands:
2525
Field should be optional. Default behavior is inferred from adapter registry presence: tools with a registered adapter resolve to `adapter`; tools with no adapter registration and no explicit annotation resolve to `none`.
2626
Capability values use kebab-case string tokens for consistency with serialized metadata conventions.
2727

28-
Initial explicit override:
28+
Initial explicit overrides:
2929

30-
- Trae -> `skills-invocable`
30+
- ForgeCode -> `skills-invocable`
31+
- Kimi CLI -> `skills-invocable`
32+
- Mistral Vibe -> `skills-invocable`
33+
34+
Trae no longer belongs in this override set once its `.trae/commands/opsx-<id>.md` adapter is available; it should resolve to `adapter` like other file-backed command integrations.
3135

3236
### 2. Make delivery behavior capability-aware
3337

@@ -62,12 +66,12 @@ Update summaries to show effective delivery outcomes per tool (for example, when
6266

6367
### 4. Update docs and tests
6468

65-
- document capability model and Trae behavior under delivery modes
69+
- document capability model and skills-invocable behavior under delivery modes
6670
- ensure CLI docs and supported-tools docs reflect effective behavior
6771
- add test coverage for:
68-
- `init --tools trae` with `delivery=commands`
69-
- `update` with Trae configured under `delivery=commands`
70-
- mixed selections (`claude + trae`) across all delivery modes
72+
- `init --tools kimi` with `delivery=commands`
73+
- `update` with Kimi CLI configured under `delivery=commands`
74+
- mixed selections (`claude + kimi`) across all delivery modes
7175
- explicit error path for tools with no command surface under `delivery=commands`
7276

7377
### 5. Coordinate with install-scope behavior
@@ -94,7 +98,7 @@ Implementation tests should cover mixed-tool matrices to ensure deterministic be
9498

9599
## Impact
96100

97-
- `src/core/config.ts` - add optional command-surface metadata and Trae override
101+
- `src/core/config.ts` - add optional command-surface metadata and skills-invocable tool overrides
98102
- `src/core/command-generation/registry.ts` (or shared helper) - capability inference from adapter presence
99103
- `src/core/init.ts` - capability-aware generation/removal planning + compatibility validation + summary messaging
100104
- `src/core/update.ts` - capability-aware sync/removal planning + compatibility validation + summary messaging

openspec/changes/add-tool-command-surface-capabilities/tasks.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
- [ ] 1.1 Extend tool metadata in `src/core/config.ts` with an optional command-surface capability field
1111
- [ ] 1.2 Define supported capability values: `adapter`, `skills-invocable`, `none`
12-
- [ ] 1.3 Mark Trae as `skills-invocable`
12+
- [ ] 1.3 Mark known skills-invocable tools such as ForgeCode, Kimi CLI, and Mistral Vibe as `skills-invocable`
1313
- [ ] 1.4 Add a shared capability resolver (explicit metadata override first, inferred fallback from adapter presence second)
1414
- [ ] 1.5 Add focused unit tests for capability resolution (explicit override, inferred adapter, inferred none)
1515

@@ -20,7 +20,7 @@
2020
- [ ] 2.3 In `delivery=commands`, fail fast before writes when any selected tool resolves to `none`
2121
- [ ] 2.4 Update init output to clearly report effective behavior for `skills-invocable` tools (skills used as command surface)
2222
- [ ] 2.5 Ensure init no longer reports "no adapter" for tools intentionally using `skills-invocable`
23-
- [ ] 2.6 Add/adjust init tests for `delivery=commands` + `trae` (skills retained/generated, no adapter error), mixed tools (`claude,trae`) with per-tool expected outputs, and deterministic failure path for unsupported command surface (`none`)
23+
- [ ] 2.6 Add/adjust init tests for `delivery=commands` + `kimi` (skills retained/generated, no adapter error), mixed tools (`claude,kimi`) with per-tool expected outputs, and deterministic failure path for unsupported command surface (`none`)
2424

2525
## 3. Update: Capability-Aware Sync and Drift Detection
2626

@@ -30,7 +30,7 @@
3030
- [ ] 3.4 Update profile/delivery drift detection to avoid perpetual drift for `skills-invocable` tools under commands delivery
3131
- [ ] 3.5 Ensure configured-tool detection still includes `skills-invocable` tools under commands delivery when managed skills exist
3232
- [ ] 3.6 Update summary output so skills-invocable behavior is reported as expected behavior (not implicit skip/error)
33-
- [ ] 3.7 Add/adjust update tests for `delivery=commands` + configured Trae (skills retained/generated), idempotent second update (no false drift loop), mixed configured tools (`claude` + `trae`), and deterministic preflight failure for unsupported command surface (`none`)
33+
- [ ] 3.7 Add/adjust update tests for `delivery=commands` + configured Kimi CLI (skills retained/generated), idempotent second update (no false drift loop), mixed configured tools (`claude` + `kimi`), and deterministic preflight failure for unsupported command surface (`none`)
3434

3535
## 4. UX and Error Messaging
3636

@@ -40,7 +40,7 @@
4040

4141
## 5. Documentation Updates
4242

43-
- [ ] 5.1 Update `docs/supported-tools.md` to document command-surface semantics for Trae and clarify delivery interactions
43+
- [ ] 5.1 Update `docs/supported-tools.md` to document command-surface semantics for skills-invocable tools and clarify delivery interactions
4444
- [ ] 5.2 Update `docs/cli.md` delivery guidance to explain capability-aware behavior for `delivery=commands`
4545
- [ ] 5.3 Add a short troubleshooting note for "commands-only + unsupported tool" failures
4646

@@ -49,5 +49,5 @@
4949
- [ ] 6.1 Run targeted tests: `test/core/init.test.ts` and `test/core/update.test.ts`
5050
- [ ] 6.2 Run any new capability/unit test files added in this change
5151
- [ ] 6.3 Run full test suite (`pnpm test`) and resolve regressions
52-
- [ ] 6.4 Manual smoke check: `openspec init --tools trae` with `delivery=commands`
53-
- [ ] 6.5 Manual smoke check: mixed tools (`claude,trae`) with `delivery=commands`
52+
- [ ] 6.4 Manual smoke check: `openspec init --tools kimi` with `delivery=commands`
53+
- [ ] 6.5 Manual smoke check: mixed tools (`claude,kimi`) with `delivery=commands`

openspec/specs/command-generation/spec.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting
4949
- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields
5050
- **AND** file path SHALL follow pattern `.windsurf/workflows/opsx-<id>.md`
5151

52+
#### Scenario: Trae adapter formatting
53+
54+
- **WHEN** formatting a command for Trae
55+
- **THEN** the adapter SHALL output YAML frontmatter with `name` and `description` fields
56+
- **AND** file path SHALL follow pattern `.trae/commands/opsx-<id>.md`
57+
5258
### Requirement: Command generator function
5359

5460
The system SHALL provide a `generateCommand` function that combines content with adapter.
@@ -94,4 +100,3 @@ The body content of commands SHALL be shared across all tools.
94100
- **WHEN** generating the 'explore' command for Claude and Cursor
95101
- **THEN** both SHALL use the same `body` content
96102
- **AND** only the frontmatter and file path SHALL differ
97-

src/core/command-generation/adapters/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ export { qoderAdapter } from './qoder.js';
2929
export { lingmaAdapter } from './lingma.js';
3030
export { qwenAdapter } from './qwen.js';
3131
export { roocodeAdapter } from './roocode.js';
32+
export { traeAdapter } from './trae.js';
3233
export { windsurfAdapter } from './windsurf.js';

0 commit comments

Comments
 (0)