ADR-0015: No terminal pane; a headless command primitive only
- Status: Accepted
- Date: 2026-06-25
- Deciders: jka
- Decision: D15
Context
Many IDEs embed a terminal. An interactive terminal emulator is the most difficult cross-platform component an editor can carry: PTY handling, ANSI and cursor emulation, resizing, and under a curses frontend a terminal inside a terminal. Git and the agent, however, both need to run commands and read their output.
Decision
rio ships no terminal pane and no terminal emulator, not even as an option. The bottom of the window is a one-line status bar. Interactive work and manual testing happen in the user's own terminal, which is the documented workflow.
The core keeps a headless command-execution primitive: exec.run {argv, ?cwd?, ?stdin?} returns {exitcode, stdout, stderr}. Its rules:
- The command is an argument vector, never a shell string. There is no quoting or
injection surface and no dependence on
/bin/sh, so behaviour is the same on Windows. - A command that runs and exits non-zero is a successful operation; the exit code
is data. Only a failure to launch raises
io_error. - Output is captured as bytes, with no line-ending or encoding translation.
When command output needs to be seen, it appears in the flow that asked for it, for example in the agent conversation.
Consequences
- An entire UI region and its complexity are removed without losing a function git or the agent needs.
- Users who want a terminal keep using theirs.
exec.runis synchronous and blocks the core while it runs, which is acceptable for short git commands. The agent's command tool needed an asynchronous variant with a timeout (ADR-0083).