tmux + AI agents

Session visibility
for your agents.

jawn-tmux watches your tmux sessions and shows you what your AI agents are doing — with colored pane borders, a live sidebar, and cross-node status across machines.

version Python 3.11+ platform license
houseofjawn — tmux 3.5a
jamditis@houseofjawn:~$ jt status houseofjawn 16:42:05 main active 52h claude morning-wake active 4m claude Checking email... Found 1 transcript. checkin-wake silent ~ 12m bash No new transcripts. jamditis@houseofjawn:~$ [0] main [1] morning-wake [2] checkin-wake houseofjawn morning-wake — claude Processing transcript... ✓ Read 3 action items Checking calendar... ✓ 2 events found Drafting summary... ● active checkin-wake — bash No new transcripts found. Email check: 0 new. CLAUDE_TASK_COMPLETE:0 ~ silent port :6248 · jtd running

overview

What is jawn-tmux?

When you run multiple AI agents in parallel tmux sessions, it's hard to tell what's happening without switching between each one. jawn-tmux solves that with a lightweight daemon that watches all your sessions and gives you instant visual feedback.

Visual pane attention

Pane borders change color automatically — green when an agent is active, amber when it's gone silent, gray when done, red on error. No switching required.

Live sidebar

A 36-column pane on the right edge of your terminal shows all sessions, their statuses, and the last few lines of output — always visible while you work.

Cross-node status

Running agents on multiple machines? jt nodes aggregates status from all your configured nodes over Tailscale in one combined view.

session states

Each session is classified every 2 seconds by the daemon based on output activity.

active Output in the last 20 seconds
silent No output for 20+ seconds
done CLAUDE_TASK_COMPLETE:0 marker seen
error Non-zero exit code in marker

architecture

How it works

Two processes. One writes state, one reads it. No dependencies beyond the Python standard library and tmux itself.

jtd — daemon

Runs as a systemd user service

  • Polls tmux list-sessions every 2 seconds
  • Computes status from output activity and exit markers
  • Updates pane border colors via tmux select-pane -P
  • Writes /tmp/jt-state.json atomically
  • Serves JSON on port 6248 for cross-node polling

jt — CLI

Reads state, controls sessions

  • Reads /tmp/jt-state.json directly (no subprocess)
  • Renders a table, watch loop, or popup
  • Spawns, kills, and attaches to sessions
  • Fetches remote nodes via HTTP for jt nodes
state schema — /tmp/jt-state.json JSON
// written by jtd every 2 seconds { "node": "houseofjawn", "updated_at": 1740000000, "sessions": { "morning-wake": { "status": "active", // active | silent | done | error "command": "claude", "elapsed_secs": 720, "last_activity_secs": 8, "output_tail": ["Checking email...", "Found 1 transcript."], "output_file": "/tmp/claude_scheduled_1740000000.txt" } } }
tmux keybindings

Ctrl+B a — popup

Quick interactive status overlay

  • Shows all sessions + output tails
  • Press k to kill a session by name
  • Press q to dismiss

Ctrl+B A — sidebar

Toggle the live watch pane

  • Opens a 36-column right pane running jt watch
  • Refreshes every 2 seconds
  • Press again to close it

getting started

Install

Requires Python 3.11+, tmux 3.0+, and systemd. Works on Linux ARM64 (Raspberry Pi), x86_64, and WSL2.

step 1
Clone the repo
git clone https://github.com/\ jamditis/jawn-tmux.git \ ~/projects/jawn-tmux
step 2
Run the installer
cd ~/projects/jawn-tmux chmod +x install.sh ./install.sh
step 3
Verify it's running
systemctl --user status jtd jt status
what install.sh does
# 1. Install the jt + jtd entry points pip3 install --break-system-packages -e . # 2. Add keybindings to ~/.tmux.conf (idempotent) source-file ~/projects/jawn-tmux/tmux/jt.conf # 3. Install and start the systemd user service systemctl --user enable --now jtd
multi-node setup

To monitor sessions across multiple machines, edit ~/.config/jt/nodes.json with each node's Tailscale IP.

houseofjawn
100.122.208.15:6248
─── jt nodes ───
officejawn
100.84.214.24:6248
───
yournode
<tailscale-ip>:6248
~/.config/jt/nodes.json JSON
[ { "name": "houseofjawn", "ip": "100.122.208.15", "port": 6248 }, { "name": "officejawn", "ip": "100.84.214.24", "port": 6248 } ]

reference

Commands

All commands read local state from /tmp/jt-state.json — no subprocess overhead for status queries.

command description
jt [status] Print a table of all local sessions with status, elapsed time, and output tails.
jt watch Live re-render loop (2s interval). Used by the sidebar pane.
jt popup Interactive status popup via tmux display-popup. Press q to close, k to kill a session.
jt sidebar [on|off|toggle] Toggle a 36-column persistent right pane running jt watch.
jt spawn <name> <cmd> Create a named tmux session running the given command.
jt kill <name> Kill a tmux session by name.
jt attach <name> Attach to a named tmux session.
jt nodes Aggregate and display status from all configured nodes via HTTP. Unreachable nodes are shown as such.

prior art

Inspired by cmux

jawn-tmux exists because of cmux — a native macOS terminal emulator built on Ghostty that pioneered the idea of visual session state for parallel AI agent workflows. cmux adds blue ring indicators when agents need attention, a vertical sidebar per workspace showing git branches, port status, and notification history, and a built-in scriptable browser. It has 2,300+ GitHub stars and is the reference implementation of this concept on macOS.

jawn-tmux is the Linux answer to the same problem. If you're on macOS and using Ghostty, go use cmux — it's much more complete. jawn-tmux is for everyone running headless Linux servers, Raspberry Pis, WSL2, and SSH sessions where a native macOS app simply isn't an option.

comparison

Where they overlap and where they diverge.

capability jawn-tmux cmux
Platform Linux, WSL2, ARM64 macOS only
Terminal Add-on to existing tmux sessions Full emulator — replaces your terminal app
Language / deps Python stdlib, zero runtime deps Swift + AppKit, native macOS frameworks
Session indicators Pane border colors (green / amber / gray / red) Blue ring on pane + tab highlight when agent needs attention
Sidebar Live 36-col pane showing session table (jt sidebar) Vertical tabs with branch, PR status, ports, notifications per workspace
Cross-node status HTTP polling — jt nodes aggregates any number of machines Not built-in
Built-in browser No Yes — scriptable via accessibility tree and element refs
Headless / SSH Works fully over SSH, no display required Requires a macOS display
Install ./install.sh — pip + systemd user service macOS app bundle
Maturity v0.1.0, early 2,300+ stars, active community

TL;DR   macOS + Ghostty user? Use cmux. Linux / SSH / Raspberry Pi user? You're in the right place.