Skip to content

Commands API ​

The Commands API allows you to register custom commands, execute existing commands, and manage keyboard shortcuts in Trae IDE.

Overview ​

The Commands API enables you to:

  • Register custom commands
  • Execute built-in and custom commands
  • Handle command parameters
  • Create keyboard shortcuts
  • Manage command lifecycle

Basic Usage ​

Registering Commands ​

typescript
import { TraeAPI } from '@trae/api';

// Register a simple command
const disposable = TraeAPI.commands.registerCommand('myExtension.helloWorld', () => {
  TraeAPI.window.showInformationMessage('Hello World!');
});

// Register command with parameters
TraeAPI.commands.registerCommand('myExtension.greet', (name: string) => {
  TraeAPI.window.showInformationMessage(`Hello, ${name}!`);
});

// Register async command
TraeAPI.commands.registerCommand('myExtension.asyncOperation', async () => {
  try {
    const result = await performAsyncOperation();
    TraeAPI.window.showInformationMessage(`Result: ${result}`);
  } catch (error) {
    TraeAPI.window.showErrorMessage(`Error: ${error.message}`);
  }
});

Executing Commands ​

typescript
// Execute a command
await TraeAPI.commands.executeCommand('workbench.action.files.save');

// Execute command with parameters
await TraeAPI.commands.executeCommand('myExtension.greet', 'Alice');

// Execute command and get result
const result = await TraeAPI.commands.executeCommand<string>('myExtension.getData');
console.log('Command result:', result);

Getting Available Commands ​

typescript
// Get all available commands
const commands = await TraeAPI.commands.getCommands();
console.log('Available commands:', commands);

// Filter commands
const myCommands = commands.filter(cmd => cmd.startsWith('myExtension.'));

Command Registration ​

Command with Context ​

typescript
class MyExtension {
  private context: TraeAPI.ExtensionContext;

  constructor(context: TraeAPI.ExtensionContext) {
    this.context = context;
    this.registerCommands();
  }

  private registerCommands() {
    // Register command with class method
    const disposable = TraeAPI.commands.registerCommand(
      'myExtension.processFile',
      this.processFile.bind(this)
    );

    this.context.subscriptions.push(disposable);
  }

  private async processFile(uri?: TraeAPI.Uri) {
    const fileUri = uri || TraeAPI.window.activeTextEditor?.document.uri;
    if (!fileUri) {
      TraeAPI.window.showErrorMessage('No file selected');
      return;
    }

    // Process the file
    const document = await TraeAPI.workspace.openTextDocument(fileUri);
    console.log(`Processing file: ${document.fileName}`);
  }
}

Command with Validation ​

typescript
TraeAPI.commands.registerCommand('myExtension.validateAndRun', async (...args) => {
  // Validate arguments
  if (args.length === 0) {
    TraeAPI.window.showErrorMessage('Command requires at least one argument');
    return;
  }

  const [firstArg] = args;
  if (typeof firstArg !== 'string') {
    TraeAPI.window.showErrorMessage('First argument must be a string');
    return;
  }

  // Execute command logic
  console.log('Executing with argument:', firstArg);
});

Built-in Commands ​

File Operations ​

typescript
// Save current file
await TraeAPI.commands.executeCommand('workbench.action.files.save');

// Save all files
await TraeAPI.commands.executeCommand('workbench.action.files.saveAll');

// Open file
await TraeAPI.commands.executeCommand('workbench.action.files.openFile');

// New file
await TraeAPI.commands.executeCommand('workbench.action.files.newUntitledFile');

Editor Operations ​

typescript
// Format document
await TraeAPI.commands.executeCommand('editor.action.formatDocument');

// Go to definition
await TraeAPI.commands.executeCommand('editor.action.revealDefinition');

// Find and replace
await TraeAPI.commands.executeCommand('editor.action.startFindReplaceAction');

// Comment/uncomment lines
await TraeAPI.commands.executeCommand('editor.action.commentLine');

Workspace Operations ​

typescript
// Open folder
await TraeAPI.commands.executeCommand('workbench.action.files.openFolder');

// Close workspace
await TraeAPI.commands.executeCommand('workbench.action.closeFolder');

// Reload window
await TraeAPI.commands.executeCommand('workbench.action.reloadWindow');

Keyboard Shortcuts ​

Defining Shortcuts in package.json ​

