Skip to content

Repository files navigation

Claude Notch

Claude Notch

Watch and steer your Claude Code sessions from the notch.

CI

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.

The notch glowing while Claude works

Resting state: just the light around the cutout. Press it and it opens up.

Expanded, showing the current tool call and a stop button


Requirements

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.

Install

curl -fsSL https://raw.githubusercontent.com/MasterYoav/claude-notch/main/install.sh | sh

That 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-hooks removes 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.

⚠️ It isn't notarized

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-hooks

Build from source

git clone https://github.com/MasterYoav/claude-notch && cd claude-notch
./build.sh                                                    # → ClaudeNotch.app
./ClaudeNotch.app/Contents/MacOS/ClaudeNotch --install-hooks
open ClaudeNotch.app

Needs the Xcode command line tools (xcode-select --install). Nothing is downloaded, so Gatekeeper never enters into it.

Launching at login

System Settings → General → Login Items → +ClaudeNotch.app.

Uninstalling

/Applications/ClaudeNotch.app/Contents/MacOS/ClaudeNotch --uninstall-hooks
rm -rf /Applications/ClaudeNotch.app ~/.claude/claude-notch

Right-click the notch to quit the app — it has no Dock icon or menu bar, so that's the way out.


What it does

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.

A held Bash call with Deny and Approve buttons

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:

Model picker with a reasoning slider and permission mode

Recent sessions — pick one to resume it in a new terminal window:

Recent sessions with project names and paths

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.


Which terminals work

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 like

tmux 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.


Model, reasoning, mode and sessions

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:

  1. an explicit --set-terminal choice;
  2. the terminal you ran --install-hooks from, captured at install time;
  3. any known terminal that's running;
  4. 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 it

Known: 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.


Approving tool calls from the notch

Off by default. Turn it on per-tool:

ClaudeNotch --enable-approvals Bash,Write,Edit
ClaudeNotch --disable-approvals

A 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.

⚠️ Read this before enabling

The gate can't tell whether Claude Code would have prompted at all. That's decided after PreToolUse hooks 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 Bash wedged a live session during development, which is why these guardrails exist:

  • a permission_mode that never prompts (bypassPermissions, dontAsk, plan) is skipped, and so is an absent one;
  • nothing is held unless the overlay is actually running;
  • approvalTimeout is a short 20s, and a timeout returns defer, never deny — 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-approvals is the first thing to try.

Settings live in ~/.claude/claude-notch/config.json.


Troubleshooting

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.


How it works

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.

Development

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 PreToolUse

The 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.

License

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.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages