Skip to main content

Overview

The TerminalHandle class provides methods to interact with a terminal created by an agent. It allows you to get output, wait for completion, kill processes, and release resources. Terminal handles are typically created by agents and provided to clients for terminal management operations. See the source at lib/src/acp.dart:1126-1213.

Constructor

TerminalHandle(String id, String sessionId, Connection connection)
id
String
required
The unique identifier for this terminal instance
sessionId
String
required
The session this terminal belongs to
connection
Connection
required
The connection for sending requests

Properties

id

final String id
The unique identifier for this terminal instance.

Methods

currentOutput

Future<TerminalOutputResponse> currentOutput()
Gets the current terminal output without waiting for the command to exit. Returns the current stdout, stderr, and exit status if the command has already completed.
return
Future<TerminalOutputResponse>
A future that resolves with the terminal output response

Example

final output = await terminalHandle.currentOutput();
print('Terminal output: ${output.output}');
if (output.exitStatus != null) {
  print('Command exited with code: ${output.exitStatus!.exitCode}');
}

waitForExit

Future<WaitForTerminalExitResponse> waitForExit()
Waits for the terminal command to complete and returns its exit status. This method blocks until the command finishes execution, then returns the exit code that indicates the command’s success or failure.
return
Future<WaitForTerminalExitResponse>
A future that resolves when the command exits

Example

final exitStatus = await terminalHandle.waitForExit();
if (exitStatus.exitCode == 0) {
  print('Command succeeded');
} else {
  print('Command failed with exit code: ${exitStatus.exitCode}');
}

kill

Future<KillTerminalCommandResponse> kill()
Kills the terminal command without releasing the terminal. The terminal remains valid after killing, allowing you to:
  • Get the final output with currentOutput()
  • Check the exit status
  • Release the terminal when done
Useful for implementing timeouts or cancellation.
return
Future<KillTerminalCommandResponse>
A future that resolves when the kill request completes

Example

// Kill a long-running command
await terminalHandle.kill();

// Get the final output
final output = await terminalHandle.currentOutput();
print('Output before kill: ${output.output}');

// Release when done
await terminalHandle.release();

release

Future<ReleaseTerminalResponse> release()
Releases the terminal and frees all associated resources. If the command is still running, it will be killed. After release, the terminal ID becomes invalid and cannot be used with other terminal methods. Tool calls that already reference this terminal will continue to display its output.
Important: Always call this method when done with the terminal to prevent resource leaks.
return
Future<ReleaseTerminalResponse>
A future that resolves when the terminal is released

Example

try {
  // Use terminal
  final output = await terminalHandle.currentOutput();
  print(output.output);
} finally {
  // Always release
  await terminalHandle.release();
}

dispose

Future<void> dispose()
Disposes of the terminal handle and releases resources. This is the Dart equivalent of TypeScript’s [Symbol.asyncDispose]. It ensures proper cleanup by calling release(). Implements the AsyncDisposable interface.
return
Future<void>
A future that completes when disposal is done

Example

// Using with try-finally
final terminal = await createTerminal(...);
try {
  await terminal.waitForExit();
} finally {
  await terminal.dispose();
}

Complete Usage Example

import 'package:acp_dart/acp_dart.dart';

Future<void> runCommand(AgentSideConnection connection, String sessionId) async {
  // Create terminal
  final response = await connection.createTerminal(
    CreateTerminalRequest(
      sessionId: sessionId,
      command: 'npm',
      args: ['test'],
      cwd: '/path/to/project',
    ),
  );
  
  // Create handle (in practice, this would be done by the SDK)
  final terminal = TerminalHandle(
    response!.terminalId,
    sessionId,
    connection._connection,
  );
  
  try {
    // Poll for output
    var output = await terminal.currentOutput();
    print('Initial output: ${output.output}');
    
    // Wait for completion
    final exitStatus = await terminal.waitForExit();
    
    // Get final output
    output = await terminal.currentOutput();
    print('Final output: ${output.output}');
    
    if (exitStatus.exitCode == 0) {
      print('Tests passed!');
    } else {
      print('Tests failed with code ${exitStatus.exitCode}');
    }
  } finally {
    // Always clean up
    await terminal.dispose();
  }
}

See Also

Build docs developers (and LLMs) love