【开源自荐】 CC-Monitor : 监测+审计AI agent Claude code 在电脑上进行的所有操作

Author: cn0xrootCreated Sep 17, 2026Updated Sep 17, 2026

最近出现AI中转站被恶意投毒、执行窃取Token key 凭证数据的新闻:

https://x.com/shoucccc/status/2098169782541631871

https://x.com/shoucccc/status/2042423713019412941

https://arxiv.org/abs/2604.08407

由此萌生了做AI操作监测审计工具的想法

项目地址: https://github.com/cn0xroot/CC-Monitor 官网: https://www.cc-monitor.com/

——————————

CC-Monitor

English | 简体中文

还在为 AI 开发时不知道 AI Agent 在你的电脑上执行了哪些操作吗?试试这个工具吧,实时监测 Claude Code 在本机的文件读写、命令执行、网络访问等操作,对高危操作拦截/确认,全部操作 留痕审计,避免 AI 工具误操作破坏系统或泄露数据。技术方案见 DESIGN.mdEnglish)。

Web UI

webui/ 是一个独立的 Node.js 服务,提供浏览器界面:

cd webui
npm install
node server.js          # 默认监听 http://127.0.0.1:9999,只绑定 localhost
  • 首页:概览统计——进行中的终端会话数、监测到的 Claude Code 会话总数、审计事件总数、拦截/疑似绕过次数、文件读/写/编辑/删除次数、日志类型与风险等级分布。"会话总数"/"审计事件总数"/"已拦截的高危操作"三张卡片可以点开看下钻详情(分别是会话列表、按事件类型+所属 session 的明细、被拦截操作的完整列表)。
  • Log 审计:全宽的实时审计日志查看(按会话过滤,会话下拉框显示"文件夹 · 模型 · 短ID"而不是一串看不出区别的 ID),复用 CLI 那套人类可读的事件翻译逻辑。
  • 终端会话:直接在浏览器里开一个 Claude Code 终端对话(node-pty 起 PTY),不用再切到本地终端软件;用 xterm.js + WebGL 插件渲染,有 GPU 就用 GPU 加速,没有自动退化成 Canvas。侧边栏可以切换到网格视图(herdr 风格),同屏显示所有进行中的会话,点哪个面板就给哪个发键盘输入。
  • Claude Tap:查看某个会话发给/收到模型的完整对话内容(不只是"调用了哪个工具")——文本、思考、工具调用、工具结果、token 用量,按字段分色渲染。数据来源是 Claude Code 自己写在本地的 transcript JSONL 文件(hook payload 里的 transcript_path),不是抓包/MITM。CLI 等价命令:CC-Monitor tap [--session ID] [-f]
  • AI 审批台:把 Claude Code 的"是否允许执行"确认框同步到网页上——效果类似 Mac 平台 Vibe Island 在灵动岛里弹卡片让你点 Allow/Deny,区别是我们 跨平台(网页而不是 Mac 专属的 UI),而且目前只接管我们自己规则表里标为 confirm 的 那部分操作(其余工具仍然走 Claude Code 自己的原生询问,不会被我们静默放行)。同一条 请求既可以在触发它的终端里直接按 y/N,也可以在这个页面点按钮,谁先给结果就用谁的; 网页这边选"允许"会通过 hook 的 permissionDecision: allow 输出直接让 Claude Code 跳过它自己的原生弹窗,不会二次询问。选项有:允许一次、拒绝一次、批准且 10/30 分钟内 不再询问、一直允许(仅当前 session,其它 session 跑一样的操作还是照常问)。支持浏览器 桌面通知(Notification API),有新请求时哪怕没开着这个页面也能弹系统通知,点一下直接 跳回来处理。
  • 状态信息:账号级额度(单次 5 小时窗口 / 周额度 / 分模型周额度 + 重置时间,跟 ccstatusline 读同一份 Claude Code OAuth 凭证查询同一个 api.anthropic.com/api/oauth/usage 接口)+ 每个会话的模型、token 用量、吞吐速率(tok/s,由 transcript 估算)、cwd、git 分支、活跃时长、拦截情况。
  • 中英文切换 + 多主题:右上角语言按钮(中文/EN)和主题下拉(标准配色/深色/浅色/Dracula/Nord/Midnight/Ocean/Forest/Sunset/Rose,后 5 个移植自 AI_Web_Search 的配色方案),选择存 localStorage。翻译范围是界面文案(导航、按钮、标题、空状态提示、风险/操作/状态标签),不翻译数据本身(命令文本、工具输出、transcript 对话原文)。审计日志的风险/操作类型/状态徽章用固定的高饱和配色(不随主题变化),高危操作整行标红加粗。

