dirijor is diri's command-line tool. It talks to the same background Engine as the app, so anything you script with it shows up in the window. Agents use it too: diri's hooks and MCP server run through it.
Where it lives
| Platform | Path |
|---|---|
| macOS | /Applications/diri.app/Contents/Resources/bin/dirijor |
| Linux | dirijor on your PATH, installed by the .deb package |
The Engine also keeps a copy in ~/Library/Application Support/Dirijor/bin/dirijor on macOS. Agents that diri starts get its path in $DIRIJOR_CLI, along with $DIRIJOR_SESSION_ID for their own session.
To use it from your own terminal on macOS, link it onto your PATH:
mkdir -p ~/.local/bin
ln -sf /Applications/diri.app/Contents/Resources/bin/dirijor ~/.local/bin/dirijorThe CLI finds the Engine through its socket. Set DIRIJOR_SOCKET to point at a different one.
Conventions
- Targets. Most commands take a target: a full session id, a unique id prefix, or a unique part of the session title (case-insensitive). Commands documented with
IDneed the id itself. Every terminal diri opens has its own id in$DIRIJOR_SESSION_ID. --json. Prints one line of JSON instead of a table.- Arguments are literal.
session runpasses everything after--as separate arguments. Nothing is run through a shell.
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Failure, including bad arguments |
2 | Timed out |
3 | Session not found |
4 | Engine unreachable |
5 | Ambiguous target: the id prefix or title matches more than one session |
6 | Refused: an agent tried to stop or remove a session outside its reach (see Stopping sessions from an agent) |
run --wait is the exception: it exits with the command's own status (128 + N when signal N ended it), 124 when --timeout passes, and 125 when dirijor itself fails.
Overview
| Command | What it does |
|---|---|
dirijor list, new, send, capture, run | Short scripting verbs. See Scripting. |
dirijor send-key, wait, kill, split, focus, zoom, move, swap, resize | Press keys, wait, stop, and arrange panes by session. See Session verbs. |
dirijor whoami, version | Your own session, tab and pane; the CLI and Engine versions. |
dirijor completion fish|zsh|bash | Print a shell completion script. See Shell completion. |
dirijor status [--json] | List every session, archived ones included. |
dirijor activity [--limit N] [--json] | Recent activity. N is 1 to 300, default 50. |
dirijor session ... | List, read, drive, start and stop sessions. |
dirijor worktree ... | List, create and remove git worktrees. |
dirijor workspace, tab, pane | Change the window layout. |
dirijor artifacts SESSION [--json] | Links, pull requests and listening ports found for a session. |
dirijor ports [--json] | Listening ports across all sessions. |
dirijor events ... | Stream or wait for Engine events. |
dirijor note ... | Write and edit notes. notes works too. |
dirijor notify ... | Post a notification from a terminal. |
dirijor doctor | Check the Engine, agents and state file. |
dirijor mcp-tools | Print the MCP tool definitions as JSON. |
dirijor mcp-call --tool NAME | Call one MCP tool with JSON from stdin. |
dirijor help [COMMAND] | Print usage. dirijor COMMAND --help works too. |
dirijor hook, dirijor notify JSON and dirijor mcp-stdio are called by agents that diri launches. You do not need to run them.
Cheat sheet
Every command people type, with its options. dirijor help COMMAND prints the same thing for one command.
<!-- generated by dirijor help --markdown: start -->
| Command | Options | What it does |
|---|---|---|
list | --all, --json | List sessions (alias ls) |
status | --json | List every session, archived ones included |
new | --kind KIND, -c, --cwd PATH, --label TEXT, --prompt TEXT, --host ID, --json | Open a shell (or --kind agent) tab and print its id |
run -- PROGRAM [ARG...] | --wait, --timeout DURATION, --rm, -c, --cwd PATH, --label TEXT, --host ID, --keep-open, --split EDGE, --beside TARGET, --ratio PERCENT, --focus[=BOOL], --json | Run a command in a new tab, or a split with --split |
split [TARGET] [-- PROGRAM [ARG...]] | --edge EDGE, --ratio PERCENT, -c, --cwd PATH, --label TEXT, --keep-open, --focus[=BOOL], --json | Open a shell or command beside a session's pane |
send TARGET [--] TOKEN... | -l, --literal, --json | Type text and tmux-style keys (Enter, C-c) |
send-key TARGET KEY... | --repeat N, --json | Press keys: enter, ctrl+c, shift+tab, alt+left, f5 |
capture TARGET | --lines N, --scrollback, --json | Print the screen or scrollback as text |
wait TARGET | --for DURATION, --until STATUS, --json | Wait until a session exits (or reaches --until) |
kill TARGET | --keep, --json | Stop a session and close it |
focus TARGET | --json | Show a session in the app and focus its pane |
zoom TARGET | --on, --off, --json | Zoom a session's pane; toggles without --on/--off |
move TARGET EDGE ANCHOR | --ratio PERCENT, --json | Move a session's pane beside another session's |
swap TARGET OTHER | --json | Swap two sessions' panes |
resize TARGET | --ratio PERCENT, --json | Set a pane's share of its split |
whoami | --json | This terminal's session, tab and pane |
version | --json | CLI and Engine versions |
completion SHELL | Print a fish, zsh or bash completion script | |
activity | --limit N, --json | Recent activity |
session list | --all, --status PREFIX, --json | List sessions (alias ls) |
session get TARGET | --json | Show a session |
session inspect TARGET | --json | A session with its tabs, panes and process (JSON) |
session rename TARGET TITLE | --for-user, --json | Rename a session |
session close TARGET | --json | Stop a session and remove it (same as kill) |
session read TARGET | --source SOURCE, --lines N, --json | Print the screen or scrollback |
session send TARGET [TEXT...] | --no-submit, --json | Type text and press Return |
session key ID KEY | --ctrl, --alt, --shift, --cmd, --repeat, --json | Press one key |
session wait TARGET | --until STATUS, --timeout SECONDS, --json | Wait for a status (default done) |
session spawn KIND | --cwd PATH, --worktree, --branch NAME, --prompt TEXT, --title TEXT, --host ID, --json | Start an agent |
session run -- PROGRAM [ARG...] | -c, --cwd PATH, --host ID, --label TEXT, --keep-open, --json | Run a command in a new session |
session fork TARGET | --json | Fork the conversation |
session release TARGET | --remove, --json | Stop a session |
session archive TARGET | --undo, --json | Archive a session |
session reconnect ID | --json | Reconnect a remote session |
session process ID | --json | Process id, group, executable, folder |
session terminal-title ID | --json | The title the program set |
session reset-terminal ID | Reset the emulator, not the process | |
worktree list [REPO] | --json | List worktrees |
worktree create [REPO] | --branch NAME, --base REF, --json | Create a worktree |
worktree remove REPO PATH | --force, --json | Remove a worktree |
workspace list | Print the layout with ids | |
workspace create NAME | --revision N | Add a workspace |
workspace rename ID NAME | --revision N | Rename |
workspace remove ID | --revision N | Remove |
workspace move ID INDEX | --revision N | Reorder |
workspace apply | Apply a mutation from stdin | |
tab list | --json | One row per tab (alias ls) |
tab create WORKSPACE SESSION | --revision N | Open a session as a tab |
tab rename TAB TITLE | --revision N | Rename |
tab remove TAB | --revision N | Close the tab |
tab move TAB WORKSPACE INDEX | --revision N | Move |
tab select WORKSPACE TAB | --revision N | Select |
pane list [TARGET] | --json | One row per pane (alias ls) |
pane split TAB PANE SESSION EDGE | --revision N | Split |
pane remove TAB PANE | --revision N | Close |
pane move SOURCE_TAB PANE DEST_TAB TARGET_PANE EDGE | --revision N | Move |
pane move-group SOURCE_TAB SPLIT DEST_TAB TARGET_PANE EDGE | --revision N | Move a split |
pane swap TAB PANE TAB PANE | --revision N | Swap |
pane resize TAB SPLIT FRACTION | --revision N | Resize |
pane focus TAB PANE | --revision N | Focus |
pane zoom TAB PANE|none | --revision N | Zoom |
events subscribe | -s, --session TARGET, --all, --kind NAME, --since-seq N, --count N, --timeout SECONDS, --json | Print events as they happen (the default) |
events wait | -s, --session TARGET, --until STATUS, --kind NAME, --timeout SECONDS, --json | Wait for one status or event |
artifacts TARGET | --json | Links, pull requests and ports of a session |
ports | --json | Listening ports across sessions |
notify | --title TEXT, --body TEXT | Post a notification from a terminal |
doctor | Check the Engine, agents and state file | |
mcp-tools | Print the MCP tool definitions | |
mcp-call | --tool NAME | Call an MCP tool with JSON from stdin |
script [FILE] [KEY=VALUE ...] | -e, --eval CODE, --for SECONDS, --check, --args JSON, --session ID, --allow-exec PROGRAM | Run a Lua script against Diri, a line of Lua, or a prompt |
keymap | --json | Every key binding, what it runs and the file:line that bound it |
help [COMMAND] | Print usage |
<!-- generated by dirijor help --markdown: end -->
Scripting
Short verbs for shell scripts, modelled on tmux. They do the same things as the session commands below.
| Command | Flags | What it does |
|---|---|---|
list | --all, --json | List sessions. Same as session list. |
new | --kind KIND (default shell), --cwd PATH, --name TEXT, --prompt TEXT, --host ID, --json | Open a shell or agent tab. Prints only the new session id. |
send TARGET [--] TOKEN... | -l, --json | Type into a session, like tmux send-keys. Each token is a key name or literal text; text tokens are joined without spaces. Reads stdin as literal text when no tokens are given. -l types every token literally. |
capture TARGET | --lines N, --scrollback, --unwrap, --ansi, --trim, --json | Print the visible screen as plain text, or the whole scrollback. Trailing blanks and empty rows are dropped, so --lines N gives the last N rows of output. --unwrap joins rows the terminal wrapped at its width back into the line the program wrote, so long URLs, paths and JSON come out whole (--lines N then counts those lines). --ansi keeps colours and text styles as escape sequences. --trim is accepted for scripts written for other tools; trimming is always on. |
run -- PROGRAM [ARG...] | --wait, --timeout SECONDS, --rm, --cwd PATH, --name TEXT, --host ID, --json | Run a command in a new terminal tab and print its id. With --wait, block until it exits, print its output and exit with its status. --rm closes the tab afterwards. |
send key names (case-insensitive): Enter, Tab, Escape, BSpace, Space, Up, Down, Left, Right, Home, End, PageUp, PageDown, Insert, Delete, F1 to F12. Prefix C- for Control, M- for Alt and S- for Shift, for example C-c, M-b or S-Tab. Anything else is typed as text.
id=$(dirijor new --cwd ~/code/app)
dirijor send "$id" "npm run dev" Enter
dirijor capture "$id" --lines 5
dirijor send "$id" C-c
dirijor run --wait --rm -- cargo test --workspace && echo greenSession verbs
These take a target like every other command. Where the table says so, a left-out target means your own session ($DIRIJOR_SESSION_ID), so dirijor split inside a diri terminal opens a shell beside you.
| Command | What it does |
|---|---|
send-key TARGET KEY... | Press keys in order: enter, tab, escape, backspace, space, up, pageup, home, f5, keypad:5, a single character, and chords such as ctrl+c, shift+tab, alt+left or ctrl+alt+delete. The tmux spellings C-c and M-x work too. Letter keys are case-insensitive: G types g, shift+g types G. Use send for text. --repeat N presses each key N times. Every key is checked before the first one is pressed. |
wait TARGET | Block until a terminal's program exits, or until an agent is done or needs you. --until STATUS (repeatable) picks other statuses, --for 30s gives up after a while (500ms, 2m, 1h, 1m30s, or plain seconds) and exits 2. A timeout says nothing about how the command will end. --json adds exitCode and signal. |
kill TARGET | Stop the session and close it. --keep keeps the stopped session's record and output. session close is the same command. |
split [TARGET] [-- PROGRAM ARG...] | Open a shell, or run a program, in a new pane beside TARGET's pane. --edge right (default), left, up or down; --ratio 30 gives the new pane 30% of the split; -c DIR sets its folder (default: the folder TARGET's terminal is in, on TARGET's host); --label names it; --keep-open keeps a command's pane after it exits; --focus shows it. Prints the new id; --json adds where it was placed. |
run --split EDGE -- PROGRAM ARG... | run in a new pane instead of a new tab, beside --beside TARGET or your own pane, with --ratio and --focus as for split. --wait still returns the program's exit status. |
focus TARGET | Show the session in the app and focus its pane. |
zoom TARGET | Zoom the session's pane to fill its tab. --on and --off set it; without either it toggles. |
move TARGET EDGE ANCHOR | Move TARGET's pane beside ANCHOR's (in any tab), on right, left, up or down. A session not shown anywhere gets a new pane. --ratio N sizes it. The program keeps running. |
swap TARGET OTHER | Swap two sessions' panes, in the same tab or across tabs. |
resize TARGET --ratio N | Give the session's pane N% of its split, 10 to 90. |
whoami | Your session, title, kind and status, the tabs and panes that show it, and the Engine you are connected to. Outside diri it reports no session; a stale $DIRIJOR_SESSION_ID is called out. |
version | The CLI version and the running Engine's build. Works when the Engine is down. |
session inspect TARGET | The session's record, every pane and tab showing it (in session ids), and its process, as JSON. |
session rename TARGET TITLE | Rename a session. Run by an agent, the name is a suggestion your own names outrank, as with the MCP rename; --for-user passes on a name you asked the agent for. |
tab ls, pane ls [TARGET] | One row per tab or pane, with their ids and the sessions they show. --json for scripts. |
New panes and tabs from the CLI do not take focus unless you pass --focus, so scripts never pull the window away from you.
id=$(dirijor run -c ~/code/app --label tests --keep-open -- npm test)
dirijor wait "$id" --for 10m --json # exitCode, or exit 2 if still running
logs=$(dirijor split --edge down --ratio 25 --label logs -- tail -f app.log)
dirijor send-key "$logs" ctrl+c
dirijor zoom "$id" --on
dirijor kill "$logs"Stopping sessions from an agent
kill, session close and session release follow the same rule as the MCP release_agent tool when an agent runs them: a root agent may stop sessions in its own project, a delegated agent only its direct children, and no agent its own session. A refusal exits 6 and names the rule. Nothing is gated when you run them yourself: from a terminal outside diri, or at a diri shell prompt with no agent in the foreground.
Shell completion
dirijor completion SHELL prints a completion script generated from the same command list as --help. It completes commands, options, option values (--until, --edge, key names) and live session ids with their titles.
# fish
dirijor completion fish > ~/.config/fish/completions/dirijor.fish
# zsh (or: source <(dirijor completion zsh) in ~/.zshrc)
dirijor completion zsh > "${fpath[1]}/_dirijor"
# bash
dirijor completion bash > ~/.local/share/bash-completion/completions/dirijorSessions
dirijor session with no action is the same as dirijor session list.
| Command | Flags | What it does |
|---|---|---|
session list | --all, --status PREFIX, --json | List sessions. Archived ones appear only with --all. --status filters by status, for example needsInput. |
session get TARGET | --json | Show id, title, agent, status, folder and host. |
session read TARGET | --source screen or scrollback, --lines N, --json | Print the visible screen (default) or scrollback. --lines keeps the last N lines. |
session send TARGET [TEXT...] | --no-submit, --json | Type text and press Return. Reads stdin when no text is given. --no-submit leaves it unsent. |
session key ID KEY | --ctrl, --alt, --shift, --cmd, --repeat, --json | Press one key. send takes any target and several keys. |
session wait TARGET | --until STATUS (repeatable), --timeout SECONDS, --json | Block until the session reaches a status. Default --until done, default timeout 600 seconds. |
session spawn KIND | --cwd PATH, --worktree, --branch NAME, --prompt TEXT, --title TEXT, --host ID, --json | Start an agent, for example claude or codex. The folder defaults to the current one. |
session run -- PROGRAM [ARG...] | --cwd PATH, --host ID, --title TEXT, --keep-open, --json | Run a command in a new terminal session. A remote run needs --cwd with an absolute path on that host. The tab closes when the command succeeds and stays open when it fails or is killed within 250 ms, so you can read the error. --keep-open keeps it open after any exit. |
session fork TARGET | --json | Fork the conversation into a new session (agents that support fork). |
session release TARGET | --remove, --json | Stop the session. --remove also deletes its record. Agents follow the release rule. |
session archive TARGET | --undo, --json | Archive the session, or unarchive it with --undo. |
session reconnect ID | --json | Reconnect a remote session whose connection failed. |
session process ID | --json | Show the process id, group, executable, folder and account. |
session terminal-title ID | --json | Print the terminal title the program set. Local sessions only. |
session reset-terminal ID | Clear the screen, history, modes and title. The process is not touched. |
--name is accepted as an alias for --title. --host takes a host id from your remote hosts.
For spawn usage, all supported options, and a local example, run dirijor session spawn --help (or -h). --help anywhere in a spawn command prints help instead, so it never starts a session or creates a worktree, and works without a running Engine. Unknown options are rejected rather than ignored.
Wait statuses
--until value | Matches |
|---|---|
done, idle | Idle |
working | Working |
needsInput (also blocked) | Waiting for you |
exited | The process ended |
starting, unknown | Those states |
Keys
KEY is a single character or one of enter (or return), escape (or esc), tab, backspace, delete, insert, home, end, up, down, left, right, pageup, pagedown, f1 to f12. Use keypad:0 to keypad:9 for the numeric keypad.
Worktrees
REPO defaults to the current folder.
| Command | Flags | What it does |
|---|---|---|
worktree list [REPO] | --json | List the repository's worktrees. |
worktree create [REPO] | --branch NAME, --base REF, --json | Create a worktree. Prints its branch and path. |
worktree remove REPO PATH | --force, --json | Remove a worktree. |
See Worktrees and review.
Workspaces, tabs and panes
These commands change the layout the app shows. Each one prints the new layout as JSON. Add --revision N to fail if someone else changed the layout first.
| Command | What it does |
|---|---|
workspace list | Print the current layout, with ids. |
workspace create NAME | Add a workspace. |
workspace rename ID NAME, workspace remove ID, workspace move ID INDEX | Rename, remove or reorder a workspace. |
workspace apply | Apply a mutation read as JSON from stdin. |
tab create WORKSPACE SESSION | Open a session as a tab. |
tab rename TAB TITLE, tab remove TAB, tab move TAB WORKSPACE INDEX, tab select WORKSPACE TAB | Manage tabs. |
pane split TAB PANE SESSION EDGE | Split a pane and put a session in the new half. EDGE is left, right, above or below. |
pane remove TAB PANE, pane focus TAB PANE, pane zoom TAB PANE | Close, focus or zoom a pane. Use none as the pane to unzoom. |
pane move SOURCE_TAB PANE DEST_TAB TARGET_PANE EDGE | Move a pane. pane move-group moves a whole split. |
pane swap TAB PANE TAB PANE | Swap two panes. |
pane resize TAB SPLIT FRACTION | Resize a split. |
Events
| Command | Flags | What it does |
|---|---|---|
events subscribe | --session TARGET or -s TARGET (repeatable; --all, the default, takes every session), --kind NAME (repeatable), --since-seq N, --count N, --timeout SECONDS, --json | Print events as they happen. Stops after --count events or the timeout (default one day). |
events wait | --session TARGET, --until STATUS or --kind NAME, --timeout SECONDS, --json | Wait for one status or event. --until needs --session. You cannot combine --until and --kind. |
Notes
dirijor note TEXT writes a quick note for the current project. The first line is its title.
| Command | What it does |
|---|---|
note add [TEXT] | Write a note. Reads stdin when TEXT is left out. Flags: --title T, --project FOLDER or --inbox, --pin, --open. |
note append NOTE TEXT | Add Markdown to the end of a note. |
note todo TEXT | Add a to-do to the project's "To-dos" note, or another note with --to NOTE. |
note list | List notes. Flags: --project FOLDER, --mentions SESSION or me, --all, --json. |
note check NOTE TODO | Tick a to-do. --undo unticks it. |
note link NOTE TODO SESSION | Attach a session to a to-do. |
note show NOTE | Print a note as Markdown. |
note edit NOTE --old TEXT --new TEXT | Replace exact text. --all replaces every match. An empty --new deletes. |
note replace-section NOTE HEADING | Replace everything under a heading with stdin. |
note history NOTE [VERSION] | List earlier versions, or print one. |
note restore NOTE VERSION | Bring back an earlier version. The current text stays in history. |
note path | Print the notes folder. |
NOTE is a note id or part of its title.
Notifications
dirijor notify --title TEXT --body TEXT prints a notification escape sequence to the terminal, so it works in local and remote sessions without a socket. diri shows it like an agent notification.
MCP from the shell
dirijor mcp-tools prints every tool the MCP server offers. dirijor mcp-call --tool NAME reads the tool's input as JSON from stdin and prints {"ok": ...} or {"error": ...}. Write tools need a live diri session identity, so call them from inside a diri session. See the MCP tool reference and the security model.
Examples
These work in fish, zsh and bash.
Find sessions waiting for you:
dirijor session list --status needsInputStart Codex in a new worktree with a task, then wait for it to finish:
dirijor session spawn codex --worktree --branch fix-login --title fix-login --prompt "Fix the failing login test"
dirijor session wait fix-login --until done --until needsInput --timeout 1800Read the last 20 lines of a session's screen:
dirijor session read fix-login --lines 20Run tests in their own terminal session and wait until the command exits:
dirijor session run --title tests -- cargo test --workspace
dirijor session wait tests --until exitedDismiss a prompt with Escape, then send a follow-up. session key needs the exact id from session list; replace SESSION_ID with it:
dirijor session key SESSION_ID escape
dirijor session send fix-login "Use the existing helper instead"Pipe a file into a new note:
cat plan.md | dirijor note add --title "Release plan" --pin