Skip to content

Terminal Channel

Reference for the ahp-terminal:/<id> channel — long-lived pseudo-terminals that can be attached to clients and/or sessions. See Terminal Channel specification for the wire-level overview.

JSON Schema: state.schema.json

State Types

TerminalInfo

Lightweight terminal metadata exposed on the root state.

FieldTypeRequiredDescription
resourceURIYesTerminal URI (subscribable for full terminal state)
titlestringYesHuman-readable terminal title
claimTerminalClaimYesWho currently holds this terminal
exitCodenumberNoProcess exit code, if the terminal process has exited

TerminalClaimKind

Discriminant for terminal claim kinds.

MemberValue
Client'client'
Session'session'

TerminalClientClaim

A terminal claimed by a connected client.

FieldTypeDescription
kindTerminalClaimKind.ClientDiscriminant
clientIdstringThe clientId of the claiming client

TerminalSessionClaim

A terminal claimed by a session, optionally scoped to a specific turn or tool call.

FieldTypeRequiredDescription
kindTerminalClaimKind.SessionYesDiscriminant
sessionURIYesSession URI that claimed the terminal
turnIdstringNoOptional turn identifier within the session
toolCallIdstringNoOptional tool call identifier within the turn

TerminalClaim

Describes who currently holds a terminal. A terminal may be claimed by either a connected client or a session (e.g. during a tool call).

TerminalClientClaim | TerminalSessionClaim

TerminalState

Full state for a single terminal, loaded when a client subscribes to the terminal's URI.

FieldTypeRequiredDescription
titlestringYesHuman-readable terminal title
cwdURINoCurrent working directory of the terminal process
colsnumberNoTerminal width in columns
rowsnumberNoTerminal height in rows
contentTerminalContentPart[]YesTyped content parts, replacing the flat content: string.

Naive consumers that only need the raw VT stream can reconstruct it with: content.map(p =&gt; p.type === 'command' ? p.output : p.value).join('')

Consumers that need command boundaries can filter by part type.
exitCodenumberNoProcess exit code, set when the terminal process exits
claimTerminalClaimYesWho currently holds this terminal
supportsCommandDetectionbooleanNoWhether this terminal emits terminal/commandExecuted and terminal/commandFinished actions and populates command-typed parts.

Clients MUST check this flag before relying on command detection. Do NOT use the presence of a command part as a feature flag — parts are absent in the normal idle state.

TerminalContentPart

A content part within terminal output.

TerminalUnclassifiedPart | TerminalCommandPart

TerminalUnclassifiedPart

Unstructured terminal output — content before, between, or after commands, or from terminals that do not support command detection.

FieldTypeDescription
type'unclassified'Discriminant
valuestringAccumulated VT output. Appended to by terminal/data when no command is executing.

TerminalCommandPart

A single command: its command line and the output it produced.

While isComplete is false the command is still executing; output grows as terminal/data actions arrive. At terminal/commandFinished the part is mutated in-place with isComplete: true and the completion metadata.

FieldTypeRequiredDescription
type'command'YesDiscriminant
commandIdstringYesStable id matching the commandId on the corresponding terminal/commandExecuted and terminal/commandFinished actions.
commandLinestringYesThe command line submitted to the shell.
outputstringYesAccumulated VT output. Appended to by terminal/data while isComplete is false. Shell integration escape sequences are stripped by the server.
timestampnumberYesUnix timestamp (ms) when execution started, as reported by the server.
isCompletebooleanYesWhether the command has finished.
exitCodenumberNoShell exit code. Set at completion. undefined if unknown.
durationMsnumberNoWall-clock duration in milliseconds. Set at completion.

Actions

Mutate TerminalState. Scoped to a terminal URI via the enclosing ActionEnvelope.channel.

JSON Schema: actions.schema.json

terminal/data

Terminal output data (pty → client direction).

Appends data to the terminal's content in the reducer.

terminal/data and terminal/input are intentionally separate actions because standard write-ahead reconciliation is not safe for terminal I/O. A pty is a stateful, mutable process — optimistically applying input or predicting output would produce incorrect state. Instead, terminal/input is a side-effect-only action (client → server → pty), and terminal/data is server-authoritative output (pty → server → client).

