Automation

dirijor CLI

Reference for the dirijor command-line tool. List, read, start and drive diri sessions, manage worktrees, layouts and notes, and script diri from a shell.

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

PlatformPath
macOS/Applications/diri.app/Contents/Resources/bin/dirijor
Linuxdirijor 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:

Terminal
mkdir -p ~/.local/bin
ln -sf /Applications/diri.app/Contents/Resources/bin/dirijor ~/.local/bin/dirijor

The 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 ID need 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 run passes everything after -- as separate arguments. Nothing is run through a shell.

Exit codes

CodeMeaning
0Success
1Failure, including bad arguments
2Timed out
3Session not found
4Engine unreachable
5Ambiguous target: the id prefix or title matches more than one session
6Refused: 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

CommandWhat it does
dirijor list, new, send, capture, runShort scripting verbs. See Scripting.
dirijor send-key, wait, kill, split, focus, zoom, move, swap, resizePress keys, wait, stop, and arrange panes by session. See Session verbs.
dirijor whoami, versionYour own session, tab and pane; the CLI and Engine versions.
dirijor completion fish|zsh|bashPrint 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, paneChange 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 doctorCheck the Engine, agents and state file.
dirijor mcp-toolsPrint the MCP tool definitions as JSON.
dirijor mcp-call --tool NAMECall 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 -->

CommandOptionsWhat it does
list--all, --jsonList sessions (alias ls)
status--jsonList every session, archived ones included
new--kind KIND, -c, --cwd PATH, --label TEXT, --prompt TEXT, --host ID, --jsonOpen 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], --jsonRun 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], --jsonOpen a shell or command beside a session's pane
send TARGET [--] TOKEN...-l, --literal, --jsonType text and tmux-style keys (Enter, C-c)
send-key TARGET KEY...--repeat N, --jsonPress keys: enter, ctrl+c, shift+tab, alt+left, f5
capture TARGET--lines N, --scrollback, --jsonPrint the screen or scrollback as text
wait TARGET--for DURATION, --until STATUS, --jsonWait until a session exits (or reaches --until)
kill TARGET--keep, --jsonStop a session and close it
focus TARGET--jsonShow a session in the app and focus its pane
zoom TARGET--on, --off, --jsonZoom a session's pane; toggles without --on/--off
move TARGET EDGE ANCHOR--ratio PERCENT, --jsonMove a session's pane beside another session's
swap TARGET OTHER--jsonSwap two sessions' panes
resize TARGET--ratio PERCENT, --jsonSet a pane's share of its split
whoami--jsonThis terminal's session, tab and pane
version--jsonCLI and Engine versions
completion SHELLPrint a fish, zsh or bash completion script
activity--limit N, --jsonRecent activity
session list--all, --status PREFIX, --jsonList sessions (alias ls)
session get TARGET--jsonShow a session
session inspect TARGET--jsonA session with its tabs, panes and process (JSON)
session rename TARGET TITLE--for-user, --jsonRename a session
session close TARGET--jsonStop a session and remove it (same as kill)
session read TARGET--source SOURCE, --lines N, --jsonPrint the screen or scrollback
session send TARGET [TEXT...]--no-submit, --jsonType text and press Return
session key ID KEY--ctrl, --alt, --shift, --cmd, --repeat, --jsonPress one key
session wait TARGET--until STATUS, --timeout SECONDS, --jsonWait for a status (default done)
session spawn KIND--cwd PATH, --worktree, --branch NAME, --prompt TEXT, --title TEXT, --host ID, --jsonStart an agent
session run -- PROGRAM [ARG...]-c, --cwd PATH, --host ID, --label TEXT, --keep-open, --jsonRun a command in a new session
session fork TARGET--jsonFork the conversation
session release TARGET--remove, --jsonStop a session
session archive TARGET--undo, --jsonArchive a session
session reconnect ID--jsonReconnect a remote session
session process ID--jsonProcess id, group, executable, folder
session terminal-title ID--jsonThe title the program set
session reset-terminal IDReset the emulator, not the process
worktree list [REPO]--jsonList worktrees
worktree create [REPO]--branch NAME, --base REF, --jsonCreate a worktree
worktree remove REPO PATH--force, --jsonRemove a worktree
workspace listPrint the layout with ids
workspace create NAME--revision NAdd a workspace
workspace rename ID NAME--revision NRename
workspace remove ID--revision NRemove
workspace move ID INDEX--revision NReorder
workspace applyApply a mutation from stdin
tab list--jsonOne row per tab (alias ls)
tab create WORKSPACE SESSION--revision NOpen a session as a tab
tab rename TAB TITLE--revision NRename
tab remove TAB--revision NClose the tab
tab move TAB WORKSPACE INDEX--revision NMove
tab select WORKSPACE TAB--revision NSelect
pane list [TARGET]--jsonOne row per pane (alias ls)
pane split TAB PANE SESSION EDGE--revision NSplit
pane remove TAB PANE--revision NClose
pane move SOURCE_TAB PANE DEST_TAB TARGET_PANE EDGE--revision NMove
pane move-group SOURCE_TAB SPLIT DEST_TAB TARGET_PANE EDGE--revision NMove a split
pane swap TAB PANE TAB PANE--revision NSwap
pane resize TAB SPLIT FRACTION--revision NResize
pane focus TAB PANE--revision NFocus
pane zoom TAB PANE|none--revision NZoom
events subscribe-s, --session TARGET, --all, --kind NAME, --since-seq N, --count N, --timeout SECONDS, --jsonPrint events as they happen (the default)
events wait-s, --session TARGET, --until STATUS, --kind NAME, --timeout SECONDS, --jsonWait for one status or event
artifacts TARGET--jsonLinks, pull requests and ports of a session
ports--jsonListening ports across sessions
notify--title TEXT, --body TEXTPost a notification from a terminal
doctorCheck the Engine, agents and state file
mcp-toolsPrint the MCP tool definitions
mcp-call--tool NAMECall an MCP tool with JSON from stdin
script [FILE] [KEY=VALUE ...]-e, --eval CODE, --for SECONDS, --check, --args JSON, --session ID, --allow-exec PROGRAMRun a Lua script against Diri, a line of Lua, or a prompt
keymap--jsonEvery 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.

