news 2026/10/3 17:10:39

Coucou的Hook+Socket中继机制剖析:如何做到永不阻塞Claude Code

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Coucou的Hook+Socket中继机制剖析:如何做到永不阻塞Claude Code

Coucou的Hook+Socket中继机制剖析:如何做到永不阻塞Claude Code

【免费下载链接】coucouA tiny friend that lives in your notch (macOS) or at the top of your screen (Windows, Linux) and keeps an eye on your coding agents: Claude Code, Gemini CLI, Antigravity and more.项目地址: https://gitcode.com/gh_mirrors/co/coucou

Coucou 是一款常驻在 Mac 刘海(Windows 则在屏幕顶部)的开源小工具,它通过一套Hook + Socket 中继机制实时盯着你的 Claude Code 会话,还能在刘海里直接审批权限。这套机制最"较真"的一条设计原则就是——永不阻塞 Claude Code:无论 Coucou 是否启动、是否崩溃、界面是否卡死,Claude Code 都会像没装它一样照常运行。本文就来拆解它到底是怎么做到的。

一、前提:Claude Code 自带的 Hook 机制

要理解中继,得先知道 Claude Code 本身提供了Hooks(钩子)能力。你可以在配置文件~/.claude/settings.json里,为一系列生命周期事件注册一条"要执行的命令"。比如会话开始、提交提示词、使用工具前后、请求权限、会话结束等:

  • SessionStart/SessionEnd:会话开始与结束
  • UserPromptSubmit:你提交了一段提示词
  • PreToolUse/PostToolUse:工具调用前后
  • PermissionRequest:请求执行敏感操作,需要人工批准
  • Stop/StopFailure:一次任务完成或失败

每当这些事件触发,Claude Code 就会把一段 JSON 通过标准输入(stdin)喂给你注册的命令,并等待命令结束。Coucou 要做的事情,就是注册一条"中继命令",把这段 JSON 转发给自己的主程序。

⚠️ 关键点:Claude Code 的耐心是有限的——每个 hook 都有一个超时(多数事件 10 秒,PermissionRequest是 120 秒)。超时的后果是"命令被放弃、Claude Code 继续走"。所以中继脚本必须又快又稳。

二、中继脚本:把 stdin 转成一条 Socket 消息

中继脚本是"夹在 Claude Code 和 Coucou 主程序之间"的轻量角色。它负责两件事:读取 stdin 的 JSON、通过本地 Socket 发出去。

macOS:nb-hook+nb-hook.py(Unix 域套接字)

在 macOS 上,Coucou 会往~/Library/Application Support/NotchBuddy/写两个脚本:

  • nb-hook:Shell 外壳,由 Claude Code 直接调用。它内部调用 Python 中继脚本,并且无论发生什么都exit 0——这是"永不阻塞"的第一道保险。
  • nb-hook.py:Python 中继,把 JSON 发往本地Unix 域套接字nb.sock(App Store 沙盒版本则发往容器内的路径)。

Windows:coucou-hook.exe(命名管道)

Windows 上对应的是一个用 Rust 编译的原生小工具coucou-hook.exe。它读取 stdin、补充一点终端上下文(比如TERM_PROGRAM),再把 JSON 通过命名管道\\.\pipe\coucou-<sid>发给主程序。管道名里带了当前用户的 SID,避免同一台机器上不同账号"撞"到同一条管道。

三、服务端:HookServer 与命名管道服务器

中继发出去的消息,由 Coucou 主程序里的"服务器"接收,再把事件翻译成界面状态。

macOS:HookServer(Swift,原生 Darwin Socket)

HookServer.swift 在后台线程上监听nb.sock,每来一个连接就开一个独立线程处理,绝不占用主线程。它有几条"防守":

  • 只接受与当前用户同一 UID的连接(getpeereid校验);
  • 并发连接上限32 个;
  • 单条消息上限1 MB,收包超时5 秒;
  • 套接字权限0600、目录权限0700,别人读不到。

Windows:pipe.rs(Rust + tokio)

pipe.rs 用 tokio 的命名管道实现同样的逻辑。除PermissionRequest外,其它事件都是"转发即断开":把事件emit给岛窗口、然后立刻disconnect。

四、关键设计:为什么永远不会阻塞 Claude Code

这是整篇文章的"题眼"。Coucou 用五层兜底确保 Claude Code 永远不会被它卡住。

1. 外壳脚本"永远 exit 0"

macOS 的nb-hook脚本最后一行就是exit 0。哪怕 Python 中继出错、超时、崩溃,外壳都会安静地以 0 退出——对 Claude Code 而言,这就等于"命令正常执行完了"。

2. 极短的"连接超时" + 发后即忘

对绝大多数事件(非权限请求),中继采用fire-and-forget(发后即忘):

  • macOS 的 Python 中继只给自己0.3 秒去连接;
  • Windows 的coucou-hook给连接300 毫秒,整个"发完就走"的事件给了2 秒预算。

如果 Coucou 没开、Socket/管道不存在,中继在几百毫秒内就放弃、空着 stdout 退出。结果就是:Claude Code 完全感受不到它的存在,会话照常推进。

