Setting up herdr with Ghostty for Agentic Workflows Developer Oli Morris detailed his setup of herdr, a terminal multiplexor built around AI agents, integrated with Ghostty and CodeCompanion.nvim, after abandoning tmux two years ago. Morris, who moved from Wezterm to Ghostty in December 2025, uses herdr to manage multiple agent workflows across projects, citing CodeCompanion's output as comparable to Claude Code and highlighting the use of git worktrees for testing features. I’m defining herdr https://herdr.dev/ as a terminal multiplexor built around agents. If you’re running multiple agents across different projects, a dedicated space to keep tabs on all of them is pretty darn nice. In this post I share how I ended up back in a multiplexor, two years after ditching tmux https://github.com/tmux/tmux , and how I’ve wired it up with Ghostty https://ghostty.org/ and CodeCompanion https://github.com/olimorris/codecompanion.nvim . Important This post was written by me and only me. An LLM checked my spelling and grammar How I’m coding in 2026 I dumped https://github.com/olimorris/dotfiles/commit/86bf8b880095b235db2fc7e8ff174e85eb4fd677 tmux https://github.com/tmux/tmux two years ago when I moved from Kitty https://sw.kovidgoyal.net/kitty/ to Wezterm https://wezterm.org . Wezterm’s multiplexing made it a no-brainer as I could drop another dependency. Then I moved https://blog.olimorris.com/2025/12/06/moving-to-ghostty-from-wezterm/ to Ghostty https://ghostty.org/ yes, this makes me sound like I can’t settle on a config and didn’t fancy dusting off my old tmux config. Redesigning my statusline, hunting for colours and glyphs, checking my “sensible tmux defaults” were still sensible - all super off-putting. Truth is, I only ever used tmux to sessionize : following ThePrimeagen’s https://www.youtube.com/watch?v=GXxvxSlzJdI approach of scripting tmux sessions into an fzf https://github.com/junegunn/fzf menu for fast switching. So, no multiplexor, no sessionizing. Meanwhile, I’ve been using agents more and more. CodeCompanion.nvim https://github.com/olimorris/codecompanion.nvim has reached a point where I’m getting output as good, if not better, than Claude Code https://claude.com/product/claude-code . Its versatility means I can use it for tasks beyond coding with great results too. As an aside, if you’re not making use of the Prompt Library https://codecompanion.olimorris.dev/configuration/prompt-library , you’re missing out. I trust CodeCompanion enough to let an agent make a first pass at a fix or feature, along with the tests. Now that code reviews https://codecompanion.olimorris.dev/usage/code-review are part of the workflow, reviewing an agent’s edits line by line is trivial. Before that, I’d switch branch in the CodeCompanion repo and run nvim to test things out. Despite endless videos and the YouTube algorithm telling me git worktrees https://git-scm.com/docs/git-worktree would help, I ignored them…until last month. One edit to my init.lua file: local codecompanion worktree = vim.fn.getenv "CODECOMPANION WORKTREE" if codecompanion worktree == vim.NIL then codecompanion worktree = "main" else vim.schedule function vim.notify "Using worktree " .. codecompanion worktree .. " ", vim.log.levels.INFO, { title = "CodeCompanion" } end end vim.cmd string.format "set rtp+=%s", om.home .. "/Code/Neovim/codecompanion.nvim/" .. codecompanion worktree Followed by nvimcc feature-a , and I can open Neovim with the feature-a worktree of CodeCompanion ready to go. It’s a huge time saver and means I can use the stable main , while I build out a fix or feature. I use lazygit https://github.com/jesseduffield/lazygit to create and switch between worktrees and branches. I still need to blog about how I’m really using agents in H2 of 2026, but needless to say I’m jumping between Ghostty windows, tabs, and Neovim instances. If an agent finishes analysing a financial report or reviewing a feature I’ve crafted in CodeCompanion, I only find out when I manually navigate to that window and tab. herdr’s value proposition It’s not my intention to steelman herdr here. Plenty of YouTube and Reddit posts do that better than I can in a single blog post. Instead, I want to focus on what I saw as herdr’s value proposition when I first discovered it, and how I see it after a week of use. When I saw Typecraft’s https://www.youtube.com/@typecraft dev video https://www.youtube.com/watch?v=yQDARWdrPeY on herdr https://herdr.dev , my immediate thought was “surely this is just tmux with a dedicated panel for your agents” . Having used it for a week, I can confirm that’s exactly what it is. Oh, except it’s written in Rust. That’s not a dig. I’ve used it for a week and it’s now an integral part of my workflow. It handles git worktrees nicely, displaying them in the spaces panel like so: What’s odd is that this was a random discovery with prefix+G . Nowhere could I find it in herdr’s quick start https://herdr.dev/docs/quick-start/ guide. To me, this is a huge feature, and I’m sure it would be for many others. Being able to cycle between worktrees with ease and jump to a worktree’s agent? Up until this point I was using Lazygit to create, manage and switch worktrees. But herdr can do this and show them as children of a space? Huuuuuuge Now, showing herdr in action: Keep a keen eye open on the bottom left and you’ll see the agent status indicator go from yellow “working” to hollow green “done” . If you’re not in the window when an agent needs you, you’ll see the indicator turn “red” and you’ll get a notification if your agent supports it: For my way of working, sans multiplexor , this is pretty darn nice. Throw in herdr’s impressive plugin ecosystem https://herdr.dev/plugins/ where I finally got my sessionizer https://github.com/salkhalil/herdr-sessionizer back and you have one compelling application. But the logical next question was… Tmux users: Is herdr just a shiny new thing? Ultimately, this was the question I was wrestling with throughout. Is herdr differentiated enough from tmux so that it’s anything other than that “shiny new thing”? Or, if I have tmux already, is it worth migrating? herdr very much is the shiny new thing, and honestly, I don’t think it’s worth migrating for. Especially since someone’s already built workmux https://github.com/raine/workmux , giving tmux its own agent panel and git worktree support. If you have a tmux workflow you’re happy with, plus muscle memory to boot, it’s not worth uprooting for herdr. At least not yet. So why have I moved to herdr? As I said above - no desire to dust off that old tmux config which ran across multiple files . I’m essentially net new to multiplexing and feel like I got my miles out of tmux. I do want that shiny new thing this time round and given my open-source work these days is building agentic dev tooling, I feel like I should . My herdr and Ghostty setup With that decision made, I added support https://github.com/olimorris/codecompanion.nvim/blob/main/lua/codecompanion/integrations/herdr.lua to CodeCompanion to get those nice agent status indicators and notifications. The last step to feeling fully integrated with herdr was getting Ghostty to play nicely with it. From my prior post https://blog.olimorris.com/2025/12/06/moving-to-ghostty-from-wezterm/ , you’ll know I blooming love Ghostty. It’s been my terminal since the start of December and nothing but a joy to use. But now I’m back to multiplexing, a ton of Ghostty’s features no longer make sense - windows and tabs, mainly. So re-routing my muscle memory to herdr via keymaps was where I started. Important After a week of use, it’s worth clarifying how simple herdr is to configure. My tmux config ran for pages - a monster of options and settings needed to get it playing nicely with my terminal and Neovim. herdr, on the other hand, is so damn simple. Oh, and before I forget, you can see my full herdr https://github.com/olimorris/dotfiles/blob/main/.config/herdr/config.toml and Ghostty https://github.com/olimorris/dotfiles/blob/main/.config/ghostty/config config over in my dotfiles. Thinking horizontally First up: how do I want to move around in herdr? I started with tabs. Since herdr displays tabs much the same way Ghostty does, I wanted to cycle between them with Ctrl+Tab or jump to specific ones with Command+n where n is a number - essentially mimicking macOS behaviour. To my herdr config, I simply added: next tab = "ctrl+tab" previous tab = "ctrl+shift+tab" switch tab = "cmd+1..9" For my Ghostty config, this is where the first of many challenges appeared. Ghostty can unbind https://ghostty.org/docs/config/keybind action a key combination, so I tried setting keybind = ctrl+tab=unbind and keybind = ctrl+shift+tab=unbind . Nothing. Turns out I needed the raw escape sequence, which CodeCompanion with Sonnet-5 duly delivered: keybind = ctrl+tab=text:\x1b 9;5u keybind = ctrl+shift+tab=text:\x1b 9;6u Now for the Command+n keymap. I wrongly assumed keybind = cmd+1=unbind and keybind = cmd+2=unbind etc. would work. Nothing. Cue a period of trial and error with CodeCompanion. Eventually we settled on: keybind = cmd+1=unbind keybind = cmd+digit 1=unbind ... keybind = cmd+9=unbind keybind = cmd+digit 9=unbind Note I spent a good 20 mins searching GitHub for other people’s herdr and Ghostty setups. I couldn’t find any. I wonder if anyone has even made theirs public yet. So with no GitHub, Google or Stack Overflow and unable to find it in the docs, where do you turn? In the old days, to the source code. Trawling hours looking for some obscure reference that would unlock a single keymap. Not exactly time well spent…CodeCompanion and Sonnet-5, took about 3 mins of back and forth. Thinking vertically As I mentioned, herdr has a beautiful left-sided pane housing workspaces and agents. Given they’re stacked on top of each other, adding vertical movements with j and k felt logical: next workspace = "cmd+j" previous workspace = "cmd+k" I also thought it’d be cool to move between agents too, so: next agent = "cmd+shift+j" previous agent = "cmd+shift+k" Surprisingly, in Ghostty, to enable all four of those mappings, I only needed to set: keybind = cmd+shift+j=unbind keybind = cmd+shift+k=unbind Other mappings To bring this closer to macOS, I also added the following keymaps to my herdr config: new tab = "cmd+t" close tab = "cmd+w" new workspace = "cmd+n" toggle sidebar = "cmd+s" Updating my Ghostty config to: keybind = cmd+t=unbind keybind = cmd+w=unbind keybind = cmd+n=unbind Again, cmd+s didn’t need to be unbound. The key point with these mappings: I don’t have to change my muscle memory. I’ve simply mimicked the way I use Ghostty, in herdr. I should point out that I keep the sidebar collapsed most of the time. This just leaves the status icons next to the workspace and agent numbers. Other settings I like my prefix key to be: keys prefix = "ctrl+v" I find it more ergonomic. I’ve also set my sessionizer to: keys.command key = "ctrl+w" type = "plugin action" command = "sessionizer.pick" description = "fuzzy-switch workspace" My current gripes with herdr herdr is by no means perfect and there are a few rough edges that annoy me. For me, it’s integral that I can rice an app to my liking so it blends into my terminal and Neovim. There are some theming issues in particular I hope they sort out soon. Custom themes herdr only lets you define a custom theme https://herdr.dev/docs/config-reference/ ref-theme by manually adding colours to your config. You can’t link to external custom themes like you can with Ghostty or Wezterm. I’ve raised this as a feature request https://github.com/herdrdev/herdr/discussions/3071 . Custom light/dark themes In your herdr config you can only specify one theme, so you have to choose between light OR dark. Thankfully, 2324 https://github.com/herdrdev/herdr/pull/2324 will close that gap once merged. Still, this was a heck of a miss, especially given they’ve already built in a theme auto switch https://herdr.dev/docs/config-reference/ ref-theme . Navigating spaces and worktrees There’s also a weird issue: when the spaces panel on the left is open, I can move sequentially through everything using my