{"slug": "show-hn-baton-know-which-of-your-ai-coding-agents-needs-you", "title": "Show HN: Baton - Know which of your AI coding agents needs you", "summary": "Neil Patel launched Baton, a free open-source macOS menu bar tool that monitors Claude Code and Codex sessions and alerts users when an AI coding agent is waiting for their input. The tool uses FSEvents for instant updates without polling, supports click-to-jump navigation, and provides a live count of sessions needing attention.", "body_md": "**A local command center for every AI agent you have in flight.** Claude Code sessions and\nCodex threads, in one glance, so you always know *which one needs you right now*.\n\nAs agents do more work unattended, the hard part stops being *doing the work* and becomes\n*knowing which of your N running things is waiting on a decision*. Baton reads the signals your\nmachine already emits (zero manual entry) and surfaces the one that matters: the\n**🎽 \"the baton's with you\"** bucket, an agent that ran its leg and handed back to you. That's\nthe thing that's easy to drop when you're looking elsewhere.\n\nIt lives in your **macOS menu bar** (a relay runner + \"N batons for you\"); click for the full\npicture, click any session to **jump straight to it**.\n\n```\ncurl -fsSL https://raw.githubusercontent.com/neilkpatel/baton/main/install.sh | bash\n```\n\nThat clones Baton into `~/.baton`\n\n, sets up an isolated Python venv (the only deps are `rumps`\n\nand the FSEvents binding), and installs a login LaunchAgent. The 🎽 appears in your menu bar\nimmediately, starts at login, and relaunches if it crashes.\n\nPrefer to look first? Clone and run the same script from the checkout:\n\n```\ngit clone https://github.com/neilkpatel/baton.git && cd baton\nbash install.sh                  # or: bash install.sh --no-autostart\n```\n\n**Update:** re-run the same one-liner. It pulls the latest into `~/.baton`\n\nand restarts the app.\nRemove the autostart anytime with `bash install.sh --uninstall`\n\n.\n\n**Requirements:** macOS, Python 3.9+ (3.11+ enables Codex scheduled-automation tracking), and\nClaude Code and/or Codex. Baton shows whatever it finds; either alone is fine.\n\n**Menu bar glance:** the title is a live count of sessions waiting on you. Always visible, updates in**under a second**(it*watches*your session files with FSEvents rather than polling, so it's both instant and battery-cheap; it idles until something actually changes).**Two agents, one view:** the dropdown groups what's waiting by tool (Claude Code / Codex), then Working, then Done.**Click to jump:** click a Claude session and its**Terminal.app tab** comes to the front; click a Codex thread and it opens in**Codex** via its`codex://`\n\ndeep link. No more hunting through windows.**Accurate \"waiting\" signals, per tool:****Claude Code:** a session that's idle with an assistant answer as its last turn = waiting.**Codex:** mirrors Codex's own**unread (blue-dot)** state, so a thread you've already opened doesn't nag you.\n\n**Click-to-acknowledge:** jumping to a waiting session clears it from the count until it produces a*new*answer, and the session you currently have open in Terminal isn't counted while you're looking at it. The number goes down when you deal with things.**Optional hand-off notifications:** off by default (the menu bar is the calm channel); one toggle turns on a banner the moment a baton comes back.**Recognizable labels:** each session is titled by Claude Code's own running summary (`ai-title`\n\n), so you know what it's about at a glance.\n\nThere's also a full HTML dashboard (`server.py`\n\n+ `index.html`\n\n) for the rich multi-tab view.\nOpen it from the dropdown (\"Open full dashboard →\"), or:\n\n```\nbash start.sh        # python3 server.py --port 8787  → http://127.0.0.1:8787\n```\n\nEvery source is a **collector** that normalizes into one `track`\n\nrecord, so the UI never changes\nas sources are added:\n\n```\n{ id, source, title, project, status, lastActive, detail, alive, extras }\nstatus ∈ waiting | working | done | idle | scheduled\n```\n\n| Source | Read from | Signal |\n|---|---|---|\nClaude Code |\n`~/.claude/sessions/{pid}.json` + transcripts |\nlive `busy` /`idle` + last turn → working vs waiting-on-you |\nCodex threads |\n`~/.codex/session_index.jsonl` + `.codex-global-state.json` |\nunread (blue-dot) → waiting; rollout transcript → the agent's closing line |\nCodex automations |\n`~/.codex/automations/*/automation.toml` |\nscheduled pipelines → next/last run |\n\nClaude Code (`~/.claude`\n\n) and Codex (`~/.codex`\n\n) are separate tools with separate state dirs;\nBaton reads both independently. Detection is **event-driven** (FSEvents on the session dir) with\na slow safety-net poll.\n\nSingle-file collectors + menu bar app in **stdlib Python** (plus `rumps`\n\nfor the menu bar and\n`pyobjc-framework-FSEvents`\n\nfor the watcher, in an isolated `.venv`\n\n). The dashboard is\ndependency-free vanilla HTML/CSS/JS. No build step, no framework.\n\n**Click-to-jump raises Terminal.app tabs only.** If you run Claude Code in iTerm, Ghostty, or another terminal, detection and counts still work fine; clicking a Claude session just can't raise your tab yet (it opens the dashboard instead). Codex jumps work regardless, via deep link.**Claude Code has no native read/unread flag**(Codex does, and Baton mirrors it directly). For Claude, \"waiting\" clears when you view the session's Terminal tab, click it in Baton, or hit \"Mark all as seen\", and it comes back when the session produces a new answer.**macOS only** by nature: FSEvents watcher, menu bar app, AppleScript jump.\n\nEntirely local and strictly read-only over `~/.claude`\n\nand `~/.codex`\n\n: Baton never mutates your\nsession state, and nothing leaves your machine. The live payload contains your real prompts and\nworking directories, so the dashboard server **binds to 127.0.0.1 only**, never\n\n`0.0.0.0`\n\n.\nCaptured state (`state.json`\n\n) is git-ignored; only scrubbed sample data is committed.`menubar.py`\n\n(the app) · `collectors.py`\n\n(the signal readers) · `server.py`\n\n+ `index.html`\n\n(dashboard) · `install.sh`\n\n· `start.sh`\n\n· `requirements.txt`\n\n· `state.example.json`\n\n(the\n`track`\n\ncontract).", "url": "https://wpnews.pro/news/show-hn-baton-know-which-of-your-ai-coding-agents-needs-you", "canonical_source": "https://github.com/neilkpatel/baton", "published_at": "2026-07-13 02:36:43+00:00", "updated_at": "2026-07-13 03:05:50.497363+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["Baton", "Neil Patel", "Claude Code", "Codex", "macOS"], "alternates": {"html": "https://wpnews.pro/news/show-hn-baton-know-which-of-your-ai-coding-agents-needs-you", "markdown": "https://wpnews.pro/news/show-hn-baton-know-which-of-your-ai-coding-agents-needs-you.md", "text": "https://wpnews.pro/news/show-hn-baton-know-which-of-your-ai-coding-agents-needs-you.txt", "jsonld": "https://wpnews.pro/news/show-hn-baton-know-which-of-your-ai-coding-agents-needs-you.jsonld"}}