treacle

A workspace for Claude Code and Codex sessions, on the Mac you leave on.

Six agents running.One window shows them all.The terminal is still yours.

Six agents running.One screen shows them all.The terminal stays yours.

Treacle is a visual layer over the coding-agent sessions on your Mac. Every worktree and every session on one screen, a lamp that says who is working and who is waiting, and the questions as cards you answer in place. tmux and git worktrees underneath, so nothing is hidden from you. A Chrome app at the desk, the same app on your phone, so nothing is tied to a device.

Treacle is a visual layer over the coding-agent sessions on your Mac. Every worktree and every session on one screen, a lamp that says who is working and who is waiting, and the questions as cards you answer with a tap. tmux and git worktrees underneath, so nothing is hidden from you. The same app you use at the desk, on the phone in your pocket.

$ curl -fsSL https://treacle.dev/install | sh

macOS on Apple silicon. Needs tmux and an agent you already run. Self-hosted, one binary, no account. Then treacle setup on the Mac that stays on.

Treacle⋮
9:41▰▰▰

treacle

7 worktreesboard+ folder🔊🔔
needs you1
harbour : hbr-212-rate-limit-invites Rate-limit invite links ↳ claude · harbour 3m ago
✕
Commit and open the PR?
HBR-212 is done. Type-check, lint and 1,212 unit tests are green. Nothing is committed yet.
Yes, open itAmend the last commitother…
›harbour 21 3 worktrees
hbr-212-rate-limit-invites3m agofocusedHBR-212PR #114
Adding a per-inviter token bucket, then a 429 with a retry hint.
Rate-limit invite links3m✕
+ tab⌖ host🗑 delete
hbr-219-webhook-backoff12m agoHBR-219
Retrying the webhook relay with backoff instead of dropping the event.
claude · harbour12m✕
zsh · harbour1h✕
main2h agocheckoutPR #109 merged
codex · harbour2h✕
›treacle 1 2 worktrees
›tidepool1 worktree
2 quiet folders ›

Terminals don't scale past three agents.

See everything. One worktree per ticket, one agent per worktree, and you are cycling through six tmux windows to find the one that stopped. Treacle puts them on one screen: a lamp per session, a subject line per worktree, the ticket and the PR, how much context and quota is left. The sessions waiting on you go to the top, with the question and its options as buttons.

Keep control. Every card has a box for answering in your own words. The mode chip cycles plan and auto. Send becomes stop while the agent works. Deleting a worktree with uncommitted changes makes you type CLOSE. And the raw tmux pane is one clicktap away, because it is the same pane: quit treacle and your shells are exactly where you left them.

Any device. Install it as a Chrome app and it lives in the Dock with a badge that counts the inbox. Open the same address on your phone and it is the same app, with push notifications for when you are away from the desk. Served over your tailnet from your own Mac. No cloud in the middle.

Any device. Add it to the home screen and the icon counts the inbox; a push finds you when a session needs you. Back at the desk it is a Chrome app in the Dock, the same app at the same address. Served over your tailnet from your own Mac. No cloud in the middle.

Everything the terminal says, said better.

The same session, twice. On the left, what tmux shows. On the right, what treacle shows: tool calls as one-line rows, edits as real diffs, the agent's reply as rendered markdown, and the question as a card you can answer. Both are live. Type in either and the other follows.

the tmux panethe same session in treacle
Treacle⋮
9:41▰▰▰
‹
harbour : hbr-212-rate-limit-invitesRate-limit invite links
workingAUTOterm
+/Tell the agent…●Send

Decisions in place, not in scrollback.

Questions become cards. Permission prompts too.

Claude Code's hooks tell treacle the instant a session is waiting on you, so the lamp flips to needs-you before you would have noticed in the terminal. The question lands in the inbox with its options as buttons, and as a push notification with the same buttons if the app is closed.

