Guide
Stop babysitting your AI agent: how to actually know when Claude Code needs you
You give the agent a task, and then you sit there. Claude Code greps, edits files, runs the test suite — and you watch a scrolling wall of output you're not really reading, waiting for the one moment it stops and asks "Allow this command? (y/n)". Tab away to do anything useful and you'll come back five minutes later to find it has been blocked on that prompt the whole time. The agent is autonomous right up until it isn't, and the gap between "it needs me" and "I noticed" is pure dead time.
The fix isn't a better agent. It's a notification that fires on exactly three events — it needs a decision, it has a question, or it's done — and stays silent otherwise. Here are the DIY options, ranked honestly, then what "good" actually looks like.
The DIY ladder, worst to best
1. The terminal bell. The zero-effort option: make your shell beep when a
long-running command exits. In zsh you can hook precmd; plenty of people just append
; printf '\a' to the command. It costs nothing and it's better than nothing. But the
bell fires on every command completion, not on the events you care about, it says nothing
about what happened, and a single \a is trivially easy to miss. It also can't
tell "finished successfully" from "blocked waiting for your approval" — which is the distinction
that matters most.
2. Claude Code's own hooks. This is the real answer for BYO Claude, and it's underused. Claude Code fires hooks on lifecycle events, and two of them are exactly what you want:
Stop— fires when the agent finishes its turn and hands control back to you. This is how you know when Claude Code finishes without watching.Notification— fires when it's waiting on you, including permission prompts and idle-input nudges. This is the "it needs a decision" signal.PreToolUse— fires before a tool runs and can block it (allow/deny), which is how approval gating is implemented under the hood.
A hook is just a shell command in settings.json that receives a JSON payload on stdin.
So a minimal "ping me when Claude Code finishes" is a one-liner on the Stop event that
shells out to a notifier. The catch: you're now writing and maintaining shell glue per machine,
you have to parse the payload to say anything useful, and a bare notification still drops you back
to step zero — you see the toast, then you still have to find the right terminal, focus it, and
read the scrollback to know what it's asking. Verify the current hook names and payload shapes in
the docs before you wire anything up; they've shifted over releases.
3. Desktop notifiers. Pair the hook above with a tool that puts a native banner on
screen. On macOS that's terminal-notifier
(brew install terminal-notifier); on Linux, notify-send. Now your
Stop hook can pop "Claude finished in api-server" in the corner with a sound. This is a
genuine upgrade — it's glanceable and it survives a buried terminal. The tradeoffs: notification
fatigue is real if you fire on too many events, banners stack and disappear into Notification
Center, and clicking one still yanks focus from whatever you were doing. It tells you something
happened; it doesn't let you act without context-switching.
4. Phone push. If you walk away from the desk, route the hook to your phone with
Pushover (a single curl to their API with your
token) or an ntfy topic. Great for "the deploy agent finished while I was at lunch." Useless for
the common case, where you're sitting right there and a buzz in your pocket is more interruption
than help — and you still can't answer the prompt from your phone.
What "good" looks like
Stack those up and the pattern is clear. Every DIY option nails one piece and misses the rest. The bar for not babysitting is actually three things at once:
- Interrupt only on a real event. A needed decision, a question, or a finish —
not every tool call, not every line of output. Map this to
NotificationandStop, ignore the noise. Signal-to-noise is the whole game; a notifier you learn to ignore is worse than none. - Make status glanceable. When you do look, you should read the state in under a second — running, waiting on you, done — without scrolling. A banner that says "something happened" fails this; you still have to go dig.
- Don't make me leave what I'm doing. The expensive part of any interruption isn't the alert, it's the context switch — focusing the terminal, finding the prompt, then clawing back to your editor or browser. Good notification lets you answer in place.
Most homegrown setups ace the first point with hooks, get partway on the second with a desktop notifier, and completely whiff on the third. That last one — answer without leaving — is the difference between a reminder and an actual workflow.
The shortcut
This is the problem Backgrind is built around, so you don't have to assemble the
ladder yourself. It wraps your real Claude Code CLI (your login, your history, your config) in an
always-on-top overlay and consumes the same Notification / Stop /
PreToolUse hooks for you. When the agent needs a decision, asks a question, or
finishes, the window flashes, chimes, and the relevant tab gets an accent ring — and it stays quiet
the rest of the time. Because the terminal is already floating over your editor or game, "answer in
place" is just typing; no focus-stealing, no hunting for the right window. Tap a key and it goes
click-through so your mouse passes to whatever's underneath.
If you'd rather wire it up by hand, the hook approach above is solid and worth doing — and we go deeper on the always-hidden, always-running side of it in running Claude Code in the background and an always-on-top terminal over any app. Either way, the principle is the same: let the agent earn the interruption, and the rest of the time, get out of the terminal.