Copilot CLI on a Mac

Get a Mac notification when GitHub Copilot CLI is done or needs you

Two ways. Turn on Copilot’s own notifications and beep settings in ~/.copilot/settings.json; both are off by default. Or add two hooks: notification, which fired the moment Copilot asked to run a command in our test, and agentStop, which fired when it finished. The hooks run a script of yours, so the banner can name the project and does not depend on your terminal.

Last updated: October 2026

Written by the developer of Crest, 8 October 2026. Tested that day on a 16-inch MacBook Pro (Mac16,7) on macOS 27.0.1 with GitHub Copilot CLI 1.0.88 in a throwaway COPILOT_HOME, with nothing signed in: a small local server played the model through Copilot’s bring-your-own-model mode, so the replies were scripted, while the prompt, the settings and the hooks were Copilot’s own. Crest comes last, and you do not need it.

Which switch catches what

Momentbeepnotificationsnotification hookagentStop hook
Copilot asks to run a commandA bell, in our runAn OS notification, per Copilot’s help (not seen here, see below)Fired within a second, type permission_promptNo
Copilot finishes its turnA bell, in our runAn OS notification, per Copilot’s helpNothing in our run, over 70 seconds of waitingFired under a second after the last command
A copilot -p runNo prompt to ring forNo prompt to showNothing (the command was allowed up front)Fired
Out of the boxOffOffOnly if you add itOnly if you add it

So the hooks are the dependable pair: notification for “needs you” and agentStop for “done”. In our run the notification hook never reported a finished turn, even though GitHub lists agent_completed and agent_idle among its types, so do not count on it for that.

Copilot’s own switches: beep and notifications

Put both in ~/.copilot/settings.json, or set them from /settings inside Copilot:

{
  "beep": true,
  "notifications": true
}

Use settings.json, not config.json. On 1.0.88 the top of config.json reads “User settings belong in settings.json. This file is managed automatically.”, and our first try, with the two keys in config.json, changed nothing.

What Copilot’s help says they do: beep beeps “when user attention is required”, and notifications shows “OS notifications when user attention is required and when the agent finishes”, suppressed “while the terminal window already has focus”. A third setting, terminalNotifications, hands them to Ghostty and WezTerm as a terminal notification instead.

What we saw: with beep on, the terminal got a bell when Copilot asked and another when it finished. With both off, Copilot sent no bell and no notification at all, only the window title and a progress marker. We could not see whether the OS notification appeared: our Copilot ran in a background pseudo-terminal, not in a window macOS shows, so we make no claim about it. If it does not show for you, the hooks below do not depend on it.

Hooks: a banner that names the project

Save this as ~/.copilot/hooks/notify.sh:

#!/bin/sh
# ~/.copilot/hooks/notify.sh: a macOS banner when Copilot CLI needs you or is done.
# The hook file passes the event name as the first argument; Copilot sends the
# details as JSON on stdin. jq and osascript both ship with macOS.
input=$(cat)
project=$(basename "$(printf '%s' "$input" | jq -r '.cwd // empty')")
case "$1" in
  notification)
    case "$(printf '%s' "$input" | jq -r '.notification_type // empty')" in
      permission_prompt|elicitation_dialog) ;;
      *) exit 0 ;;
    esac
    title="Copilot needs you: $project"
    text=$(printf '%s' "$input" | jq -r '.message // "Waiting for your answer" | .[0:120]') ;;
  agentStop)
    title="Copilot is done: $project"
    text="Finished its turn" ;;
  *) exit 0 ;;
esac
osascript -e 'on run argv' \
  -e 'display notification (item 2 of argv) with title (item 1 of argv) sound name "Glass"' \
  -e 'end run' "$title" "$text"
exit 0

Then save this as ~/.copilot/hooks/notify.json, with your own home folder in the paths. Copilot loads every .json file in that folder when it starts, so this one sits beside any hooks you already have; in our test it ran next to a second file without either noticing the other.

{
  "version": 1,
  "hooks": {
    "notification": [
      { "type": "command", "bash": "sh /Users/you/.copilot/hooks/notify.sh notification", "timeoutSec": 10 }
    ],
    "agentStop": [
      { "type": "command", "bash": "sh /Users/you/.copilot/hooks/notify.sh agentStop", "timeoutSec": 10 }
    ]
  }
}

Restart Copilot so it reads the file. The notification hook gets details like these on standard input:

{"message":"Run command: touch notes.txt","title":"Permission needed",
 "hook_event_name":"Notification","notification_type":"permission_prompt", ...}

and our script turned the two moments into these banners (we recorded what it asked osascript for): “Copilot needs you: cp-proj” with “Run command: touch notes.txt”, then “Copilot is done: cp-proj”. elicitation_dialog, when Copilot asks you a question, is in the script because GitHub lists it; our test did not make Copilot ask one.

Hook, in the order they ranWhen, in our run
permissionRequestThe moment Copilot decided to ask
notification, permission_prompt0.03 and 0.7 seconds later, in two runs
(you answer)
postToolUseAs the command finished
agentStop0.6 seconds after that, as the turn ended
sessionEndWhen we quit Copilot

