Skip to content

Commit 3c52b22

Browse files
authored
docs: improve README scannability and document the exit-code contract (#150)
1 parent 04be56e commit 3c52b22

3 files changed

Lines changed: 43 additions & 9 deletions

File tree

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Give your AI agent a real terminal it can drive, and get back reviewable snapsho
99
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](./LICENSE)
1010
![Node](https://img.shields.io/node/v/agent-tty)
1111

12+
[Quickstart](#quickstart) · [Why](#why-not-just-tmux-expect-asciinema-or-playwright) · [How it works](#how-it-works) · [Commands](#command-surface) · [Contributing](#contributing)
13+
1214
![agent-tty: drive a terminal session and watch it live in the dashboard](./assets/hero.gif)
1315

1416
Tools like `tmux` or `screen` help _you_ manage your own terminal windows. `agent-tty` is for handing a real, long-lived terminal to an AI coding agent, so it can run commands, drive interactive apps like `nvim` or `htop`, and read the screen back. Because every session is recorded, you never have to take the agent's word for what happened: you (or another agent) get a plain-text snapshot, a real screenshot, or a video of the actual screen, and can replay it to check the work. It works just as well for plain shell automation and CI smoke tests with no agent involved.
@@ -48,13 +50,13 @@ npm install -g agent-tty
4850
export AGENT_TTY_HOME="$(mktemp -d)"
4951
agent-tty doctor --json # check your environment
5052

51-
# Open a session, do something, wait for it, look at the result.
52-
SID=$(agent-tty create --json -- /bin/bash | jq -r '.result.sessionId')
53-
agent-tty run "$SID" 'printf "hello from agent-tty\n"' --json
54-
agent-tty wait "$SID" --text 'hello from agent-tty' --json
55-
agent-tty snapshot "$SID" --format text --json
56-
agent-tty screenshot "$SID" --json
57-
agent-tty destroy "$SID" --json
53+
# The canonical loop:
54+
SID=$(agent-tty create --json -- /bin/bash | jq -r '.result.sessionId') # 1. open a session
55+
agent-tty run "$SID" 'printf "hello from agent-tty\n"' --json # 2. type into it
56+
agent-tty wait "$SID" --text 'hello from agent-tty' --json # 3. wait for the screen
57+
agent-tty snapshot "$SID" --format text --json # 4. read it back
58+
agent-tty screenshot "$SID" --json # 5. capture proof
59+
agent-tty destroy "$SID" --json # 6. clean up
5860
```
5961

6062
Driving an interactive TUI is the same loop, with key chords and a wait for the screen to settle:
@@ -111,9 +113,17 @@ A colleague then used `agent-tty` to build an experimental TUI for Coder agents
111113

112114
## Command surface
113115

114-
Every user-facing command takes `--json` and returns a stable, machine-readable envelope. The commands cover the session lifecycle (`create`, `list`, `inspect`, `destroy`, `gc`), input and control (`run`, `type`, `paste`, `send-keys`, `batch`, `resize`, `signal`, `mark`), observation and capture (`wait`, `snapshot`, `screenshot`, `record export`), the live `dashboard`, and environment checks (`version`, `doctor`, `skills`).
116+
Every user-facing command takes `--json` and returns a stable, machine-readable envelope, and exits with a stable code (`0` success, `2` usage error, `3` session not found, …) so scripts can branch without parsing output.
117+
118+
| Group | Commands |
119+
| ----------------------- | ------------------------------------------------------------------------ |
120+
| Session lifecycle | `create`, `list`, `inspect`, `destroy`, `gc` |
121+
| Input and control | `run`, `type`, `paste`, `send-keys`, `batch`, `resize`, `signal`, `mark` |
122+
| Observation and capture | `wait`, `snapshot`, `screenshot`, `record export` |
123+
| Live view | `dashboard` |
124+
| Environment | `version`, `doctor`, `skills` |
115125

116-
See [`docs/USAGE.md`](./docs/USAGE.md) for the full flag reference and [`docs/TROUBLESHOOTING.md`](./docs/TROUBLESHOOTING.md) for renderer and environment issues.
126+
The CLI documents itself: `agent-tty --help` lists every command, and `agent-tty <command> --help` shows its flags. The full reference, including the exit-code table, is in [`docs/USAGE.md`](./docs/USAGE.md); renderer and environment issues are in [`docs/TROUBLESHOOTING.md`](./docs/TROUBLESHOOTING.md).
117127

118128
## Agent skills
119129

docs/USAGE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ Useful flags:
104104
- `--exit`: wait for the process to exit.
105105
- `--timeout <ms>`: maximum wait time in milliseconds, with `0` meaning infinite.
106106

107+
On timeout, a standalone `wait` still exits `0` and reports `matched: false` / `timedOut: true` in the JSON result — check the envelope, not the exit code. Inside `batch`, a timed-out `wait` step is a step failure (`WAIT_TIMEOUT`, exit code `11` under fail-fast).
108+
107109
### Screen Hash
108110

109111
`snapshot` results (both `--format structured` and `--format text`) and a **matched** `wait` result carry an optional `screenHash`: a lowercase 64-character hex SHA-256 of the visible screen text. Compare it across two calls to tell whether the visible screen actually changed — equal hashes mean identical visible content, even if the event-log sequence advanced on a no-op repaint.
@@ -229,6 +231,27 @@ agent-tty create --env PROMPT_EOL_MARK='%B%S%#%s%b' -- /bin/zsh
229231

230232
A lone `'%'` does **not** restore the marker (zsh treats it as a prompt escape that expands to nothing); use `'%B%S%#%s%b'` for the styled default or `'%%'` for a plain percent. The default is applied at spawn time and is not stored in the manifest, so it does not appear in `inspect`, `list`, or `create --json` output. If your `~/.zshrc` assigns `PROMPT_EOL_MARK` it runs after the environment is imported and wins, so the marker can reappear — remove that line or set the value you want via `--env`.
231233

234+
## Exit Codes
235+
236+
Every command exits with a stable code, so scripts can branch without parsing output. The `--json` error envelope carries the precise `error.code` (for example `WAIT_TIMEOUT`); the exit code is a coarser, stable summary of it.
237+
238+
| Exit code | Meaning |
239+
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
240+
| `0` | Success. |
241+
| `1` | Internal or unclassified error. |
242+
| `2` | Usage error: unknown command or flag, or an invalid argument (session ID, dimensions, keys, duration, signal, input). |
243+
| `3` | Session not found. |
244+
| `4` | Session is not running or already destroyed. |
245+
| `5` | Session host timed out. |
246+
| `6` | Session host unreachable. |
247+
| `7` | Export failed. |
248+
| `8` | Storage read/write or manifest validation error. |
249+
| `9` | Protocol or RPC error. |
250+
| `10` | Replay failed. |
251+
| `11` | A `wait` step inside a fail-fast `batch` timed out (standalone `wait` exits `0` with `timedOut: true` in the result — see [`wait`](#wait)). |
252+
253+
A fail-fast `batch` exits with the failed step's code (for example `11` for a wait timeout); `--keep-going` exits `1` if any step failed.
254+
232255
## Anti-Patterns
233256

234257
- Do not reach for `tmux`, `screen`, or ad hoc PTY wrappers first when `agent-tty` can provide an isolated, inspectable session.

src/cli/exitCodes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ERROR_CODES } from '../protocol/errors.js';
22

3+
// Public contract: documented in docs/USAGE.md ("Exit Codes"). Keep in sync.
34
const EXIT_CODE_BY_ERROR_CODE: Readonly<Record<string, number>> = Object.freeze(
45
{
56
[ERROR_CODES.INVALID_SESSION_ID]: 2,

0 commit comments

Comments
 (0)