CommandFlagsWhat it does
list--all, --jsonList sessions. Same as session list.
new--kind KIND (default shell), --cwd PATH, --name TEXT, --prompt TEXT, --host ID, --jsonOpen a shell or agent tab. Prints only the new session id.
send TARGET [--] TOKEN...-l, --jsonType 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, --jsonPrint 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, --jsonRun 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.

Terminal
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 green

Session 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.

CommandWhat 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 TARGETBlock 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 TARGETStop 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 TARGETShow the session in the app and focus its pane.
zoom TARGETZoom the session's pane to fill its tab. --on and --off set it; without either it toggles.
move TARGET EDGE ANCHORMove 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 OTHERSwap two sessions' panes, in the same tab or across tabs.
resize TARGET --ratio NGive the session's pane N% of its split, 10 to 90.
whoamiYour 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.
versionThe CLI version and the running Engine's build. Works when the Engine is down.
session inspect TARGETThe session's record, every pane and tab showing it (in session ids), and its process, as JSON.
session rename TARGET TITLERename 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.

Terminal
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.

Terminal
# 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/dirijor

Sessions

dirijor session with no action is the same as dirijor session list.

CommandFlagsWhat it does
session list--all, --status PREFIX, --jsonList sessions. Archived ones appear only with --all. --status filters by status, for example needsInput.
session get TARGET--jsonShow id, title, agent, status, folder and host.
session read TARGET--source screen or scrollback, --lines N, --jsonPrint the visible screen (default) or scrollback. --lines keeps the last N lines.
session send TARGET [TEXT...]--no-submit, --jsonType 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, --jsonPress one key. send takes any target and several keys.
session wait TARGET--until STATUS (repeatable), --timeout SECONDS, --jsonBlock 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, --jsonStart 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, --jsonRun 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--jsonFork the conversation into a new session (agents that support fork).
session release TARGET--remove, --jsonStop the session. --remove also deletes its record. Agents follow the release rule.
session archive TARGET--undo, --jsonArchive the session, or unarchive it with --undo.
session reconnect ID--jsonReconnect a remote session whose connection failed.
session process ID--jsonShow the process id, group, executable, folder and account.
session terminal-title ID--jsonPrint the terminal title the program set. Local sessions only.
session reset-terminal IDClear 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 valueMatches
done, idleIdle
workingWorking
needsInput (also blocked)Waiting for you
exitedThe process ended
starting, unknownThose 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.

CommandFlagsWhat it does
worktree list [REPO]--jsonList the repository's worktrees.
worktree create [REPO]--branch NAME, --base REF, --jsonCreate a worktree. Prints its branch and path.
worktree remove REPO PATH--force, --jsonRemove 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.

CommandWhat it does
workspace listPrint the current layout, with ids.
workspace create NAMEAdd a workspace.
workspace rename ID NAME, workspace remove ID, workspace move ID INDEXRename, remove or reorder a workspace.
workspace applyApply a mutation read as JSON from stdin.
tab create WORKSPACE SESSIONOpen a session as a tab.
tab rename TAB TITLE, tab remove TAB, tab move TAB WORKSPACE INDEX, tab select WORKSPACE TABManage tabs.
pane split TAB PANE SESSION EDGESplit 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 PANEClose, focus or zoom a pane. Use none as the pane to unzoom.
pane move SOURCE_TAB PANE DEST_TAB TARGET_PANE EDGEMove a pane. pane move-group moves a whole split.
pane swap TAB PANE TAB PANESwap two panes.
pane resize TAB SPLIT FRACTIONResize a split.

Events

CommandFlagsWhat 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, --jsonPrint 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, --jsonWait 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.

CommandWhat 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 TEXTAdd Markdown to the end of a note.
note todo TEXTAdd a to-do to the project's "To-dos" note, or another note with --to NOTE.
note listList notes. Flags: --project FOLDER, --mentions SESSION or me, --all, --json.
note check NOTE TODOTick a to-do. --undo unticks it.
note link NOTE TODO SESSIONAttach a session to a to-do.
note show NOTEPrint a note as Markdown.
note edit NOTE --old TEXT --new TEXTReplace exact text. --all replaces every match. An empty --new deletes.
note replace-section NOTE HEADINGReplace everything under a heading with stdin.
note history NOTE [VERSION]List earlier versions, or print one.
note restore NOTE VERSIONBring back an earlier version. The current text stays in history.
note pathPrint 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:

Terminal
dirijor session list --status needsInput

Start Codex in a new worktree with a task, then wait for it to finish:

Terminal
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 1800

Read the last 20 lines of a session's screen:

Terminal
dirijor session read fix-login --lines 20

Run tests in their own terminal session and wait until the command exits:

Terminal
dirijor session run --title tests -- cargo test --workspace
dirijor session wait tests --until exited

Dismiss a prompt with Escape, then send a follow-up. session key needs the exact id from session list; replace SESSION_ID with it:

Terminal
dirijor session key SESSION_ID escape
dirijor session send fix-login "Use the existing helper instead"

Pipe a file into a new note:

Terminal
cat plan.md | dirijor note add --title "Release plan" --pin