Targeting
Action commands (read, send, kill) take a surface handle — there is deliberately no dor kill "npm dev". You name the surface you want one of three ways:
Hold the handle. Commands that create surfaces (
split,ensure,iframe) print the new ref (created surface:3). Capture it and act on it directly — refs stay valid across any layout churn.Address by identity key. Surfaces with a natural identity skip handle bookkeeping:
dor ensure --uses its exact command + cwd as an implicit key (match-or-create in one idempotent call), and browser surfaces are addressed by an explicit key (<command> dor ab --). A browser you did not create has no key you know — hold its ref and usekey <name> dor ab --.surface <ref> Rediscover. When you hold nothing — a fresh session, or a process the user started by hand —
dor list(filtered) turns a description (--,command --,cwd --) into a handle.port
Text output is designed for you to read: it is terse and carries the same refs. Reach for -- (every command except dor ab supports it) only when a shell script or pipeline using jq consumes the output.
Surface handles
surface:N— short ref, e.g.surface:3. Stable for the surface's whole life: reordering, minimizing, zooming, and focus changes never change it, and numbers are never reused after a kill. A ref for a killed surface fails loudly instead of silently retargeting, so refs from earlier in your session stay safe to use.A stable surface id (or
surface:<stable-) — fromid> --output.json surface:self— the terminal you are running in.surface:focused— whatever the user currently has focused.title:<exact title>— exists for human recovery; avoid it in automation (titles drift). Prefer refs from command responses ordor list.
Bare numbers and pane:N are not valid handles.
dor
dor --help
dor split [--left|--right|--up|--down|--auto] [--json] [--minimize] [--surface id|ref] [-- <command>...]
dor ensure [--json] [--minimize] [--restart] [--surface id|ref] [--cwd path] -- <command>...
dor version [--json]
dor skill [--install] [--json]
dor send <surface> ([--text value] [--key value] | --stdin | --sequence json) [--json] [--raw]
dor read <surface> [--json] [--lines count] [--scrollback]
dor await <surface> --until condition [--json] [--timeout seconds]
dor kill <surface> [--confirm-if-read text|--confirm-dangerously] [--json]
dor iframe [--json] [--minimize] [--surface id|ref] <target>
dor agent-browser [--key name|--session name|--surface handle] [args...]
dor list [--command text] [--cwd path] [--id-format refs|ids|both] [--json] [--kind terminal|browser] [--port number] [--ports] [--view paned|zoomed|minimized]
dor --helpDormouse bundles the dor CLI into every terminal it launches.
FLAGS
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
COMMANDS
| split | Create a new terminal surface by splitting an existing surface. |
| ensure | Ensure one surface is running a command. |
| version | Print the dor CLI version. |
| skill | Print the Dormouse agent skill, or install its bootstrap stub. |
| send | Send text or key input to a terminal surface. |
| read | Read terminal text from a surface. |
| await | Wait until a terminal surface finishes. |
| kill | Kill a surface. |
| iframe | Open a target in an iframe surface. |
| agent-browser | Drive a browser surface via your agent-browser install (alias: dor ab). |
| list | List Dormouse Surfaces. |
Exact dor --help output
USAGE
dor split [--left|--right|--up|--down|--auto] [--json] [--minimize] [--surface id|ref] [-- <command>...]
dor ensure [--json] [--minimize] [--restart] [--surface id|ref] [--cwd path] -- <command>...
dor version [--json]
dor skill [--install] [--json]
dor send <surface> ([--text value] [--key value] | --stdin | --sequence json) [--json] [--raw]
dor read <surface> [--json] [--lines count] [--scrollback]
dor await <surface> --until condition [--json] [--timeout seconds]
dor kill <surface> [--confirm-if-read text|--confirm-dangerously] [--json]
dor iframe [--json] [--minimize] [--surface id|ref] <target>
dor agent-browser [--key name|--session name|--surface handle] [args...]
dor list [--command text] [--cwd path] [--id-format refs|ids|both] [--json] [--kind terminal|browser] [--port number] [--ports] [--view paned|zoomed|minimized]
dor --help
Dormouse bundles the dor CLI into every terminal it launches.
FLAGS
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
COMMANDS
split Create a new terminal surface by splitting an existing surface.
ensure Ensure one surface is running a command.
version Print the dor CLI version.
skill Print the Dormouse agent skill, or install its bootstrap stub.
send Send text or key input to a terminal surface.
read Read terminal text from a surface.
await Wait until a terminal surface finishes.
kill Kill a surface.
iframe Open a target in an iframe surface.
agent-browser Drive a browser surface via your agent-browser install (alias: dor ab).
list List Dormouse Surfaces.
Commands
dor split
dor split --help
dor split [--left|--right|--up|--down|--auto] [--json] [--minimize] [--surface id|ref] [-- <command>...]
dor split --helpIf no direction is provided, --auto is used. --auto chooses right when the target surface is wide, down when it is narrow, and right when the target is minimized.
Use -- followed by a command to run an initial command in the new terminal surface.
Focus depends only on whether you pass --. A bare "dor split" (no --) moves focus to the new surface so a human can start typing in it — avoid it in automation, since it steals the user's keystrokes. Anything with -- leaves focus on the caller: "dor split -- <command>" runs the command in the background, and a bare "dor split --" opens a blank terminal without stealing focus.
--minimize creates the surface and immediately sends it to the minimized area.
--surface selects the surface to split. If the target is minimized, the new surface is created minimized too and inserted immediately to the right of the target door. If omitted, Dormouse uses the caller surface when available, then the focused surface.
split creates terminal Surfaces. Compose browser content commands through the initial command:
dor split --right -- dor iframe https://example.com dor split --auto -- dor agent-browser open https://example.com
FLAGS
| [--left|--right|--up|--down|--auto] | Split direction. Mutually exclusive; default is --auto. |
| [--json] | Print JSON output. |
| [--minimize] | Create the surface minimized. |
| [--surface] | Surface to split. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
Text output:
created surface:2 [right]
created surface:3 [down] [minimized] "pnpm dev"JSON output:
{
"status": "created",
"surface_id": "pane-abc",
"surface_ref": "surface:2",
"direction": "right",
"minimized": false,
"command": "pnpm dev"
}Exact dor split --help output
USAGE
dor split [--left|--right|--up|--down|--auto] [--json] [--minimize] [--surface id|ref] [-- <command>...]
dor split --help
If no direction is provided, --auto is used. --auto chooses right when the target surface is wide, down when it is narrow, and right when the target is minimized.
Use -- followed by a command to run an initial command in the new terminal surface.
Focus depends only on whether you pass --. A bare "dor split" (no --) moves focus to the new surface so a human can start typing in it — avoid it in automation, since it steals the user's keystrokes. Anything with -- leaves focus on the caller: "dor split -- <command>" runs the command in the background, and a bare "dor split --" opens a blank terminal without stealing focus.
--minimize creates the surface and immediately sends it to the minimized area.
--surface selects the surface to split. If the target is minimized, the new surface is created minimized too and inserted immediately to the right of the target door. If omitted, Dormouse uses the caller surface when available, then the focused surface.
split creates terminal Surfaces. Compose browser content commands through the initial command:
dor split --right -- dor iframe https://example.com
dor split --auto -- dor agent-browser open https://example.com
Text output:
created surface:2 [right]
created surface:3 [down] [minimized] "pnpm dev"
JSON output:
{
"status": "created",
"surface_id": "pane-abc",
"surface_ref": "surface:2",
"direction": "right",
"minimized": false,
"command": "pnpm dev"
}
FLAGS
[--left|--right|--up|--down|--auto]
Split direction. Mutually exclusive; default is --auto.
[--json] Print JSON output.
[--minimize] Create the surface minimized.
[--surface] Surface to split.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
dor ensure
dor ensure --help
dor ensure [--json] [--minimize] [--restart] [--surface id|ref] [--cwd path] -- <command>...
dor ensure --helpEnsures one surface in the current workspace is running the given command at the given path. If it's already running, no-op. If it isn't, then it creates a split and runs the command.
ensure never changes focus. Whether it reuses a match, restarts one, or creates a new split, the surface you ran it from keeps focus — a newly created surface (visible or minimized) starts in the background.
Matching uses the command each shell reports it is running via Dormouse shell integration (OSC 633), not process inspection. This captures the typed command (`npm run dev`), not the forked child process (`node .../vite`), and works for shells the user started by hand as well as shells Dormouse started. The match is exact: `npm run dev` and `npm run dev --host` are different commands and get separate surfaces.
ensure requires that integration: a surface can only be matched, reused, or restarted if its shell reports its command. So if the shell has no OSC 633 integration (e.g. cmd.exe), ensure fails with an error rather than starting an untrackable surface — run it from a shell with integration, such as Git Bash or PowerShell.
A surface matches only while the command is live. Once the command exits and the shell returns to its prompt, the surface no longer matches; the next ensure causes a fresh split rather than reusing the idle shell. Minimized surfaces participate in matching. Closed/killed surfaces do not.
Two surfaces running the same command in different working directories are distinct (e.g. the same dev server in two worktrees). Both keep running; ensure never collapses them.
--cwd sets the working directory used both for matching and for the new command. If omitted, Dormouse uses the directory dor was invoked from. The path is resolved to an absolute path and matched exactly; symlinks are not resolved, so two routes to the same directory are treated as distinct.
--minimize applies only when creating a new surface; it does not minimize an existing match.
--restart applies only to an already-running match: it interrupts the live command (Ctrl+C), waits for the shell to return to its prompt, then re-runs the command in place and blocks until the command is live again. A restarted surface keeps its minimized/visible state. If no surface is running the command, --restart behaves like a plain ensure and creates one.
--surface selects the surface to split only when creating a new surface. If the target is minimized, the new surface is created minimized too and inserted immediately to the right of the target door. If omitted, Dormouse uses the same caller/focused fallback as dor split.
FLAGS
| [--json] | Print JSON output. |
| [--minimize] | Create the surface minimized. |
| [--restart] | Restart a matching surface in place. |
| [--surface] | Surface to split when creating. |
| [--cwd] | Working directory for matching and for the new command. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
Text output:
created surface:3 "npm run dev"
existing surface:3 "npm run dev"
restarted surface:3 "npm run dev"JSON output:
{
"status": "created",
"surface_id": "pane-def",
"surface_ref": "surface:3",
"command": "npm run dev",
"cwd": "/Users/me/projects/site",
"minimized": false
}Exact dor ensure --help output
USAGE
dor ensure [--json] [--minimize] [--restart] [--surface id|ref] [--cwd path] -- <command>...
dor ensure --help
Ensures one surface in the current workspace is running the given command at the given path. If it's already running, no-op. If it isn't, then it creates a split and runs the command.
ensure never changes focus. Whether it reuses a match, restarts one, or creates a new split, the surface you ran it from keeps focus — a newly created surface (visible or minimized) starts in the background.
Matching uses the command each shell reports it is running via Dormouse shell integration (OSC 633), not process inspection. This captures the typed command (`npm run dev`), not the forked child process (`node .../vite`), and works for shells the user started by hand as well as shells Dormouse started. The match is exact: `npm run dev` and `npm run dev --host` are different commands and get separate surfaces.
ensure requires that integration: a surface can only be matched, reused, or restarted if its shell reports its command. So if the shell has no OSC 633 integration (e.g. cmd.exe), ensure fails with an error rather than starting an untrackable surface — run it from a shell with integration, such as Git Bash or PowerShell.
A surface matches only while the command is live. Once the command exits and the shell returns to its prompt, the surface no longer matches; the next ensure causes a fresh split rather than reusing the idle shell. Minimized surfaces participate in matching. Closed/killed surfaces do not.
Two surfaces running the same command in different working directories are distinct (e.g. the same dev server in two worktrees). Both keep running; ensure never collapses them.
--cwd sets the working directory used both for matching and for the new command. If omitted, Dormouse uses the directory dor was invoked from. The path is resolved to an absolute path and matched exactly; symlinks are not resolved, so two routes to the same directory are treated as distinct.
--minimize applies only when creating a new surface; it does not minimize an existing match.
--restart applies only to an already-running match: it interrupts the live command (Ctrl+C), waits for the shell to return to its prompt, then re-runs the command in place and blocks until the command is live again. A restarted surface keeps its minimized/visible state. If no surface is running the command, --restart behaves like a plain ensure and creates one.
--surface selects the surface to split only when creating a new surface. If the target is minimized, the new surface is created minimized too and inserted immediately to the right of the target door. If omitted, Dormouse uses the same caller/focused fallback as dor split.
Text output:
created surface:3 "npm run dev"
existing surface:3 "npm run dev"
restarted surface:3 "npm run dev"
JSON output:
{
"status": "created",
"surface_id": "pane-def",
"surface_ref": "surface:3",
"command": "npm run dev",
"cwd": "/Users/me/projects/site",
"minimized": false
}
FLAGS
[--json] Print JSON output.
[--minimize] Create the surface minimized.
[--restart] Restart a matching surface in place.
[--surface] Surface to split when creating.
[--cwd] Working directory for matching and for the new command.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
dor version
dor version --help
dor version [--json]
dor version --helpPrints the latest released Dormouse version from CHANGELOG.md, the build commit, and a prerelease-style build suffix when the build contains commits after that version tag.
FLAGS
| [--json] | Print JSON output. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
Text output:
dor 0.11.0 [1a2b3c4d] (0.11.0+12)JSON output:
{
"version": "0.11.0",
"commit": "1a2b3c4d",
"commits_since_version": 12,
"build": "0.11.0+12"
}Exact dor version --help output
USAGE
dor version [--json]
dor version --help
Prints the latest released Dormouse version from CHANGELOG.md, the build commit, and a prerelease-style build suffix when the build contains commits after that version tag.
Text output:
dor 0.11.0 [1a2b3c4d] (0.11.0+12)
JSON output:
{
"version": "0.11.0",
"commit": "1a2b3c4d",
"commits_since_version": 12,
"build": "0.11.0+12"
}
FLAGS
[--json] Print JSON output.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
dor skill
dor skill --help
dor skill [--install] [--json]
dor skill --helpPrints the Dormouse agent skill — instructions that teach a coding agent to drive Dormouse through the dor CLI: run background processes in visible panes, open browser surfaces, and launch and coordinate sub-agents. The text ships inside the CLI, so it always matches the Dormouse that staged it.
--install instead writes a marker-delimited bootstrap stub into the project's agent instructions file. The stub is the detection rule — if DORMOUSE_SURFACE_ID is set, run `dor skill` and follow it — plus two loud, mandatory directives (use `dor ensure` for long-running processes, `dor ab` for browsers) that must land before an agent would think to run `dor skill`. It stays otherwise fact-free, so a committed stub does not go stale.
If AGENTS.md or CLAUDE.md already contains the block, it is rewritten in place. Otherwise the stub goes to AGENTS.md when it exists, else to CLAUDE.md when it exists and does not already import AGENTS.md (via `@AGENTS.md`), else to a newly created AGENTS.md. Everything outside the markers is left untouched, so re-running is idempotent.
FLAGS
| [--install] | Install the bootstrap stub into the project's agent instructions file. |
| [--json] | Print JSON output. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
Text output:
created AGENTS.md
updated CLAUDE.mdJSON output:
{
"status": "created",
"file": "AGENTS.md"
}Exact dor skill --help output
USAGE
dor skill [--install] [--json]
dor skill --help
Prints the Dormouse agent skill — instructions that teach a coding agent to drive Dormouse through the dor CLI: run background processes in visible panes, open browser surfaces, and launch and coordinate sub-agents. The text ships inside the CLI, so it always matches the Dormouse that staged it.
--install instead writes a marker-delimited bootstrap stub into the project's agent instructions file. The stub is the detection rule — if DORMOUSE_SURFACE_ID is set, run `dor skill` and follow it — plus two loud, mandatory directives (use `dor ensure` for long-running processes, `dor ab` for browsers) that must land before an agent would think to run `dor skill`. It stays otherwise fact-free, so a committed stub does not go stale.
If AGENTS.md or CLAUDE.md already contains the block, it is rewritten in place. Otherwise the stub goes to AGENTS.md when it exists, else to CLAUDE.md when it exists and does not already import AGENTS.md (via `@AGENTS.md`), else to a newly created AGENTS.md. Everything outside the markers is left untouched, so re-running is idempotent.
Text output:
created AGENTS.md
updated CLAUDE.md
JSON output:
{
"status": "created",
"file": "AGENTS.md"
}
FLAGS
[--install] Install the bootstrap stub into the project's agent instructions file.
[--json] Print JSON output.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
dor send
dor send --help
dor send <surface> ([--text value] [--key value] | --stdin | --sequence json) [--json] [--raw]
dor send --helpSends text or key input to a target terminal surface. Special keys must be sent with --key so values like "enter" are never confused with literal text.
Exactly one input mode is required: --text/--key, --stdin, or --sequence. --text and --key may be combined only in that order; text is sent first, then the key. Duplicate input flags are rejected. Use --sequence for arbitrary ordering or multiple text/key events.
Text input interprets backslash escapes for \n, \r, \t, and \\ unless --raw is set.
Supported keys: enter, escape, esc, tab, backspace, delete, up, down, left, right, ctrl-a through ctrl-z.
Sequence input is an ordered JSON array of {"text":"..."} and {"key":"..."} objects.
FLAGS
| [--json] | Print JSON output. |
| [--key] | Send a named key or chord. |
| [--raw] | Do not interpret backslash escapes in text input. |
| [--sequence] | Send an ordered JSON sequence of text and key events. |
| [--stdin] | Read text from standard input and send it as text. |
| [--text] | Send literal text. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
ARGUMENTS
| surface | Target surface. |
Examples:
dor send surface:3 --text "echo hello"
dor send surface:3 --text "npm test" --key enter
dor send surface:3 --key ctrl-c
cat script.sh | dor send surface:3 --stdin
dor send surface:3 --sequence '[{"text":"npm test"},{"key":"enter"}]'JSON output:
{
"status": "sent",
"surface_id": "...",
"surface_ref": "surface:3",
"input_count": 1
}Exact dor send --help output
USAGE
dor send <surface> ([--text value] [--key value] | --stdin | --sequence json) [--json] [--raw]
dor send --help
Sends text or key input to a target terminal surface. Special keys must be sent with --key so values like "enter" are never confused with literal text.
Exactly one input mode is required: --text/--key, --stdin, or --sequence. --text and --key may be combined only in that order; text is sent first, then the key. Duplicate input flags are rejected. Use --sequence for arbitrary ordering or multiple text/key events.
Text input interprets backslash escapes for \n, \r, \t, and \\ unless --raw is set.
Supported keys: enter, escape, esc, tab, backspace, delete, up, down, left, right, ctrl-a through ctrl-z.
Sequence input is an ordered JSON array of {"text":"..."} and {"key":"..."} objects.
JSON output:
{
"status": "sent",
"surface_id": "...",
"surface_ref": "surface:3",
"input_count": 1
}
Examples:
dor send surface:3 --text "echo hello"
dor send surface:3 --text "npm test" --key enter
dor send surface:3 --key ctrl-c
cat script.sh | dor send surface:3 --stdin
dor send surface:3 --sequence '[{"text":"npm test"},{"key":"enter"}]'
FLAGS
[--json] Print JSON output.
[--key] Send a named key or chord.
[--raw] Do not interpret backslash escapes in text input.
[--sequence] Send an ordered JSON sequence of text and key events.
[--stdin] Read text from standard input and send it as text.
[--text] Send literal text.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
ARGUMENTS
surface Target surface.
dor read
dor read --help
dor read <surface> [--json] [--lines count] [--scrollback]
dor read --helpReads the visible screen text from the target terminal surface. Use --scrollback to include terminal history, and --lines to limit how much text is returned.
Text mode prints terminal text directly.
FLAGS
| [--json] | Print JSON output. |
| [--lines] | Maximum number of lines to return. |
| [--scrollback] | Include terminal scrollback/history instead of only the visible screen. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
ARGUMENTS
| surface | Surface to read. |
JSON output:
{
"workspace_ref": "workspace:1",
"surface_id": "...",
"surface_ref": "surface:3",
"text": "..."
}Exact dor read --help output
USAGE
dor read <surface> [--json] [--lines count] [--scrollback]
dor read --help
Reads the visible screen text from the target terminal surface. Use --scrollback to include terminal history, and --lines to limit how much text is returned.
Text mode prints terminal text directly.
JSON output:
{
"workspace_ref": "workspace:1",
"surface_id": "...",
"surface_ref": "surface:3",
"text": "..."
}
FLAGS
[--json] Print JSON output.
[--lines] Maximum number of lines to return.
[--scrollback] Include terminal scrollback/history instead of only the visible screen.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
ARGUMENTS
surface Surface to read.
dor await
dor await --help
dor await <surface> --until condition [--json] [--timeout seconds]
dor await --helpWaits until a terminal surface finishes what it is doing, then reports why the wait ended. Lets an agent block on a peer it launched with `dor split` instead of polling `dor list` in a loop.
Prints no terminal text. Follow with `dor read` to see the screen.
--until says what counts as finished: quiet The surface settled, the running command exited, or the surface rang the bell. Use for agents that keep running, such as claude or codex. exit The running command exited, and nothing else. Use for builds and test runs, which can fall silent mid-run without being finished.
Waiting absorbs the alert. A surface that finishes while awaited does not ring the bell, speak an alarm, or notify a paired phone, and is not marked TODO — the wait already delivered the news.
Text mode prints the cause alone on stdout: quiet, exit, bell, or idle. An idle result means nothing was running and nothing started, so there was never anything to wait for.
A one-line summary naming the cause and how long the wait took goes to stderr, so it stays out of the captured value: `quiet: output stopped after 10m 15s`. The duration is how long this command blocked, not how long the surface had been working.
--timeout accepts whole seconds up to 86400 (24h). The default is 600.
Exits 0 on any resolution, 2 on timeout, and 3 if the surface died before finishing. The JSON above is printed only on a resolution; a timeout or a death reports itself through the exit code and the stderr line, with nothing on stdout.
FLAGS
| [--json] | Print JSON output. |
| [--timeout] | Seconds to wait before giving up. Default 600; max 86400. |
| --until | What to wait for: quiet or exit. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
ARGUMENTS
| surface | Surface to wait on. |
Examples:
dor await surface:3 --until quiet
dor await surface:3 --until quiet && dor read surface:3
dor await surface:3 --until exit --timeout 1800
CAUSE=$(dor await surface:3 --until quiet)JSON output:
{
"workspace_ref": "workspace:1",
"surface_id": "...",
"surface_ref": "surface:3",
"cause": "quiet",
"waited_ms": 615000,
"detail": "output stopped after 10m 15s"
}Exact dor await --help output
USAGE
dor await <surface> --until condition [--json] [--timeout seconds]
dor await --help
Waits until a terminal surface finishes what it is doing, then reports why the wait ended. Lets an agent block on a peer it launched with `dor split` instead of polling `dor list` in a loop.
Prints no terminal text. Follow with `dor read` to see the screen.
--until says what counts as finished:
quiet The surface settled, the running command exited, or the surface rang the bell. Use for agents that keep running, such as claude or codex.
exit The running command exited, and nothing else. Use for builds and test runs, which can fall silent mid-run without being finished.
Waiting absorbs the alert. A surface that finishes while awaited does not ring the bell, speak an alarm, or notify a paired phone, and is not marked TODO — the wait already delivered the news.
Text mode prints the cause alone on stdout: quiet, exit, bell, or idle. An idle result means nothing was running and nothing started, so there was never anything to wait for.
A one-line summary naming the cause and how long the wait took goes to stderr, so it stays out of the captured value: `quiet: output stopped after 10m 15s`. The duration is how long this command blocked, not how long the surface had been working.
--timeout accepts whole seconds up to 86400 (24h). The default is 600.
JSON output:
{
"workspace_ref": "workspace:1",
"surface_id": "...",
"surface_ref": "surface:3",
"cause": "quiet",
"waited_ms": 615000,
"detail": "output stopped after 10m 15s"
}
Exits 0 on any resolution, 2 on timeout, and 3 if the surface died before finishing. The JSON above is printed only on a resolution; a timeout or a death reports itself through the exit code and the stderr line, with nothing on stdout.
Examples:
dor await surface:3 --until quiet
dor await surface:3 --until quiet && dor read surface:3
dor await surface:3 --until exit --timeout 1800
CAUSE=$(dor await surface:3 --until quiet)
FLAGS
[--json] Print JSON output.
[--timeout] Seconds to wait before giving up. Default 600; max 86400.
--until What to wait for: quiet or exit.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
ARGUMENTS
surface Surface to wait on.
dor kill
dor kill --help
dor kill <surface> [--confirm-if-read text|--confirm-dangerously] [--json]
dor kill --helpKills a surface. One confirmation mode is required.
--confirm-if-read kills only if dor read <surface> would return visible text containing the provided text. The text must contain at least 4 non-whitespace characters.
--confirm-dangerously kills without further confirmation. Use only when automation has already validated the target.
FLAGS
| [--confirm-dangerously] | Kill without further confirmation. |
| [--confirm-if-read] | Kill only if dor read contains this text. |
| [--json] | Print JSON output. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
ARGUMENTS
| surface | Surface to kill. |
Text output:
killed surface:3JSON output:
{
"status": "killed",
"surface_id": "...",
"surface_ref": "surface:3"
}Exact dor kill --help output
USAGE
dor kill <surface> [--confirm-if-read text|--confirm-dangerously] [--json]
dor kill --help
Kills a surface. One confirmation mode is required.
--confirm-if-read kills only if dor read <surface> would return visible text containing the provided text. The text must contain at least 4 non-whitespace characters.
--confirm-dangerously kills without further confirmation. Use only when automation has already validated the target.
Text output:
killed surface:3
JSON output:
{
"status": "killed",
"surface_id": "...",
"surface_ref": "surface:3"
}
FLAGS
[--confirm-dangerously] Kill without further confirmation.
[--confirm-if-read] Kill only if dor read contains this text.
[--json] Print JSON output.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
ARGUMENTS
surface Surface to kill.
dor iframe
dor iframe --help
dor iframe [--json] [--minimize] [--surface id|ref] <target>
dor iframe --helpOpens a target in a high-fidelity iframe surface for human inspection.
If the caller surface is an untouched terminal, Dormouse replaces that terminal with the iframe. Otherwise Dormouse creates a split next to the caller/focused surface.
The target is one of: <url> An absolute http:// or https:// URL (an explicit scheme is always honored). host:port A schemeless host:port, defaulted to http:// (e.g. localhost:5173, box.ts.net:3000). The explicit port marks a dev/infra server, which is http far more often than not. :<port> Sugar for http://localhost:<port> (e.g. :5173). surface:<ref> A terminal Surface handle (surface:N, surface:self, surface:focused, or a stable id). Dormouse scans that terminal's listening ports and opens http://localhost:<port>/; it fails if the terminal owns zero or multiple ports.
FLAGS
| [--json] | Print JSON output. |
| [--minimize] | Create or replace the surface minimized. |
| [--surface] | Surface to replace or split from. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
ARGUMENTS
| target | URL, host:port, :port, or surface handle to open. |
Text output:
created surface:3 "http://localhost:5173"
replaced surface:1 "http://localhost:5173"JSON output:
{
"status": "created",
"surface_id": "pane-abc",
"surface_ref": "surface:3",
"url": "http://localhost:5173",
"minimized": false
}Exact dor iframe --help output
USAGE
dor iframe [--json] [--minimize] [--surface id|ref] <target>
dor iframe --help
Opens a target in a high-fidelity iframe surface for human inspection.
If the caller surface is an untouched terminal, Dormouse replaces that terminal with the iframe. Otherwise Dormouse creates a split next to the caller/focused surface.
The target is one of:
<url> An absolute http:// or https:// URL (an explicit scheme is
always honored).
host:port A schemeless host:port, defaulted to http:// (e.g.
localhost:5173, box.ts.net:3000). The explicit port marks a
dev/infra server, which is http far more often than not.
:<port> Sugar for http://localhost:<port> (e.g. :5173).
surface:<ref> A terminal Surface handle (surface:N, surface:self,
surface:focused, or a stable id). Dormouse scans that terminal's
listening ports and opens http://localhost:<port>/; it fails if
the terminal owns zero or multiple ports.
Text output:
created surface:3 "http://localhost:5173"
replaced surface:1 "http://localhost:5173"
JSON output:
{
"status": "created",
"surface_id": "pane-abc",
"surface_ref": "surface:3",
"url": "http://localhost:5173",
"minimized": false
}
FLAGS
[--json] Print JSON output.
[--minimize] Create or replace the surface minimized.
[--surface] Surface to replace or split from.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
ARGUMENTS
target URL, host:port, :port, or surface handle to open.
dor agent-browser
dor agent-browser --help
dor agent-browser [--key name|--session name|--surface handle] [args...]
dor agent-browser --helpForwards all arguments verbatim to your own agent-browser binary and binds the session to a Dormouse browser surface.
dor intercepts exactly three mutually exclusive identity flags: --key <name> Managed, workspace-scoped browser identity (default "default"). Maps to agent-browser session dormouse.1.<name>. --session <name> Attach to a raw agent-browser session by its literal name. --surface <handle> Drive the browser Surface a handle names (surface:N, surface:focused, a stable id, title:<title>). dor asks the host which agent-browser session that Surface is bound to, which is the only way to address a GUI-spawned session.
Everything else — subcommands, flags, selectors — is agent-browser's own command surface. The binary is resolved from PATH (override with DORMOUSE_AGENT_BROWSER_BIN) and is never bundled; install it with: npm i -g agent-browser
After a successful command, dor opens (or reuses) the browser surface bound to the session: one session is always exactly one surface.
In an "open" command, dor also resolves a Dormouse target in place of a URL: a schemeless host:port (and the ":<port>" localhost shorthand) defaults to http:// rather than agent-browser's https://, and a terminal Surface handle (surface:N, surface:self, surface:focused, or a stable id) resolves to the dev-server URL that terminal owns via the host port scan.
FLAGS
| [--key] | Workspace-scoped browser key (default "default"). |
| [--session] | Raw agent-browser session name (mutually exclusive with --key/--surface). |
| [--surface] | Surface handle whose bound session to drive (mutually exclusive with --key/--session). |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
ARGUMENTS
| args... | Arguments forwarded verbatim to agent-browser. |
Examples:
dor ab open http://localhost:5173 # key "default"
dor ab open localhost:5173 # → http://localhost:5173/
dor ab open :5173 # → http://localhost:5173/
dor ab open surface:3 # open the port terminal surface:3 owns
dor ab --key storybook open http://localhost:6006
dor ab click @e3 # drives key "default"
dor ab --key storybook reload # drives key "storybook"
dor ab --surface surface:4 click @e3 # drives whatever surface:4 is bound toExact dor agent-browser --help output
USAGE
dor agent-browser [--key name|--session name|--surface handle] [args...]
dor agent-browser --help
Forwards all arguments verbatim to your own agent-browser binary and binds the session to a Dormouse browser surface.
dor intercepts exactly three mutually exclusive identity flags:
--key <name> Managed, workspace-scoped browser identity (default "default").
Maps to agent-browser session dormouse.1.<name>.
--session <name> Attach to a raw agent-browser session by its literal name.
--surface <handle> Drive the browser Surface a handle names (surface:N,
surface:focused, a stable id, title:<title>). dor asks the
host which agent-browser session that Surface is bound to,
which is the only way to address a GUI-spawned session.
Everything else — subcommands, flags, selectors — is agent-browser's own
command surface. The binary is resolved from PATH (override with
DORMOUSE_AGENT_BROWSER_BIN) and is never bundled; install it with:
npm i -g agent-browser
After a successful command, dor opens (or reuses) the browser surface bound to
the session: one session is always exactly one surface.
In an "open" command, dor also resolves a Dormouse target in place of a URL:
a schemeless host:port (and the ":<port>" localhost shorthand) defaults to
http:// rather than agent-browser's https://, and a terminal Surface handle
(surface:N, surface:self, surface:focused, or a stable id) resolves to the
dev-server URL that terminal owns via the host port scan.
Examples:
dor ab open http://localhost:5173 # key "default"
dor ab open localhost:5173 # → http://localhost:5173/
dor ab open :5173 # → http://localhost:5173/
dor ab open surface:3 # open the port terminal surface:3 owns
dor ab --key storybook open http://localhost:6006
dor ab click @e3 # drives key "default"
dor ab --key storybook reload # drives key "storybook"
dor ab --surface surface:4 click @e3 # drives whatever surface:4 is bound to
FLAGS
[--key] Workspace-scoped browser key (default "default").
[--session] Raw agent-browser session name (mutually exclusive with --key/--surface).
[--surface] Surface handle whose bound session to drive (mutually exclusive with --key/--session).
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments
ARGUMENTS
args... Arguments forwarded verbatim to agent-browser.
dor list
dor list --help
dor list [--kind terminal|browser] [--view paned|zoomed|minimized] [--command text] [--cwd path] [--port number] [--ports] [--json] [--id-format refs|ids|both]
dor list --helpLists every Surface in the current Workspace — terminals and browser Surfaces, including minimized ones (view "minimized").
Text output prints one row per Surface: a * marks the focused Surface, then the handle, kind, render mode ("-" for terminals), view, location (cwd for terminals, URL for browser Surfaces), and title. Trailing tags: (you) for the calling terminal, [ringing], [todo], [awaited] while a dor await is parked on it, and listening ports with --ports.
--ports adds each terminal's listening TCP ports. The host shells out per pane (lsof / PowerShell), so it is opt-in; remote sessions report none.
--port <number> filters to terminal Surfaces listening on that port. It implies the same opt-in port scan as --ports, includes port details in JSON, and shows port tags in text output.
Filters are ANDed. --command is an exact match against the running command reported by shell integration. --cwd resolves to an absolute path like dor ensure --cwd, relative to the invoking shell's PWD when available.
JSON output (--json) always includes both stable ids and refs, and each row carries has_terminal (a PTY) and has_browser (a browser renderer) — gate on those, not on kind, so a Surface that has both still matches. It adds top-level caller_surface_ref/caller_surface_id and focused_surface_ref/focused_surface_id — the calling and focused Surfaces, null when neither is in the list — plus workspace_ref, window_ref, and a host block (app, workspace, cli_js_path, node_path): the identity dump dor identify used to print.
FLAGS
| [--command] | Exact running command to match. |
| [--cwd] | Working directory to match. |
| [--id-format] | Handle format for text output. |
| [--json] | Print JSON output. |
| [--kind] | Surface kind to show. |
| [--port] | Show terminal Surfaces listening on this TCP port. |
| [--ports] | Include each terminal's listening ports. |
| [--view] | Surface view to show. |
| -h --help | Print help information and exit |
| -- | All subsequent inputs should be interpreted as arguments |
Text output:
* surface:1 terminal - paned ~/projects/site pnpm dev :5173Exact dor list --help output
USAGE
dor list [--kind terminal|browser] [--view paned|zoomed|minimized] [--command text] [--cwd path] [--port number] [--ports] [--json] [--id-format refs|ids|both]
dor list --help
Lists every Surface in the current Workspace — terminals and browser Surfaces, including minimized ones (view "minimized").
Text output prints one row per Surface: a * marks the focused Surface, then the handle, kind, render mode ("-" for terminals), view, location (cwd for terminals, URL for browser Surfaces), and title. Trailing tags: (you) for the calling terminal, [ringing], [todo], [awaited] while a dor await is parked on it, and listening ports with --ports.
--ports adds each terminal's listening TCP ports. The host shells out per pane (lsof / PowerShell), so it is opt-in; remote sessions report none.
--port <number> filters to terminal Surfaces listening on that port. It implies the same opt-in port scan as --ports, includes port details in JSON, and shows port tags in text output.
Filters are ANDed. --command is an exact match against the running command reported by shell integration. --cwd resolves to an absolute path like dor ensure --cwd, relative to the invoking shell's PWD when available.
JSON output (--json) always includes both stable ids and refs, and each row carries has_terminal (a PTY) and has_browser (a browser renderer) — gate on those, not on kind, so a Surface that has both still matches. It adds top-level caller_surface_ref/caller_surface_id and focused_surface_ref/focused_surface_id — the calling and focused Surfaces, null when neither is in the list — plus workspace_ref, window_ref, and a host block (app, workspace, cli_js_path, node_path): the identity dump dor identify used to print.
Text output:
* surface:1 terminal - paned ~/projects/site pnpm dev :5173
FLAGS
[--command] Exact running command to match.
[--cwd] Working directory to match.
[--id-format] Handle format for text output.
[--json] Print JSON output.
[--kind] Surface kind to show.
[--port] Show terminal Surfaces listening on this TCP port.
[--ports] Include each terminal's listening ports.
[--view] Surface view to show.
-h --help Print help information and exit
-- All subsequent inputs should be interpreted as arguments