Start a session with TREACLE_REMOTE_PERMISSIONS=1 and gated shell commands arrive as an Allow or Deny card with the full command shown. Ignore it and the terminal prompt takes over after two minutes, as it always did. Nothing is ever auto-approved.

An agent can also ask on purpose. Over MCP it can put up a choice, or a whole proposal with Approve and Reject, and block until you answer. Dismiss the card and it is told it was dismissed, not answered.

Treacle⋮
9:41▰▰▰
‹
treacle : fold-quiet-foldersFold quiet folders behind one row
needs youPLANterm
decision
Allow Bash?
bun test packages/web
Allow
run it, this once
Deny
block this call — the agent is told no
decision
Approve the migration plan?

Split the folders table. Move quiet-folder state into its own table so a collapse never rewrites a repo row.

Two migrations, both reversible. No data moves.

Approve
go ahead as proposed
Reject
do not do this
Or answer in your own words…Send
+/Tell the agent…●Send

The header knows the state of the work.

Name a branch the Linear way and the session links its ticket, with the ticket's title and status once you add an API key. The PR comes from gh and shows its checks and review state. A plan the agent publishes pins under the header and ticks off in place as it works.

The strip at the bottom is the part you usually have to squint at: the model, the account, how many files changed and by how much, how full the context is, and how much of the five-hour and seven-day usage windows is gone. It turns amber past 80%.

AUTO / PLAN
clicktap the chip to cycle the agent's mode, the same as Shift+Tab
■ stop
Send becomes stop while the agent is working; it sends Escape
term
the real pane, cursor-true, with a key bar for esc, tab, ^C and the arrows
Treacle⋮
9:41▰▰▰
‹
harbour : hbr-212-rate-limit-invitesRate-limit invite links
workingAUTOterm
plan3/4Cover the burst case in tests›
✓Add a token bucket per inviter
✓Return 429 with a retry hint
▸Cover the burst case in tests
·Note the limit in the API docs
⏺Edit invites.ts +6 −1
⏺$ bun test src/invites
claude
The bucket refills at ten a minute per inviter, and a burst past it returns 429 with a retry-after. Both read the same clock, so they can't disagree.
working…
opus-5you@example.comΔ 4 files +42 −7ctx 118k/200k5h 41%7d 83%
+/Tell the agent…●■ stop

The real terminal is one clicktap away.

Cursor-true tmux mirroring over control mode, in the same window. Select, Paste and Copy for the things a browser is bad at, and a key bar for esc, tab, the control keys and the arrows for when there is no keyboard. Interactive commands open here on their own. It is the same pane you would attach to from a shell, so nothing treacle shows you is a summary of something you can't see.

Cursor-true tmux mirroring over control mode. A key bar for esc, tab, the control keys and the arrows, because a phone keyboard has none of them. Select, Paste and Copy for the rest. Interactive commands open here on their own. On an iPad with a keyboard it is a place you can work from, not just check on.

Treacle⋮
9:41▰▰▰
‹‹Rate-limit invite links+SelectPasteDone
● Now the full suite, to catch anything the bucket change disturbed: Ran 3 shell commands ● Duplicate import from the same barrel, folding it in: Ran 2 shell commands ● HBR-212 is done. Both acceptance criteria are met, and the gate is green: type-check, lint, and 1,212 unit tests across 96 files. What changed 1. A token bucket per inviter — src/invites/bucket.ts:12 Ten a minute, refilled on read. The bucket key is the inviter id, so a burst from one account cannot starve another. 2. 429 with a retry hint — src/invites/route.ts:41 A burst past the limit returns 429 and a retry-after header computed from the same clock the bucket reads. Tests - bucket.test.ts covers refill, the burst boundary either side, and two inviters sharing a second. - route.test.ts pins the header value against a frozen clock. One thing to flag - Password resets are still unlimited. Same shape, same fix. Worth a follow-up ticket if you agree. ● Baked for 6m 02s · done 9:41 AM ❯ hbr-212 git:(hbr-212-rate-limit-invites) [Opus 5] ctx:41% ▶▶ auto mode on (shift+tab to cycle) · PR #114 · ← 2 agents
^esctab^C^D^Z^R↑↓←→⏎

