Tutorial
Stay aware: triggers, notifications & annotations
The best thing a terminal can do while you're looking somewhere else is tell you when something needs you. This walkthrough wires that up end to end: fire a notification the instant a line of output matches, post banners from your own scripts, stamp every scrollback row with a relative time, pin notes to the exact lines that matter, watermark each pane with its context, and roll all of it up in one panel that tells you which tab to look at next.
On macOS, ⌘ is the modifier. On Linux, read ⌘ as ⌃ (Ctrl) throughout. Every shortcut here maps to an action you can remap — see Keybindings.
1. Fire a notification on matching output
Triggers watch a pane's output and raise a desktop notification the moment a line
matches a regular expression. Each trigger entry is a
regex, optionally followed by | Title to set a custom notification
title; the matched line becomes the notification body. Add a
couple to your config:
// ~/.config/sinclair/settings.json
{
"trigger": [
"error|Build failed",
"\\bDONE\\b | Job finished"
]
}
Now kick off a long build in one pane and go read something in another. When a line
containing error scrolls by, a banner titled Build failed pops
with that line as the body; when your job prints DONE, you get
Job finished. This is the payoff — you stop babysitting the scrollback of
long-running work and let the failures and finishes come to you.
The part before the optional | is the regex, so escape or anchor it
the way you would any pattern (\bDONE\b matches the whole word, not
DONELIST). Leave off | Title and the notification uses a
default title with the matched line as the body.
2. Post a notification from anything
Triggers cover output you don't control. When you do control the program, it can raise a banner itself by emitting an OSC 9, OSC 777, or OSC 99 escape sequence. And for scripts and agent hooks that can't easily emit an escape sequence, post one straight from the command line:
sinclair notify --title "Deploy" "Production is live"
The general form is sinclair notify [--title T] <message>. Drop it
at the end of a slow script and you'll hear about it wherever you are:
./scripts/migrate.sh && sinclair notify "Migration complete"
The awareness carries into the tab strip, too. When a program in a
background tab emits an in-pane notification escape (OSC 9, 777,
or 99), that tab grows an attention dot that stays until you focus
it — so even if you missed the banner, you can see at a glance which session was
trying to reach you. (sinclair notify runs outside your panes, so it
posts the desktop notification without marking a tab.) See the
CLI page for sinclair notify.
3. Stamp scrollback with relative times
"How long ago did that line print?" is a question you ask constantly while a job churns. Answer it permanently with one config key:
// ~/.config/sinclair/settings.json
{
"timestamps": true
}
Now each scrollback row carries a faint relative time beside it —
5s, 2m, 1h, 3d — captured as the
row scrolls into history and travelling with the content as you scroll. No more
guessing whether that stack trace landed a moment ago or ten minutes back.
4. Pin a note to a line
When you find the line that matters — the error, the config value, the request id —
mark it so you can find it again. Put the cursor's line in view and press
⌘⌥A (annotate): a small dialog takes the text, and your note
is drawn as a pill in that row's left gutter.
Annotations are keyed to a stable line sequence, so the pill scrolls with the content and survives until the line falls off the end of the scrollback. Scatter a few — "the error is here", "good build" — across a long session and you've built yourself a set of bookmarks you can scroll back to instead of re-hunting the same output.
5. Watermark each pane with its context
With a grid of panes open, "which host am I on?" gets dangerous. A badge answers it
without stealing space: it's a faint watermark drawn in the pane's corner. Set
badge to any text, and {cwd} and {host} are
substituted per pane:
// ~/.config/sinclair/settings.json
{
"badge": "{host} · {cwd}"
}
Every pane now quietly labels itself with its own host and working directory. It reads as a background watermark, not chrome — present when you glance for it, invisible when you're working — and it's the cheapest insurance there is against running the wrong command on the wrong box.
6. Roll it all up in the Activity dashboard
Everything above tells you about one pane. The Activity sidebar panel — the ◉ icon on the activity bar — rolls every tab up to a single status dot, so you can see who's blocked, working, done, or idle at a glance across all your shell and agent panes. Click a row to focus that tab.
When a pane reports an agent state, its dot follows that state:
| Dot | State |
|---|---|
| 🔴 | blocked |
| 🟡 | working |
| 🔵 | done |
| 🟢 | idle |
A pane that isn't reporting an agent state falls back to the terminal's own signals, so the panel is useful for plain shells too: 🔴 attention (an OSC 9/777/99 notification fired while the tab was in the background), 🟡 a foreground command is running, and 🟢 idle. That's the whole awareness story in one column — a notifying background job turns its tab red, a running build shows yellow, and you know exactly where to click.
Coding agents can drive these dots directly by reporting their state. To wire that up — Claude Code's lifecycle hooks and reporting status from any script — walk through Agent status at a glance.