Tour budgets live in spreadsheets that several people edit at once, and the numbers are money people trust.
Headliner moves them into one shared app where an AI agent can suggest changes but only a person can accept them.
An agent proposes edits to a budget; a person accepts one and rejects another. Seeded data.
A grid of my own, not AG Grid
I wrote my own spreadsheet so the AI’s suggestions could live inside it. It cost months of extra work, and bought a pending change that sits on its cell with accept and reject, and no per-developer licences.
People always win
If a person edits a cell the AI had suggested a change for, the suggestion is dropped, and the server refuses any approval it did not issue. More plumbing, in exchange for no silent or forged writes to financial data.
The simpler realtime, then paying for it
I deleted my own WebSocket server for managed realtime, knowing it meant last-write-wins, then fixed each cost in turn: echo dedup, stale-write guards, a written contract.
Next.js, React, TanStack Table, Supabase, Anthropic SDK, Bun, Vercel. In production with a design-partner tour management firm.
Designed and built with agents: I designed the grid, the approval model and the realtime tradeoffs.
The repo is private.
Visit Headliner ↗
I kept running several Claude Code sessions at once and losing track of which were working, which were stuck on a permission prompt, and which were editing the same files. Mori gives each agent its own git worktree and shows them all in one window, so I can watch and steer them like units in a strategy game.
Several agents work at once; one is blocked and waits for an answer. Placeholder, not a capture.
Show a prompt only when the screen agrees
The parser is built to raise a permission question only when it finds a question, two or more numbered options and a selection cursor together. A late prompt beats a wrong keystroke.
The main process keeps the state
The record of what every agent is doing lives in one place, and the window only mirrors it. More plumbing, in exchange for a pending question that survives switching views.
One worktree per agent
Each agent works in its own copy of the project, with a generated note listing who touched which files in the last ten minutes. Branch clutter, in exchange for agents that cannot overwrite each other.
Electron, React, TypeScript, Zustand, node-pty. A personal tool, not released. Started December 2025. Designed and built with agents: I designed the permission handling, the state model and the worktree setup.
Repo not public.
Claude Code conversations are linear, so trying a different approach at message 12 means losing or muddying the original thread. Claude Timeline shows the conversation as a tree and lets me branch from any message.
A conversation drawn as a tree, forking at one message. Placeholder, not a capture.
A fork is a copy under new IDs
To branch, it copies the transcript up to the chosen message into a new session file, re-keys every message, and tells Claude to resume the copy. It works with stock Claude Code, and leans on an undocumented file format.
The family tree lives beside the transcripts
Claude does not know about branches, so a small parent and children map in a separate file records them. Claude’s own files are never touched. The tree is invisible outside the tool, and can drift if a session file is deleted.
Polling, because the quiet way missed changes
The viewer is a React terminal UI that redraws as the conversation grows. It checks the files ten times a second, because the cheaper operating-system notifications kept missing changes on macOS. A little more CPU, a timeline that stays live.
Node, Ink (React for the terminal), chokidar, tmux. A personal tool, one commit. Started September 11, 2025. Claude Code shipped session forking on September 18 and rewind on September 29. The repo is public.
Not on npm: to try it, clone the repo.
View on GitHub ↗
I run several Claude Code agents in tmux at once, and each one stalls on a permission prompt or an error until I walk back to the desk. This puts those stalls in a priority queue on my phone, so I can approve or dictate an answer from across the room.
A blocked terminal on the left, the phone’s queue on the right. Placeholder, not a capture.
A prompt has to look like one
A numbered list could be a question or an agent listing findings. The detector accepts it only with a selection chevron, a question mark above it, or a hint like “Esc to cancel”. A few odd prompts may be missed; the phone is not spammed.
Look at the last twenty lines for errors
Matching the whole scrollback made errors sticky: one early error kept a pane red after the agent had recovered. Old problems stop haunting a recovered pane, at the cost of a real error that scrolled off.
Dictation is pasted, not typed
Sending characters one by one dropped and chunked long transcripts. The daemon pastes the text through a tmux buffer, waits 120 milliseconds, then presses Enter. A timing constant, and a spoken paragraph arrives intact.
Bun and TypeScript on the Mac, SwiftUI on the iPhone, tmux. A personal tool: files dated April 2026, no commits yet, built to my phone by hand.
Local network only; the daemon has no auth yet.
Repo not public.
I wanted an assistant that lives on my own machine, with my messages as its working context, instead of a chat window that forgets me. So I built the plumbing: watchers that notice things, small agents that decide what matters, and a way to text me about it.
A text comes in, is routed, and an answer goes back. Placeholder, not a capture.
Claude as the classifier, rules as the fallback
Each incoming text gets a cheap keyword check, then Claude decides where it goes. If the call fails or times out, a fixed default route answers instead. Smarter routing, paid for in latency.
The locks are files
Parallel agents share state through lock files, each tied to a process and cleared automatically if its holder died. No database or queue to run, and a crashed program cannot jam the rest.
Instant when it can, a timer when it cannot
The message watcher reacts to filesystem events. After ten empty triggers it falls back to checking every thirty seconds. Instant when events are reliable, predictable when they are not.
Python, bash, Node and TypeScript, SQLite, the Claude CLI. A personal tool for macOS, one snapshot of history. Started September 2025.
Repo private.