A hooks file in a repository’s .github/hooks/ folder does the same for that project only.

If nothing shows up

  • Script Editor may not post notifications. osascript posts as Script Editor and fails silently without permission. Run osascript -e 'display notification "test"' once, then allow Script Editor in System Settings > Notifications.
  • The file is not where Copilot looks. Hooks live in ~/.copilot/hooks/, or under $COPILOT_HOME if you set it; each file needs "version": 1; and Copilot reads them when it starts.
  • Hooks are switched off. disableAllHooks set to true in your settings turns every hook off.
  • A Focus is on. Banners wait in Notification Center.
  • The settings went into config.json. Move beep and notifications to settings.json.

Or answer it on the notch

A banner sends you back to the terminal. Crest, a Mac notch app, puts the request itself on the notch: Copilot, the command, and Deny and Allow, on every display. It uses Copilot’s permissionRequest hook through one file of its own, ~/.copilot/hooks/crest.json, and never touches yours. When you start Copilot with --yolo or an --allow-all or --allow-tool flag, Crest stays out of the way and Copilot does what you told it.

Crest's closed notch with Copilot CLI waiting: it wants to run gh pr checks 42.

A Copilot CLI request on Crest’s notch. The pill names the agent and the command; rest the pointer on it for Deny and Allow.

  • A chime and a macOS banner, “Copilot is waiting on you”, come with each request. Both are on by default, as “Chime when an agent asks” and “Notify me on every screen” in Settings > Coding agents.
  • When a turn ends, Crest posts nothing. Keep the agentStop hook above for that; the two work side by side.
  1. Download Crest. Signed and notarized.Free tier, no account · 7-day Pro trial, no card · macOS 14 or later
  2. Open Crest’s Settings, go to Coding agents and turn on “Allow or deny commands here”.
  3. Start Copilot CLI again; it picks up Crest’s hook at its next start.

Answering from the notch is free and needs no account. Crest Pro adds the Agents widget; Pro, with Take and Minutes, is $24.99 once or $2.99 a month. The full Copilot side is on Copilot CLI approvals in the notch.

Sources

  • GitHub Copilot CLI 1.0.88, its own help: copilot help config (beep, notifications, terminalNotifications, hooks, disableAllHooks), copilot help commands (/settings) and copilot help providers. Read 8 October 2026.
  • GitHub Docs, GitHub Copilot hooks reference. Read 8 October 2026. The hook events, the notification types (permission_prompt, elicitation_dialog, agent_completed, agent_idle and the two shell ones), agentStop, and where hook files live.
  • Our own runs, 8 October 2026, on a 16-inch MacBook Pro with macOS 27.0.1 and Copilot CLI 1.0.88, in a throwaway COPILOT_HOME with nothing signed in. A small local server played the model through Copilot’s bring-your-own-model mode and asked to run touch notes.txt once; every hook wrote its time and payload to a log, and a stand-in for osascript recorded the two banners the script asked for. The terminal output was recorded byte for byte.
  • Crest source, read 8 October 2026: CopilotCLIHook.swift, ApprovalNotifier.swift, SettingsCatalog.swift.

FAQ

How do I get a notification when Copilot CLI is done?

Add an agentStop hook in ~/.copilot/hooks/ that runs osascript to show a banner. In our test on Copilot CLI 1.0.88 it fired under a second after the last command, every turn, including copilot -p runs. Copilot's notifications setting also covers finishing, per its help.

Does GitHub Copilot CLI have notifications?

Yes. Copilot CLI 1.0.88 has a notifications setting for OS notifications when it needs you and when it finishes, and a beep setting. Both are off by default; turn them on in ~/.copilot/settings.json or with /settings.

How do I make Copilot CLI beep when it needs me?

Set beep to true in ~/.copilot/settings.json. In our test the terminal got a bell when Copilot asked to run a command and another when it finished.

Why are my Copilot CLI settings ignored?

On 1.0.88 user settings belong in ~/.copilot/settings.json. config.json is managed by Copilot and says so at the top; keys put there did nothing in our test.

Does Copilot CLI have hooks?

Yes. Files in ~/.copilot/hooks/ or a repository's .github/hooks/ can run commands on events such as sessionStart, permissionRequest, notification, agentStop and sessionEnd. Each file needs version 1.

Do I need Crest for this?

No. Everything above is Copilot CLI and macOS. Crest is for answering the request from the notch instead of the terminal, which is free.

Try Crest free

Download it with no account. Now Playing, the Shelf, the Clipboard and window snapping are free for good, and signing in gives you 7 days of Pro with no card. Pro, with Take and Minutes, is $24.99 once, on 2 Macs, or $2.99 a month.

Download Crest for macOS Get Crest Pro, $24.99

macOS 14 Sonoma or later · signed and notarized by Apple · 7-day refund

Keep reading: Claude Code usage limits · Codex usage limits · Claude Code notifications · Codex notifications · Claude Code vs Codex · Crest overview