The status line at the bottom is Claude Code's own. The key bar underneath is treacle's, and matters most on a tablet.

A board for work that outlives a session.

A session is a conversation. A task is a thing that has to be finished. The board holds the second kind, and it will not take a wish: every task needs a definition of done and, ideally, a command that proves it. Flip between sessions and board with one button in the header.

Start cuts the worktree and briefs the agent.

ClickTap start on a ready task and treacle creates a worktree from the base ref, writes the brief to .treacle/task.md, launches the agent you chose and sends the opening message. Watch it in the session feed or go and do something else.

The agent reports back over MCP: a note, a link, or done. Done runs the task's check command in the worktree and moves the task to review, where it waits for you with the evidence and a diff against base. Accept, or send it back with a reason.

Tasks can wait on other tasks, be blocked with a reason, and be given grants: things the agent may see. The board says what is running now, what is next up, what is proposed, what is blocked, and what got done today.

Treacle⋮
9:41▰▰▰

treacle

connectedsessions+ folder🔊🔔
now
⬤
harbour: Rate-limit invite linkswants review
3m ago
▮
harbour: Retry the webhook relayworking
12m ago
next up · 2 ready
○
treacle: Fold quiet folders behind one rowafter Inbox counts the worktree
○
tidepool: Rebuild the photo index nightly
+
task
proposed · 1
○
treacle: Usage figures say how old they aredraft
1 blocked›
3 done today›

A task you can read.

Open a task and you get what it is for, what would count as finished, the check that proves it, and every attempt with what it produced. The changes tray shows the files against base with a diff you can unfold.

Drafting one takes a title, a done-when, an intent, a check command, an agent and a base ref. The hint under done-when says it plainly: the board is not for wishes.

Treacle⋮
9:41▰▰▰
Rate-limit invite links review
projectharbour
intentOne account must not be able to mint invite links without limit. Leave the invite schema alone.
done whenInvites are capped per inviter, a burst returns 429 with a retry hint, and tests cover both.
checkbun test
runs asClaude · from main · harbour
afternothing — can start any time
attempt · donehbr-212-rate-limit-invites · Claude
check ✓   note · 1,212 tests, 96 files
link · PR #114
changes4 files against main
invites.ts +18 −2
bucket.ts +9 −3
send back…accept

Worktrees and tabs, without touching a shell.

New branch, new worktree, pick the agent.

Every registered repo lists its worktrees as cards with a colour, the branch, the ticket and PR pills, and a one-line subject a small model writes about what is going on in there. Tabs are tmux sessions, busiest first, each with a lamp. Merged work shows purple at a glance.

Add a worktree with a branch name and a base. Add a tab with Terminal, Claude or Codex, and pick the account if you have more than one. Codex sessions get a feed and question cards of their own.

Deleting refuses while anything is running or uncommitted in there, says which, and makes you type CLOSE to override it. Folders with nothing going on for a day fold away behind one row.

Treacle⋮
9:41▰▰▰
new worktree in harbour
branchhbr-231-audit-loga Linear-style name links its ticket
frommainthe branch to cut it from — blank uses the checkout's HEAD
CancelNext
new worktree hbr-231-audit-log
Terminal›
Claude2 accounts›
Codex›
Cancel

The same app, wherever you are.

It is one web app on your own Mac. Chrome installs it as a desktop app with its own window and a Dock badge. Your phone adds it to the home screen. Your iPad gets the terminal with a key bar. They all reach the same server over your tailnet, and none of them holds any state, so you can pick up on one exactly where you left off on another.

9:41▰▰▰

treacle

