heddle: your agent knows more than it is telling you
I run coding agents over Matrix. It is a genuinely good arrangement — the agent lives on a server, I talk to it from whatever machine I happen to be holding, and the history is encrypted and syncs everywhere without my having to build any of that. The weak link is the client. Every Matrix client I tried treats an agent session as the thing it superficially resembles: a chat log.
So when the agent edits a file, this is what arrives:
🔧 edit: "src/main.rs..."
No result. No diff. No exit code. No duration. The agent knew every one of those things — it had the typed tool call, the result and the timing sitting in memory — and then flattened the lot into a single human-readable string on the way out the door. A client reading only that is permanently capped at pretty chat. No amount of cleverness at my end recovers information that was never sent.
heddle is two weekends of doing something about it.
The idea worth stealing
Matrix already has the hierarchy. Spaces contain rooms, rooms contain threads. If your agent opens a thread per session — mine does, automatically — then the structure you want is already sitting there in the protocol, fully populated, and no client is drawing it.
| heddle | Matrix | What it is to you |
|---|---|---|
| Workspace | Space | A project |
| Tab | Room | A lane of work within it |
| Pane | Thread | One live agent session |
A room full of agent threads is a workspace full of agent panes. heddle just renders it that way: tiled, tabbed and keyboard-driven, with the prefix key on ctrl+a so the muscle memory transfers straight from tmux. That is the whole conceit. Everything else is execution.
What it is actually like to use
- Tool calls arrive as collapsible cards with a status glyph and a duration. Failures expand themselves and mark the gutter red, on the grounds that those are the ones you wanted to see anyway.
- A diff renders as a diff, with a proper gutter. JSON renders as a tree you can fold. Markdown renders as markdown. Long output folds itself rather than burying the pane.
- Every pane carries a state — blocked, working, done, idle — which rolls up into the tab and then the workspace, so a single badge tells you which of six parallel sessions is the one waiting on you.
- When an agent asks permission, you press
yornand there is a live countdown. It only steals focus if nothing else is mid-flight, because being yanked out of a running session to approve something trivial is its own small tragedy. - End-to-end encryption throughout — device verification, cross-signing, key backup, the lot. Unglamorous, and not something a client holding every Megolm key your device has seen gets to skip.
On the name: a heddle is the part of a loom that guides an individual thread through the warp. Threads are the core abstraction here. The metaphor was too neat to pass up.
The honest part
heddle is version 0.2.0 and about eight days old. Nothing in it has been run by anyone who did not write it.
Two things I would want to know before installing a stranger’s weekend project.
The lossless path has no producer yet. heddle can read a structured payload attached alongside the plain message — the real tool call, result, exit code and timing, travelling intact. Nothing currently emits it. So in practice every message today goes through the fallback parser, which reconstructs what it can from the printed output and marks the pane with a dim ~ to say so. That mark is deliberate and it is staying. I would rather show you that something was lost than quietly pretend it was not.
It is an agent client, not a chat client. It cannot join a room, upload a file or render an image. Those were deferred on purpose and it is a real limitation, not a coming-soon. If what you want is a general-purpose Matrix TUI, iamb and gomuks are both excellent and this is emphatically not that.
It also requires a homeserver with native sliding sync. That is a hard requirement with no fallback path by design — Synapse is verified, others may simply not work. heddle --check will tell you before you waste an evening on it.
Get it
Static binaries for x86_64 Linux, glibc and musl, are on the releases page — no Rust toolchain needed. Or build it yourself if you would rather.
→ github.com/SynthSwarm/heddle
Apache-2.0, issues are open. I would particularly like to hear from anyone whose agent setup looks nothing like mine: the adapter layer is a lookup table rather than a bespoke parser precisely so that teaching it a second agent is a small change instead of a rewrite.