json
{
  "contributes": {
    "commands": [
      {
        "command": "myExtension.quickAction",
        "title": "Quick Action",
        "category": "My Extension"
      }
    ],
    "keybindings": [
      {
        "command": "myExtension.quickAction",
        "key": "ctrl+shift+q",
        "mac": "cmd+shift+q",
        "when": "editorTextFocus"
      }
    ]
  }
}

Conditional Keybindings ​

json
{
  "keybindings": [
    {
      "command": "myExtension.debugAction",
      "key": "f5",
      "when": "debuggersAvailable && !inDebugMode"
    },
    {
      "command": "myExtension.testAction",
      "key": "ctrl+t",
      "when": "resourceExtname == .test.js"
    }
  ]
}

Command Palette Integration ​

Adding Commands to Palette ​

json
{
  "contributes": {
    "commands": [
      {
        "command": "myExtension.analyze",
        "title": "Analyze Code",
        "category": "Code Analysis",
        "icon": "$(search)"
      }
    ]
  }
}

Context Menu Integration ​

json
{
  "contributes": {
    "menus": {
      "editor/context": [
        {
          "command": "myExtension.refactor",
          "when": "editorHasSelection",
          "group": "1_modification"
        }
      ],
      "explorer/context": [
        {
          "command": "myExtension.processFile",
          "when": "resourceExtname == .js"
        }
      ]
    }
  }
}

Advanced Usage ​

Command Chaining ​

typescript
TraeAPI.commands.registerCommand('myExtension.complexOperation', async () => {
  // Chain multiple commands
  await TraeAPI.commands.executeCommand('editor.action.selectAll');
  await TraeAPI.commands.executeCommand('editor.action.formatSelection');
  await TraeAPI.commands.executeCommand('workbench.action.files.save');
  
  TraeAPI.window.showInformationMessage('Complex operation completed');
});

Command with Progress ​

typescript
TraeAPI.commands.registerCommand('myExtension.longRunningTask', async () => {
  await TraeAPI.window.withProgress({
    location: TraeAPI.ProgressLocation.Notification,
    title: 'Processing...',
    cancellable: true
  }, async (progress, token) => {
    for (let i = 0; i < 100; i++) {
      if (token.isCancellationRequested) {
        break;
      }
      
      progress.report({ increment: 1, message: `Step ${i + 1}/100` });
      await new Promise(resolve => setTimeout(resolve, 50));
    }
  });
});

Command with User Input ​

typescript
TraeAPI.commands.registerCommand('myExtension.createFile', async () => {
  const fileName = await TraeAPI.window.showInputBox({
    prompt: 'Enter file name',
    placeHolder: 'example.txt'
  });
  
  if (!fileName) {
    return;
  }
  
  const fileType = await TraeAPI.window.showQuickPick(
    ['JavaScript', 'TypeScript', 'JSON', 'Markdown'],
    { placeHolder: 'Select file type' }
  );
  
  if (fileType) {
    // Create file based on user input
    await createFileWithType(fileName, fileType);
  }
});

API Reference ​

registerCommand() ​

typescript
registerCommand(
  command: string,
  callback: (...args: any[]) => any,
  thisArg?: any
): Disposable;

executeCommand() ​

typescript
executeCommand<T = unknown>(
  command: string,
  ...rest: any[]
): Thenable<T | undefined>;

getCommands() ​

typescript
getCommands(filterInternal?: boolean): Thenable<string[]>;

Best Practices ​

  1. Use descriptive command names with extension prefix
  2. Handle errors gracefully in command handlers
  3. Provide user feedback for long-running operations
  4. Validate command parameters before execution
  5. Dispose of command registrations properly
  6. Use appropriate keyboard shortcuts that don't conflict
  7. Add commands to appropriate menus for discoverability

Error Handling ​

typescript
TraeAPI.commands.registerCommand('myExtension.safeCommand', async () => {
  try {
    const result = await riskyOperation();
    TraeAPI.window.showInformationMessage(`Success: ${result}`);
  } catch (error) {
    console.error('Command failed:', error);
    TraeAPI.window.showErrorMessage(`Failed: ${error.message}`);
  }
});

Testing Commands ​

typescript
// In test file
import * as assert from 'assert';
import { TraeAPI } from '@trae/api';

suite('Command Tests', () => {
  test('should execute custom command', async () => {
    const result = await TraeAPI.commands.executeCommand('myExtension.testCommand');
    assert.strictEqual(result, 'expected result');
  });
});

Your Ultimate AI-Powered IDE Learning Guide