The notch glows while Claude works, turns red when it needs you, green when it's done, then retracts into the bezel. Press it to see what Claude is doing, stop it, send a follow-up, switch model or permission mode, or jump to another session.
Anything Claude asks you mid-run — a permission decision, a "switch model?" confirmation, any choice — surfaces on the notch as buttons, so you never open a terminal just to answer it. While it works, the notch also shows how full the context window is, what it's costing, and whether it has delegated to a subagent.
Resting state: just the light around the cutout. Press it and it opens up.
| macOS | 14 or newer |
| Claude Code | any recent version |
| Dependencies | none — the app links only against frameworks that ship with macOS |
| Optional | tmux, if your terminal is not iTerm2 or Terminal.app |
Universal binary — Apple Silicon and Intel. Xcode is only needed to build it, never to run it.
curl -fsSL https://raw.githubusercontent.com/MasterYoav/claude-notch/main/install.sh | shThat downloads the latest release, verifies its SHA-256, installs to /Applications, adds the hooks
Claude Code needs, and launches. Read the script first — it's short and that's the
point of one you can read.
Then restart any Claude Code sessions that were already running — hooks are read at session start, so existing sessions won't report anything until they restart.
What it changes on your machine
/Applications/ClaudeNotch.app— the app.~/.claude/settings.json— adds nine hooks. A timestamped backup is written first (settings.json.notch-backup-<time>), any hooks you already have are left alone, and--uninstall-hooksremoves only ours.~/.claude/claude-notch/— its own config and one small file per live session.- Removes the download quarantine flag from the app (see below).
CLAUDE_NOTCH_NO_HOOKS=1 installs the app without touching settings.json.
Notarizing requires a paid Apple developer account, so macOS refuses to open this app once it's been downloaded. There are three ways around that. They end in the same place and differ only in who you're trusting:
| Effort | Gatekeeper | |
|---|---|---|
curl … | sh above |
one command | the script strips the quarantine flag — a bypass |
| Download + right-click → Open | four steps | macOS's own "I trust this" path — no bypass |
| Build from source | needs Xcode | never involved — nothing is downloaded |
If piping a script into your shell makes you uneasy, use the middle one: grab ClaudeNotch.zip from
Releases, unzip it, drag it to
/Applications, then right-click the app → Open and confirm once. macOS remembers. Then:
/Applications/ClaudeNotch.app/Contents/MacOS/ClaudeNotch --install-hooksgit clone https://github.com/MasterYoav/claude-notch && cd claude-notch
./build.sh # → ClaudeNotch.app
./ClaudeNotch.app/Contents/MacOS/ClaudeNotch --install-hooks
open ClaudeNotch.appNeeds the Xcode command line tools (xcode-select --install). Nothing is downloaded, so Gatekeeper
never enters into it.
System Settings → General → Login Items → + → ClaudeNotch.app.
/Applications/ClaudeNotch.app/Contents/MacOS/ClaudeNotch --uninstall-hooks
rm -rf /Applications/ClaudeNotch.app ~/.claude/claude-notchRight-click the notch to quit the app — it has no Dock icon or menu bar, so that's the way out.
Glow states. Orange while Claude works, red when it's waiting on you, green when it finishes, then it retracts. The light drifts around the rim rather than sitting still.
The status line shows the current tool call — Reading foo.swift, Running npm test,
Searching … — with a stop button that sends SIGINT, exactly what ⌃C does.
Answer any in-session choice from the notch. When Claude genuinely needs a permission decision
(the PermissionRequest hook), the notch reddens and shows Approve / Deny — no opt-in, no
guessing. And a slash-command confirmation like "Switch model to Sonnet?" fires no hook at all;
the notch catches it by reading the terminal screen and offers the numbered options as buttons. The
point is that every choice reaches the notch, so opening the session just to confirm something never
makes sense.
It opens itself when something needs you. A permission ask or a finish pops the notch out on its own — no hover — long enough to read and click, then it retracts. Turn on a sound for those moments in settings (off by default).
Context, cost and subagents, at a glance. While Claude works the status line carries a slim meter of how full the context window is (it climbs toward the auto-compaction the notch also announces), a badge when work has been delegated to a subagent, and — in the sessions drawer — a rough running cost for the session.
Approve or deny tool calls before Claude Code would even prompt — an opt-in gate for tools you name (see below).
Model, reasoning and permission mode for the live session, in one drawer:
Recent sessions — pick one to resume it in a new terminal window:
Several sessions at once? The notch sticks to one until it goes quiet rather than flipping between them on every tool call, and names the project on the right so you always know what stop and send are aimed at. A session waiting on an approval jumps the queue. The sessions drawer lists every live session too, sorted by who needs you first — click one to bring its terminal forward, or approve/deny a sibling's held prompt inline without switching to it.
Everything that reads Claude's state — the glow, the status line, stop, approvals — works everywhere, including Claude Code running inside the Claude desktop app.
Everything that means typing at Claude needs a way into the terminal, and there is no universal
one on macOS. The mechanism that would be (TIOCSTI, which injects into a tty regardless of
emulator) is blocked by the kernel. So input goes through whatever each terminal chooses to expose —
and most expose nothing.
| Route | Send a message | Permission mode | Works in |
|---|---|---|---|
| tmux | ✅ | ✅ | any terminal — Ghostty, Warp, Zed, VS Code, Alacritty, kitty… |
| iTerm2 | ✅ | ✅ | iTerm2 |
| Terminal.app | ✅ | ❌ | Terminal.app |
| — | ❌ | ❌ | everything else |
If your terminal isn't iTerm2 or Terminal.app, run Claude Code inside tmux:
brew install tmux
tmux new -s work # then run claude in here, from whatever terminal you liketmux is worth it regardless — it's the only route that survives changing terminals, and it's the one
that can deliver raw keys, which permission-mode switching needs. Terminal.app can't do that at all
(do script always appends Return), so mode is disabled there.
In the Claude desktop app there's no tty and no local port, so nothing can type into it. What does work: while Claude is still working, a message you send is queued and handed over the moment it finishes. An already-idle desktop session can't be reached, and the notch says so rather than swallowing your message.
The model pill opens a drawer with the models, a reasoning slider, and permission mode — one control, since all three describe the same session. They drive the live session by typing into its terminal, so they grey out when there's no way in.
| Control | How |
|---|---|
| Model | /model <name> |
| Reasoning | /effort <level> |
| Permission mode | Shift-Tab cycle |
There is no /permission-mode command — Claude Code answers "Unknown command" — so mode rides the
TUI's Shift-Tab cycle (manual → accept edits → plan → auto). Because it's a cycle, reaching a
specific mode means stepping to it, which relies on knowing the current one; that comes from the
hooks. It refuses to move from an unknown mode rather than risk landing you in auto.
Model and reasoning also persist as your default for new sessions — that's Claude Code's behaviour, not something Claude Notch adds.
The session pill lists recent sessions and resumes one via claude --resume in a new terminal
window. It's labelled with the connected project's name.
Which terminal resume opens
Opening a .command file plainly hands it to whatever macOS registered for shell scripts — usually
Terminal.app — so living in iTerm2 or Ghostty got you a window you never asked for. Instead Claude
Notch picks, in order:
- an explicit
--set-terminalchoice; - the terminal you ran
--install-hooksfrom, captured at install time; - any known terminal that's running;
- the system default.
ClaudeNotch --set-terminal # show what it will use
ClaudeNotch --set-terminal ghostty # pin one
ClaudeNotch --test-terminal # open a window there to prove itKnown: iTerm2, Ghostty, Warp, WezTerm, kitty, Alacritty, Hyper, Terminal. Detection is limited to
that list on purpose — it finds whatever launched the installer, and if that's an editor or a chat
app, handing it a shell script is worse than falling back. Installing from inside tmux can't detect
the terminal (the shell's parent is the tmux server), so --set-terminal is the answer there.
Off by default. Turn it on per-tool:
ClaudeNotch --enable-approvals Bash,Write,Edit
ClaudeNotch --disable-approvalsA listed tool is held by the PreToolUse hook — the notch turns red, and pressing it reveals
Approve / Deny. The hook process itself is the pause, so this works in the desktop app too.
The gate can't tell whether Claude Code would have prompted at all. That's decided after
PreToolUsehooks return, so a listed tool is held unconditionally — including calls your allow-rules would have waved straight through, and sessions that prompt for nothing.In a session where everything is auto-approved, every listed call therefore stops and waits for a click you have no reason to make, with nothing on screen explaining the stall. That is not hypothetical: enabling it for
Bashwedged a live session during development, which is why these guardrails exist:
- a
permission_modethat never prompts (bypassPermissions,dontAsk,plan) is skipped, and so is an absent one;- nothing is held unless the overlay is actually running;
approvalTimeoutis a short 20s, and a timeout returnsdefer, neverdeny— Claude Code then prompts exactly as it would without Claude Notch;- after 3 unanswered holds the gate switches itself off.
Keep the list short and prefer tools you genuinely get prompted for. If a session feels sluggish,
--disable-approvalsis the first thing to try.
Settings live in ~/.claude/claude-notch/config.json.
The notch never lights up. Hooks are read at session start — restart your Claude Code session.
Check they're installed with grep ClaudeNotch ~/.claude/settings.json, and that the app is running
(it has no Dock icon; pgrep -f ClaudeNotch).
Stop does nothing. The session needs to have been started after the hooks were installed — that's when its process id is recorded. Restart it.
Send says "that session has no terminal". It's a Claude desktop session, or one whose terminal isn't reachable. Run Claude Code in tmux — see Which terminals work.
"ClaudeNotch is damaged / can't be opened." The quarantine flag is still set. Either
xattr -dr com.apple.quarantine /Applications/ClaudeNotch.app, or right-click the app → Open.
Everything feels slow after enabling approvals. That's the gate holding calls. Run
ClaudeNotch --disable-approvals.
I can't quit it. Right-click the notch.
claude ──hooks──► ClaudeNotch --hook <Event> ──► ~/.claude/claude-notch/<session>.json
│ (directory watch)
SIGINT / tmux / AppleScript ◄── app ──┘
Claude Code's hooks report what's happening; each writes one small JSON file per session, so concurrent sessions can't race each other. The app watches that directory.
| Hook | Notch |
|---|---|
SessionStart |
records the session's pid + tty |
UserPromptSubmit |
orange — Thinking |
PreToolUse |
orange — the current tool call; also the opt-in approval gate; counts Task subagents |
PermissionRequest |
red — holds a real permission decision for Approve / Deny |
Notification |
red for any choice (permission_prompt, agent_needs_input, …); idle_prompt goes quiet |
PreCompact |
orange — Compacting |
SubagentStop |
drops the subagent count |
Stop |
green ✓, then retracts; also delivers a queued message |
SessionEnd |
clears the session |
A slash-command confirmation (/model and friends) fires none of these — Claude Code draws it
straight in the terminal — so the notch surfaces those by reading the screen (iTerm2 / tmux only),
polling fast only just after it sends a command.
swift build
./.build/debug/ClaudeNotch --self-test # escaping, settings surgery, routes, session picking,
# TUI-menu parsing, usage + cost, subagent counting…The self-test is the whole safety net — pure logic behind an assertion — and CI runs it on every push and PR (macOS runner; the app links AppKit).
Point it at a throwaway config to avoid touching your own — both the app and the hook honour
CLAUDE_CONFIG_DIR:
export CLAUDE_CONFIG_DIR=/tmp/fake-claude
./ClaudeNotch.app/Contents/MacOS/ClaudeNotch &
echo '{"session_id":"demo","tool_name":"Read","tool_input":{"file_path":"/a/b.swift"}}' \
| ./ClaudeNotch.app/Contents/MacOS/ClaudeNotch --hook PreToolUseThe window and animation code can only really be judged on a physical bezel — swift build proves it
compiles, not that it looks right.
Releases: ./release.sh v0.1.2 builds universal, packs with ditto, checksums, and publishes.
The app icon
ClaudeNotch.icon is an Icon Composer document and has to be compiled, not copied. build.sh
runs actool over it, emitting both a modern Assets.car and a legacy .icns. Two things actool is
silently fussy about: the .icon must be passed directly (inside an .xcassets it compiles to
an empty catalog), and --minimum-deployment-target must be 26.0 regardless of the app's own
LSMinimumSystemVersion — below that it reports success and produces nothing.
AGPL-3.0. The notch overlay is derived from Sentient OS (AGPL-3.0), so Claude Notch inherits that license — see NOTICE for exactly what came from where.
Unofficial. Not affiliated with, or endorsed by, Anthropic.