因为这个 UI 还在快速迭代,静态资源都设了 Cache-Control: no-store——改完代码直接刷新页面就能看到最新效果,不用担心浏览器缓存旧版本。

默认只绑定 127.0.0.1,因为这是个能直接开终端 spawn 进程的工具,没做认证。首页有个 "允许其它设备访问"开关,但它只是设置一个标志位——安全边界始终是进程启动时绑定的地址, 不是运行时能被网页动态改掉的东西:真要监听所有网卡,需要显式设 CC_MONITOR_WEBUI_HOST=0.0.0.0 重启服务,那个开关才会真正生效(默认关,绑成 0.0.0.0 之后也是先拒绝所有非本机请求,开关打开才放行)。

截图

首页概览 会话列表下钻
事件类型明细 被拦截的高危操作
审计日志

功能介绍

CC-Monitor 是双层监测架构:

  • 应用层(Claude Code Hooks):注册 PreToolUse/PostToolUse hook,拿到每次工具调用的 语义信息(工具名、命令、文件路径),按规则判定放行/拦截/需要确认。这是主力,成本低、覆盖面广。
  • 系统层(eBPF 探针,Linux)CC-Monitor-probebpftrace 独立于 Claude Code 之外,直接在 内核层跟踪 claude 进程派生出的整棵子孙进程树的 execve/connect,交叉验证应用层 hooks 有没有被绕过或篡改——这是第二道防线,即使 hooks 配置被破坏也能兜底发现异常。

具体能力:

