cc-sticky-notify
A pinned sticky note notification system for Mac. Key Claude Code events appear as a yellow floating sticky note in the top-right corner, persisting until manually closed.
File Structure (fully self-contained)
CODEBLOCK0
Two-layer notification mechanism:
- 1.
display notification — no permissions required, appears instantly in top-right corner - Swift NSWindow (
.floating level) — pinned sticky note, close manually with ✕
Hook coverage (consistent with popo-notify):
| Hook | Trigger | Sticky note content |
|---|
| INLINECODE2 | Task completed | ✅ Task completed + time/project/session |
| INLINECODE3 |
Permission approval needed | 🔐 Permission approval required |
|
Notification/idle_prompt | Waiting for user selection | 💬 Awaiting your input |
|
PostToolUse/Bash (on failure) | Command execution failed | ❌ Command failed, exit code |
Requirements
- - macOS 12 Monterey or later
- Xcode Command Line Tools — required for compiling the Swift floating window, code signing, and JSON parsing
CODEBLOCK1
All dependencies (swiftc, codesign) come from Xcode CLT. install.sh will check and exit early if CLT is missing.
Installation
When the user requests installation, follow these steps:
Step 1 — Run install.sh
CODEBLOCK2
What this script does:
- 1. Check Xcode CLT — exits early with instructions if
xcode-select -p fails. chmod +x notify.sh — ensures the script is executable (git clone may strip the +x bit).- Build
.app bundle — compiles sticky-window.swift, writes Info.plist + entitlements, signs with codesign. Skipped if the bundle already exists. - Check hook configuration — inspects
~/.claude/settings.json for existing cc-sticky-notify entries and prints the required hook commands if none are found. - Smoke test — fires a test notification via
notify.sh.
Step 2 — Configure settings.json hooks
Read ~/.claude/settings.json and append one sticky-notify entry to each of the following four locations in the hooks field (skip if already present).
Stop — append to Stop[0].hooks:
CODEBLOCK3
Notification/permission_prompt — append:
CODEBLOCK4
Notification/idle_prompt — append:
CODEBLOCK5
PostToolUse/Bash — append (triggers only on failure):
CODEBLOCK6
Step 3 — Verify
CODEBLOCK7
A yellow sticky note and system notification appearing in the top-right corner confirms successful installation.
Configuration
CCSTICKYNOTIFYCLOSETIMEOUT — Auto-close timeout
Sticky notes automatically close after 1 hour (3600 seconds) by default. Override with this environment variable:
CODEBLOCK8
- - Unit: seconds (decimals supported, e.g.
30.5) - Must be greater than 0; otherwise falls back to the default 3600 seconds
- Set a large value (e.g.
86400) to keep the note visible for nearly a full day
To persist the setting, add it to your shell config (~/.zshrc or ~/.bashrc):
CODEBLOCK9
Troubleshooting
No system notification either
- - Verify the hooks configuration is correctly written in INLINECODE25
- Path should be INLINECODE26
xcrun: error: invalid active developer path during compilation
- - Xcode Command Line Tools path is broken (common after macOS upgrade or Xcode reinstall)
- Fix: INLINECODE28
- If that doesn't work, reinstall: INLINECODE29
- The floating sticky window will be disabled if swiftc can't compile, but system notifications still work
Permission denied on notify.sh
- - The script is missing execute permission — happens when files are cloned/copied without preserving permissions
- Fix: INLINECODE31
- Re-run
install.sh after fixing (the latest version auto-runs chmod +x on startup)
cc-sticky-notify
Mac系统上的固定便签通知系统。关键的Claude Code事件会以黄色浮动便签的形式显示在屏幕右上角,并持续显示直至手动关闭。
文件结构(完全自包含)
~/.claude/skills/cc-sticky-notify/
├── SKILL.md
├── install.sh ← 一次性设置:chmod +x 及 settings.json 指引
└── scripts/
├── notify.sh ← 主通知脚本(由钩子直接调用)
├── sticky-window.swift ← Swift源代码(首次安装时由install.sh编译)
└── sticky-notify.app/ ← .app 应用包(首次使用时自动构建)
└── Contents/
├── Info.plist
└── MacOS/
└── sticky-notify-app
双层通知机制:
- 1. display notification — 无需权限,立即在右上角显示
- Swift NSWindow(.floating层级)— 固定便签,通过✕手动关闭
钩子覆盖范围(与popo-notify一致):
| 钩子 | 触发条件 | 便签内容 |
|---|
| Stop | 任务完成 | ✅ 任务完成 + 时间/项目/会话 |
| Notification/permission_prompt |
需要权限批准 | 🔐 需要权限批准 |
| Notification/idle_prompt | 等待用户选择 | 💬 等待您的输入 |
| PostToolUse/Bash(失败时) | 命令执行失败 | ❌ 命令失败,退出码 |
系统要求
- - macOS 12 Monterey 或更高版本
- Xcode命令行工具 — 用于编译Swift浮动窗口、代码签名和JSON解析
bash
xcode-select --install
所有依赖项(swiftc、codesign)均来自Xcode CLT。install.sh会检查CLT是否安装,如果缺失则会提前退出。
安装
当用户请求安装时,请按以下步骤操作:
步骤1 — 运行install.sh
bash
bash ~/.claude/skills/cc-sticky-notify/install.sh
此脚本执行以下操作:
- 1. 检查Xcode CLT — 如果xcode-select -p失败,则提前退出并显示说明。
- chmod +x notify.sh — 确保脚本可执行(git clone可能会移除+x权限位)。
- 构建.app应用包 — 编译sticky-window.swift,写入Info.plist + 授权文件,使用codesign签名。如果应用包已存在则跳过。
- 检查钩子配置 — 检查~/.claude/settings.json中是否已有cc-sticky-notify条目,如果未找到则打印所需的钩子命令。
- 冒烟测试 — 通过notify.sh触发测试通知。
步骤2 — 配置settings.json钩子
读取~/.claude/settings.json,在hooks字段的以下四个位置各添加一个sticky-notify条目(如果已存在则跳过)。
Stop — 追加到Stop[0].hooks:
json
{
type: command,
command: $HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh
}
Notification/permission_prompt — 追加:
json
{
type: command,
command: $HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh 🔐 Claude Code需要权限批准,请检查终端
}
Notification/idle_prompt — 追加:
json
{
type: command,
command: $HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh 💬 Claude Code等待您的输入,请检查终端
}
PostToolUse/Bash — 追加(仅在失败时触发):
json
{
type: command,
command: bash -c INPUT=$(cat); STATUS=$(echo \$INPUT\ | jq -r \.tool_response.exitCode // 0\); [ \$STATUS\ != \0\ ] && $HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh \❌ Claude Code命令失败,退出码:$STATUS\ || true
}
步骤3 — 验证
bash
测试参数模式(模拟Notification钩子)
$HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh ✅ 安装验证成功
测试stdin模式(模拟Stop钩子)
echo {session_id:test12345678} | $HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh
如果在右上角出现黄色便签和系统通知,则表示安装成功。
配置
CCSTICKYNOTIFYCLOSETIMEOUT — 自动关闭超时时间
便签默认在1小时(3600秒)后自动关闭。可通过此环境变量覆盖:
bash
export CCSTICKYNOTIFYCLOSETIMEOUT=300 # 5分钟后自动关闭
- - 单位:秒(支持小数,例如30.5)
- 必须大于0;否则回退到默认的3600秒
- 设置较大值(例如86400)可使便签保持显示近一整天
要持久化此设置,请将其添加到shell配置文件中(~/.zshrc或~/.bashrc):
bash
echo export CCSTICKYNOTIFYCLOSETIMEOUT=300 >> ~/.zshrc
故障排除
系统通知也未显示
- - 检查~/.claude/settings.json中的钩子配置是否正确
- 路径应为$HOME/.claude/skills/cc-sticky-notify/scripts/notify.sh
编译时出现xcrun: error: invalid active developer path
- - Xcode命令行工具路径损坏(常见于macOS升级或Xcode重新安装后)
- 修复方法:sudo xcode-select --reset
- 如果无效,请重新安装:xcode-select --install
- 如果swiftc无法编译,浮动便签窗口将被禁用,但系统通知仍可正常工作
notify.sh出现Permission denied
- - 脚本缺少执行权限 — 当文件被克隆或复制时未保留权限时会发生
- 修复方法:chmod +x ~/.claude/skills/cc-sticky-notify/scripts/notify.sh
- 修复后重新运行install.sh(最新版本会在启动时自动运行chmod +x)