# Supervised processes and terminals
Ordinary command syntax is convenient for interactive work. `run_process`
provides structured control when a script must set a deadline, environment,
working directory, or stream files.
```shy
let $result = run_process ["/usr/bin/printf", "%s", "inspection"] [
"stdout_file": "inspection.txt", "timeout_ms": 1000]
let $text: String
"inspection.txt" -> $text
echo $result["exit_code"] $result["timed_out"] $text
```
```text
0 false inspection
```
The command is an array of arguments; it is not a shell command string.
Options include `cwd`, `env`, `stdin_file`, `stdout_file`, `stderr_file`, and
`timeout_ms`. Omitting `env` inherits exported variables. Supplying an `env` map replaces the
entire child environment; `[:]` clears it. Stream file paths are resolved relative
to the calling shell, independently of the child's `cwd`. The runner does not invoke a second shell for parsing.
The result hash separates `exit_code`, `signal`, `timed_out`, and launch `error`.
A deadline supervises the process group, terminates/escalates when needed, and
reaps the child. Inspect these fields rather than assuming every failure is a
nonzero normal exit.
```shy
let $result = run_process ["/usr/bin/printenv", "SHELLY_WIKI_ONLY"] [
"env": ["SHELLY_WIKI_ONLY": "limited"], "timeout_ms": 1000]
echo $result["exit_code"]
```
```text
limited
0
```
## Interactive child processes
`open_terminal arguments options` creates a child and returns a shared `Terminal`.
Its options are `cwd`, `env`, `rows`, and `columns`; default dimensions are 40 by
140. `terminal_write handle text` sends input. `terminal_read handle timeout_ms`
returns a hash with `text`, `eof`, `timed_out`, and process-result fields.
A read timeout leaves the child running and does not imply EOF. Reads can return
partial text; split UTF-8 sequences are retained until complete.
`terminal_close handle` stops and reaps the child group and returns its status.
Closing again returns the same status; reading or writing after close is an
error. Dropping the last handle also cleans up. Writes have a bounded deadline.
The native Terminal API owns a child pseudoterminal. It can send text and keys,
read output with a deadline, select its initial dimensions, and close
the child lifetime. This is how Shelly's own tests exercise a real REPL without
using another shell as a wrapper.
A pseudoterminal and redirected process files serve different purposes: programs
may change buffering, colors, and behavior when attached to a terminal. Use
ordinary commands unless a script actually needs supervision or terminal driving.
---
Related: [Commands](Commands-and-Exit-Status) · [Errors and cleanup](Errors-and-Cleanup) · [Line editing](Line-Editing)