【开源自荐】 CC-Monitor : 监测+审计AI agent Claude code 在电脑上进行的所有操作
最近出现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.md(English)。
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/PostToolUsehook,拿到每次工具调用的 语义信息(工具名、命令、文件路径),按规则判定放行/拦截/需要确认。这是主力,成本低、覆盖面广。 - 系统层(eBPF 探针,Linux):
CC-Monitor-probe用bpftrace独立于 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-Monitor、bin/CC-Monitor-hook、bin/CC-Monitor-probe都是带#!/usr/bin/env python3shebang 的可执行脚本,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、sudo、git push --force、读写 SSH 密钥/凭据文件、写系统目录等。
功能开发进展
每个版本具体实现了什么功能,见 CHANGELOG.md(English)。
已实现
- 应用层 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 的"显示思考详情"开关 在有正文的时候能完整展开,没有正文时如实说明原因,不会假装能变出不存在的数据。
Source: GitHubDaily/GitHubDaily