Skip to content

zidane-ui/terminal/headless

import { … } from 'zidane-ui/terminal/headless'ui/src/terminal/headless/index.ts

Functions#

createMemoryTerminalLayoutsFunction#

Creates TerminalLayouts held in memory, per scope key.

TypeScript
function createMemoryTerminalLayouts(): TerminalLayouts

ui/src/terminal/headless/layout.ts:42

createTerminalStoreFunction#

Creates the TerminalStore over a host. An app creates one per page and hands it to TerminalProvider (code outside React reads it too).

TypeScript
function createTerminalStore(host: TerminalHost): TerminalStore
Parameters
NameTypeDescription
hostTerminalHost

The terminal host.

ui/src/terminal/headless/store.ts:652

scopeOfTerminalKeyFunction#

The scope a key names when nothing better is known (a reload after a signal from an unknown scope).

TypeScript
function scopeOfTerminalKey(key: string): TerminalScope
Parameters
NameTypeDescription
keystring

A terminalScopeKey.

ui/src/terminal/headless/scope.ts:53

terminalProjectKeyFunction#

The key of a project's or a draft's list, as the host names it (root, draftId).

TypeScript
function terminalProjectKey(signal: { draftId?: string; root: string }): string
Parameters
NameTypeDescription
signal{ draftId?: string; root: string }

The project root and the draft, if any.

string

ui/src/terminal/headless/scope.ts:40

terminalScopeKeyFunction#

A scope's identity: the session id when bound, else draft:<id> or project:<root> (a session id never starts with either).

TypeScript
function terminalScopeKey(scope: TerminalScope): string
Parameters
NameTypeDescription
scopeTerminalScope

The scope.

string

ui/src/terminal/headless/scope.ts:29

Classes#

TerminalStoreClass#

The terminal store: every scope's terminals, the live views, the layouts.

TypeScript
class TerminalStore
TypeScript
new TerminalStore(host: TerminalHost)
Parameters
NameTypeDescription
hostTerminalHost

The terminal host.

TerminalStore properties
NameTypeDescription
hostreadonlyTerminalHost

The host the store reads and acts through.

layoutsreadonlyTerminalLayouts

Where the per-scope layouts live: the host's, else in memory.

addView()

TypeScript
addView(terminalId: string, view: TerminalViewSink): () => void

Registers a live view of terminalId; returns its unregister.

Parameters
NameTypeDescription
terminalIdstring

The terminal it shows.

viewTerminalViewSink

What it does with the terminal's signals.

() => void

adoptDraft()

TypeScript
adoptDraft(draft: TerminalScope, session: TerminalScope): Promise<void>

Hands the draft's terminals to the session created from it. Shown in the session at once (the host's lists follow); a failed hand-over (or a host that cannot hand over) gives them back to the project, never leaving them tied to a draft nobody shows.

Parameters
NameTypeDescription
draftTerminalScope

The draft's scope.

sessionTerminalScope

The session's scope.

Promise<void>

autoOpen()

TypeScript
autoOpen(
  scope: TerminalScope,
  placement: TerminalPlacement,
  measure?: () => TerminalGrid | null,
): Promise<void>