7 worktreesboard🔊🔔
needs you1
harbour : hbr-212-rate-limit-invitesRate-limit invite links↳ claude · harbour3m ago
✕
Commit and open the PR?
HBR-212 is done. Type-check, lint and 1,212 unit tests are green.
Yes, open itAmend the last commitother…
›harbour213 worktrees
hbr-212-rate-limit-invitesHBR-212PR #114
Rate-limit invite links3m

On the phone, the whole app. The inbox and its buttons, every session's feed, the board, worktrees, the terminal. The compose box types straight into the pane, so iOS dictation just works, and a mic button sends audio to whisper.cpp on the host.

9:41
Tuesday 8 September
harbour : hbr-212now
Commit and open the PR?
Yes, open it · Amend the last commit
treacle : fold-quiet-folders2m ago
finished a turn — waiting for you
2
the icon counts the inbox

A push finds you, and only when it should. Web Push from your own host, only while the app is closed, only for a session flipping to needs-you, a decision opening, or an agent calling notify. It carries the question and its options. Tapping it opens that session. While the app is open it chimes instead.

claude
Both routes now share the bucket. Do you want the same limit on password resets, or leave it for a follow-up ticket?
0:07
+/leave resets for a follow-up, open the PR●Send

Talk to it. Tap the mic, speak, tap again, and the words land in the compose box for a glance before you send. Audio goes to the host over the tailnet and whisper.cpp transcribes it there. One command installs the model.

Treacle⋮

treacle

7 worktreesboard+ folder🔊🔔
needs you1
harbour : hbr-212-rate-limit-invitesRate-limit invite links↳ claude · harbour3m ago
✕
Commit and open the PR?
HBR-212 is done. Type-check, lint and 1,212 unit tests are green. Nothing is committed yet.
Yes, open itAmend the last commitother…
›harbour213 worktrees
hbr-212-rate-limit-invites3m agofocusedHBR-212PR #114
Adding a per-inviter token bucket, then a 429 with a retry hint.
Rate-limit invite links3m✕
+ tab⌖ host🗑 delete
hbr-219-webhook-backoff12m agoHBR-219
claude · harbour12m✕

At the desk, a Chrome app. Its own window next to your editor, no address bar, the same inbox and feed and board. Wider, so the worktree cards carry their actions and the terminal view has room.

2

In the Dock, with a badge. The icon counts the inbox the same way the phone's does, and Chrome delivers the same push notifications when the window is closed.

Install app?
Treacle
mini.tail0000.ts.net
CancelInstall

One click to install. The icon at the end of Chrome's address bar. No download, nothing to update by hand: the app updates itself whenever the server does.

From curl to a Dock iconthe home screen in one sitting.

Setup is a walkthrough, not a checklist. It ticks off what it can do itself, asks about the two things that edit Claude Code's config, and does not call the host reachable until a device of yours has actually loaded the app. Re-run it after every update; it only changes what changed.

1

Install the binary

One file. It is the server, the CLI, the MCP server and the hooks. The installer puts it in ~/.treacle/bin, links it into /usr/local/bin when it can, and otherwise adds it to your shell's PATH once.

zsh · the Mac that stays on
$ curl -fsSL https://treacle.dev/install | sh pouring treacle ... installed: /usr/local/bin/treacle next, on the machine that stays on: treacle setup
2

Run treacle setup

Six things happen on their own: an access token, a tmux config, the web app, and a launchd service that keeps the server up across reboots. Then it asks which repos to manage and whether to wire up Claude Code. The last step is the only one that can fail, and when it does, setup walks you through fixing it.

