Watch your coding agent work — its checklist, live, in a pane beside it.
fbtodo displays your Freebuff agent's todo list in a side pane while it works. It shows:
- What's done, running, and next — with live timers
- How much time is left — estimates based on your project history
- If it's stuck or waiting — with optional alerts to your phone
No configuration: it reads the list your agent already keeps. Freebuff's list turns up on its own; anything else can push one over stdin — see docs/SOURCES.md.
Installation · Commands · FAQ · Install guide · Settings · Deep docs
The clip above shows - fbtodo pane in real time. It monitors a scripted session through eight steps, updating continuously until all tasks are marked complete and the session ends—the exact trigger required for the notification bell.
To see how the pane mirrors the active session, here is the side-by-side pairing: the scripted session on the left, and the fbtodo pane tracking it on the right:
Note: The recording script exports animations as lossless WebP files rather than standard video formats. This ensures crisp, pixel-perfect inline rendering directly within GitHub Markdown.
One line — takes the first method your machine already has (Homebrew, uv,
pipx, a plain venv, or a clone), and never runs as root:
curl -fsSL https://raw.githubusercontent.com/TLE47/fbtodo/main/install.sh | shHomebrew
brew install TLE47/tap/fbtodo # brew taps it for youuv / pipx — an isolated venv, nothing to manage on your PATH:
uvx fbtodo # run it once, install nothing
uv tool install fbtodo # ...or keep it
pipx install fbtodoFrom the checkout — no install at all:
brew install tmux # or: apt install tmux
git clone https://github.com/TLE47/fbtodo ~/Projects/fbtodo
mkdir -p ~/.local/bin && ln -sf ~/Projects/fbtodo/fbtodo ~/.local/bin/fbtodo
tmux new -s work
fbtodo # opens the pane automaticallyRequirements: Python 3.9+ and tmux. If the pane does not appear, run
fbtodo doctor — it names what is missing. Every route, with pinned versions and
how to uninstall, is in docs/INSTALL.md.
For a one-word launcher that updates and manages everything:
fbtodo init # writes the launcher + adds the source line to your shell rc
fb # now use 'fb' instead of 'fbtodo'fbtodo init detects your shell ($SHELL, then the launching process), writes the
fb function into ~/.config/fbtodo/, and adds the source line to your startup
file — all idempotently, so it's safe to re-run after upgrading. It knows the
Bourne family (bash, zsh, ksh, mksh, dash, sh → a POSIX body and
fb.sh) and fish (a native body and fb.fish), and picks the right startup
file for each. You can still source the example file by hand if you prefer:
. ~/Projects/fbtodo/examples/fb.sh # manual install — adds 'fb' to this shell only
fb # now use 'fb' instead of 'fbtodo'--shell SHELL overrides auto-detection, --startup-file PATH names one for a
shell not in the table, and --dry-run previews without writing.
Each installer updates itself — brew upgrade fbtodo, uv tool upgrade fbtodo,
pipx upgrade fbtodo. To pin a release, name it; the tag is the version:
uv tool install fbtodo==4.30.0
pipx install fbtodo==4.30.0
pipx install "git+https://github.com/TLE47/fbtodo@4.30.0" # from the tagNo Python dependencies are required, though displaying the pane still needs tmux.
Your agent writes a todo list (by calling write_todos). fbtodo watches that list and displays it in a side pane. The pane updates in real time as the agent works through tasks.
No configuration needed — fbtodo reads the list your agent already creates. Just make sure your agent is keeping one. You can ask it once per session: "Plan this as a todo list and check off items as you go."
fbtodo # watch the pane (default)
fbtodo bar # show "todos 3/5" in your status bar
fbtodo snap # print one snapshot
fbtodo status # show pane info and why it might be emptyOther commands: ledger (forecast vs. actual), why (pane location), pin (resize pane), keep (pane-repair switch), locks (claim-file audit; --fix clears leftovers and ends untied processes, --fix --restart re-claims the watcher and keeper through the normal ask afterwards, --watch streams a line per finding and rings the kit's locks bell), stop (close watcher), prune (clean up old data).
Run fbtodo -h for all flags.
Create ~/.config/fbtodo/theme.json:
{
"accent": "#89b4fa",
"active": "#cdd6f4",
"success": "#a6e3a1"
}Or use environment variables:
export FBTODO_ACCENT="#89b4fa"
export FBTODO_SUCCESS="#a6e3a1"Three presets are included in examples/ (Catppuccin, Gruvbox, Nord).
fbtodo pin --size 24 --side h # 24 columns wide, beside the session
fbtodo pin --size 12 --side v # 12 lines tall, below the session
fbtodo pin --list # show current settings--size is counted along the split: columns for --side h (the pane sits beside the
session) and lines for --side v (below it). The pane remembers your last size and opens
that way next time. Default: 12 lines below.
If you only want the status bar:
export FBTODO_NO_PANE=1
fbtodo bar # just show "todos 3/5"Get notifications when your agent finishes, gets stuck, or asks for input:
# Install the notification kit
mkdir -p ~/.config/freebuff-notify
cp scripts/notify/*.py scripts/notify/*.sh ~/.config/freebuff-notify/
chmod +x ~/.config/freebuff-notify/*.sh
~/.config/freebuff-notify/phone.sh --initSee scripts/notify/README.md for details on iMessage and ntfy alerts.
| Problem | Fix |
|---|---|
| Pane is empty | Run fbtodo status — it'll tell you why. Usually the agent hasn't written a list yet. |
| Pane won't appear | Make sure you're in tmux and fbtodo is in your PATH. |
| Pane closed | It'll reopen automatically. If it doesn't, try fbtodo stop then run fbtodo again. |
| Wrong size/position | Use fbtodo pin --side h (beside) or --side v (below), with --size N in columns or lines respectively. |
| List looks old | Run fbtodo status to check how long ago it was written. |
Do I need Freebuff?
For the built-in stores, yes. But you can use any agent that writes a JSON state file — see docs/SOURCES.md.
Does this send my data anywhere?
No. fbtodo reads local files only. The only outbound traffic is optional phone notifications (if you install them).
Will it slow my agent down?
No. It reads files that are being written anyway — the overhead is negligible.
Can I run multiple sessions?
Yes. Each session gets its own pane, bound to its task list.
Works on Windows?
WSL only. Windows Terminal + WSL works fine. Native Windows won't work (tmux isn't available).
I just want a status bar, no pane.
Set FBTODO_NO_PANE=1 and use fbtodo bar. It prints todos 3/5 and updates every few seconds.
Run the test suite:
python3 scripts/fbtodo-selfcheck.py # full suite (~90-160 seconds)
python3 scripts/fbtodo-selfcheck.py --only local-session # one test
bash scripts/notify/test-freebuff-notify.sh # notification testsMIT — see LICENSE.

