Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ComposioHQ/agent-orchestrator/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Terminal interface manages how humans view and interact with running sessions. Terminal plugins open IDE tabs, browser windows, or terminal sessions for direct agent interaction.
Plugin Slot: terminal
Default Plugin: iterm2
Interface Definition
export interface Terminal {
readonly name: string;
openSession(session: Session): Promise<void>;
openAll(sessions: Session[]): Promise<void>;
isSessionOpen?(session: Session): Promise<boolean>;
}
Methods
Plugin name identifier (e.g. "iterm2", "web", "none").
openSession
(session: Session) => Promise<void>
required
Open a session for human interaction.Parameters:
session - Session to open
Implementation:
- iTerm2: Create new tab with tmux attach command
- Web: Open browser to web terminal URL
- None: No-op (headless mode)
openAll
(sessions: Session[]) => Promise<void>
required
Open all sessions for a project.Parameters:
sessions - Array of sessions to open
Implementation:
- iTerm2: Create window with multiple tabs
- Web: Open browser with multiple tabs
- None: No-op
isSessionOpen
(session: Session) => Promise<boolean>
Optional: Check if a session is already open in a tab/window.Parameters:
session - Session to check
Returns: true if session is open, false otherwise
Usage Examples
Implementing a Terminal Plugin (iTerm2)
import type { Terminal, Session } from "@composio/ao-core";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
const execFileAsync = promisify(execFile);
export function create(): Terminal {
return {
name: "iterm2",
async openSession(session: Session): Promise<void> {
if (!session.runtimeHandle) {
throw new Error("Cannot open session: no runtime handle");
}
const tmuxSession = session.runtimeHandle.id;
// AppleScript to create iTerm2 tab with tmux attach
const script = `
tell application "iTerm"
activate
tell current window
create tab with default profile
tell current session
write text "tmux attach -t ${tmuxSession}"
end tell
end tell
end tell
`;
await execFileAsync("osascript", ["-e", script], { timeout: 5_000 });
},
async openAll(sessions: Session[]): Promise<void> {
if (sessions.length === 0) return;
// Create window with tabs for each session
const tmuxSessions = sessions
.map(s => s.runtimeHandle?.id)
.filter(Boolean);
if (tmuxSessions.length === 0) return;
const script = `
tell application "iTerm"
activate
create window with default profile
tell current window
${tmuxSessions.map((id, i) => `
${i > 0 ? 'create tab with default profile' : ''}
tell current session
write text "tmux attach -t ${id}"
end tell
`).join('')}
end tell
end tell
`;
await execFileAsync("osascript", ["-e", script], { timeout: 10_000 });
},
async isSessionOpen(session: Session): Promise<boolean> {
// Check if iTerm has a tab attached to this tmux session
// This is complex - simplified implementation returns false
return false;
}
};
}
Implementing a Web Terminal Plugin
import type { Terminal, Session } from "@composio/ao-core";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
const execFileAsync = promisify(execFile);
export function create(config: { baseUrl: string }): Terminal {
return {
name: "web",
async openSession(session: Session): Promise<void> {
const url = `${config.baseUrl}/terminal/${session.id}`;
// Open in browser
await execFileAsync("open", [url], { timeout: 5_000 });
},
async openAll(sessions: Session[]): Promise<void> {
// Open browser with multiple tabs
const urls = sessions.map(s => `${config.baseUrl}/terminal/${s.id}`);
for (const url of urls) {
await execFileAsync("open", [url], { timeout: 5_000 });
}
}
};
}
Using Terminal in CLI
import type { Terminal } from "@composio/ao-core";
const terminal: Terminal = registry.get("terminal", "iterm2");
// Open single session
await terminal.openSession(session);
// Open all sessions for project
const sessions = await sessionManager.list("my-app");
await terminal.openAll(sessions);
Implementation Notes
Runtime Integration
Terminal plugins should use runtime.getAttachInfo() to get connection details:
import type { AttachInfo } from "@composio/ao-core";
const runtime = registry.get("runtime", session.runtimeHandle!.runtimeName);
const attachInfo: AttachInfo | undefined = await runtime.getAttachInfo?.(session.runtimeHandle!);
if (attachInfo) {
switch (attachInfo.type) {
case "tmux":
// Open iTerm2 tab with tmux attach
break;
case "docker":
// Run docker exec in terminal
break;
case "web":
// Open browser to URL
break;
}
}
Terminal plugins should check platform:
if (process.platform === "darwin") {
// Use iTerm2 or Terminal.app
} else if (process.platform === "linux") {
// Use gnome-terminal, konsole, or xterm
} else {
// Fallback to web terminal
}
Session Deduplication
The isSessionOpen() method helps avoid opening duplicate tabs:
if (terminal.isSessionOpen && await terminal.isSessionOpen(session)) {
console.log("Session already open");
return;
}
await terminal.openSession(session);
Built-in Plugins
- iterm2 - iTerm2 on macOS (default)
- web - Web-based terminal (browser)
- none - No-op for headless/CI environments
Future plugins could support:
- terminal-app - macOS Terminal.app
- gnome-terminal - GNOME Terminal on Linux
- konsole - KDE Konsole on Linux
- vscode - VS Code integrated terminal
- warp - Warp terminal
See Also
- Runtime - Runtime execution environment interface
- Session - Session interface
- Notifier - Notification interface