hty run
Start a program in a new detached PTY session. The session runs in the background — use watch, snapshot, or attach to interact with it.
Reference
hty run [--name NAME] [--rows N] [--cols N] [--cwd PATH] [--scrollback N] [--attach] -- program [args...]
Create a new session and start `program` inside a fresh PTY. The session
is detached from your terminal; observe it with `hty watch` and drive it
with `hty send`/`hty snapshot`/`hty wait`.
Flags:
--name NAME Human-friendly alias for the session. Must be unique.
--rows N Initial row count (default 24)
--cols N Initial column count (default 80)
--cwd PATH Child's working directory
--scrollback N Scrollback buffer size (default 10000)
--attach Spawn + attach in one invocation. Streams PTY
output to stdout and forwards stdin into the
session, just like `hty attach`. Ctrl-A d
detaches (session persists unless --remove is
also set). Mutually exclusive with --snapshot
and any --wait-until-* flag.
--remove Automatically remove the session from the registry
once the child process exits (success, failure, or
signal). Tied to child lifetime; off by default so
sessions persist for `hty list` / `hty logs` /
`hty replay` until `hty delete`. Pairs naturally
with --attach: `hty run --attach --remove -- ...`
is a one-shot "foreground a command in a PTY".
Wait + snapshot flags (let `run` block until the program is ready and
return the initial render in one round-trip):
--snapshot Include the post-spawn snapshot in the response.
Requires one of --wait-until-* or --wait-duration.
--wait-duration DUR Sleep DUR after spawn, then snapshot.
--wait-until-idle [MS] Block until the screen has been quiet for MS
milliseconds (default 100).
--wait-until-text STR Block until STR appears in the rendered buffer.
--wait-until-regex RE Block until RE (POSIX extended) matches.
--wait-until-exit Block until the child process exits.
--timeout DUR Cap on any --wait-until-* (default 30s; 0 = none).
--ansi With --snapshot, print styled ANSI rendering.
`--detach` is accepted as a no-op — every `hty run` session is
detached by default. Use `hty attach` afterwards, or `--attach`
on this invocation, for an interactive view.
Example:
hty run --name debug-vim -- vim /tmp/foo.txt
hty run --name app --snapshot --wait-until-idle -- create-next-app my-app
hty run --attach --remove -- bash -c 'echo hi'
Examples
# Simple session
hty run -- vim /tmp/notes.txt
# Named session with custom terminal size
hty run --name my-vim --rows 40 --cols 120 -- vim /tmp/notes.txt
# With working directory
hty run --name build --cwd /my/project -- npm testFused run + wait + snapshot
For agent workflows that want “start the program, wait until it’s ready, give me the first screen” in a single call, combine --snapshot with a --wait-* flag:
# Launch create-next-app, wait for it to settle, and return the first prompt
hty run --name app --snapshot --wait-until-idle -- \
npx create-next-app my-app
# Launch a script and wait for a specific line before reading
hty run --name install --snapshot --wait-until-text "Finished" --timeout 60000 -- \
./install.sh
# Launch a quick command and wait for it to exit
hty run --snapshot --wait-until-exit -- echo hello| Flag | Effect |
|---|---|
--snapshot | Include the post-spawn screen in the response. Requires one of the --wait-* flags below. |
--wait-duration DUR | Sleep DUR after spawn, then snapshot. |
--wait-until-idle [MS] | Wait until the screen has been quiet for MS ms (default 100). |
--wait-until-text STR | Wait until STR appears in the rendered buffer. |
--wait-until-regex RE | Wait until RE (POSIX extended) matches. |
--wait-until-exit | Wait until the child exits. |
--timeout DUR | Cap on any --wait-until-* (default 30s; 0 = no cap). |
--ansi | With --snapshot, return the styled ANSI rendering instead of plain text. |
The -- separator is required when passing arguments to the program. Without it, hty cannot distinguish its own flags from the program’s arguments.
--detach is accepted as a no-op — every hty run session is detached by default. The old -d short form was removed; use the long --detach, or pass --attach to spawn and attach in one go.
Foreground with --attach
--attach spawns the session and immediately attaches to it, just like hty attach would — your terminal goes into raw mode, stdin is forwarded into the PTY, output streams back to stdout, and Ctrl-A d detaches. On clean exit, the child’s exit status becomes the hty run exit status.
# One-shot: edit a file interactively. Ctrl-A d detaches, session persists.
hty run --attach -- vim /tmp/notes.txt
# One-shot with auto-cleanup: run, print output, remove the session when done.
hty run --attach --remove -- bash -c 'echo hello'
# Handy for agents with background-process support (Claude Code, etc.):
# background the invocation and read the harness's streaming stdout — no
# polling, no `hty snapshot` loop, and `--remove` ties the session's
# lifetime to the backgrounded shell.
hty run --attach --remove -- npm test &--attach is mutually exclusive with --snapshot and every --wait-until-* flag (including --wait-duration) — the fused wait/snapshot path and the interactive attach loop have no meaningful combination. Pass one or the other.
See hty attach for the detach keybinds and multi-client behavior. All of that applies to run --attach too.
Auto-cleanup with --remove
By default, an exited hty run session lingers in the registry as a “zombie” record so hty list, hty logs, and hty replay keep working on it until you run hty delete. That’s the right behavior for sessions you want to inspect after the fact — but it’s a leak for one-shot invocations (migrations, test scripts, throwaway agent calls) where you will never look at the record again.
Pass --remove to tie the session’s lifetime to the child process. The moment the child exits — whether it succeeded, failed, was signalled, or was terminated by hty kill — the session is automatically deleted from the registry and its log file is removed from disk. No zombies, no follow-up hty delete.
# One-shot migration: session disappears from `hty list` as soon as the script ends.
hty run --remove -- ./migrate.sh
# Combine with --wait-until-exit to block until the child exits; on return the
# session is already gone. Exit code propagates from the child.
hty run --remove --wait-until-exit -- sh -c 'exit 7'
echo $? # 7
# While the child is still running, `hty list` shows the session normally —
# auto-removal only fires after the child exits.
hty run --remove --name long -- sleep 60
hty list # shows "long" while sleep is running
# …sleep exits after 60s, then a subsequent `hty list` is empty.Running hty kill on a --remove session still works as expected: the session terminates, the auto-remove sweep reaps the record shortly after, and the two paths don’t race.
--remove is especially useful in AI agent workflows. Agents routinely forget to hty kill sessions once they’ve finished reading the last screen; over time the registry fills with stale entries. Adding --remove to every hty run the agent issues makes the leak structurally impossible.