Skip to content

Conversation

@WilliamMunch
Copy link

@WilliamMunch WilliamMunch commented Feb 4, 2026

Description

Enhance the use of OpenSpec in Trae by supporting slash commands.

Changes

A new adapter has been added to src/core/command-generation/adapters/trae.ts to generate trae slash command files.

Commands Directory

Commands are installed to .trae/commands/

Summary by CodeRabbit

  • New Features
    • Introduced Trae adapter for the command generation system, enabling commands to be formatted and stored as Markdown files with structured metadata including name, ID, category, and description.

@WilliamMunch WilliamMunch requested a review from TabishB as a code owner February 4, 2026 03:02
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Adds a new Trae command adapter to the command-generation system that formats commands into Trae's frontmatter-based Markdown files. The adapter is exported from the adapters index and registered in the command adapter registry.

Changes

Cohort / File(s) Summary
Trae Adapter Implementation
src/core/command-generation/adapters/trae.ts
Introduces a new traeAdapter object implementing ToolCommandAdapter interface with toolId "trae", getFilePath() method for .trae/commands/opsx-{commandId}.md paths, and formatFile() method that constructs Markdown with YAML frontmatter. Includes private escapeYamlValue() helper for YAML-safe character escaping.
Adapter Registration and Export
src/core/command-generation/adapters/index.ts, src/core/command-generation/registry.ts
Exports new traeAdapter from index and registers it in CommandAdapterRegistry static initializer to include it among built-in adapters.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested reviewers

  • TabishB

Poem

🐰 A new adapter hops on in,
Trae commands in Markdown spin,
YAML escapes with careful grace,
Registry greets this new space!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for Trae integration via slash commands. It matches the new adapter implementation and registration.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/core/command-generation/adapters/trae.ts`:
- Around line 32-45: Sanitize the commandId before using it in file paths and
frontmatter: in getFilePath(commandId) normalize and strip any path separators,
drive letters or unsafe characters (e.g., allow only alphanumerics,
dashes/underscores) to produce a safeId and use that for the path (replace
path.join('.trae','commands',`opsx-${safeId}.md`)). In formatFile(content)
compute the same sanitized id from content.id and use it for both the
frontmatter name and id fields, and ensure those fields are escaped or quoted
(in addition to using escapeYamlValue for category/description) so YAML-breaking
characters cannot corrupt the frontmatter.
🧹 Nitpick comments (1)
src/core/command-generation/adapters/trae.ts (1)

15-21: Consider quoting YAML implicit scalars to avoid type coercion.

escapeYamlValue doesn’t quote values like true, null, or 123, which YAML will parse as booleans/null/numbers instead of strings. If Trae expects strings, consider quoting those scalars too.

Comment on lines +32 to +45
getFilePath(commandId: string): string {
return path.join('.trae', 'commands', `opsx-${commandId}.md`);
},

formatFile(content: CommandContent): string {
return `---
name: /opsx-${content.id}
id: opsx-${content.id}
category: ${escapeYamlValue(content.category)}
description: ${escapeYamlValue(content.description)}
---

${content.body}
`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Sanitize commandId for file paths and escape name/id in frontmatter.

Line 33 builds a path directly from commandId; if it contains path separators or drive prefixes, it can escape .trae/commands. Also name/id are unescaped, so YAML-breaking characters in content.id could corrupt frontmatter. Sanitize the ID and reuse it for both the path and the frontmatter values.

🔧 Suggested fix
+function sanitizeCommandId(commandId: string): string {
+  const sanitized = commandId
+    .replace(/[\\/:]/g, '-')
+    .replace(/[\r\n]/g, ' ')
+    .trim();
+  if (!sanitized) {
+    throw new Error('Command id must not be empty');
+  }
+  return sanitized;
+}
+
 export const traeAdapter: ToolCommandAdapter = {
   toolId: 'trae',
 
   getFilePath(commandId: string): string {
-    return path.join('.trae', 'commands', `opsx-${commandId}.md`);
+    const safeId = sanitizeCommandId(commandId);
+    return path.join('.trae', 'commands', `opsx-${safeId}.md`);
   },
 
   formatFile(content: CommandContent): string {
+    const safeId = sanitizeCommandId(content.id);
+    const name = `/opsx-${safeId}`;
+    const id = `opsx-${safeId}`;
     return `---
-name: /opsx-${content.id}
-id: opsx-${content.id}
+name: ${escapeYamlValue(name)}
+id: ${escapeYamlValue(id)}
 category: ${escapeYamlValue(content.category)}
 description: ${escapeYamlValue(content.description)}
 ---
 
 ${content.body}
 `;
   },
 };
🤖 Prompt for AI Agents
In `@src/core/command-generation/adapters/trae.ts` around lines 32 - 45, Sanitize
the commandId before using it in file paths and frontmatter: in
getFilePath(commandId) normalize and strip any path separators, drive letters or
unsafe characters (e.g., allow only alphanumerics, dashes/underscores) to
produce a safeId and use that for the path (replace
path.join('.trae','commands',`opsx-${safeId}.md`)). In formatFile(content)
compute the same sanitized id from content.id and use it for both the
frontmatter name and id fields, and ensure those fields are escaped or quoted
(in addition to using escapeYamlValue for category/description) so YAML-breaking
characters cannot corrupt the frontmatter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant