A tmux sidebar for keeping Claude Code and Codex panes visible at once. See status, prompts, Git state, activity, and worktrees without switching windows.
- One sidebar for all tmux sessions and windows.
- Live prompts, tool calls, responses, Git state, and pane metadata.
- Task progress and subagent trees for supported agents.
- Worktree visibility and lifecycle actions from the sidebar.
- Desktop notifications when something needs attention.
Desktop notifications are enabled by default.
Supported events:
stop— assistant finished responding (Stophook; Claude Code and Codex)notification— permission prompt or other attention request (Notificationhook; Claude only)task_completed— subagent / Task tool completion (TaskCompletedhook; Claude only)stop_failure— assistant ended with an error (StopFailurehook; Claude only)permission_denied— permission explicitly denied (PermissionDeniedhook; Claude only)
Restrict which events fire notifications with @sidebar_notifications_events (comma-separated event names; all fires every event, unset = every event except task_completed):
set -g @sidebar_notifications_events "stop,notification" # drop error notifications
set -g @sidebar_notifications_events "stop,notification,task_completed" # enable subagent notifications
set -g @sidebar_notifications_events all # explicit "fire everything"Setting an empty value disables every event without touching the master @sidebar_notifications switch.
Delivery depends on the platform:
- macOS uses
osascript - Linux uses
notify-send - Windows is not supported yet
If the required notification command is missing, the feature quietly disables itself.
Notification layout:
┌─────────────────────────────────────────────┐
│ repo (branch) / agent ← title │
│ <event body> ← body │
└─────────────────────────────────────────────┘
Title falls back to repo / agent when the branch is unknown, and to agent alone when there is no repo. Body per event:
| Event | Body | Fallback |
|---|---|---|
stop |
assistant's last message (truncated to ~240c) | Task completed |
notification |
wait reason | Permission required |
task_completed |
Task completed: {task_subject} |
Task completed |
stop_failure |
Task failed: {error} |
Task failed |
permission_denied |
(no payload) | Permission required |
- tmux 3.0+
- TPM (for plugin installation)
- GitHub CLI (optional, for displaying PR numbers in the Git tab)
- Rust (only if building from source)
Option A: Installation with TPM (recommended).
Add the plugin to your tmux.conf:
set -g @plugin 'hiroppy/tmux-agent-sidebar'Reload tmux.conf (tmux source ~/.tmux.conf), then press prefix + I to install. On the first run, an install wizard prompts you to download a pre-built binary or build from source.
To update later, press prefix + U in TPM's plugin list and select tmux-agent-sidebar. The install wizard runs again if the bundled binary has changed.
Option B: Manual
- Clone the repository:
git clone https://github.com/hiroppy/tmux-agent-sidebar.git ~/.tmux/plugins/tmux-agent-sidebar- Add the plugin to your
tmux.conf:
run-shell ~/.tmux/plugins/tmux-agent-sidebar/tmux-agent-sidebar.tmux- Install the binary using one of the following methods:
# macOS (Apple Silicon)
curl -fSL https://github.com/hiroppy/tmux-agent-sidebar/releases/latest/download/tmux-agent-sidebar-darwin-aarch64 \
-o ~/.tmux/plugins/tmux-agent-sidebar/bin/tmux-agent-sidebar
chmod +x ~/.tmux/plugins/tmux-agent-sidebar/bin/tmux-agent-sidebar
cd ~/.tmux/plugins/tmux-agent-sidebar
cargo build --releaseAfter updating tmux.conf, press prefix + r to reload the config.
The sidebar receives status updates through agent hooks. Add the following hook definitions to your agent settings.
The repository ships as a Claude Code plugin, so setup is automatic.
Inside Claude Code, register the marketplace and install the plugin:
/plugin marketplace add ~/.tmux/plugins/tmux-agent-sidebar
/plugin install tmux-agent-sidebar@hiroppyEither install path wires up the Claude Code hooks. Run /reload-plugins (or restart Claude Code) to activate them.
If your environment can't use the plugin, you can register hooks in `settings.json` with the prompt below.
Run ~/.tmux/plugins/tmux-agent-sidebar/target/release/tmux-agent-sidebar setup claude (fall back to ~/.tmux/plugins/tmux-agent-sidebar/bin/tmux-agent-sidebar if that path is missing). Add these hooks to ~/.claude/settings.json. If hooks already exist, merge them without making destructive changes.
- Open a Codex pane in tmux and focus it.
- Press
prefix + eto toggle the sidebar. A yellowⓘbadge appears in the top row of the sidebar when required hooks are missing. - Click
ⓘ, then click[copy]next tocodexin the Notices popup. - Switch back to the Codex pane and paste. Codex will run
tmux-agent-sidebar setup codexand merge the hooks into~/.codex/hooks.json.
| Key | Action |
|---|---|
prefix + e |
Toggle sidebar |
prefix + E |
Toggle sidebar in all windows |
j / Down |
Move selection down |
k / Up |
Move selection up |
h / Left |
Previous status filter |
l / Right |
Next status filter |
r |
Open repo filter popup |
Enter |
Jump to the selected pane or confirm the repo popup |
Tab |
Cycle status filter |
Shift+Tab |
Switch bottom panel tab |
Esc |
Return focus or close the popup |
| Mouse click | Jump to a pane, filter by status, or open the repo popup |
| Key | Action |
|---|---|
n |
Spawn a new worktree + agent |
x |
Remove the selected spawn-created pane |
Mouse click + |
Open the spawn modal for that repo |
Mouse click × |
Open the close-pane modal for that worktree |
Opened with n or by clicking the + button next to a repo header.
| Key | Action |
|---|---|
| Text keys | Type the name (used as the branch slug and tmux window name, e.g. add login form → agent/add-login-form) |
↑ / ↓ / Tab / Shift+Tab |
Move focus between NAME / AGENT / MODE fields |
← / → |
Cycle the value when the agent or mode field has focus |
Enter |
Create the worktree + window and launch the agent |
Esc / click outside |
Cancel |
Opened with x on a spawn-created pane.
| Key | Action |
|---|---|
y / Enter |
Close the tmux window, remove the git worktree (--force), and delete the branch the spawn created (git branch -D) |
c |
Close the tmux window only, keep the worktree and branch on disk |
n / Esc |
Cancel |
Branches are force-deleted because the sidebar auto-generates them under the agent/ prefix for short-lived explorations. A normal git branch -d can refuse squash- or rebase-merged work, so the close action uses git branch -D instead. Recover via git reflog if needed.
| Feature | Claude Code | Codex | Notes |
|---|---|---|---|
| Status tracking (running / idle / error) | ✅ | ✅ | Driven by SessionStart / UserPromptSubmit / Stop |
| Prompt text display | ✅ | ✅ | Saved from UserPromptSubmit |
Response text display (▷ ...) |
✅ | ✅ | Populated from Stop payload |
| Waiting status + wait reason | ✅ | ❌ | Populated from Notification, PermissionDenied, and TeammateIdle (all Claude-only) |
| API failure reason display | ✅ | ❌ | StopFailure is wired only for Claude |
| Permission badge | ✅ (plan / edit / auto / !) |
✅ (auto / ! only) |
Codex badges are inferred from process arguments |
| Git branch display | ✅ | ✅ | Uses the pane cwd; Claude updates dynamically via CwdChanged |
| Elapsed time | ✅ | ✅ | Since the last prompt |
| Task progress | ✅ | ❌ | Requires PostToolUse; Codex fires PostToolUse only for Bash, so task progress from tools is unavailable |
| Task lifecycle notifications | ✅ | ✅ (Stop only) |
Stop desktop notifications fire for both. Notification, TaskCompleted, StopFailure, and PermissionDenied are Claude-only because Codex does not emit those hooks |
| Subagent display | ✅ | ❌ | Requires SubagentStart / SubagentStop |
| Activity log | ✅ | ✅ (Bash only) | Codex's PostToolUse fires only for Bash tool calls; Read/Edit/Write/Grep/Glob/etc. are not reported |
| Worktree lifecycle tracking | ✅ | ❌ | Requires WorktreeCreate / WorktreeRemove |
- Waiting status (Claude Code) — After you approve a permission prompt, the status stays
waitinguntil the next hook event fires. This is a limitation of the Claude Code hook system. - Codex hook coverage — Codex emits
SessionStart,UserPromptSubmit,Stop, andPostToolUse.PostToolUseis limited to theBashtool (Codex's schema typestool_inputas{ command: string }), so the Codex activity log shows only Bash commands. Waiting status, task progress, subagent display, and worktree tracking remain unavailable.
Most options can be set before loading the plugin in your tmux.conf:
# Sidebar
set -g @sidebar_key T # keybinding (default: e)
set -g @sidebar_key_all Y # keybinding for all windows (default: E)
set -g @sidebar_width 32 # width in columns or % (default: 15%)
set -g @sidebar_bottom_height 20 # bottom panel height in lines (default: 20, 0 to hide)
set -g @sidebar_auto_create off # disable auto-create on new windows (default: on)
set -g @sidebar_notifications off # desktop notifications for task completion/failure and permission prompts (default: on)
set -g @sidebar_notifications_events "stop,notification" # limit desktop notifications to selected hook events (default: all except task_completed)
# Spawn worktree modal defaults (optional)
set -g @agent-sidebar-default-agent codex # agent launched by `n` (default: claude)
set -g @agent-sidebar-branch-prefix wip/ # branch prefix for new worktrees (default: agent/)
# Colors (256-color palette numbers) — all defaults live in src/ui/colors.rs
set -g @sidebar_color_all 111 # selected "all" filter icon (default: 111 sky blue)
set -g @sidebar_color_running 114 # selected running filter icon and running pane status (default: 114 green)
set -g @sidebar_color_waiting 221 # selected waiting filter icon, waiting pane status, version banner (default: 221 yellow)
set -g @sidebar_color_idle 110 # selected idle filter icon and idle pane status (default: 110 soft blue)
set -g @sidebar_color_error 167 # selected error filter icon and error pane status (default: 167 soft red)
set -g @sidebar_color_filter_inactive 245 # unselected status filter icons and zero counts (default: 245 mid gray)
set -g @sidebar_color_border 240 # unfocused panel borders and tab separators (default: 240 dark gray)
set -g @sidebar_color_accent 153 # active pane marker, focused repo header, focused bottom panel border, repo popup border (default: 153 pale sky blue)
set -g @sidebar_color_session 39 # session name (default: 39 blue)
set -g @sidebar_color_agent_claude 174 # Claude brand color (default: 174 terracotta)
set -g @sidebar_color_agent_codex 141 # Codex brand color (default: 141 purple)
set -g @sidebar_color_text_active 255 # primary text (active rows, counts, filtered repo label) (default: 255 white)
set -g @sidebar_color_text_muted 252 # secondary text (tree branches, empty-state messages, inactive bottom tabs, activity log labels) (default: 252 light gray)
set -g @sidebar_color_text_inactive 244 # body text of unfocused pane rows (prompt/response, idle hint) (default: 244 mid gray)
set -g @sidebar_color_port 246 # port numbers (default: 246 light gray)
set -g @sidebar_color_wait_reason 221 # wait reason text (default: 221 yellow)
set -g @sidebar_color_selection 239 # selected row background (default: 239 slightly lighter dark gray)
set -g @sidebar_color_branch 109 # git branch name (default: 109 teal)
set -g @sidebar_color_task_progress 223 # task progress summary (default: 223 pale yellow)
set -g @sidebar_color_subagent 73 # subagent tree (default: 73 green)
set -g @sidebar_color_commit_hash 221 # commit hash (default: 221 yellow)
set -g @sidebar_color_diff_added 114 # added diff lines (default: 114 green)
set -g @sidebar_color_diff_deleted 174 # deleted diff lines (default: 174 terracotta)
set -g @sidebar_color_file_change 221 # file change stats (default: 221 yellow)
set -g @sidebar_color_pr_link 117 # PR link / number (default: 117 blue)
set -g @sidebar_color_section_title 109 # section titles (default: 109 teal)
set -g @sidebar_color_activity_timestamp 109 # activity timestamps (default: 109 teal)
set -g @sidebar_color_response_arrow 81 # response arrow (default: 81 bright cyan)
# Icons (Unicode glyphs; defaults keep the current look)
set -g @sidebar_icon_all ≡ # status filter bar "all" icon
set -g @sidebar_icon_running ● # running status icon
set -g @sidebar_icon_waiting ◐ # waiting status icon
set -g @sidebar_icon_idle ○ # idle status icon
set -g @sidebar_icon_error ✕ # error status icon
set -g @sidebar_icon_unknown · # unknown status icon
run-shell ~/.tmux/plugins/tmux-agent-sidebar/tmux-agent-sidebar.tmuxThe sidebar stores agent status in tmux pane options, which you can read from your own scripts or status bar:
# Get a specific pane's agent status
tmux show -t "$pane_id" -pv @pane_status
# Returns: running / waiting / idle / error / (empty)
# Get agent type
tmux show -t "$pane_id" -pv @pane_agent
# Returns: claude / codex / (empty)This is useful for integrating agent status into your tmux status bar, custom scripts, or notifications.
If you build your own notifications, the same pane options can be used to drive them.
- Remove the
set -g @plugin(orrun-shell) line from yourtmux.conf - Remove hook entries or plugins from your Claude Code / Codex settings
- Remove the plugin directory:
rm -rf ~/.tmux/plugins/tmux-agent-sidebar
Symlink the plugin directory to your working copy so that builds are picked up without copying artifacts. If TPM already cloned the plugin, remove it first:
rm -rf ~/.tmux/plugins/tmux-agent-sidebar
ln -s <path-to-this-repo> ~/.tmux/plugins/tmux-agent-sidebarThen build — the binary that your local tmux sidebar loads is replaced in place. Toggle the sidebar off → on to pick up the new build.
cargo build --release
# or, enable the `debug` feature to force-display notices (version, missing hooks, claude plugin)
cargo build --release --features debugThis repository is itself a Claude Code marketplace (see .claude-plugin/marketplace.json). Because ~/.tmux/plugins/tmux-agent-sidebar is symlinked to the repo, the same install flow from 3.1 Claude Code already points Claude Code at your working copy:
/plugin marketplace add ~/.tmux/plugins/tmux-agent-sidebar
/plugin install tmux-agent-sidebar@hiroppy
After editing plugin files, pick up changes without reinstalling:
hooks/hooks.json,.claude-plugin/plugin.json,hook.sh— run/reload-pluginsin Claude Code (or restart it).- Rust sources —
cargo build --release, then toggle the sidebar off → on.
To iterate from a git worktree, register the worktree path as its own marketplace:
/plugin marketplace add <worktree-path>
/plugin install tmux-agent-sidebar@hiroppy

