Repository navigation
Terminal Engine
English · Русский
The emulator is written in commonMain — pure Kotlin over a cell grid, no platform terminal
library — so desktop and Android render the same state.
flowchart LR
CH[ShellChannel<br/>ssh · telnet · serial · mosh · pty] --> SES[TerminalSession<br/>coroutine loop, PTY size]
SES --> EMU[TerminalEmulator<br/>grid, cursor, modes]
EMU --> SNAP[render snapshot<br/>TermSnapshotRow]
SNAP --> UI[TerminalScreenState → Compose]
SES --> REC[SessionRecorder<br/>asciicast v2]
EMU --> MARK[TerminalStepMark<br/>runbook step boundaries]
| Type | What it models |
|---|---|
TermCell |
one cell: text (a String, so astral characters and combining sequences fit), style, width |
TermWidth |
Single / Wide (leading cell of a CJK or emoji pair) / Continuation
|
TermStyle |
the full SGR attribute set; underline is a shape (4:x — double, curly, dotted, dashed) plus its own colour |
TermColor |
Default, Indexed (xterm 0–255) or Rgb truecolor — UI-independent; the renderer maps it into the theme palette |
TermRow |
cells plus a wrapped flag: true means auto-wrap (DECAWM) cut the line, an honest \n leaves it false
|
TermSnapshotRow |
an immutable row in a render snapshot; equal snapshots let an unchanged screen skip recomposition |
TerminalReflow is a pure function over row lists: soft-wrapped physical rows are joined into
logical lines and re-split at the new width, the cursor following its text, with the bottom rows
becoming the grid and the rest the scrollback (trimmed to the configured limit). Because it holds
no emulator state it is tested directly as well as through resize tests.
| Concern | Where |
|---|---|
| SGR parsing | SgrParser |
| Glyph metrics (for hit-testing and layout) | CharMetrics |
| Selection and its fragments | TerminalSelection |
| Scrollback search | TerminalSearch |
| Mouse reporting | TerminalMouse |
| Cross-session command history |
CommandHistory, TerminalHistoryStore
|
| fish-style completion |
AutocompleteEngine, CommandSuggestions, FuzzyMatch
|
| Input safety (what may be sent) | SafeTerminalInput |
| Syntax highlighting | terminal/highlight/ |
SessionRecorder writes asciicast v2: a JSON
header line and one [time, "o", data] line per output chunk, so a recording plays in any
asciinema player. The whole recording is held in memory and written once at the end — terminal
output is untrusted and unbounded (cat a large file and it never stops), so maxEvents and
maxBytes bound it and truncated says when a limit was hit rather than the app quietly eating
memory. Recordings hold whatever the server printed, so they are only ever written when the user
exports one.
Runbooks need to know where a step's output starts and ends without printing protocol on the
screen. TerminalStepMark defines a private OSC code, OSC 8375 (S,K in ASCII decimal):
-
OSC 8375 ; <token> ; BEL— the step's output starts here; -
OSC 8375 ; <token> ; <exit code> BEL— the step finished with that status.
The emulator acts on a mark only for a step the client declared through expectStep, so an
ordinary session parks nothing and a host echoing a token it read off the screen cannot close a
capture window this client never opened. TerminalEchoFilter hides the echo of what the client
typed. The runbook layer only builds the probes (runbook/RunbookMarker).
What a mark says is what the host's shell said: a compromised host can emit any status it likes. Runbooks are not a security boundary over a hostile host.
ui/terminal/TerminalScreenState holds screen state for Compose, including scrollback search.
Geometry derived from settings (font size → mouse hit-testing) is recomputed when the setting
changes rather than cached forever, and nothing is allocated per recomposition.
User guide
- Installation
- Getting started
- Hosts and connections
- Vault and credentials
- Terminal
- Files (SFTP)
- Port forwarding
- Remote desktops
- Snippets and runbooks
- Monitoring and guard
- AI assistant
- Sync and devices
- Teams and sharing
- Settings and shortcuts
- Android
- Troubleshooting
Development
- Architecture
- Building and running
- Connections and transports
- Terminal engine
- Vault and crypto
- Sync protocol
- Remote desktop stacks
- UI layer
- Testing and the gate
- Contributing and releases
Русский — оглавление