Skip to content

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 ​

  1. Install herdr and confirm owt can reach it
  2. Create a worktree hosted in herdr with --herdr
  3. Attach, send a follow-up, and watch the agent sidebar update
  4. Make herdr the default for a repo with [backend] mode
  5. Use named sessions to separate work and personal daemons
  6. 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 new flow 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:

bash
$ 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.sock

If 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:

bash
$ cd ~/projects/my-app

$ owt new "Add a Redis caching layer" --herdr

Output:

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:

bash
$ 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 quit

Press 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:

bash
$ 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:

toml
[backend]
mode          = "auto"      # tmux | herdr | auto
herdr_session = "default"
mode valueBehavior
"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:

bash
$ owt new "Add rate limiting"   # no flag needed -- picks herdr via [backend] mode

Step 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
toml
# 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:

bash
$ owt new "Quick hotfix" --tmux

For an entire shell, set an environment override:

bash
$ 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:

bash
$ owt new "Run the nightly batch" --headless   # no backend resolution; --herdr is rejected here

Step 7: Ship and Tear Down ​

Shipping is backend-agnostic -- owt reads the recorded backend and cleans up the right surface:

bash
$ owt ship add-redis-caching-layer

For 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 / --tmux override per command; [backend] mode sets the repo default; auto detects 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 ​