Opens a terminal for the user when a placement is opened on a scope with none of theirs (none at all, or only the agent's). The drawer opens one only when the user opened it (toggleDrawer). A drawer open because the scope copied its project's layout, or left open before a relaunch, starts no shell: otherwise every session visited would keep one. Skipped while another open is in flight (the keybinding opens the drawer and a terminal at once).

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

placementTerminalPlacement

The placement that opened.

measure?() => TerminalGrid | null

Measures the grid the area fits, once the state is in.

Promise<void>

close()

TypeScript
close(scope: ScopeRef, terminalId: string): Promise<void>

Closes a terminal.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key (where an error shows).

terminalIdstring

The terminal.

Promise<void>

dismissError()

TypeScript
dismissError(scope: ScopeRef): void

Clears the scope's error.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

ensure()

TypeScript
ensure(scope: TerminalScope): Promise<void>

Loads the scope's state once (callers mount per scope).

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

Promise<void>

forget()

TypeScript
forget(scope: ScopeRef): void

Forgets a scope whose session was deleted. One a view still shows is kept, and stays after the view goes (one entry per such scope); a later signal for the scope starts it afresh.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

get()

TypeScript
get(scope: ScopeRef | null): ScopeTerminals

A scope's terminals (by its scope or key).

Parameters
NameTypeDescription
scopeScopeRef | null

The scope or its key; null reads as none.

layout()

TypeScript

The scope's layout (drawer, order, agent filter).

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

open()

TypeScript
open(
  scope: TerminalScope,
  target?: TerminalTarget,
  size?: TerminalGrid,
): Promise<TerminalInfo | null>

Opens a terminal and makes it active. Resolves null when it failed (see error).

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

target?TerminalTarget

A session's terminal: in its environment or on the user's machine. Ignored without a session.

size?TerminalGrid

The first grid. Default: the last one fitted, else 80×24.

Promise<TerminalInfo | null>

openInDrawer()

TypeScript
openInDrawer(scope: TerminalScope): void

Opens the drawer and a new terminal in it.

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

panelOnScreen()

TypeScript
panelOnScreen(scope: ScopeRef): boolean

Whether the side panel's Terminal tab is on screen for the scope.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

boolean

refresh()

TypeScript
refresh(scope: TerminalScope): Promise<void>

Reads the scope's state again (one read in flight per scope).

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

Promise<void>

releaseDraft()

TypeScript
releaseDraft(draftId: string): Promise<void>

Gives the draft's terminals back to the project (a discarded draft). Never rejects.

Parameters
NameTypeDescription
draftIdstring

The draft.

Promise<void>

restart()

TypeScript
restart(scope: ScopeRef, terminalId: string): Promise<void>

Restarts a terminal's process.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key (where an error shows).

terminalIdstring

The terminal.

Promise<void>

reveal()

TypeScript
reveal(scope: ScopeRef, terminalId: string, placement: TerminalPlacement): void

Makes terminalId the active terminal, focused by placement, with no shell auto-opened over it (revealTerminal picks the placement).

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

terminalIdstring

The terminal.

placementTerminalPlacement

The placement that focuses it.

revealTerminal()

TypeScript
revealTerminal(scope: TerminalScope, terminalId: string): void

Shows one of the scope's terminals, focused: in the side panel's Terminal tab when it is on screen, else in the drawer, opened for it. Opening the drawer this way starts no shell of the user's, and the strip shows the agent's terminals again when it hid the one revealed.

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

terminalIdstring

The terminal.

runIn()

TypeScript
runIn(scope: TerminalScope, input: string): Promise<TerminalInfo | null>

Opens a new terminal in the scope, shows it, and types input into it (a reply's shell block, Run in a terminal). The shell reads what was typed once it starts. Resolves with the terminal, or null when none opened (the scope's error says why).

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

inputstring

What to type, newline included to run it.

Promise<TerminalInfo | null>

setActive()

TypeScript
setActive(scope: ScopeRef, terminalId: string): void

Makes terminalId the scope's active terminal.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

terminalIdstring

The terminal.

setFittedSize()

TypeScript
setFittedSize(scope: TerminalScope, size: TerminalGrid | null): void

Remembers the grid the scope's terminal area fits: new terminals start at it.

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

sizeTerminalGrid | null

The grid, or null (not laid out: keeps the last one).

setHidden()

TypeScript
setHidden(scope: ScopeRef, terminalId: string, hidden: boolean): Promise<void>

Hides a terminal from the agent, or shows it again.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key (where an error shows).

terminalIdstring

The terminal.

hiddenboolean

Hide it.

Promise<void>

showPanel()

TypeScript
showPanel(scope: ScopeRef): () => void

The side panel's Terminal tab shows the scope's terminals, on screen; returns its unregister.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

() => void

showPlacement()

TypeScript
showPlacement(scope: ScopeRef): () => void

A placement (drawer, panel tab) is showing the scope's terminals; clears the badge. Returns its unregister.

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

() => void

subscribe()

TypeScript
subscribe(listener: () => void): () => void

Registers a listener called after any scope changed. Returns its unsubscribe.

Parameters
NameTypeDescription
listener() => void

Called after each change.

() => void

takeFocus()

TypeScript
takeFocus(scope: ScopeRef, seq: number): void

The placement took focus request seq: drop it (a newer request stays).

Parameters
NameTypeDescription
scopeScopeRef

The scope or its key.

seqnumber

The request taken.

terminal()

TypeScript
terminal(terminalId: string): TerminalInfo | null

The terminal with this id, in whichever scope holds it.

Parameters
NameTypeDescription
terminalIdstring

The terminal.

toggleDrawer()

TypeScript
toggleDrawer(scope: TerminalScope): void

Shows or hides the scope's drawer.

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

updateLayout()

TypeScript
updateLayout(scope: TerminalScope, patch: Partial<TerminalLayout>): void

Changes the scope's layout.

Parameters
NameTypeDescription
scopeTerminalScope

The scope.

patchPartial<TerminalLayout>

The fields to change.

ui/src/terminal/headless/store.ts:85

Constants#

DEFAULT_TERMINAL_LABELSConstant#

The default English strings of the terminal components.

TypeScript
const DEFAULT_TERMINAL_LABELS: { terminalActions: string; terminalAddToChat: string; terminalAddToChatNowhere: string; terminalClear: string; terminalClose: (title: string) => string; terminalConnecting: string; terminalCopy: string; terminalCouldNotLoad: (message: string) => string; terminalDisconnected: string; terminalDismissError: string; terminalDrawer: string; terminalExitedPlain: string; terminalExitedWith: (code: number) => string; terminalFailedToStart: string; terminalGlyphAgent: string; terminalGlyphDisconnected: string; terminalGlyphError: string; terminalGlyphStarting: string; terminalHiddenFromAgent: string; terminalHiddenFromAgentIcon: string; terminalHide: string; terminalHideAgentTerminals: string; terminalHideFromAgent: string; terminalLinkOnServer: (serverName: string) => string; terminalNew: string; terminalNewLocal: string; terminalNoneOpen: string; terminalNotAvailable: string; terminalOpenSettings: string; terminalPaste: string; terminalReconnect: string; terminalRestart: string; terminalRestartAction: string; terminalShow: string; terminalShowAgentTerminals: string; terminalShowToAgent: string; terminalStartedByAgent: (taskId?: string) => string; terminalStarting: string; terminalStopAgentTask: (title: string) => string; terminalTabs: string; terminalToggleLabel: (open: boolean, startedByAgent: number) => string; terminalUnreachable: string }

ui/src/terminal/headless/labels.ts:11

DEFAULT_TERMINAL_LAYOUTConstant#

The layout of a scope nobody changed.

TypeScript
const DEFAULT_TERMINAL_LAYOUT: TerminalLayout

ui/src/terminal/headless/layout.ts:34

Interfaces#

ScopeTerminalsInterface#

One scope's terminals as the components read them.

TypeScript
interface ScopeTerminals
ScopeTerminals properties
NameTypeDescription
activeIdstring | null

The active terminal.

errorstring | null

The last failed call (open, restart, …), shown until the next success.

focusTerminalFocusRequest | null

A revealed terminal waiting for its placement to focus it.

stateTerminalSessionState | null

Null until the first state answers.

unseenAgentnumber

Agent terminals that started while nothing showed terminals (sessions only).

ui/src/terminal/headless/store.ts:54

TerminalAttachResultInterface#

What a client needs to start showing a terminal: its history, and where live output resumes.

TypeScript
interface TerminalAttachResult
TerminalAttachResult properties
NameTypeDescription
datastring

Output history to show first.

offsetnumber

Character offset where live output resumes.

terminalTerminalInfo

The terminal that was attached.

dist/media-type-BzRZ4FqT.d.ts:4265

TerminalDataSignalInterface#

A batch of a terminal's output starting at stream offset offset (or, for a reset, its history up to there).

TypeScript
interface TerminalDataSignal
TerminalDataSignal properties
NameTypeDescription
datastring

The output.

offsetnumber

Stream offset of the first character of data.

terminalIdstring

The terminal.

ui/src/terminal/headless/host.ts:24

TerminalFocusRequestInterface#

A terminal revealed on request, for the placement it was revealed in to focus once (takeFocus).

TypeScript
interface TerminalFocusRequest
TerminalFocusRequest properties
NameTypeDescription
placementTerminalPlacement

The placement that focuses it.

seqnumber

Increases with every request.

terminalIdstring

The terminal.

ui/src/terminal/headless/store.ts:44

TerminalGridInterface#

A grid size in cells.

TypeScript
interface TerminalGrid
TerminalGrid properties
NameTypeDescription
colsnumber

Columns.

rowsnumber

Rows.

ui/src/terminal/headless/store.ts:68

TerminalHostInterface#

The terminal host.

TypeScript
interface TerminalHost
TerminalHost properties
NameTypeDescription
layouts?TerminalLayouts

Where the per-scope terminal layouts live. Absent: they last as long as the page.

ack(terminalId: string, clientId: string, offset: number) => Promise<void>

A view wrote the output up to offset, so the host keeps it flowing.

adoptDraft?(draftId: string, sessionId: string) => Promise<{ adopted: string[] }>

Moves a draft's terminals into the session it became; resolves with the ids moved. Absent: they go back to the project.

attach(terminalId: string, clientId: string) => Promise<TerminalAttachResult>

Attaches a view (clientId) and resolves with the history to replay and where live output resumes.

close(terminalId: string) => Promise<void>

Closes a terminal (an agent's: ends its task).

detach(terminalId: string, clientId: string) => Promise<void>

Detaches a view.

listen(sink: TerminalSignalSink) => () => void

Starts telling sink what happens. Returns its unsubscribe.

open(scope: TerminalScope, options: TerminalOpenOptions) => Promise<TerminalInfo>

Opens a terminal in the scope, at that size.

releaseDraft?(draftId: string) => Promise<void>

Gives a draft's terminals back to the project (the draft was discarded). Absent: nothing to give back.

resize(terminalId: string, clientId: string, cols: number, rows: number, claim: boolean) => Promise<void>

A view asks for a grid size; claim: it is the one being looked at and takes the size.

restart?(terminalId: string) => Promise<void>

Restarts a terminal's process. Absent: no Restart.

setHidden?(terminalId: string, hidden: boolean) => Promise<void>

Hides a session's terminal from its agent, or shows it again. Absent: no such toggle.

state(scope: TerminalScope) => Promise<TerminalSessionState>

The scope's terminals and whether this host can run them. Rejects when they cannot be read.

write(terminalId: string, data: string, from?: TerminalWriteOrigin) => Promise<void>

Sends input (typing, a paste, an emulator reply).

ui/src/terminal/headless/host.ts:70

TerminalInfoInterface#

Description of one terminal, as the host reports it to clients.

TypeScript
interface TerminalInfo
TerminalInfo properties
NameTypeDescription
colsnumber

Width in character cells.

createdAtnumber

Creation time in epoch ms.

cwdstring

Working directory the terminal started in.

environmentstring

Environment kind it runs in (local, worktree, docker, e2b, …).

error?string

Failure message, when status is error.

exitCode?number

Exit code, once the process has exited.

hiddenFromAgentboolean

The agent's terminal tools skip it.

idstring

Terminal id.

labelstring

Stable name ("Terminal 2", or the agent's command).

lastActivityAtnumber

Time of the last output or input in epoch ms.

ownerTerminalOwner

Who started the terminal.

program?string

The program in the foreground, for terminals on this machine.

rowsnumber

Height in character cells.

scope?TerminalProjectScope

Set on project / draft terminals (sessionId is '').

sessionIdstring

The session it belongs to; '' for a project / draft terminal (see scope).

sizeSeqnumber

Bumped on every size change: signals and attach replies reach a view by different routes, so it keeps the newest size, not the last to arrive.

statusTerminalStatus

Connection and process state.

targetTerminalTarget

Where the terminal runs.

taskId?string

The background task it runs (agent terminals).

title?string

Title the program set (OSC 0/2), if any.

dist/media-type-BzRZ4FqT.d.ts:4155

TerminalLayoutInterface#

A scope's terminal layout.

TypeScript
interface TerminalLayout
TerminalLayout properties
NameTypeDescription
terminalHeightnumber | null

The drawer's height (px); null: the default.

terminalHideAgentboolean

The tab strip leaves the agent's terminals out.

terminalOpenboolean

The drawer under the chat is shown.

terminalOrderreadonly string[]

Terminal ids in the user's dragged order (orderTerminals).

ui/src/terminal/headless/layout.ts:10

TerminalLayoutsInterface#

Where the per-scope layouts live.

TypeScript
interface TerminalLayouts
TerminalLayouts properties
NameTypeDescription
get(scope: TerminalScope) => TerminalLayout

The scope's layout. The same object until it changes (components read it with useSyncExternalStore).

show?(scope: TerminalScope) => void

A component shows the scope (the app may seed its layout from the project's). Absent: nothing to do.

subscribe(listener: () => void) => () => void

Registers a listener called after any layout changed. Returns its unsubscribe.

update(scope: TerminalScope, patch: Partial<TerminalLayout>) => void

Changes the scope's layout.

ui/src/terminal/headless/layout.ts:22

TerminalOpenOptionsInterface#

Where a new terminal starts, and its first grid size.

TypeScript
interface TerminalOpenOptions
TerminalOpenOptions properties
NameTypeDescription
colsnumber

Columns.

rowsnumber

Rows.

target?TerminalTarget

A session's terminal: in its environment (session, the default) or on the user's machine (local).

ui/src/terminal/headless/host.ts:52

TerminalScopeInterface#

Whose terminals a store entry, a drawer or a panel shows.

TypeScript
interface TerminalScope
TerminalScope properties
NameTypeDescription
cwdstring

Where a terminal without session opens.

draft?string

The new-chat draft (never together with session).

rootstring

The project root: a scope without session or draft is keyed by it.

session?string

The session the terminals are a session's.

ui/src/terminal/headless/scope.ts:9

TerminalSessionStateInterface#

The terminals of one session and whether this host can run them.

TypeScript
interface TerminalSessionState
TerminalSessionState properties
NameTypeDescription
availableboolean

False when this host can't run terminals (the GUI without the daemon).

environment{ kind: string; remote: boolean }

Kind of the session's environment, and whether it runs somewhere else.

reason?string

Why not, when available is false.

terminalsTerminalInfo[]

Terminals of the session.

dist/media-type-BzRZ4FqT.d.ts:4201

TerminalSignalSinkInterface#

What the host tells the store, as it happens.

TypeScript
interface TerminalSignalSink
TerminalSignalSink properties
NameTypeDescription
output(signal: TerminalDataSignal) => void

Output of a terminal some view is attached to.

projectChanged(signal: { draftId?: string; root: string; terminals: TerminalInfo[] }) => void

A project's (draftId absent) or a draft's full list changed.

relink(connected: boolean) => void

The link to what runs the terminals changed (a daemon restarted, a connection came back): every scope reloads, and with connected every view attaches again (the new link has none).

reset(signal: TerminalDataSignal) => void

A view fell too far behind: its content is replaced with the terminal's history.

sessionChanged(sessionId: string, terminals: TerminalInfo[]) => void

A session's full list of terminals changed (its agent started one, one exited…).

ui/src/terminal/headless/host.ts:34

TerminalViewSinkInterface#

What a view does with the signals of the terminal it shows.

TypeScript
interface TerminalViewSink
TerminalViewSink properties
NameTypeDescription
output(offset: number, data: string) => void

Live output from offset.

reattach() => void

The link came back: attach again from scratch.

reset(offset: number, data: string) => void

The view's content is replaced with the history up to offset.

ui/src/terminal/headless/store.ts:31

TerminalWriteOriginInterface#

What a view sends along with a write.

TypeScript
interface TerminalWriteOrigin
TerminalWriteOrigin properties
NameTypeDescription
clientIdstring

The view writing.

response?boolean

The emulator's answer to a query in the output, not typing (the host keeps only the size owner's).

ui/src/terminal/headless/host.ts:62

Types#

TerminalLabelsType#

The shape of the terminal label dictionary.

TypeScript
type TerminalLabels = typeof DEFAULT_TERMINAL_LABELS

ui/src/terminal/headless/labels.ts:69

TerminalPlacementType#

Where a scope's terminals show: the drawer under the chat, or the side panel's Terminal tab.

TypeScript
type TerminalPlacement = 'drawer' | 'panel'

ui/src/terminal/headless/store.ts:41

TerminalTargetType#

Where it runs: the session's environment, or this machine in the project.

TypeScript
type TerminalTarget = 'session' | 'local'

dist/media-type-BzRZ4FqT.d.ts:4135