FieldTypeDescription
typeActionType.TerminalData
datastringOutput data (may contain ANSI escape sequences)

terminal/input

Keyboard input sent to the terminal process (client → pty direction).

This is a side-effect-only action: the server forwards the data to the terminal's pty. The reducer treats this as a no-op since terminal/data actions will reflect any resulting output.

See terminal/data for why these two actions are kept separate.

FieldTypeDescription
typeActionType.TerminalInput
datastringInput data to send to the pty

terminal/resized

Terminal dimensions changed.

Dispatchable by clients to request a resize, or by the server to inform clients of the actual terminal dimensions.

FieldTypeDescription
typeActionType.TerminalResized
colsnumberTerminal width in columns
rowsnumberTerminal height in rows

terminal/claimed

Terminal claim changed. A client or session transfers ownership of the terminal.

The server SHOULD reject if the dispatching client does not currently hold the claim.

FieldTypeDescription
typeActionType.TerminalClaimed
claimTerminalClaimThe new claim

terminal/titleChanged

Terminal title changed.

Fired by the server when the terminal process updates its title (e.g. via escape sequences), or dispatched by a client to rename a terminal.

FieldTypeDescription
typeActionType.TerminalTitleChanged
titlestringNew terminal title

terminal/cwdChanged

Terminal working directory changed.

FieldTypeDescription
typeActionType.TerminalCwdChanged
cwdURINew working directory

terminal/exited

Terminal process exited.

FieldTypeRequiredDescription
typeActionType.TerminalExitedYes
exitCodenumberNoProcess exit code. undefined if the process was killed without an exit code.

terminal/cleared

Terminal scrollback buffer cleared.

FieldTypeDescription
typeActionType.TerminalCleared

terminal/commandDetectionAvailable

Shell integration has loaded and the terminal now supports command detection. The server dispatches this when shell integration becomes available (which may happen asynchronously after the terminal is created).

Clients MUST NOT assume command detection is available until this action (or terminal/commandExecuted) has been received.

FieldTypeDescription
typeActionType.TerminalCommandDetectionAvailable

terminal/commandExecuted

A command has been submitted to the shell and is now executing. All subsequent terminal/data actions (until the matching terminal/commandFinished) constitute this command's output.

FieldTypeDescription
typeActionType.TerminalCommandExecuted
commandIdstringStable identifier for this command, scoped to the terminal URI. Allows correlating commandExecutedcommandFinished pairs.
commandLinestringThe command line text that was submitted
timestampnumberUnix timestamp (ms) of when the command started executing, as measured on the server.

terminal/commandFinished

A command has finished executing.

The sequence of terminal/data actions between the preceding terminal/commandExecuted (same commandId) and this action constitutes the complete output of the command.

FieldTypeRequiredDescription
typeActionType.TerminalCommandFinishedYes
commandIdstringYesMatches the commandId from the corresponding commandExecuted
exitCodenumberNoShell exit code. undefined if the shell did not report one.
durationMsnumberNoWall-clock duration of the command in milliseconds, as measured by the shell integration script on the server side.

Commands

JSON Schema: commands.schema.json

createTerminal

Creates a new terminal on the server.

After creation, the client should subscribe to the terminal URI to receive state updates. The server dispatches root/terminalsChanged to update the root terminal list.

PropertyValue
DirectionClient → Server
TypeRequest

Parameters:

FieldTypeRequiredDescription
channelURIYesTerminal URI (client-chosen).
claimTerminalClaimYesInitial owner of the terminal
namestringNoHuman-readable terminal name
cwdURINoInitial working directory URI
colsnumberNoInitial terminal width in columns
rowsnumberNoInitial terminal height in rows

Result: null on success.


disposeTerminal

Disposes a terminal and kills its process if still running.

The server dispatches root/terminalsChanged to remove the terminal from the root terminal list.

PropertyValue
DirectionClient → Server
TypeRequest

Parameters:

No parameters.

Result: null on success.


Released under the MIT License.