ilmari
Minimal tmux popup radar that can be used standalone like a sidebar or as a tmux-popup.
Supported agent CLIs: Antigravity CLI (agy), Gemini CLI (gemini), Codex (codex), Amp (amp), Claude Code (claude), OpenCode (opencode), Pi (pi, pi-agent), Auggie (auggie), Grok (grok), GitHub Copilot CLI (copilot), and Kiro CLI (kiro-cli).
Planned agent CLI support: Cursor CLI (cursor), Aider (aider), Cline CLI (cline), Goose CLI (goose), and OpenHands CLI (openhands). PRs welcome: each linked CLI name opens its tracking issue.
Platform support
Ilmari is built for Unix-like tmux environments. The supported release artifacts are Linux and macOS binaries, and runtime usage assumes a Unix-like shell with tmux available. Windows is currently out of scope: no Windows release artifact is published unless Windows tmux behavior is implemented and tested.
Ilmari exists for the moment when a tmux workspace has multiple agent panes and you need to answer three questions quickly:
- which pane is still running
- which pane is waiting on you
- which workspace that pane belongs to
It opens as a tmux popup, inspects the panes you already have running, groups them by workspace, shows agent state plus a visible output excerpt, and jumps you straight to the selected pane.
Ilmari is popup-first and observer-only. It does not launch agents, manage workflows, or own your tmux layout. It gives you a fast index over the agent sessions that already exist.
What Ilmari Solves
When several agents are running at once, the normal tmux workflow gets noisy:
- waiting panes are easy to miss
- finished panes and still-running panes blur together
- workspaces get split across sessions and windows
- you end up cycling panes manually just to find the one that matters
Ilmari reduces that to a popup:
- detect supported agent panes from tmux metadata and output
- classify panes as running, waiting, finished, terminated, or unknown
- group panes by workspace path
- show lightweight git change context per workspace
- jump to the selected pane and get out of the way
Installation
Cargo (crates.io)
Homebrew
GitHub Releases
Download a prebuilt Linux or macOS archive from the GitHub Releases page,
extract it, and place ilmari on your PATH. Windows archives are not
published because Windows runtime behavior is not supported yet.
From source
Popup-First Setup
tmux popup support requires tmux 3.2 or newer.
1. Add a tmux binding
Assuming ilmari is already installed and available on your PATH:
bind-key i display-popup -E -w 90% -h 85% "ilmari"
Reload tmux after editing ~/.tmux.conf:
2. Open the popup
Press your tmux prefix, then the bound key.
Typical popup flow:
- open
ilmari - move selection with
j/kor arrow keys - press
Enterto jump to the selected pane - press
qorEscto quit
When ilmari is launched as a tmux popup, activation returns you to the target
pane and closes the popup.
Configuration
Ilmari configures through command-line flags and environment variables. It reads environment defaults first, then command-line flags override the same setting for that run.
| Flag | Purpose | Env fallback |
|---|---|---|
--refresh-seconds <SECONDS> |
Main tmux scan cadence | ILMARI_REFRESH_SECONDS |
--process-refresh-seconds <SECONDS> |
CPU and memory sampling cadence | ILMARI_PROCESS_REFRESH_SECONDS |
--palette <CSV> |
18-slot palette override | ILMARI_TUI_PALETTE, then ILMARI_PALETTE |
--no-tui |
Run headless without terminal UI | ILMARI_TUI=0 |
--no-git |
Start with git summaries hidden | none |
--no-output-tail |
Skip pane output tail capture | ILMARI_OUTPUT_TAIL=0 |
--no-bell |
Disable terminal bell alerts | none |
--socket |
Enable local JSON socket publishing | ILMARI_SOCKET=1 |
--no-socket |
Disable local JSON socket publishing | ILMARI_SOCKET=0 |
--socket-path <PATH> |
Local JSON socket path override | ILMARI_SOCKET_PATH |
--mcp |
Enable loopback MCP resource server | ILMARI_MCP=1 |
--no-mcp |
Disable loopback MCP resource server | ILMARI_MCP=0 |
--mcp-port <PORT> |
Loopback MCP port, 0 chooses a free port |
ILMARI_MCP_PORT |
--help / -h |
Print help | none |
--version / -V |
Print version | none |
| Variable | Purpose | Default | Notes |
|---|---|---|---|
ILMARI_REFRESH_SECONDS |
Main tmux scan cadence | 5 |
Positive integer seconds. Empty, invalid, or non-positive values fall back to the default. |
ILMARI_PROCESS_REFRESH_SECONDS |
CPU and memory sampling cadence | 15 |
Separate from the main refresh so ilmari does not call ps on every redraw. Empty, invalid, or non-positive values fall back to the default. |
ILMARI_TUI |
Terminal UI | enabled when compiled with feature tui |
Set to 0, false, no, or off to run headless. |
ILMARI_OUTPUT_TAIL |
Pane output tail capture | enabled | Set to 0, false, no, or off to skip tmux capture-pane output tail capture. |
ILMARI_SOCKET |
Local JSON socket publisher | disabled | Set to 1, true, yes, or on to enable. |
ILMARI_SOCKET_PATH |
Local JSON socket path | temp dir path scoped by user and tmux socket | Setting a path enables the socket unless ILMARI_SOCKET=0 is also set. |
ILMARI_MCP |
Loopback MCP resource server | disabled | Set to 1, true, yes, or on to enable. |
ILMARI_MCP_PORT |
Loopback MCP port | 0 |
Setting a port enables MCP unless ILMARI_MCP=0 is also set. |
ILMARI_TUI_PALETTE |
Primary palette override | terminal ANSI theme | Takes an 18-slot CSV palette. Takes precedence over ILMARI_PALETTE. |
ILMARI_PALETTE |
Compatibility alias for palette override | terminal ANSI theme | Used only when ILMARI_TUI_PALETTE is unset. |
Examples:
ILMARI_REFRESH_SECONDS=10
ILMARI_PROCESS_REFRESH_SECONDS=30
ILMARI_OUTPUT_TAIL=0
ILMARI_SOCKET_PATH=/tmp/ilmari.sock
Build-time features
The default Cargo build includes the TUI and both endpoint implementations:
Features can be removed at build time:
Feature meanings:
| Feature | Effect |
|---|---|
tui |
Builds the terminal UI and pulls in ratatui and crossterm. |
socket |
Builds the local Unix-domain JSON socket endpoint. |
mcp |
Builds the loopback MCP resource endpoint and pulls in rmcp, axum, tokio, tokio-util, and MCP annotation timestamp support. |
rmcp |
Alias for mcp, for builds that name the backing crate explicitly. |
Runtime flags remain parseable when an endpoint is compiled out. Enabling a
compiled-out endpoint reports a status warning such as socket support was not compiled in or MCP support was not compiled in. Builds without feature tui
run in headless mode.
Local JSON socket
When enabled, Ilmari publishes a local Unix-domain socket while it is running. The socket is not a network listener. It accepts one line commands and returns one JSON object per request:
ping
list
ls
detail 12
detail %12
detail ilmari://1/7/12
detail accepts bare pane numbers like 12, tmux pane ids like %12, and
prefixed ids like tmux:%12, plus Ilmari resource URIs. Responses use the
canonical tmux pane id form.
When Ilmari successfully owns the socket, it also writes the path into the tmux
global option @ilmari_socket_path so connector processes can discover it from
tmux. If another Ilmari process already owns the same socket, the later process
keeps running without taking over that endpoint.
list returns a compact action queue for consumers. Items include the pane id,
resource URI, consumer state, agent slug, current workspace path, and a prebuilt
tmux argv command where an immediate tmux action is useful. Finished sessions
use the result intent:
MCP resources
When enabled with --mcp or ILMARI_MCP=1, Ilmari starts a local-only MCP
Streamable HTTP server on 127.0.0.1. --mcp-port 0 asks the OS for a free
port. The server publishes its URL to the tmux global option
@ilmari_mcp_url, for example http://127.0.0.1:58321/mcp.
The MCP server exposes resources only. It does not expose tools. Resource
descriptors and contents carry _meta.readOnly = true. Resource descriptors are
annotated for assistant audiences with priorities and lastModified
timestamps.
Available resources:
| Resource | Shape |
|---|---|
ilmari://list |
Same JSON as socket list. |
ilmari://<session>/<window>/<pane> |
Same JSON as socket detail, using sigil-free tmux ids such as ilmari://1/7/12. |
Resource subscriptions are supported through MCP resources/subscribe.
Subscribers to a pane URI receive notifications/resources/updated when that
pane resource changes. Subscribers to ilmari://list receive
notifications/resources/updated when the list JSON changes and
notifications/resources/list_changed when the visible resource set changes.
State mapping:
| Ilmari status | Consumer state | Next intent |
|---|---|---|
running |
running |
wait |
waiting-input |
needs-input |
inspect |
finished |
done |
result |
terminated |
gone |
cleanup |
unknown |
unknown |
inspect |
Pane output privacy
By default, Ilmari captures a small recent tail from supported agent panes with
tmux capture-pane so it can classify waiting states and show the latest output
excerpt. That pane buffer/history text may contain prompts, command output, file
paths, tokens, or other sensitive information. If you do not want Ilmari to read
pane contents, disable output tail capture with ILMARI_OUTPUT_TAIL=0; pane
tails remain enabled by default unless that variable is set to 0, false,
no, or off.
Ilmari uses semantic color roles in code, but by default those resolve through
your terminal's current ANSI palette. If you want explicit colors, provide an
18-slot CSV palette override using ILMARI_TUI_PALETTE or ILMARI_PALETTE.
Slot order:
fg,bg,black,red,green,yellow,blue,magenta,cyan,white,bright_black,bright_red,bright_green,bright_yellow,bright_blue,bright_magenta,bright_cyan,bright_white
Accepted color formats:
#RRGGBB0xRRGGBB0XRRGGBBRRGGBBrgb:RR/GG/BBrgb:RRRR/GGGG/BBBB
Behavior:
ILMARI_TUI_PALETTEtakes precedence overILMARI_PALETTE- empty or malformed palette values are ignored
- if neither is set,
ilmariuses the terminal's default ANSI theme