能力 说明
高危操作拦截 命中规则的 Bash/Write/Edit 等操作可以直接拒绝(如 rm -rf /、写 ~/.ssh/
人工确认 中风险操作在终端弹出确认提示 + 桌面通知,超时/无 tty 默认拒绝
审计日志 所有事件落盘 SQLite,tool_input/tool_response 全量留存
人类可读实时日志 CC-Monitor tail 把原始 JSON 翻译成"事件类型 + 摘要 + 结果",终端自动彩色高亮,Bash 命令按语法(命令名/参数/字符串/变量/管道)着色
绕过检测 CC-Monitor verify 比对系统层探针观测到的命令和 hook 记录,标出"探针看到了、但 hook 没记录"的可疑命令
网络层可视化 eBPF 直接抓 connect() 目标 IP:port,不解密 TLS、不用装 CA 证书

实现原理

功能介绍是"能做什么",这里是"怎么做到的",每条机制都能在源码里直接对上号(完整版见 DESIGN.md):

  • Hook 拦截:Claude Code 每次调用工具前后,会把一份 JSON payload 通过 stdin 传给 settings.json 里配置的 hook 命令,同步等它退出。CC-Monitor-hook 退出码是 2 就代表拒绝—— stderr 里的原因会被 Claude Code 展示出来。它是每次调用都拉起的一次性子进程,不是常驻服务, 所以也没有"进程挂了监控就失效"这种问题(但也意味着改完规则不用重启任何东西,下一次调用直接生效)。
  • 规则引擎default_rules.json 是一份有序规则表,policy.evaluate() 按顺序逐条尝试, 第一条命中就生效(first-match-wins),所以更具体的规则要写在更通用的规则前面。每条规则声明 tools(适用哪些工具)、field(从 tool_input 里取哪个字段,比如 command/file_path/url)、 pattern(正则)、risk/action。规则文件首次使用时从 default_rules.json 拷贝到 ~/.cc-monitor/rules.json,之后可以自己改。
  • 系统层 eBPF 探针probe_linux.bt 挂在内核的 execve/connect 等 tracepoint 上,先用 comm=="claude" 认出 Claude Code 自己的进程,再监听 sched_process_fork 事件,把"正在被监控" 这个标记沿着进程树一路传给它 fork 出来的所有子孙进程——不管子进程改名叫什么都跟得上。 CC-Monitor verify 拿探针观测到的命令去匹配同一时间窗口内 hook 记录的命令文本(做了引号归一化, 兼容 zsh 快照包装命令时对引号的转义),标出"探针看到了、hook 却没记录"的可疑差异。
  • Claude Tap:hook 的 JSON payload 里有个 transcript_path 字段,指向 Claude Code 自己写在本地 的对话 transcript JSONL 文件。直接读这个文件、解析里面的 user/assistant/tool_use/tool_result 等条目就能还原完整对话——不抓包、不用装 CA 证书、不需要中间人代理。
  • 账号额度显示:读 ~/.claude/.credentials.json 里 Claude Code 自己保存的 OAuth token, 拿它去调 Anthropic 官方的 api.anthropic.com/api/oauth/usage 接口(带上 anthropic-beta: oauth-2025-04-20 请求头)——跟 ccstatusline 读的是同一份凭证、查的是同一个接口,不是我们自己另外维护了一套用量统计。
  • Web 终端:用 node-pty 起一个真正的伪终端(PTY),跟你在本地开一个终端窗口没有本质区别; 创建之后自动往这个 PTY 里"敲"claude\r帮你启动。Claude Code 第一次打开一个没信任过的目录时会弹 一个"是否信任这个文件夹"的确认框,默认高亮选项是"No, exit"——这里检测到这段提示文本后会自动按 方向键+回车替你选"Yes, I trust this folder",不然这个确认框没人处理的话,后续任何一次正常的回车 操作都会把 Claude Code 意外退出,界面上却看起来"终端明明是好的"。
  • 数据持久化/归档:首页"持久化归档"用的是 SQLite 官方的 backup() API 给当前 events.db 做一次完整快照(不是简单复制文件——backup() 会正确处理 WAL 模式下还没落盘的数据),存到 ~/.cc-monitor/archives/ 下;"清空当前数据"则是对同一个库执行 DELETE 并重置自增 ID。

安装

依赖:Python 3(标准库即可,无第三方包依赖)。系统层探针额外依赖 Linux 的 bpftrace

赶时间的话./install.sh 一键装好(hooks 注册 + Web UI 依赖),装完用 ./start.sh 一键启动 Web UI(没装过依赖会先自动装一次)。想更细粒度控制的话,往下看手动步骤。

有两种装法,效果一样,选一种就行:

方式一:直接在当前目录用(不动系统路径)

# 1. 把整个 CC-Monitor 目录放到你想要的位置(这里假设已经在 ~/Tools/CC-Monitor)
cd ~/Tools/CC-Monitor

# 2. 安装 hooks 到 Claude Code 配置(会自动 chmod +x bin/ 下的脚本)
python3 install.py                       # 全局安装:写入 ~/.claude/settings.json
python3 install.py --project /path/to/proj   # 只对某个项目生效
python3 install.py --target /path/to/settings.json  # 显式指定 settings.json(跨用户安装时用)

# 3.(可选)如果要用系统层探针,装 bpftrace
sudo apt install bpftrace        # Debian/Ubuntu
# 其它发行版参考 bpftrace 官方文档;macOS 暂不支持系统层探针

安装脚本按 command 字段去重合并写入 PreToolUse/PostToolUse hook 数组,不会覆盖你已有 的其它 hooks 配置;遇到损坏的 settings.json 会自动备份成 .json.bak 再重建。安装后重启 Claude Code 新开的会话才会读到新配置。

方式二:make install 装到系统路径

想要有个全局命令、不用记着这份代码放在哪个目录,可以装到系统里:

sudo make install                    # 默认装到 /usr/local/lib/cc-monitor + /usr/local/bin
sudo make install PREFIX=/opt/cc-monitor   # 或者自定义前缀

# 装完之后,任意目录都能直接用命令,再照方式一的第 2 步注册 hooks(用装完之后打印出来的路径):
CC-Monitor tail -v
python3 /usr/local/lib/cc-monitor/install.py

make install 只负责"把代码放到系统里、建好命令行链接",不会自动改你的 ~/.claude/settings.json——注册 hooks 这一步需要自己手动跑一遍 install.py(命令行结尾会 打印出装好之后的准确路径)。卸载用 sudo make uninstall(同样只删代码和命令链接,settings.json 里的 hooks 条目需要自己手动删)。

编译方式

CC-Monitor 是纯 Python 实现(标准库 sqlite3/json/argparse/re 等,无第三方依赖),不需要编译

  • bin/CC-Monitorbin/CC-Monitor-hookbin/CC-Monitor-probe 都是带 #!/usr/bin/env python3 shebang 的可执行脚本,install.py 会自动给它们加执行权限。
  • 系统层探针依赖的 bpftrace 是系统包管理器直接安装的现成二进制,不需要自己编译;cc_monitor/probe_linux.bt 是 bpftrace 脚本,运行时由 bpftrace 解释执行,同样不需要编译。
  • Makefile 里的 make install 不是编译,只是把文件拷到 PREFIX 下再建命令行链接,见上面"安装"一节。
  • 目前没有打包成单文件可执行程序(比如用 PyInstaller/Nuitka),这属于待办事项,见下方"开发进展"。

使用方式

# 实时查看监测到的事件(Ctrl+C 退出)
./bin/CC-Monitor tail
./bin/CC-Monitor tail -v          # 额外打印原始 JSON

# 查看当前生效的规则
./bin/CC-Monitor rules

# 查看统计(按风险等级/决策结果计数)
./bin/CC-Monitor stats

# 系统层探针(需要 root,用于交叉验证 hooks 有没有被绕过)
sudo ./bin/CC-Monitor-probe

# 查看探针标记的"可能绕过监测"的记录
./bin/CC-Monitor verify

环境变量

变量 作用
CC_MONITOR_HOME 覆盖事件库/规则文件目录(默认 ~/.cc-monitor/
CC_MONITOR_COLOR always/never 强制开关终端配色(默认按是否为真终端自动判断)
NO_COLOR 设置后强制关闭配色(通用约定)

事件与规则存放在 ~/.cc-monitor/events.db(SQLite 审计日志)、rules.json(可编辑规则,改了 立即生效不用重启)。

规则格式rules.json 是规则数组):

{
  "id": "规则名",
  "risk": "high | medium | low",
  "action": "block | confirm | log",
  "tools": ["Bash"],
  "field": "command | file_path | url",
  "pattern": "正则表达式"
}
  • block:直接拦截,Claude Code 收到拒绝原因。
  • confirm:终端弹出确认提示(等待 tty 输入 y 才放行)+ 桌面通知,无 tty/超时默认拒绝。
  • log:放行但记录审计日志。

默认规则见 cc_monitor/default_rules.json,涵盖:危险删除、磁盘覆写 命令、curl|bash、递归 777、sudogit push --force、读写 SSH 密钥/凭据文件、写系统目录等。

功能开发进展

每个版本具体实现了什么功能,见 CHANGELOG.mdEnglish)。

