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