treacle setup
treacle agents on a machine that stays on ──────────────────────────────────────── ✓ Access token generated ✓ tmux config installed ✓ Shell cleanup nothing to do ✓ Web UI embedded in the binary ✓ Background service installed and started ⠋ Remote access setting up the host…
treacle setup · folders
Folders to manage git repos found nearby — the phone lists these ▸ ◉ harbour ~/Dev ◉ treacle ~/Dev ◉ tidepool ~/Dev ◯ dotfiles ~ ↑↓ move · space toggles · a all · enter continues
treacle setup · Claude Code
Wire up Claude Code both are opt-in because they edit Claude Code's own config ▸ ◉ Claude Code hooks status, feed, questions on the phone edits ~/.claude/settings.json ◉ treacle MCP agents push documents, diffs, decisions edits Claude Code's config space toggles · enter applies
treacle setup · remote access
Nothing can reach this machine yet Tailscale is not installed, so nothing outside this machine can reach treacle. Install Tailscale — it is the private network your other devices join. ▸ Install Tailscale for me (Homebrew) enter to do it · s to skip

The remote-access walkthrough has one screen per state. Not installed, not signed in, HTTPS certificates off in your tailnet, no other device on the tailnet yet. Each offers to do the fix, opens the right page, and checks again. If the Mac you are sitting at is the host, you can skip this and open it on localhost; come back to it when you want other devices in.

3

Open the address it prints

Setup ends with the URL, the token, and a QR code that carries the token in the URL fragment, so the token never reaches an access log and there is nothing to type on a phone. Then it waits, for up to two minutes, until a device of yours has loaded the app, and names the device that did.

treacle setup · done
treacle ✓ host set up ✓ Access token generated ✓ tmux config installed ✓ Shell cleanup nothing to do ✓ Web UI embedded in the binary ✓ Background service installed and started ✓ Remote access https://mini.tail0000.ts.net Access token (also in ~/.treacle/config.json): a3f9…c41e Scan to open it on your phone — no typing: Waiting for a device to open it… (Ctrl-C to skip — the host is already set up) ✓ MacBook ProiPhone reached it over https://mini.tail0000.ts.net Check everything any time with: treacle doctor
4

Install it as an app, then clicktap the bell

In Chrome, the install icon at the end of the address bar puts Treacle in the Dock with its own window and a badge that counts the inbox. On the phone, Share then Add to Home Screen does the same. ClickTap the bell in the header once to allow notifications. The app updates itself whenever the server does.

mini.tail0000.ts.net⋮
Install app?
Treacle
mini.tail0000.ts.net
CancelInstall

Chrome on the Mac: one click, its own window, a Dock icon.

Treacle
mini.tail0000.ts.net
Copy⧉
Add to Home Screen⊞
Add Bookmark☆

Safari on the phone: Share, then Add to Home Screen.

treacle

connectedboard🔊🔔
needs you1
harbour : mainclaude · harbournow
✕
finished a turn — waiting for you

Bell on. The first session to stop shows up here.

TREACLE_REMOTE_PERMISSIONS=1 claude

Per session. Gated Bash calls become Allow or Deny cards in treacle, with the command shown in full.

treacle voice install

Downloads the whisper.cpp base model, about 148MB, into ~/.treacle/models. Needs ffmpeg and whisper-cpp from Homebrew.

treacle update

Checks treacle.dev for a newer build and installs it, hash and signature verified. The previous binary stays for treacle update --rollback.

treacle doctor

Says where every step stands, including whether the tailnet has HTTPS and whether any device has reached the host.

~/.treacle/config.json

Add linearWorkspace and a personal linearApiKey and ticket pills show the ticket's title and status.

How it works, in one picture.

Treacle is a single Bun binary that owns a tmux server and the git worktrees under the folders you register. Agents run in tmux panes it created. The app talks to it over WebSockets and REST with a bearer token, on localhost or inside your tailnet. There is no desktop app to install and no server of ours.

The Mac that stays on treacle-server, under launchd

  • tmux on a dedicated server. Tabs are tmux sessions; shells survive restarts and are attachable from any shell.
  • git worktrees under each registered folder, cut and removed by the server itself.
  • SQLite for the timeline of every session, so the feed survives reconnects and restarts.
  • whisper.cpp for voice, so audio never leaves the tailnet.
