TerminalAPI

Create and manage virtual terminals from your plugin. Access via context.terminal.

Overview

The TerminalAPI allows plugins to:

  • Create named terminal instances
  • Send commands to terminals programmatically
  • Listen for terminal lifecycle events
  • Get active terminal and list all terminals

Methods

createTerminal(options)

Creates a new terminal instance.

Parameters:

NameTypeRequiredDescription
optionsobject | stringNoTerminal options or name
options.namestringNoTerminal display name
options.shellPathstringNoShell executable path
options.shellArgsstring[]NoShell arguments
options.cwdstringNoWorking directory
options.envobjectNoEnvironment variables

Returns: Terminal object with methods:

  • sendText(text, addNewLine?) - Send text to terminal
  • show(preserveFocus?) - Show terminal panel
  • hide() - Hide terminal
  • dispose() - Close terminal

Example:

// Create with options object
const terminal = context.terminal.createTerminal({
  name: 'Build Terminal',
  cwd: '/path/to/project',
  env: {
    NODE_ENV: 'development'
  }
});
 
terminal.show();
terminal.sendText('npm run build');
 
// Simple form with just name
const simpleTerminal = context.terminal.createTerminal('My Terminal');

sendText(terminalId, text, addNewLine?)

Send text to a specific terminal by ID.

Parameters:

NameTypeRequiredDescription
terminalIdstringYesTerminal ID
textstringYesText to send
addNewLinebooleanNoAdd newline (default: true)

Example:

const terminal = context.terminal.createTerminal('Deploy');
context.terminal.sendText(terminal.id, 'npm run deploy', true);

getActiveTerminal()

Get the currently active terminal.

Returns: Terminal object or undefined if no active terminal.

Example:

const active = context.terminal.getActiveTerminal();
if (active) {
  context.logger.info(`Active terminal: $\\{active.name\\}`);
}

activeTerminal (getter)

Alias for getActiveTerminal().

Example:

const active = context.terminal.activeTerminal;

getTerminals()

Get all terminal instances.

Returns: Array of terminal objects.

Example:

const terminals = context.terminal.getTerminals();
terminals.forEach(t => {
  context.logger.info(`Terminal: ${t.name} (${t.id})`);
});

Events

onDidOpenTerminal(listener)

Listen for terminal creation events.

Parameters:

NameTypeDescription
listenerfunctionCallback receiving terminal object

Returns: Disposable to stop listening.

Example:

const disposable = context.terminal.onDidOpenTerminal((terminal) => {
  context.logger.info(`Terminal opened: $\\{terminal.name\\}`);
});
 
// Stop listening later
disposable.dispose();

onDidCloseTerminal(listener)

Listen for terminal close events.

Parameters:

NameTypeDescription
listenerfunctionCallback receiving \\\{ terminalId \\\}

Returns: Disposable to stop listening.

Example:

context.terminal.onDidCloseTerminal(({ terminalId }) => {
  context.logger.info(`Terminal closed: $\\{terminalId\\}`);
});

onDidChangeActiveTerminal(listener)

Listen for active terminal changes.

Parameters:

NameTypeDescription
listenerfunctionCallback receiving terminal object

Returns: Disposable to stop listening.

Example:

context.terminal.onDidChangeActiveTerminal((terminal) => {
  context.logger.info(`Active terminal changed to: $\\{terminal.name\\}`);
});

Terminal Object

The terminal object returned by createTerminal() has the following structure:

interface Terminal {
  id: string;
  name: string;
  shellPath?: string;
  shellArgs?: string[];
  cwd?: string;
  env?: Record<string, string>;
  pluginId: string;
 
  // Methods
  sendText(text: string, addNewLine?: boolean): void;
  show(preserveFocus?: boolean): void;
  hide(): void;
  dispose(): void;
}

Complete Example

export default class TerminalPlugin {
  private context: PluginContext;
  private buildTerminal?: Terminal;
 
  constructor(context: PluginContext) {
    this.context = context;
  }
 
  async activate(): Promise<void> {
    // Create a dedicated build terminal
    this.buildTerminal = this.context.terminal.createTerminal({
      name: 'Build',
      cwd: this.context.workspace?.rootPath
    });
 
    // Register command to run build
    this.context.commands.register('myPlugin.build', {
      name: 'Run Build',
      execute: () => this.runBuild()
    });
 
    // Listen for terminal events
    this.context.terminal.onDidOpenTerminal((terminal) => {
      this.context.logger.info(`New terminal: $\\{terminal.name\\}`);
    });
 
    this.context.terminal.onDidCloseTerminal(({ terminalId }) => {
      if (this.buildTerminal?.id === terminalId) {
        this.buildTerminal = undefined;
      }
    });
  }
 
  async runBuild(): Promise<void> {
    if (!this.buildTerminal) {
      this.buildTerminal = this.context.terminal.createTerminal({
        name: 'Build',
        cwd: this.context.workspace?.rootPath
      });
    }
 
    this.buildTerminal.show();
    this.buildTerminal.sendText('npm run build');
 
    this.context.ui.showInformationMessage('Build started');
  }
 
  async deactivate(): Promise<void> {
    // Clean up terminal
    this.buildTerminal?.dispose();
  }
}

Best Practices

  1. Name Your Terminals: Use descriptive names for better UX

    createTerminal({ name: 'Build Terminal' });
  2. Set Working Directory: Specify cwd for context-aware commands

    createTerminal({
      name: 'Project',
      cwd: context.workspace?.rootPath
    });
  3. Clean Up: Dispose terminals when plugin deactivates

    async deactivate() {
      this.terminal?.dispose();
    }
  4. Use Events: React to terminal state changes

    onDidCloseTerminal(({ terminalId }) => {
      // Handle cleanup
    });
  5. Preserve Focus: Use preserveFocus when showing terminals

    terminal.show(true); // Don't steal focus from editor

See Also