3. 主线程"预算制",管道卡死也甩得掉

Windows 的 main.rs 把"真正会阻塞的读写"全丢到一个工作线程里,主线程则拿着一个截止时间。一旦工作线程超时(普通事件 2 秒),主线程直接退出进程——进程一死,管道句柄也随之释放,绝无可能把 Claude Code 卡死。

4. 只有PermissionRequest会等,而且要先确认"卡片真的可见"

权限审批是唯一需要"等人点按钮"的事件,但它也做了精心的"两段式"等待(见 pipe.rs):

  1. ACK 段(约 800 毫秒):岛窗口必须先回报"审批卡片已经显示在屏幕上"。如果界面被暂停、被别的东西挡住、甚至 webview 没在监听,这一步就失败——代价只是几百毫秒,而不是两分钟;
  2. 决策段(最长 108 秒):只有卡片确实在人眼前,才开始等用户点允许 / 拒绝。

macOS 上则是 HookServer.swift 把这条连接的文件描述符挂起保留,最长 115 秒。

5. 硬超时兜底,最终把决定权交回终端

不管上面哪一步失败、超时、Coucou 彻底无响应,最终都收敛到同一件事:中继不往 stdout 写任何东西。而"Claude Code 收到 hook 命令却没输出"的默认行为,就是——回到终端里照常询问。也就是说,最坏情况等价于"根本没装 Coucou",绝不会变成一次错误或死锁。

五、顺带看几个稳健性细节

除了"不阻塞",这套机制在"不乱改用户配置"上也很有分寸(见 hooks.rs):

  • 先备份再写:写settings.json前先做一份带时间戳的备份;
  • 只合并、不清空:只增删 Coucou 自己的条目,别人的 hook 原样保留;
  • 先看 diff 再落盘:把变更差异给用户看,且用文件指纹校验"你看到的"和"要写入的"是同一份,中间被人改过就中止;
  • 原子写入:先写到临时文件再重命名覆盖,磁盘写一半也不会留下半个坏文件。

六、关键文件索引

想自己翻代码验证的话,重点看这几处:

  • macOS 中继与套接字服务器:NotchBuddy/Sources/App/HookServer.swift
  • Windows 中继可执行文件:windows/hook/src/main.rs
  • Windows 管道服务器:windows/src-tauri/src/pipe.rs
  • hook 安装与 settings.json 安全写入:windows/src-tauri/src/hooks.rs
  • 项目行为与设计原则:CLAUDE.md、README.md

一句话总结:Coucou 把 Claude Code 的 Hook 命令当成"一次性的、短命的、可以随时放弃的"中继",主程序才是真正长驻的服务端。无论这一端断了、卡了还是没人看,兜底逻辑都保证 Claude Code 最终会"回到终端继续干活"——这正是它敢承诺永不阻塞的底气所在。

【免费下载链接】coucouA tiny friend that lives in your notch (macOS) or at the top of your screen (Windows, Linux) and keeps an eye on your coding agents: Claude Code, Gemini CLI, Antigravity and more.项目地址: https://gitcode.com/gh_mirrors/co/coucou

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 17:09:41

文生图项目实战:扩散模型、LoRA、提示词和版权治理

摘要:一篇能直接复用的项目实战 这是一篇可以直接照着做的多模态AI长文项目实战。项目面向“品牌视觉草案、电商场景图、游戏概念图和创意设计”,核心方法是“Stable Diffusion、LoRA微调、ControlNet、负向提示词、调度器”,技术栈以Python、Diffusers、PyTorch、Accelera…

作者头像 李华
网站建设 2026/10/3 17:09:36

大模型Prompt评测项目:从主观感觉到可量化指标

摘要:一篇能直接复用的项目实战 这是一篇可以直接照着做的大模型与智能体长文项目实战。项目面向“企业上线前的Prompt选型、版本迭代和质量门禁”,核心方法是“黄金集评测、规则打分、LLM评审、成对比较、统计置信区间”,技术栈以Python、Pytest、Ragas、MLflow、Streamli…

作者头像 李华
网站建设 2026/10/3 17:05:01

机械臂末端规划智能模型的误区演示

机器人或计算机智能与时间相关案例汇总&#xff08;ROS2-ROS1&#xff09;-CSDN博客 复盘 结合这篇文章的核心观点 ——仿真可复现≠工程可落地、ROS 生态的版本割裂性、工程落地 80% 依赖隐性工程经验而非业务逻辑 —— 可以从五个核心维度&#xff0c;完整解释这套双机械臂协…

作者头像 李华
网站建设 2026/10/3 17:04:06

CSS图片模糊过渡:一个transition加filter就够

图片切换直接生硬地跳一下确实不太好看&#xff0c;但用JS动画库又有点重。其实CSS自己就能搞定&#xff0c;transition配合filter的blur函数&#xff0c;几行样式的事。原理说穿了很简单。transition控制过渡的时长和缓动&#xff0c;filter的blur控制模糊程度。图片从blur(10…

作者头像 李华