Muninn
An open-source macOS menu-bar companion for CLI coding agents. When a turn ends it knocks, tells you what the agent did, and keeps the reasoning, so you can walk away.

Muninn is an open-source macOS menu-bar companion for the coding agents that live in your terminal. A terminal cannot tap you on the shoulder. Claude Code, Codex, every CLI agent finishes into a window you are not looking at, so you either poll it or scroll a feed while you wait. Muninn fixes both halves. It knocks the moment a turn ends with a one-line summary of what the agent did and the reasoning behind it, and while the turn runs it gives your attention somewhere to rest that is not a feed.
The name is Odin's raven. Huginn and Muninn fly out over the world each day and return at dusk to tell him what they saw. Muninn is the one that carries memory.
One command installs it from inside a project, registers the Claude Code hooks, and drops the summary contract into the repo. No Rust, no Node, no account.
What it does
- The knock. Three soft, identical, evenly spaced tones when a turn ends, and a lower one when the agent is asking rather than finishing. Silent at night by default. It never escalates
- The panel. Top right, without taking focus, and it does not time out, because the premise is that you were not at the desk. Did it work, do you need to act, what happens next: answered before you touch anything
- The reasoning. A Details window with the agent's own explanation of how the change works, which function does what, and the constraint that ruled out the alternative. So the code stays yours
- The honesty rule. Muninn renders what the agent wrote and never vouches for it. "Tests pass" is shown as a quotation, labelled reported. A missing summary says finished, no summary. It is never invented
- History. The last fifty turns with the prompts that caused them, in a plain JSON file on disk. Searchable, exportable as Markdown
- While you wait. Off by default: Minesweeper in a 5×5×5 volume, a first-person maze, chess against a local Stockfish, a runner, a drifting raven. One thread of attention instead of a feed, and the summary always wins the screen
Everything is local. No account, no server, no telemetry. The payload is read from a hook and written to your disk, and the app works with the wifi off.
How it is built
- The shim. Claude Code fires hooks and hands over a JSON payload that already contains the agent's closing message. A 320 KB zero-dependency Rust binary forwards it to a local receiver and exits within 500 ms no matter what, so the agent never waits. If Muninn is not running, the payload spools to disk and the panel is waiting at next launch
- The receiver. Bound to 127.0.0.1 only, token-authenticated, rejecting anything that carries an Origin header. Payloads hold your working directory and the agent's full output, so nothing leaves the machine
- The app. Tauri and Rust, in three crates: shared types, the forwarding shim, and the app itself. The front end is vanilla TypeScript, and the games are TypeScript modules on Three.js with a tiny contract: draw, pause when told, snapshot once a second
- The contract.
MUNINN.mdteaches the agent to end each turn with a structured block: done, changed, verified, next, blocked, risk, explain. The parser keeps a raw fallback, so a missing or malformed block still renders the message - The site. Next.js with its own SQLite, counting visits and downloads without a cookie or a third party. The design tokens are shared with the app, so the page and the product cannot drift apart on colour
- The seams. Another agent is one file. Another OS is fenced and labelled. Another game is one module. The repo is MIT, small enough to read in an afternoon, and built to take contributions
Why I built it
I run coding agents on tasks that take five to thirty minutes, and I wanted to leave the desk and come back informed without replaying a terminal. The tools that existed answered "is it still running" and "how much have I spent". Muninn answers "what did it do". The moat, such as it is, is the summary contract: the value comes from shaping the agent's output at the source, which a passive monitor cannot do.