已实现

  • 应用层 Hook 拦截器(PreToolUse/PostToolUse),覆盖 Bash/Write/Edit/Read/WebFetch 等全部工具
  • 策略引擎:正则规则匹配 + 三种动作(block/confirm/log)+ 三级风险分类
  • SQLite 审计日志(events.db),事件对 hook 输入/输出全量留存
  • CLI:CC-Monitor tail(实时查看)/rules(查看规则)/stats(统计)/verify(绕过检测)
  • 人类可读事件格式化:把原始 JSON 翻译成"事件类型 + 摘要 + 结果"
  • 终端彩色输出:风险等级/决策结果/规则名独立配色,支持 NO_COLOR/CC_MONITOR_COLOR
  • Bash 命令语法高亮(命令名/参数/字符串/变量/管道重定向分色)
  • 终端确认(/dev/tty 交互)+ 桌面通知(notify-send/osascript
  • 安装脚本:安全合并 hooks 到 settings.json(全局/项目/自定义路径三种模式),不覆盖已有配置
  • 系统层探针(CC-Monitor-probe,仅 Linux):eBPF 跟踪 Claude Code 进程树的 execve/connect
  • 绕过检测:探针观测到的命令与 hook 记录模糊比对(进程树 + 时间窗口 + 去引号子串匹配),标记 hook_bypass_suspected
  • 网络层可视化:eBPF 直接抓 connect() 目标 IP:port + 反向 DNS,不用 MITM 代理

未实现 / 待办

  • macOS 支持:设计文档里规划的 Endpoint Security Framework 方案完全未实现(需要签名的 系统扩展 + 用户手动授权 Full Disk Access),目前 CC-Monitor 只在 Linux 上验证过
  • 强制沙箱(Phase 3):Landlock LSM / bubblewrap(Linux)、sandbox-exec/容器化(macOS), 目前只能拦截+告警,不能把 Claude Code 关进一个真正强制隔离的沙箱里
  • CC-Monitor-probe 常驻化:目前需要手动 sudo 启动,没有 systemd unit / 开机自启,需要用户自己决定要不要装成常驻服务
  • 审计日志防篡改:日志和被监测进程同一用户权限,理论上可被同用户进程删除/篡改;异地转发、只追加权限(chattr +a)等加固手段还没做
  • 多机日志集中上报 / 规则库社区化(Phase 3):目前是纯本地单机工具
  • 高危操作的图形化确认弹窗:目前只有终端 tty 文本确认,没有可点击的 GUI 允许/拒绝对话框
  • 规则语义化判断:目前纯正则匹配,没有轻量模型辅助判断命令意图(比如识别用自然语言描述的等价危险操作)
  • 打包为单文件可执行程序:目前依赖系统 Python 环境直接跑,没有用 PyInstaller/Nuitka 之类打包

已知限制

  • Web UI 进程和你平时跑 claude 的终端必须是同一个操作系统用户,否则各写各的 ~/.cc-monitor/ 数据库,互相看不到彼此(终端里的确认框、审计事件,Web UI 的 "AI 审批台"/审计日志页面会完全是空的)——CONFIG_DIR 是按当前进程的 $HOME 算的, 不是全局共享的路径。启动 Web UI 时如果用了 sudo/root 而你平时跑 claude 是普通 账号,会命中这个问题;start.sh 检测到用 root 启动会打印提醒,Web UI 自己启动时 也会在日志里打出当前运行用户,方便核对。
  • confirm 依赖 /dev/tty,无交互终端(CI/无头环境)时直接拒绝。
  • 探针的绕过检测是模糊匹配,不是精确语义分析;系统负载高、探针处理有延迟时,CC-Monitor verify 可能需要稍等片刻才能看到最新结果。
  • 网络层只看 IP:port,看不到真实域名(靠反向 DNS 尽力还原,不一定准)。
  • Claude Tap 的"思考"内容在部分模型下永远是空的——这是 Anthropic API 的 display 参数决定的,不是 CC-Monitor 的问题:Sonnet 5 / Opus 5 / Opus 4.8 / Opus 4.7 这些 较新模型默认 display: "omitted",思考正文根本不会出现在 API 响应里,Claude Code 本地 transcript 里对应的 thinking 字段自然也是空的(只留一个用于多轮校验的 signature),终端实时显示和本地文件持久化都拿不到正文。Claude Code 目前没有暴露 本地开关能把这个参数改成会返回正文的 "summarized"showThinkingSummaries 只 控制 UI 怎么渲染 API 已经返回的内容,新模型下开着也没用);Opus 4.6 / Sonnet 4.6 及更早的模型默认就是 "summarized",会有正文。CC-Monitor 的"显示思考详情"开关 在有正文的时候能完整展开,没有正文时如实说明原因,不会假装能变出不存在的数据。