Claude Codehooks report status and prompts; the MCP server pushes documents, diffs and decisions; the transcript feeds the feed
Codexits session log feeds the feed; its questions become cards

Any browser you sign in from

  • Chrome app on the desk: its own window, Dock badge, push.
  • Phone on the home screen, with push and dictation.
  • iPad with a keyboard, for the terminal view.
  • No state on the device. Close one, open another, same place.

One binary, one directory. The server, CLI, MCP server and hooks are the same executable. State lives in ~/.treacle.

Survives the things that happen. Restart the server and the tmux sessions are still there; the app reconnects and the timeline replays from SQLite.

Honest lamps. With hooks, a lamp flips to needs-you the moment Claude waits. Without them, the pane heuristics still give you working and idle.

Subject lines by a small model. Each active worktree carries one line about what is going on, written from the newest session, refreshed at most every half hour.

Files in. The + in the compose bar uploads a photo or file to the host and types its path into the prompt. You press Enter.

Previews out. An agent can proxy a dev server on the host into the session feed as a capability URL that lives for about six hours.

Questions people ask first.

Is this a phone thing?

No. Most days it is a Chrome app in the Dock next to your editor. The phone is the same app at the same address, which matters when a session needs you and you are not at the desk. Nothing about it needs a phone.

Does it replace the terminal?

No, it sits on top of it. Every tab is a tmux session on a server treacle runs, and the raw pane is one clicktap away in the app or one attach away in a shell. Anything the app cannot express, you do in the pane, and the feed catches up.

Does anything leave my machines?

No. The server runs on your Mac, your devices reach it over localhost or your tailnet, and treacle.dev serves this page and the download. Push notifications travel through the browser vendor's push service, encrypted end to end as Web Push requires; the payload is opaque to anyone but your device.

How do updates work?

treacle update asks treacle.dev for a newer build and installs it. The download is checked against its published hash and its signature before it replaces anything, and the previous binary is kept, so treacle update --rollback puts it back. The app shows a one-line banner when a newer build exists; on the phone, updating is one tap. "updates": "ask" | "auto" | "off" in ~/.treacle/config.json decides what happens. ask, the default, tells you and waits. auto installs it and restarts the server, but only when no agent is mid-turn. The check is a GET for a public file on treacle.dev that carries no token or identifier, and off turns it off entirely.

Do I have to use Tailscale?

Only to reach it from another device. On the host itself it works on localhost with no network setup at all. For the phone and the laptop, Tailscale is the network: free for personal use, installed by setup with Homebrew if you like, and the reason no ports get opened.

Which agents does it work with?

Claude Code gets the most: status hooks, permission cards, the MCP tools and the transcript-backed feed. Codex sessions have a feed and their questions become cards. Anything else runs in a plain Terminal tab with the raw tmux mirror.

What if the agent asks something a card can't answer?

Every card has an "answer in your own words" box, and the compose bar types into the pane. A multi-part question opens in the session and is answered part by part. Interactive commands open the terminal instead.

What happens if I ignore a permission card?

After two minutes, or if no treacle client is connected, the normal terminal prompt takes over. Nothing is auto-approved. Dismissing a question tells the agent it was dismissed, not answered.

Linux? Intel Macs? Windows?

Not yet. Treacle runs on macOS on Apple silicon today. The client side is any browser that can install a web app.

What does it cost?

Nothing. Treacle is free to use, personal or commercial, on machines you own or administer. The source is not open and the binary may not be rehosted. Point people here instead.

Your code never leaves your machines, because there is nothing for it to leave to.

Treacle has no backend, no accounts, no telemetry. treacle.dev serves this page and the download. That is everything it can see.

Run more agents than you can watch.
Then watch them anyway.

$ curl -fsSL https://treacle.dev/install | sh