This tutorial walks through using herdr as Open Orchestrator's multiplexer backend. By default owt hosts agent sessions in tmux. When you opt in to herdr, owt stays the orchestration brain -- it still owns the Control Plane, the status database, and the merge logic -- while herdr becomes the rendering surface: a mouse-native window manager with a live agent sidebar.
For the full reference (RPC mapping, per-worktree records, architecture), see Multiplexer Backends. This page is the hands-on version.
What You'll Do
- Install herdr and confirm owt can reach it
- Create a worktree hosted in herdr with
--herdr - Attach, send a follow-up, and watch the agent sidebar update
- Make herdr the default for a repo with
[backend] mode - Use named sessions to separate work and personal daemons
- Fall back to tmux when you need to
Prerequisites
- Open Orchestrator installed (
owt version) - A git repository to work in
- An AI coding tool (Claude Code, Pi, OpenCode, or Droid)
- herdr is not required up front -- Step 1 installs it
Heads up: herdr hosts the standard
owt newflow and per-worktree agent sessions. See Known Limitations for any backend-specific caveats.
Step 1: Install herdr
herdr is not bundled with Open Orchestrator. Install it, then confirm the daemon is up:
$ curl https://herdr.dev/install.sh | sh
$ herdr status
herdr daemon: running
socket: /Users/you/.config/herdr/herdr.sock
$ ls $XDG_CONFIG_HOME/herdr/herdr.sock
/Users/you/.config/herdr/herdr.sockIf herdr status reports the daemon is not running, start it per the herdr docs before continuing. owt never starts the daemon for you.
Step 2: Create a Worktree in herdr
Add --herdr to a normal owt new:
$ cd ~/projects/my-app
$ owt new "Add a Redis caching layer" --herdrOutput:
Task: Add a Redis caching layer
Branch: add-redis-caching-layer
Accept? [Y/n/edit]: Y
Creating worktree...
Branch: add-redis-caching-layer
Path: ../my-app-add-redis-caching-layer
Backend: herdr (workspace created)
Detecting project type...
Detected: node (npm) -> installing deps...
Starting agent in herdr workspace -> sent task.Under the hood, owt issued a workspace.create to herdr and delivered your task with pane.send_text. The worktree's status row records backend_kind = "herdr" plus the workspace id and socket, so every later command for this worktree routes to herdr automatically -- no need to repeat --herdr.
Step 3: Attach, Send, and Watch the Sidebar
Open the Control Plane to see the agent, regardless of backend:
$ owt open-orchestrator · 1 row · 09:14:02
▸ IN FLIGHT (1)
add-redis-caching-layer 2m · claude · Wiring up the cache client [a] [r]
↑↓ nav | s ship | r review | a attach | f fix | m merge | x dismiss | q quitPress a to attach -- owt runs herdr agent attach <pane_id> and hands you off into the herdr workspace. From the CLI you can also send a follow-up without attaching:
$ owt send add-redis-caching-layer "Add a 60-second TTL and a cache-bypass flag"owt delivers the message with pane.send_text through the recorded herdr backend. Because herdr types text as text rather than synthesizing an Enter key, owt appends a carriage return so TUI agents actually submit the prompt. (If your herdr build needs a different terminator, set OWT_HERDR_SUBMIT.)
As the agent works, owt writes status to SQLite and forwards it to herdr with pane.report_agent, so herdr's sidebar shows the same WORKING / WAITING / BLOCKED state you see in the Control Plane. The status DB is always the source of truth: if herdr is down, owt keeps working and the sidebar just falls behind.
Step 4: Make herdr the Default for a Repo
Rather than typing --herdr each time, set it in .worktreerc.toml:
[backend]
mode = "auto" # tmux | herdr | auto
herdr_session = "default"mode value | Behavior |
|---|---|
"tmux" | Always use tmux (the default) |
"herdr" | Always use herdr |
"auto" | Use herdr if it is installed and its socket pings; otherwise fall back to tmux |
mode = "auto" is the friendliest choice for a shared repo: teammates who have herdr get it, and everyone else transparently uses tmux. Now a plain owt new "..." lands in herdr:
$ owt new "Add rate limiting" # no flag needed -- picks herdr via [backend] modeStep 5: Separate Work and Personal Daemons (Named Sessions)
If you run more than one herdr daemon, select which one owt talks to with herdr_session. The name resolves to a socket path:
default->$XDG_CONFIG_HOME/herdr/herdr.sock- any other name ->
$XDG_CONFIG_HOME/herdr/sessions/<name>/herdr.sock
# Route this repo's worktrees to the "work" daemon
[backend]
mode = "herdr"
herdr_session = "work"The chosen socket is stored per worktree, so attach/send/delete keep talking to the right daemon even if you change the default later.
Step 6: Fall Back to tmux When You Need To
A forced flag always wins over config. To host one session in tmux even though the repo defaults to herdr:
$ owt new "Quick hotfix" --tmuxFor an entire shell, set an environment override:
$ OWT_BACKEND_MODE=tmux owt new "CI smoke test"And remember that headless runs never use a multiplexer at all, so a [backend] mode = "herdr" repo still works in CI even where herdr is not installed:
$ owt new "Run the nightly batch" --headless # no backend resolution; --herdr is rejected hereStep 7: Ship and Tear Down
Shipping is backend-agnostic -- owt reads the recorded backend and cleans up the right surface:
$ owt ship add-redis-caching-layerFor a herdr-hosted worktree this commits and merges, then issues pane.close + workspace.close to herdr before removing the worktree and status row.
What You Learned
- herdr is opt-in and additive -- tmux stays the default until you choose otherwise
--herdr/--tmuxoverride per command;[backend] modesets the repo default;autodetects herdr and falls back gracefully- owt records the backend per worktree, so follow-up commands need no flags
- The status DB stays authoritative; herdr's sidebar is a best-effort mirror
- Named sessions route to different daemons; headless never touches a multiplexer
Next Steps
- Multiplexer Backends -- Full reference, RPC mapping, and architecture
owt attach-- Backend-aware hand-offowt new-- All worktree-creation flags- The Control Plane -- The view that works across both backends