专业的 Dashboard,用于实时追踪和可视化你的 Claude Code & Codex Agent 会话、工具使用和子 Agent 编排。基于 Node.js、Express、React 和 SQLite 构建,通过 Claude Code & Codex 原生 Hook 系统直接集成,实现无缝的会话追踪和分析。
语言支持 / Language Support: English (en) · 中文 (zh) · 越南语 (vi) · 韩语 (ko) · Español (es)
切换文档:README.md · README-CN.md · README-VN.md · README-KO.md · README-ES.md
Note
需要按任务查阅的帮助?GitHub Wiki 是面向日常使用、团队运维、故障排查、CLI/MCP 自动化和部署操作的实用手册。本地化静态 Wiki 继续提供英语、越南语、中文、韩语和西班牙语的产品与架构导览;精确的技术契约仍以 docs/ 为准。
- 概述
- 多语言支持(i18n)
- 功能特性
- 快速开始
- 工作原理
- 配置
- npm 脚本
- 插件市场
- Agent 扩展
- Tabby
- 声音提示
- MCP 集成
- API 参考
- Hook 事件
- 浏览器通知
- 更新提醒
- 连接状态弹窗
- VS Code 扩展
- 桌面应用(macOS 与 Windows)
- 数据存储
- 状态栏
- 服务端架构
- 客户端路由
- Hook 处理流程
- 部署模式
- 项目结构
- 常见问题
- 许可证
通过专业的暗色主题 Web 界面追踪会话、实时监控 Agent、可视化工具使用、观察子 Agent 编排。通过 Claude Code & Codex 原生 Hook 系统直接集成。
graph LR
A["Claude Code & Codex<br/>会话"] -->|Hook 触发<br/>工具使用 / 停止| B["Hook Handler<br/>(Node.js 脚本)"]
B -->|HTTP POST| C["Dashboard 服务器<br/>(Express + SQLite)"]
C -->|WebSocket<br/>广播| D["Dashboard UI<br/>(React + Tailwind)"]
style A fill:#6366f1,stroke:#818cf8,color:#fff
style B fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style C fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style D fill:#10b981,stroke:#34d399,color:#fff
Dashboard 内置多语言界面,支持 en、zh、vi、ko、es 五种语言,适用于跨语言协作和团队共享。语言选择使用自定义下拉菜单,便于未来继续扩展。
flowchart LR
A["用户选择语言<br/>en / zh / vi / ko / es"] --> B["前端 i18n 路由"]
B --> C["翻译字典加载"]
C --> D["UI 文案与可访问性标签渲染"]
D --> E["实时仪表盘 / API 文档 / 设置页"]
style A fill:#6366f1,stroke:#818cf8,color:#fff
style B fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style C fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style D fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style E fill:#10b981,stroke:#34d399,color:#fff
完整实现细节与排障指南请见 docs/I18N.md。
配有精美的暗色主题、响应式设计和直观的导航,让你轻松浏览 Agent 活动:
📡 Dashboard · Monitor — 总览统计、活跃 Agent 卡片与最近活动流
📋 任务进度 · 概览 — Dashboard Agent 卡片与 Sessions 行在状态旁复用同一个紧凑完成度环形图;悬停或聚焦可打开带归属信息的当前工作与任务状态预览
🩺 Dashboard · Health — 综合健康评分环、存储引擎甜甜圈图、缓存/错误/成功率仪表、工具调用条形图、子Agent效能、模型Token分布、压缩统计 — 每 5 秒自动刷新
📋 Kanban 看板(Agent 视图) — Agent 按状态分布于 4 个列:工作中 / 等待中 / 已完成 / 错误。黄色的“等待中”列突出显示被用户阻塞的会话(权限请求、回合结束,或停在新会话的提示符前) — 将鼠标悬停在“等待中”徽标上即可查看原因(需要输入 / 回合结束 / 等待提示 / 已中断)。每张卡片一目了然地显示模型、费用和当前工具。
🗂️ Kanban 看板(会话视图) — 会话按状态分布于 5 个列:活跃 / 等待中 / 已完成 / 错误 / 已废弃,可在同一页面切换。将鼠标悬停在任意列标题上可查看生命周期转换的提示说明。
📂 会话 — 包含费用、模型、Agent 数和时长的可搜索、可过滤、服务端分页的会话总表;项目选择器支持带搜索的多选,排序使用自定义菜单
🤖 会话详情 · Agent — 实时概览卡片(事件、工具调用、子 Agent、压缩、错误、时长)、Top 工具用量条形图、子 Agent 类型分布、Token 流和 Agent 层级树
✅ 任务进度 · 会话详情 — 完整的带归属信息任务跟踪器包含分段完成度环形图、当前任务、完成进度条、归属统计,以及每页 10 行的任务列表
💬 会话详情 · Conversation — 实时对话查看器,支持 markdown 渲染、带行号和复制按钮的语法高亮代码块,按工具样式化的工具调用块、捕获其 TUI 输出的斜杠命令气泡,以及内联的会话重命名标记
🔬 会话详情 · Timeline — 按时间排序的事件时间线,支持多维过滤、按 `tool_use_id` 进行 Pre/Post 分组,以及工具感知的载荷渲染
📰 活动流 — 实时事件日志,支持暂停 / 恢复、分组、多维过滤,每行带"会话 →"跳转按钮
📊 分析 — 按模型的 Token 用量、工具使用频率、活动热力图与会话趋势,附在线 / 离线指示器
🔀 工作流 — Agent 编排 DAG、工具执行桑基图、协作网络,共 11 个交互式工作流智能模块
🧬 工作流运行(工作流页面) — 由 Workflow 工具派生的「动态工作流」,依据磁盘上的运行日志重建:状态、Agent 数量、token 与工具调用,可展开为按 Agent 的明细(阶段、状态、token、工具、时长),并附经过人性化处理的结果预览
🧬 工作流运行 · 展开 — 展开的一次运行:可点击的彩色阶段筛选、按 Agent 的指标表,以及完整的可点击结果项列表,点击即可展开每个 Agent 的完整提示词与结果
🧬 工作流运行(会话详情) — 同样的群组关联到其启动会话,因此会话的动态工作流子 Agent 及其已计入的 token 成本可在会话内直接查看
🧰 Agent 配置 — 在完整 Claude Code 浏览器与实时 Codex 工作区之间切换,查看默认值、模型、配置文件、MCP、项目、技能、规则、Hook、插件和指令。Codex 预览会脱敏;用户维护的配置、Hook、规则、技能和指令可安全编辑并自动备份。
🧰 Codex 配置浏览器 — Codex 工作区集中提供 config.toml、账户模型、配置文件、MCP 服务器、项目、技能、Hook、规则、插件和指令。支持编辑用户维护的文件,并自动创建带时间戳的备份;config.toml 始终仅可编辑。
🧩 Claude 配置浏览器 · 技能 — 技能标签页列出所有已发现的技能(用户、项目与插件),显示其描述与来源,可在整个集合中搜索,并可打开任意技能文件进行带时间戳备份的安全编辑
💬 运行 Agent · 实时流 — Claude stream-json 与 Codex app-server 事件都会以聊天形式呈现,包括推理、命令、文件变更和工具活动。仪表盘运行让你将 Agent 留在后台并稍后重新连接。
⚙️ 设置 — 模型定价规则、Hook 安装状态、数据管理、通知偏好与系统信息
🔔 设置 · 告警 — 基于规则的告警引擎与出站 Webhook 集于一处:告警规则(事件模式 / 不活动 / agent 卡住 / token 阈值)支持按规则冷却,实时的已触发告警流,以及 14 个一等公民 Webhook 提供方(Slack、Discord、Teams、Google Chat、Mattermost、Rocket.Chat、Telegram、PagerDuty、Opsgenie、Splunk On-Call、Zapier、Make、n8n、Pipedream)加一个支持可选 HMAC 签名的通用 JSON 端点
🛰️ 设置 · 远程数据源 — 通过 SSH 从其他机器拉取 Claude Code 和 Codex 活动:可选地分别设置远程 Claude 主目录和远程 Codex 主目录,逐个测试 provider、手动或通过后台轮询器同步,并在本地、全部数据源或指定机器之间切换全局数据范围,每个会话都带有来源徽章
侧边栏提供快速访问 Dashboard、看板、会话列表、活动流、分析、工作流和设置。每个页面旨在通过实时更新和丰富的可视化,为你提供对 Claude Code Agent 活动的深度洞察。
Dashboard 提供全面的功能来监控和分析你的 Claude Code 会话和 Agent:
Cursor 会话(仅供参考): CCAM 会导入落在
~/.claude下的所有 Agent 转录——本机以及已同步的远程机器。Cursor 的用量同样计入:Cursor 恰好与 Claude Code 使用相同的路径存放 Agent 会话。CCAM 不会区分是哪个应用写入了文件。
| 功能 | 描述 |
|---|---|
| 任务进度 | 根据 Provider 实际暴露的状态按 Agent 归属跟踪任务:当前 Claude 的 TaskCreate / TaskGet / TaskUpdate / TaskList 与任务生命周期事件、旧版 TodoWrite,以及直接调用或统一 exec 包装的 Codex update_plan。有任务状态的会话会在 Sessions 表格和 Dashboard 的每张 Agent 卡片中,于状态徽标旁显示相同的小型环形进度图及悬停/聚焦 Tooltip;会话详情则显示完整进度面板,包括状态分段、当前任务、Agent 归属统计,以及每页 10 行的任务列表。进度只属于最新的顶层工作:新的 Claude 用户回合或 Codex 任务没有暴露 tracker 时会清除旧状态;回合/任务结束却没有最终更新时,也会丢弃未完成状态。已完全完成的历史仍会保留。 |
| Dashboard | 两个标签页(存储于 localStorage):Monitor — 概览统计(6 张统计卡片)、可折叠子 Agent 层级的活跃 Agent 卡片、近期活动流,项目数量通过 ResizeObserver 动态填满视口高度。Health — 综合系统健康评分环(加权:0.4 × 成功率 + 0.25 × 缓存命中率 + 0.25 × (100 − 错误率) + 0.1 × (100 − 堆内存 %))、存储引擎甜甜圈图(记录分布)、缓存性能 / 错误率 / 成功率仪表、Top 8 工具调用水平条形图、子 Agent 效能条、模型 Token 分布、压缩影响统计。所有健康指标每 5 秒从 /api/settings/info 和 /api/workflows 自动刷新。所有图表均有跟随光标的工具提示并自动避免视口边缘溢出 |
| 看板 | 顶部带视图切换(在 localStorage 中持久化):Agent 视图 — 4 列(工作中 / 等待中 / 已完成 / 错误),以及会话视图 — 5 列(活跃 / 等待中 / 已完成 / 错误 / 已废弃)。等待中列直接映射 Agent 的持久化 waiting 状态 — 当 Claude Code 停在提示符前(新会话、回合之间或被权限 Notification 阻塞)时设置,在用户继续操作(UserPromptSubmit / PreToolUse)时转换为 working。每个列标题都有 ? 图标的工具提示解释生命周期。每列按状态从服务端独立获取(每列实际无上限),随后客户端按每列 10 张卡片分页,附「显示更多」按钮。WebSocket 订阅范围跟随当前视图(agent_* 与 session_* 帧),切换视图后另一类的更新不会触发重新加载。“等待中”徽标以悬停工具提示的形式展示该行的 awaiting_reason — 需要输入 (notification)、回合结束 (stop)、等待提示 (session_start)、已中断 (interrupted) — 在紧凑卡片上仅保留悬停提示,以便卡片标题保有空间;更宽的界面(会话表格、会话详情页头)还会以嵌套小徽章(chip)的形式内联显示原因,紧急原因(权限请求、中断)会以更醒目的琥珀色显示 |
| 会话 | 可搜索、可筛选、服务端分页的全量会话表。每次翻页请求 /api/sessions?status=&q=&limit=10&offset=…,因此费用计算只针对当前可见页运行——与数据库中会话总量无关。第一页还会显示与 Dashboard 和 Kanban 相同的本机内存 Codex 启动行;在持久会话 ID 替换它之前,该行立即可见但不可跳转,并且不会改变持久 total 或分页。搜索框(q=)在服务端对 id / name / cwd 做不区分大小写匹配,附 300 毫秒防抖;响应包含 total 计数供分页器使用。状态筛选、搜索与翻页可组合。每个会话的可读名称从 Transcript 实时读取并保持同步——显式标题(/rename、claude -n、选择器 Ctrl+R 写入的 JSONL custom-title 行)优先,否则回退到自动生成的 ai-title;若两者都没有,则用会话的首条用户 prompt(截断,并跳过 tool-result / 斜杠命令噪音)填充占位名称以及 main agent 的占位名称/任务——因此从未获得标题的会话(包括导入的会话)也能一目了然它在做什么;用户自定义的名称绝不会被自动标题覆盖。该名称(无名称时回退到短 ID)显示在 Agent 卡片、Dashboard、活动流以及 Run 恢复选择器上 |
| 会话详情 | 单会话实时概览面板,包含活跃 Agent 横幅(当前工具 + 任务)、六个统计卡片(事件数及事件/分钟速率、工具调用数、子 Agent 数、压缩次数、错误数、滚动计时的运行时长)、Top 工具使用条形图、子 Agent 类型分布、堆叠 Token 流图,以及事件类型胶囊云——所有内容均根据 Hook 事件实时刷新。下方:Agent 层级树(父/子)、完整事件时间线(多维筛选:状态、事件类型、工具、Agent、文本搜索、日期范围)、按 tool_use_id 进行 Pre/Post 分组、人类可读摘要块、工具感知的输入/响应渲染器(Bash 用终端、Edit 用统一 diff、Read/Write 用带行号代码、Grep 用匹配列表、MCP 工具用键值卡片),以及对话标签页:使用 markdown(标题、列表、引用块、表格、任务列表)、带行号和复制按钮的语法高亮代码块(js/ts、python、json、bash、html、css、sql、yaml、diff),以及按工具样式化的工具调用块(Bash → 终端、Edit → 旧/新并排、Write → 文件标签、Read → 路径胶囊、Grep → pattern 卡片)渲染对话记录。对话记录也包含回合进行中输入的消息(Claude 仍在工作时排队),显示在 Claude 实际接收它们的位置,来自框架的通知则归属为 System。当会话被用户阻塞时,页头下方会显示黄色的等待输入横幅,标明 awaiting_reason、其解释说明,以及会话已等待多久(脉冲圆点 + 相对时间);页头的“等待中”徽标也会以嵌套小徽章(chip)的形式显示同一原因 |
| 活动流 | 实时流式事件日志,支持暂停/恢复和分页;点击任意事件行可就地展开其完整 hook 载荷(内联 EventDetail 面板);每行右侧的专属「会话 →」按钮可直接跳转至会话详情页,不影响当前展开状态 |
| 分析 | Token 使用量、工具频率、活动热力图(居中显示、按周排列从周日开始、日期名称提示)、会话趋势、在线/离线连接指示器。加载时图表区域显示带脉冲动画的骨架占位符(不仅是顶部统计卡),数据到达后再渲染真实图表。Analytics 与 Workflows 中的长图例会分页,能放入一页的图例保持原样 |
| 实时更新 | WebSocket 推送 — 无轮询,即时 UI 更新 |
| 自动发现 | 会话和 Agent 会根据提供方信号自动创建。Claude Code 会在 SessionStart 立即创建一张等待中卡片。Codex 的交互式 TUI 进程一启动,就先显示一张仅存在于本机内存中的等待中卡片,即使此时 Codex 还没有分配稳定的会话 ID。随后 Hook、live-thread 行或 rollout 会创建持久会话并替换这张临时卡片。如果用户在 Codex 的 Resume 选择器中选择已有线程,CCAM 会读取该 Codex PID 已打开的 rollout 或 writer lock,并在首条新消息发送前立即切换到持久的已恢复会话。预身份卡片不会写入 SQLite、历史、分析、定价、工作流、告警或完成通知,并会在进程退出时消失。 |
| 历史导入 | 面向提供方的 Import History 可从 ~/.claude/ 导入 Claude Code 转录记录,并从 ~/.codex/sessions 导入 Codex rollout JSONL。每个标签都有自己的默认路径、说明、文件夹扫描和上传流程;两者都复用实时摄取逻辑,保留正确的 Token/成本/工具统计并保持幂等。外部 Codex rollout 会快照到仪表板存储,因此归档或源文件夹删除后仍可查看会话。 |
| 子 Agent 层级 | Dashboard 和会话详情页可折叠的父子 Agent 树。有子 Agent 的 Agent 显示展开/折叠箭头;叶子 Agent 显示圆点指示器。子 Agent 活跃时自动展开 |
| 后台 Agent | 正确追踪后台子 Agent,不会提前标记为完成 |
| 子 Agent 工具归属 | 子 Agent 内部的工具调用(Read、Bash、Edit、Grep 等)只存在于每个子 Agent 自己的 JSONL 文件中 — Claude Code 不会为其触发任何 Hook。每次 SubagentStop 后,dashboard 触发 fire-and-forget 的 scanAndImportSubagents:解析每个 subagents/agent-*.jsonl,根据 tool_use_id 配对 tool_use 与 tool_result 块,并在子 Agent 自己的 agent_id 下发出 PreToolUse + PostToolUse 事件。具备幂等性(通过 data LIKE '%"tool_use_id":"X"%' 去重),并在按类型 + 启动时间在 30 秒内匹配到 hook 创建的 live 行时合并进去,因此不会创建并行的 <sid>-jsonl-* 行。同一路径在 npm run setup 启动导入时也会运行,实现完整的历史回填 — 早于 dashboard 安装的会话也能获得完整的每子 Agent 工具时间线。Activity Feed 和会话详情页将父链以 main › coder › explorer 形式渲染嵌套子 Agent。该父链由 reconcileSubagentParents 权威重建:子 Agent 行最初被平铺插入到 main agent 之下(单个 hook 事件或 JSONL 文件不携带 spawn 方身份),随后从每个子 Agent transcript 的 Task 工具结果(toolUseResult.agentId,以 spawnedChildren 形式采集)恢复其 spawn 方,因此自己再 spawn 子 Agent 的子 Agent 会嵌套到其真正的 spawn 方之下,而不会塌陷为 main 之下的单一层级。该过程幂等且仅追加 — 只重新指向 parent_agent_id,不插入或删除行 — 并在同一次 SubagentStop 扫描中运行,该扫描返回 reparented 计数,因此即使仅是 reparent 改变了树形结构,dashboard 也会重新拉取 |
| 成本追踪 | 按模型估算成本,支持可配置定价规则和按会话明细。压缩感知的 Token 核算在上下文压缩过程中保留总量。Transcript 读取通过增量字节偏移更新缓存,实现高效 Token 提取。介绍性价格可在 Settings 中完全编辑——Model Pricing 编辑器提供一个促销截止日期以及按类别的介绍性价格(input / output / cache-read / cache-write 5m & 1h),因此未来模型发布的促销无需改动代码,只需编辑即可。子代理卡片显示每个子代理各自的成本(依据该子代理 transcript 的 Token 用量推算,并按当前价格计价),而非整个会话的总额——主代理卡片代表整个会话并显示会话总成本,而子代理卡片仅显示该子代理花费的部分,因此子代理卡片不再误导性地显示为好像它花费了整个会话的成本 |
| Transcript 缓存 | 从 JSONL Transcript 实时提取:Token、压缩、API 错误(isApiErrorMessage 条目存储为 APIError 事件)、回合耗时(存储为 TurnDuration 事件)、思考块计数和用量附加信息(service_tier、speed、inference_geo)。每条回合耗时都有稳定的 Transcript 标识;完整解析会修复旧版本产生的重复行和膨胀 metadata 总计,受限的尾部解析则保持仅追加。会话元数据实时丰富这些字段 |
| 通知 | 基于 Web Push (VAPID) 的持久化浏览器通知。即使 Dashboard 标签页未聚焦或浏览器已关闭也能送达。特别针对 macOS 音效支持进行了配置。支持按事件配置开关及订阅管理 |
| 更新提醒 | 服务端定期以非阻塞方式执行 git fetch,将本地检出与所选规范远程的默认分支对比。支持分支与 fork: 若同时存在 upstream 和 origin,优先使用 upstream(fork 的常规约定);命令也会根据用户处境调整——只有在本地分支真正跟踪规范引用时才建议 git pull --ff-only,否则给出 git fetch(fork 场景下加上 fast-forward 合并),让命令永不撒谎。侧边栏还有常驻的"检查更新"按钮及状态徽标。Dashboard 不会自行拉取或重启——用户在终端中手动执行命令——因此该机制不会破坏开发会话、pm2/systemd/Docker 进程管理,也不会留下孤立进程 |
| 设置 | 系统信息、Hook 状态、模型定价管理、通知偏好、数据导出与恢复(Import History 面板的 Restore backup 模式接受一个不超过 25 MiB 的导出 .json,并以幂等、非覆盖方式重新导入,因此可将多台机器的历史合并到一个仪表盘)、会话清理。Model Pricing 将 Anthropic Claude Model Pricing 与 OpenAI GPT Model Pricing 分开显示,两者使用相同的标题布局,并在 Add Model 左侧提供按提供方生效的 Reset Defaults。标题旁的信息浮层说明首条匹配规则、SQL 风格 % 通配符、手动价格更新与 API 费率注意事项;GPT 浮层还说明每百万 Token 的美元单位、272K Short/Long 分界、Fast mode,以及未公布的费率为何保持未定价而不是被估算。Claude Code、Codex 数据位置与 Import History 均完整支持 i18n。 |
| Codex Agent 配置 | Agent Config 的 Codex 一侧会读取完整的本地账户模型目录,不受通用预览限制影响,因此 Models 标签不会错误显示为 0,并始终包含基础/配置文件覆盖。可直接在应用中创建标准 Codex <name>.config.toml 覆盖层;每张卡均可一键复制其准确的 codex --profile <name> 命令并打开受保护的编辑器。预览路径会先规范化再做包含检查。编辑器拒绝受信任根目录下的符号链接路径组件,验证规范化父目录仍位于允许范围内,并拒绝保存含 [redacted] 的预览内容。配置文件、Hook、规则、技能和指令共用 Claude 风格的 View source / Copy path / Edit / Delete 操作。每次允许的删除都需确认并先创建备份(技能保留完整目录);config.toml 永远只能编辑。 |
| MCP 服务器(本地) | 位于 mcp/ 的完整本地 MCP 服务器,支持三种传输模式,16 个领域模块共 97 个类型化工具。覆盖应用支持的全部操作:带作用域的数据读取、Transcript 与图片、Claude/GPT 定价、工作流、告警、Webhook、导入与恢复、Claude/Codex 配置、Run Agent、远程数据源、Hook/Home/更新、推送与维护。所有传输共享同一套已验证目录,并支持分层变更/破坏性门控。直接回环 HTTP 可携带 Bearer Token,带 Token 的容器主机别名必须使用 HTTPS。请求拒绝重定向;历史上传限制为单文件 50 MiB、每次调用合计 100 MiB,二进制响应限制为 10 MiB,备份恢复限制为 25 MiB |
| 工作流 | 基于 D3.js 的可视化页面,包含 11 个交互式模块:Agent 编排 DAG、工具执行 Sankey 图、协作网络、子 Agent 有效性(按周 sparkline 通过 portal 渲染——可越过卡片的 overflow:hidden,并自动夹在视口内不再被裁切)、检测到的流程模式、模型委派流、错误传播图(带比率徽章的水平条形图、Agent 类型分解、API/会话错误卡片)、并发时间线、会话复杂度散点图、压缩影响分析和按会话下钻。全方位、多语言的丰富 tooltip: 每个图表标题旁都有一个 i 图标,可弹出结构化的「此图展示了什么 / 如何阅读 / 为何重要」浮层;悬停节点、边、条、气泡都会显示带有确定性、值相关解读的多段 tooltip(例如占源/占目标比例、成功率健康分级、Opus / Sonnet / Haiku 模型系列说明,以及前段/中段/后段等时间模式)。六张总览统计卡片各自在右下角带一个信息浮层,用自然语言解释指标的计算方式与当前数值含义。Tooltip 通过每张图唯一的 DOM ref 直接更新,并附带容器级 mouseleave 兜底,绝不会落后于光标或在重新渲染后残留。点击 检测到的工作流模式 中的任意一行会就地展开详情面板,包含完整步骤序列、统计网格、确定性叙述(循环检测、频率分级)和一条务实的建议。状态筛选标签(仅活跃 / 已完成 / 全部)可筛选全部 11 个模块。支持交叉筛选、JSON 导出和 3 秒防抖的实时 WebSocket 自动刷新。工作流运行面板呈现「动态工作流」——由 Workflow 工具(及自定节奏的 /loop)派生的 sub-agent 群组——它们不触发任何 hook,因此改为依据磁盘上的运行日志(workflows/wf_<runId>.json)重建:每次运行展示其阶段以及按 Agent 的 token / 工具调用 / 时长分解,并在日志写入前实时检测 running 状态,同时在每个会话详情页提供一个关联子区块 |
| 压缩追踪 | 从 JSONL Transcript 检测 /compact 事件,创建压缩 Agent 和事件。启动时回填历史压缩。周期性扫描器(频率从 DASHBOARD_STALE_MINUTES 派生)在无 Hook 触发时也能捕获压缩。共享 Transcript 缓存,避免重复文件读取 |
| 子会话/恢复会话 | 新事件到达时自动重新激活会话,正确处理 /resume 和孤立会话。周期性清理(每 ¼ 个 DASHBOARD_STALE_MINUTES,夹在 60 秒–5 分钟之间)标记遗漏事件检测的废弃会话 |
| 预存会话检测 | 服务器启动时已在运行的会话以"活跃"状态导入(基于近期 JSONL 文件修改时间)。Stop 事件也会重新激活已导入的完成/废弃会话,因此进行中的会话的第一个 Hook 始终会显示在 Dashboard 上 |
| 持续项目同步 | 启动时对 ~/.claude/projects 的自动导入是一次性的(由标记位把关),因此在首次启动之后才创建的项目文件夹——其会话从不经过 Hook 流入(例如 host-only Hook 被禁用)——在手动重新扫描之前都将不可见。后台同步(startSessionSync)通过三个共享同一个 mtime 缓存 + 单次合并扫描的触发器弥补了这个空隙:启动时的立即扫描、一个去抖的 fs.watch(新会话文件 / 项目文件夹一出现就触发;在 macOS/Windows 上递归监听,在 Linux 上监听根目录 + 直接子文件夹,以规避用户态递归监听器的隐患),以及一个周期性轮询(DASHBOARD_SESSION_SYNC_MS,默认 30 秒)。每次扫描只重新解析 mtime 前进过的文件,并广播 session_created/session_updated(外加主 Agent),让 UI 实时刷新;DB 中已有且未变更的会话会被跳过、不再重新解析,因此重启成本保持为 O(新增/变更文件) |
| 远程数据源 | 通过 SSH 实时从其他机器收集 Claude Code 和 Codex 数据。每个来源独立镜像 ~/.claude/projects 与 ~/.codex/sessions(另含 Codex 的轻量 session_index.jsonl,保留原生重命名标题),使用 scp;WSL 内 CLI 则使用 wsl.exe + tar。隔离暂存区使用各 provider 的本地导入器,并以 sessions.source 标记会话;一个来源可以仅有 Claude、仅有 Codex 或两者兼具。DASHBOARD_REMOTE_SYNC_MS(默认 15 秒)轮询会发布按 provider 划分的状态和计数。某个 provider 缺失、报错或卡住时,只有它的旧会话进入 stale 扫描,健康的兄弟 provider 仍由镜像管理。在 Settings → Remote Data Sources 或通过 ccam remote-sources 可选地配置独立的远程 Claude 主目录和远程 Codex 主目录;SSH 认证仍完全由主机负责,不保存任何秘密。 |
| 响应式设计 | 适配移动端的布局,堆叠网格、可滚动表格和可折叠侧边栏 |
| 界面本地化 | 内置语言切换,UI 文案与无障碍标签已覆盖英文(en)、中文(zh)、越南语(vi)和韩语(ko)及西班牙语(es)。覆盖范围现已贯穿 Workflows 页面的所有 tooltip:统计卡片的计算说明与按值分桶的解读、每个图表的「此图展示什么 / 如何阅读 / 为何重要」浮层、所有图形悬停 tooltip(编排 DAG、工具流、Pipeline、模型委派、并发时间线)、Workflow Patterns 详情面板的叙述与建议、设置页 → 模型定价的信息浮层、CLAUDE_HOME 面板,以及完整的 Import History 流程 |
| 种子数据 | 内置种子脚本,用于演示和开发 |
| 状态栏 | 彩色编码的 CLI 状态栏,显示模型、上下文使用率、Git 分支、Token 数 |
| 模型名称格式化 | 整个 UI 中使用人性化的模型名称:原始标识符如 claude-opus-4-7-20260101 或 claude-opus-4-7[1m] 显示为"Claude Opus 4.7"或"Claude Opus 4.7 (1M)"。支持 Claude、GPT 和 Gemini 家族的自动版本号点连接、日期/latest 后缀剥离、提供商前缀移除和上下文窗口标签格式化。设置页保留原始名称以配置定价规则 |
| Claude + Codex 插件市场 | 同一套 14 个插件同时提供 Claude Code 与 Codex Manifest、两个 Marketplace Catalog、66 个插件技能、18 个 Claude 子 Agent、34 个 Claude 命令和 OpenAI 技能元数据。skills.sh CLI 可通过 npx skills add hoangsonww/Claude-Code-Agent-Monitor --list 发现仓库中的 76 个技能。支持 claude plugin marketplace add、codex plugin marketplace add 和 npx skills add |
| 运行 Claude | 直接从仪表盘启动 claude 子进程,带聊天式流式 UI。两种模式:对话(多轮 — stdin 持续打开,后续轮次以 stream-json 信封通过 stdin 传送)与 单次(headless,一个 prompt → 一个响应)。对话模式还支持通过 claude --resume <id> 恢复任何已有会话 — 使用可搜索选择器从你的完整会话历史中挑选。标题栏的进行中运行切换器允许你将运行留在后台、启动另一个、稍后重新附加。重新附加是持久的:客户端会把派生进程的内存信封日志(?envelopes=1)与会话磁盘上的 JSONL 转录文件协调,优先选择 user/assistant 消息更多的那一份,因此从已恢复的运行离开再回来会保留全部历史(派生进程只看到 spawn 之后的轮次;转录文件包含先前 + 当前)。模型下拉(Opus 4.7 / 1M / Sonnet 4.6 / Haiku 4.5 / 自定义)、permission-mode 选择器(对 bypassPermissions 显式警告)、思考强度字段(low / medium / high — 映射到 --effort)、cwd 自动补全(预填用户的主目录 — 一个中性的启动位置,不会继承仪表盘仓库自身的 .claude 项目上下文(agents、skills、rules、CLAUDE.md、.mcp.json);若没有 home 建议则回退到仪表盘 cwd,建议分组以 home 优先(home → dashboard → 最近))。通过 --include-partial-messages 实现真正的逐字符流式渲染,加上客户端 打字机平滑层 通过 requestAnimationFrame 让每个 text_delta / thinking_delta 逐字浮现 — 即便是短回复(claude 把整个回答打成一两块 chunk 的情况)也呈现为打字效果。合并代码在 claude 中途送达 canonical assistant 信封时保留 _streaming 标志和增量累积的 content 数组,所以 thinking 块不会在完成时丢失。WebSocket 分发为每个信封包裹 flushSync,避免 React 自动批处理把多个 deltas 合并成一次渲染。TUI 对齐(Tier 1):限制说明横幅 可最小化为细条(永不消失)解释 stream-json 模式相对终端 TUI 能做和不能做什么;带斜杠命令自动补全的提示编辑器 使用分级评分(精确名称 → 前缀匹配 → 词边界 → 包含 → 子序列 → 描述匹配)列出用户 / 项目 / 插件命令(发送前在客户端按模板展开执行),并以"仅 CLI — 此处不会执行"标记呈现 /clear、/model、/config 等内置 CLI 命令;@ 文件引用 通过对该 run 的 cwd 进行去抖模糊搜索(跳过 node_modules、.git、dist、build 等);实时上下文窗口 / token 计 显示输入 + 输出 + 缓存命中 token 与运行成本 — 实时流式时从 stream_event / result.usage 计算,从转录恢复 / 查看 / 重新附加时也从已完结的 assistant usage 块(input / output / cache-read / cache-creation)读取,因此不会卡在 0/200k;状态头 显示当前 model、effort、permission mode、cwd、session ID、信封计数与已运行时间。自动补全下拉框向上展开,避免与下方 cwd 选择器冲突。标题旁有 Live / Offline 指示器。路由上的同源守卫防止浏览器 drive-by spawn。并发实际上不设上限(默认安全上限 10000,与终端 TUI 一致 — 仅作为防止有缺陷客户端 fork-bomb 的兜底;通过 RUN_MAX_CONCURRENT 设置真正的上限)。统一的活动运行 / 历史模态框还提供两个一键跳转按钮:对话型历史行的 Resume 按钮立即派生 claude --resume <id> 并把过去的对话记录预填入聊天视图(无需重新输入 prompt — 派生的进程会在 stdin 上空转直到你发送跟进消息);单次型历史行的 View 按钮把已捕获的转录内联加载到 run 查看器中作只读展示(不派生进程 — 同一面板,无 Stop / 跟进控件)。生成的会话触发与任何 claude 进程相同的 hooks,因此自动出现在 Sessions / Analytics / Kanban / Workflows — 而 Sessions / SessionDetail 会为当前正由 Run 页驱动的会话显示绿色 ▶ Run 徽标 / 横幅,可点击跳回 Run 页 |
| Tabby | 固定在每个页面右下角的可爱 SVG 小猫伴侣,会订阅实时会话 WebSocket 流并据此做出反应。会做出反应的吉祥物:基于实时会话流呈现 8 种情绪——空闲、观察、开心、担忧、卡住、思考、睡觉、断开连接;眼睛会追踪光标,每种情绪都有专属动画。气泡台词在值得关注的事件发生时弹出(会话开始/结束、出现错误、运行完成),带节流且可静音。点击小猫或按 ⌘B / Ctrl+B 打开面板(Esc 关闭):实时状态行(N 个进行中 · M 个出错 · 连接状态)、快捷操作(跳转到 Run Claude / 活动 / 会话 / 出错的会话,静音,清除提醒)以及一个 Ask 提问框。Ask 提问框在本地回答简单的状态类问题;其他问题则交给现有的 Run Claude 页面(/run?prompt=...)以启动一个真正的 Claude Code 会话——无需新增后端、无需 API 密钥。完全构建在现有的 WebSocket 流之上,支持无障碍(键盘、aria-live、尊重 prefers-reduced-motion),可在「设置」中开关。代码位于 client/src/components/Tabby/ |
| 声音提示 | 为实时活动提供轻柔的音频反馈,默认开启,可完全关闭。每个提示音都由 Web Audio API 在浏览器中合成——振荡器加增益包络,因此无需下载音频文件,也不新增任何依赖。七种提示音覆盖会话生命周期:会话开始时的上行纯五度、回复完成时的大三和弦解决音、出错时轻柔的下行小三度、子代理启动时的短促拨弦、Claude Code 通知时的失谐钟声、实时连接恢复或断开时的双音升/降,以及按下按钮和链接时几乎听不见的滴答声。提示音带限流(单个提示音冷却 + 全局突发预算),经过低通滤波,让声音退到工作之后;并且在你首次与页面交互前保持静音(浏览器自动播放策略)。设置 → 声音提供总开关、音量滑块和逐项开关并可即时试听;偏好设置保存在 localStorage 的 agent-monitor-sound 键下(支持 en/zh/vi/ko/es 本地化)。实现位于 client/src/lib/sound.ts 与 client/src/hooks/useSoundCues.ts |
| 告警与 Webhook | 基于规则的告警引擎在服务端评估实时事件流,支持四种条件类型:事件模式(匹配事件类型 / 工具名 / 摘要子串,可选要求在时间窗口内出现 N 次匹配——例如「2 分钟内超过 5 个错误」)、闲置(活跃会话 N 分钟无事件)、卡住的代理(代理在 working/waiting 状态下 N 分钟无活动)和令牌阈值(会话总令牌超过上限)。每条规则都按 (规则、会话、代理) 维度做冷却去重。触发的告警显示在实时列表中(支持确认 / 全部确认),并扇出到 14 个一等公民 Webhook 提供方——Slack、Discord、Microsoft Teams(通过 Power Automate Workflows 的 Adaptive Card)、Google Chat、Mattermost、Rocket.Chat、Telegram(Bot API)、PagerDuty(Events API v2)、Opsgenie(Alert API)、Splunk On-Call(VictorOps)、Zapier、Make、n8n、Pipedream——以及任意通用 JSON 端点(可选 HMAC-SHA256 签名 + 自定义请求头)。每个提供方都有各自的原生负载格式,可按规则限定范围。投递与告警流程分离且完全失败安全:请求超时、有界重试/退避、响应体校验(Splunk On-Call 返回 200 但 result:"failure")、同步的**「发送测试」**按钮以及每个目标的投递日志。URL、密钥和凭据均存储在服务端,绝不通过 API 返回(在所有响应中被掩码/脱敏)。规则与渠道在 设置 → 告警 中统一管理,每个字段都有解释性提示,并提供按提供方的设置指南(附说明:这些步骤可能已过时——请查阅官方文档) |
| Claude 配置浏览器 | /cc-config 上的 12 标签页检查器,涵盖 Claude Code 知道的一切:技能、子代理、斜杠命令、输出样式、插件(每个插件包含贡献计数 + 来自 plugin.json 的作者/许可证/主页)、市场(包含从每个 marketplace.json 读取的插件计数)、MCP 服务器、Hook(含 ~/.claude/hooks/ 脚本列表)、设置(一目了然的当前配置摘要,跨 用户/项目/项目本地 作用域解析 /config 控制的选项——model、verbose、主题、输出样式、effort、自动压缩、通知 ……,未设置项显示为默认值,外加按文件的结构化键值视图 + 原始 JSON 切换、密钥脱敏)、记忆(用户与项目 CLAUDE.md 文件,外加按项目的文件型记忆存储 —— ~/.claude/projects/<slug>/memory/ 下的每个 *.md,即一个 MEMORY.md 索引加上每条记忆事实一个文件,通常 100+ 个;Memory 标签页按项目分组(可折叠)、将索引文件与逐条事实文件分开,并带搜索框,以及可点击的 MEMORY.md 索引链接——点击后跳转到(滚动并高亮)对应的事实文件)、快捷键(按上下文分组,使用 <kbd> 字符)、状态行(配置 + 脚本内容)。对低风险文本文件表面(技能 / 代理 / 命令 / 输出样式 / 记忆,含按项目的 auto-memory 文件),页面支持带强制时间戳备份的创建/编辑/删除(auto-memory 备份落在 <memory-dir>/.cc-config-backups/auto-memory/),原子写入到 Claude Code 不扫描的目录之外,加上带自动构建 mv 恢复命令的备份模态框。插件、MCP、settings 中的 hooks 和 settings.json 文件保持只读,带说明横幅 + 可复制的 CLI 命令,以便用户知道要自行运行的确切命令。实时更新:服务端运行的 cc-watcher 通过 fs.watch 监听 ~/.claude/(平台支持时递归)以及 ~/.claude.json,以 500 ms 去抖,在 Claude Code 配置变化时(无论是仪表盘修改还是外部工具如 CLI 安装插件、手动编辑 settings.json、放入新技能)广播 cc_config_changed WebSocket 消息。页面订阅并自动重新拉取;标题旁的 Live / Offline 标识显示 WebSocket 连接状态 |
| 启动画面 | 应用加载时每个浏览器会话显示一次的品牌开场画面:根据时间的问候语(早上好 / 下午好 / 晚上好 / 夜深了)、一句醒目的本地化标语与两行副文案,以及深色背景(径向光晕、星座连线、颗粒质感)上带动画的节点图品牌标记。从首帧起即不透明(应用内容不会闪现),停留约 2.5 秒后淡出,点击任意处可跳过,尊重 prefers-reduced-motion,已本地化 en/zh/vi/ko/es |
| 渐进式 Web 应用 (PWA) | 三个独立的 PWA — 仪表盘、着陆页和维基 — 每个都有自己的 Web App Manifest 和 Service Worker。将任意一个安装到主屏幕/Dock,获得无浏览器边框的独立应用体验。仪表盘 SW 对 Vite 哈希化的 /assets/* 资源采用 cache-first(URL 每次构建都不可变,缓存命中始终正确),其他所有内容(导航、SW 自身、manifest.json、图标、根 /)采用 network-first 并以缓存兜底。配合生产环境 Express 静态中间件上的显式 Cache-Control 头(/assets/* 用 immutable, max-age=31536000,index.html、sw.js、manifest.json 用 no-cache, must-revalidate),重新构建后浏览器中的代码始终自动刷新,无需硬刷新;client/src/main.tsx 中的 controllerchange 监听器会在新 SW 接管已被控制的页面时恰好重新加载一次(首次安装不会)。VAPID 推送通知管道完全保留。着陆页和维基 SW 预缓存各自的 shell 并在首次访问时延迟缓存图片,单次加载后即可离线访问。所有 manifest 使用 SVG 图标(favicon.svg,sizes="any"),包含 apple-mobile-web-app-capable + apple-touch-icon meta 标签以支持 iOS 独立模式 |
| 自托管资源(无 CDN) | 所有字体与脚本均本地托管,零第三方 CDN 请求。React 应用通过 @fontsource 打包 Inter + JetBrains Mono(latin 子集;由 Vite 输出为带内容哈希的 WOFF2 至 dist/assets/)。着陆页与维基加载本地的 fonts/fonts.css @font-face 样式表(维基用 ../fonts/)。维基的 Mermaid 改为本地内置(wiki/mermaid.min.js,mermaid@10.9.6)而非 jsDelivr。VS Code 扩展的错误页改用系统字体栈。移除了所有 fonts.googleapis.com / gstatic / CDN 调用,因此仪表盘与文档可完全离线渲染,不向第三方泄露任何信息 |
| 桌面应用(macOS 与 Windows) | 用 Electron 35 构建的可选原生桌面应用,位于 desktop/ 工作区,与 client/、server/、mcp/、vscode-extension/ 平级。以 macOS .app(.dmg)以及 Windows .exe(NSIS 安装包 + 免安装便携版)形式分发。它将现有的 Express 服务器以进程内方式嵌入(直接 require() server/index.js —— 没有子进程、没有 IPC),并在 BrowserWindow 中渲染已构建的 React 客户端。新增了原生标题栏、菜单栏 / 通知区域(托盘)图标(单击其下拉菜单会显示一份在点击时从 SQLite 实时拉取的状态快照:会话、Agent、今日事件)、原生应用菜单、开机自启(macOS 通过 SMAppService 登录项;Windows 通过按用户的 HKCU\…\Run)、一个 ⌘Q / Ctrl+Q 确认对话框(再按一次即跳过)、关闭窗口只隐藏但服务器继续运行、单实例锁,以及 在浏览器中打开、重启服务器、查看日志 等托盘操作。优先使用端口 4820(回退到 4821–4829,再到随机高位端口),若 4820 上已有健康的 dashboard 在运行则直接采用而不重复绑定,并与 Web dashboard 共存 —— npm run dev 与桌面应用可同时运行,Hook 会同时分发到两者。通知以原生操作系统弹窗(toast)形式触发(Web Push 在 Electron 中无法可靠工作)。首次由应用自有的服务器启动时,它会自动安装 Claude Code Hook 并启动后台服务,因此仅安装应用的用户无需任何手动设置即可让事件流转。详见 DESKTOP.md 与 desktop/README.md |
提供方范围与数据位置: 设置会让 Claude Code / Codex / 两者的选择在整个应用中保持一致,并可在无需重启仪表盘的情况下更改任一会话数据目录。
本地安全边界: Run Agent 接受任意已存在的绝对工作目录,并在使用前规范化路径,因此仍支持从主目录和最近项目启动。托管 Webhook 提供方必须使用 HTTPS;generic 与 n8n 可为本地/自托管接收方使用 HTTP,投递不会跟随重定向。
- Node.js >= 22.22.0(推荐 Node 24 LTS)
- npm >= 9.0.0
git clone https://github.com/hoangsonww/Claude-Code-Agent-Monitor.git
cd Claude-Code-Agent-Monitor
npm run setupnpm run install-hooks安装程序会打开交互式多选器:使用方向键、Space 和 Enter 选择 Claude Code、Codex(beta) 或两者(默认选中 Claude Code)。Claude Code 条目位于 ~/.claude/settings.json;Codex 条目位于 ~/.codex/hooks.json。如果所选产品的 Dashboard Hook 已存在,安装程序会在仅替换本 Dashboard 的条目前发出警告——无关 Hook 会被保留。之后也可在 Settings → Hook Configuration → Install hooks 中进行相同选择。
首次进入仪表板时,请选择数据来源;应用只检查该选择所需的 Hook。Claude Code 只要求 Claude Hook,Codex 只要求 Codex Hook,选择两者则必须同时具备两套 Hook。如果所需 Hook 均已安装,仪表板会立即打开;否则设置引导只列出并安装缺失的已选提供方,同时保留无关 Hook。若状态检查失败,流程会安全地回退到手动设置。
~/.codex/sessions 中的 Codex rollout 也会持续被发现。Dashboard 会增量读取其仅追加 JSONL,优先处理最新 rollout,并将损坏的历史文件隔离后重试,因此即使漏掉某个 Hook 通知,会话、Token、成本、会话记录和 WebSocket 更新仍会保持最新。
Codex rollout 生命周期记录驱动与 Claude Code 相同的实时卡片状态:user_message 和 task_started 将主 Agent 标记为工作中;task_complete 会保持会话 active,但显示为等待中;turn_aborted 会显示带有中断原因的等待中。新的 rollout 记录会自行修复被错误标为 completed 的会话。在受支持的本地主机上,存活检测会匹配每个 Codex 进程实际打开的 rollout-*.jsonl,因此共享同一项目目录的旧 rollout 会按 completed 导入,而不会显示为虚假的 active Agent。Node 启动器与其原生 Codex 子进程会合并为一个逻辑进程,因此一个 TUI 只生成一张卡片。
Codex 的 /rename 标题会从原生会话索引读取,并实时更新会话和 agent 卡片。对话回放包含用户回合以及 exec 自定义工具调用和输出,并通过 cursor 分页在 transcript 顶部加载更早的消息。
Claude Code 和 Codex 卡片都会在各自提供方原生标题下显示最近不同用户提示的紧凑两行历史,因此简短友好的名称或简短跟进都不会隐藏当前任务。Claude 会在实时 Hook、导入和 watchdog 扫描期间从本地 transcript 缓存刷新该上下文;Codex 会从 rollout 记录刷新,并为旧导入回退到持久化的 user_message 事件。Transcript 会在可用时渲染 Claude Code 和 Codex 已持久化的 PNG/JPEG/GIF/WebP 附件,并将 Codex 重复的 response/event 副本合并为一条用户回合。
Codex 的 response_item 工具调用会通过独立 rollout cursor 仅索引一次,因此 Workflows 工具流、会话 drill-in、模型/Token 总计和 context_compacted 次数都忠实反映已记录的 Codex 数据,而不会重放生命周期或 Token 计数器。当仪表板范围仅为 Codex 时,仅适用于 Claude Code journal 的 Dynamic Workflows 面板会隐藏,而不会显示空的 Codex 数据。
# 开发模式(服务端和客户端均支持热重载)
npm run dev
# 生产模式(单进程,构建后的客户端)
npm run build && npm startTip
Makefile 替代方案 — 如果你安装了 make,所有命令也可通过 make 执行。运行 make help 查看所有目标,或使用快捷命令如 make dev、make build、make test 等。
| 模式 | 地址 |
|---|---|
| 开发 | http://localhost:5173 |
| 生产 | http://localhost:4820 |
Note
服务器默认绑定 127.0.0.1(开箱即用不可从网络访问 —— GHSA-gr74-4xfh-6jw9);如需在局域网暴露,请设置 DASHBOARD_HOST 和 DASHBOARD_TOKEN(设置后 /api/* 与 WebSocket 都需要该 token),并在 DASHBOARD_ALLOWED_HOSTS 中列出局域网主机名。参见 .env.example / .github/SECURITY.md。
npm run mcp:start # stdio(默认 — 用于 MCP 宿主集成)
npm run mcp:start:http # HTTP + SSE 服务器,端口 8819
npm run mcp:start:repl # 带 Tab 补全的交互式 CLI
ccam mcp stdio # 内置插件使用的稳定启动器stdio 模式下,配置你的 MCP 宿主(Claude Code / Claude Desktop / 其他 MCP 客户端):
- command:
ccam - args:
["mcp", "stdio"]
HTTP 模式下,远程 MCP 客户端连接 http://127.0.0.1:8819/mcp(Streamable HTTP)或 http://127.0.0.1:8819/sse(传统 SSE)。
详见 mcp/README.md 了解完整的宿主配置、传输详情、安全标志和工具目录。
npm run seed创建 8 个示例会话、23 个 Agent 和 106 个事件,让你可以立即浏览 UI。
如果你不想一直开着终端窗口,可以安装可选的原生桌面应用。它将 Express 服务器以进程内方式嵌入运行,提供菜单栏 / 通知区域(托盘)图标,并支持开机自启(macOS 登录项 / Windows 启动项)。
最快的方式是从 最新 GitHub Release 下载预构建的安装包(每当 master 上的 package.json 版本号被提升时,CI 都会自动发布一个新的 vX.Y.Z):
- macOS —— 下载
ClaudeCodeMonitor-<version>-arm64.dmg(Apple Silicon)或-x64.dmg(Intel),并将 Claude Code Monitor.app 拖入/Applications。 - Windows —— 下载
ClaudeCodeMonitor-Setup-<version>-x64.exe(安装版)或ClaudeCodeMonitor-<version>-x64-portable.exe(免安装版),然后运行它。
若希望自行构建:
npm run desktop:install # 在 desktop/ 中安装 Electron + electron-builder(预检原生依赖;失败时打印安装帮助)
npm run desktop:dmg:arm64 # macOS:Apple Silicon 专用 DMG(快速)
npm run desktop:win # Windows:NSIS 安装包 .exe(在 Windows 上运行)Tip
DMG 在 macOS 上构建,Windows .exe 在 Windows 上构建 —— electron-builder 针对宿主操作系统打包。为自己的 Mac 构建时,请使用架构专用命令(desktop:dmg:arm64 或 desktop:dmg:x64),它们速度快得多;desktop:dmg 会按架构把应用构建两次,产出两个按架构的 DMG(arm64 + x64,不做任何合并),仅在制作发布产物时才需要。
完整的生命周期语义、托盘/菜单功能、签名与公证钩子详见下文的 桌面应用(macOS 与 Windows) 章节,以及 DESKTOP.md。
OCI 镜像以非 root 用户运行,丢弃全部 capability,使用 Tini 作为 PID 1,并包含 Git、OpenSSH 与 SQLite。Docker Compose 和 Podman Compose 使用同一份文件。
# 仅 Dashboard
docker compose up -d --build
# 或
podman compose up -d --build
# 完整认证栈
umask 077
openssl rand -hex 32 > deployments/secrets/dashboard-token
openssl rand -hex 32 > deployments/secrets/hook-token
openssl rand -hex 32 > deployments/secrets/mcp-token
openssl rand -base64 32 > deployments/secrets/grafana-admin-password
npm run docker:full:up宿主机端口默认仅绑定 loopback:Dashboard 4820、MCP 8819、Nginx 8080、Prometheus 9090、Grafana 3000。Claude/Codex home 只读挂载,命名卷保存 SQLite 与 Dashboard 配置。Nginx 代理 UI、认证 REST 与 WebSocket,默认在边缘阻止 Hook、指标和 MCP。
Important
Hook 必须在宿主机安装。远程 Hook 使用 CCAM_DASHBOARD_URL=https://... 和 CCAM_HOOK_TOKEN;非 loopback URL 必须使用 HTTPS。详见 DEPLOYMENT.md。
Dashboard 通过 Claude Code 原生 Hook 系统集成,提供 Agent 活动的实时监控。以下是架构和数据流概览:
sequenceDiagram
participant CC as Claude Code
participant HH as Hook Handler
participant API as Express 服务器
participant DB as SQLite
participant WS as WebSocket
participant UI as React 客户端
CC->>HH: stdin(JSON 事件)
HH->>API: POST /api/hooks/event
API->>DB: 插入/更新记录
API->>WS: 广播更新
WS->>UI: 推送消息
UI->>UI: 重新渲染组件
Note over CC,HH: Hook 在 SessionStart、<br/>PreToolUse、PostToolUse、<br/>Stop、SubagentStop、<br/>SessionEnd、Notification 时触发。<br/>压缩从 JSONL 检测
Note over API,DB: 事务性写入<br/>带自动会话/Agent 创建
Note over WS,UI: ~0ms 延迟,<br/>无轮询
- Claude Code 在会话开始、工具使用、回合结束、子 Agent 完成和会话退出时触发 Hook
- Hook Handler(
scripts/hook-handler.js)从 stdin 读取 JSON 事件并 POST 到 API。5 秒超时静默失败,永不阻塞 Claude Code - 服务器 在 SQLite 事务内处理事件:
- 首次接触时自动创建会话和主 Agent
- 检测
Agent工具调用以追踪子 Agent 创建 SessionStart时,在会话和主 Agent 上盖上awaiting_input_since时间戳,使停在提示符前的全新 CLI 立即落入等待中UserPromptSubmit时(用户按下回车),清除等待标志并将主 Agent 提升为working— 这是文本响应回合开始的唯一可靠信号,因为它们不发出PreToolUsePreToolUse时将 Agent 设为working(同时清除等待标志),PostToolUse后保持 working 状态(也清除等待标志 — 用于处理用户在工具运行期间批准权限提示的场景)- 非错误
Stop时,主 Agent 变为waiting— Claude 完成本回合,主动权交给用户。错误Stop会将 Agent 和会话标记为error。后台子 Agent 继续运行 - 在权限
Notification时(按消息模式匹配:permission、waiting for input、needs your approval等),将 Agent 设为waiting并盖上awaiting_input_since SubagentStop故意不清除等待标志 — 后台子 Agent 完成不能说明用户是否已响应- 通过
SubagentStop单独标记子 Agent 为完成。res.json()返回后,触发 fire-and-forget 的scanAndImportSubagents,遍历会话的subagents/agent-*.jsonl文件,根据tool_use_id配对tool_use↔tool_result块,并在每个子 Agent 自己的agent_id下发出PreToolUse+PostToolUse事件 — 弥补子 Agent 内部工具调用对 dashboard 不可见的空白 SessionEnd时(CLI 进程退出),清除等待标志。如果会话已处于error状态,则保留错误状态;否则将所有 Agent 和会话标记为completedSessionStart时,任何无活动超过DASHBOARD_STALE_MINUTES(默认 180 = 3 小时,可通过环境变量覆盖)的其他活跃会话自动标记为"abandoned",其 Agent 标记为完成。处理会话内的/resume、Ctrl+C 和其他会话无SessionEnd而被孤立的场景- 错误恢复:只有
UserPromptSubmit和PreToolUse可以将会话从error恢复为active— 表示用户主动进行了重试 - 新工作事件到达时重新激活 completed/error/abandoned 会话(会话恢复)。Stop 和 SubagentStop 事件也会重新激活 completed/abandoned 会话 — 处理服务器启动前已导入的预存会话,其中第一个 Hook 事件可能是 Stop
- 检测对话压缩(JSONL Transcript 中的
isCompactSummary条目)并创建CompactionAgent 和事件。Token 基线在压缩中保留,不丢失任何用量。Transcript 读取使用基于 stat 的缓存和增量字节偏移读取 — 仅解析自上次读取后追加的新字节,长会话约提速 50 倍 - 从 JSONL Transcript 提取 API 错误(
isApiErrorMessage条目:配额限制、速率限制、invalid_request)和原始type: "error"响应,存储为APIError事件。回合耗时(system子类型turn_duration)存储为TurnDuration事件。工具结果错误(toolUseResult.is_error)追踪为ToolError事件 - 错误检测看门狗 — 后台定时器每 15 秒运行一次,扫描没有近期 Hook 事件(>10 秒)的活跃会话。它重新读取 Transcript 文件查找 API 错误(认证失败、速率限制、配额耗尽),从会话
cwd推导 Transcript 路径(用于没有transcript_path的导入会话),并在发现 API 错误时将会话/Agent 标记为error。这可以捕获 Claude CLI 在 API 错误后不触发 Hook 的情况(例如 401 认证失败时 CLI 只显示错误并等待) - 用户中断(Esc)恢复 — 用户按
Esc取消回合时不会触发任何 Hook(Claude Code 已知的限制),因此若不加干预,主 Agent 会永远卡在working状态。同一个 15 秒看门狗以两种方式恢复这些会话:(1) 当取消在 Transcript 中留下[Request interrupted by user]标记时(Esc 发生在已有部分输出之后),Transcript 缓存通过pendingInterrupt标记它 —— 该标志纯粹由 Transcript 顺序推导得出(最新的中断与最新的真实回合活动相比,使用同一时钟,因此即便是亚秒级取消也有效)—— 会话在约 15 秒内转入等待中;(2) 当 Esc 在任何输出之前按下时,Claude Code 完全不写入标记,因此应用空闲超时回退 —— 当主 Agent 处于working、没有进行中的工具(current_tool为 null),且DASHBOARD_WORKING_IDLE_SECONDS(默认120)期间既无 Hook 事件也无 Transcript 推进时,该回合被视为已死,会话转入等待中。两条路径都记录一个Interrupted事件,并将会话置于与正常Stop相同的等待中状态。流式输出(Transcript 仍在增长)和进行中的工具调用(current_tool已设置)不受影响;罕见的误判会在下一次真实 Hook 时自愈 - 死亡会话存活性回收(liveness reap) — 退出 Claude Code(Ctrl+C、关闭终端)会触发
SessionEndHook,但如果此刻仪表盘没有运行,该事件将永远丢失,会话会一直停留在等待中,直到废弃清理(默认 3 小时)。同一个 15 秒看门狗通过进程存活性探测弥补这一缺口:列出正在运行的claudeCLI 进程(macOS 上ps+lsof,Linux 上/proc),并将cwd中不存在任何存活 claude 进程的active会话标记为完成——落入与真实SessionEnd相同的completed状态,并在时间线上留下一条合成的SessionEnd事件。保护条件:在看门狗节拍上,会话的 Transcript 必须至少有DASHBOARD_LIVENESS_IDLE_SECONDS(默认60)未被写入(磁盘上没有 Transcript 时以最后一次 Hook 写入为后备时钟)——启动时的回收跳过该门槛,因此即使在启动前一秒退出的会话也会立即清除;探测在 Windows 上、容器内(看不到宿主机进程)、ps/lsof失败时,或通过DASHBOARD_LIVENESS_PROBE=0显式禁用时会报告"无法回答"(不做任何更改)。在混合部署中,回收还会自动跳过任何cwd不是 POSIX 绝对路径的会话——通过家庭 Hook(household hooks)从另一台机器转发来的会话会报告来源机器自己的路径(例如 Windows 的D:\Git\ai-deck),本地的ps/lsof//proc扫描永远无法匹配它,因此远程会话得到保护,而无需为真正本地的会话禁用探测。远程数据源会话(sessions.source≠local)同样始终被跳过——它们的cwd在另一台机器上本就是合法的 POSIX 绝对路径,因此本地进程探测对它们无从判断;它们的生命周期由远程同步核对流程掌管。误判的完成会自愈:下一个 Hook 事件会重新激活会话。除 15 秒看门狗节奏外,回收还会在启动时立即运行(清除上次运行遗留在 DB 中的死亡会话,让它们根本来不及渲染),并在约 5 秒后再运行一次(覆盖启动同步刚导入的会话),因此仪表盘停机期间死亡的会话绝不会显示为等待中 - 周期性服务器清理捕获遗漏事件检测的废弃会话和新压缩(例如
/compact不触发 Hook、会话创建后几秒内/resume)。频率从DASHBOARD_STALE_MINUTES派生(¼ 阈值,夹在 60 秒–5 分钟之间)。清理共享 Hook Handler 的 Transcript 缓存,避免重复 I/O。废弃会话清理还会驱逐 Transcript 缓存条目以限制内存使用。此周期性清理与启动时的 1 小时清理都会跳过远程数据源会话(source≠local),因为它们的updated_at跟踪的是scp同步节奏,而非远程 CLI 的真实活动——它们的状态改为依据镜像重新核对,以 JSONL 内最新事件时间戳为准 - 持续项目同步(
startSessionSync)让~/.claude/projects在一次性、由标记位把关的启动回填之外仍可被发现:之后才加入、其会话从不经过 Hook 流入的项目,否则在手动重新扫描之前都将不可见。启动时的立即扫描、一个去抖的fs.watch(在 macOS/Windows 上递归监听,在 Linux 上监听根目录 + 直接子文件夹),以及一个DASHBOARD_SESSION_SYNC_MS轮询(默认 30 秒;0禁用轮询,但监听器保持运行),三者共享同一个 mtime 缓存与一次合并扫描,只重新解析 mtime 前进过的文件 —— 并跳过已导入且未变更的会话、不再重新解析,因此重启成本保持为 O(新增/变更文件)。每个新发现/增长的会话都会广播session_created/session_updated外加其主 Agent,与 Hook 发出的帧相同
- WebSocket 将变更广播到所有已连接客户端
- UI 接收更新并重新渲染受影响的组件
持久化状态:working | waiting | completed | error。awaiting_input_since
字段是补充性的 — 它记录 Agent 开始等待的时间点,用于显示等待时长,但 waiting
现在是真正的持久化状态。
stateDiagram-v2
[*] --> waiting: ensureSession(首个 hook)
waiting --> working: PreToolUse / UserPromptSubmit / Codex task_started / user_message
working --> working: PostToolUse(工具完成)
working --> waiting: Stop,非错误 / Codex task_complete
working --> waiting: Codex turn_aborted(中断)
working --> waiting: Notification(输入提示)
working --> waiting: Esc 取消(看门狗:标记或空闲超时)
waiting --> error: Stop 有错误
working --> error: Stop 有错误
waiting --> error: 检测到 API 错误(看门狗)
working --> error: 检测到 API 错误(看门狗)
error --> working: UserPromptSubmit / PreToolUse(恢复)
working --> completed: SessionEnd
waiting --> completed: SessionEnd
note right of waiting
Agent 在回合之间或
等待用户输入
end note
持久化状态:active | completed | error | abandoned。等待中会话状态
是 UI 覆盖层(status=active 加上 awaiting_input_since 被设置)。
stateDiagram-v2
[*] --> waiting: SessionStart startup/resume/clear(status=active + 标志)
active --> active: SessionStart compact(回合中 — 保留状态,无标志)
waiting --> active: UserPromptSubmit / PreToolUse / PostToolUse / Codex task_started / user_message
active --> waiting: Stop,非错误 / Codex task_complete(标志重新盖上)
active --> waiting: Codex turn_aborted(中断)
active --> waiting: 权限 Notification(Agent → waiting)
active --> waiting: Esc 取消(看门狗:标记或空闲超时)
active --> error: Stop, stop_reason=error
active --> error: 检测到 API 错误(看门狗)
waiting --> error: 检测到 API 错误(看门狗)
error --> active: UserPromptSubmit / PreToolUse(恢复)
waiting --> completed: SessionEnd(CLI 退出)
active --> completed: SessionEnd(CLI 退出)
error --> error: SessionEnd(保留错误状态)
waiting --> abandoned: 过期 > DASHBOARD_STALE_MINUTES(默认 180)
active --> abandoned: 过期 > DASHBOARD_STALE_MINUTES
completed --> active: 会话恢复(新工作事件)
error --> active: 会话恢复
abandoned --> active: 会话恢复
completed --> [*]
error --> [*]
abandoned --> [*]
flowchart LR
TU["token_usage 行<br/>(按会话 × 模型)"] --> GROUP["按模型分组"]
PR["model_pricing 规则<br/>(基于模式匹配)"] --> SORT["按特异性排序<br/>(最长模式优先)"]
GROUP --> MATCH{"匹配模型<br/>到定价规则"}
SORT --> MATCH
MATCH --> CALC["成本 = Σ (tokens / 1M) × 费率<br/>针对 input、output、cache_read、cache_write"]
CALC --> RESULT["{ total_cost, breakdown[] }"]
style TU fill:#003B57,stroke:#005f8a,color:#fff
style PR fill:#6366f1,stroke:#818cf8,color:#fff
style RESULT fill:#10b981,stroke:#34d399,color:#fff
Important
成本计算流程基于 Token 使用量和模型定价规则。确保你的定价规则是最新的以反映准确成本。通过设置页面更新模型定价表以保持准确的成本追踪 — Dashboard 不会自动从外部来源获取定价更新。设置定价规则后,Dashboard 会追溯应用于所有会话以保持一致的成本报告。
| 环境变量 | 默认值 | 描述 |
|---|---|---|
DASHBOARD_PORT |
4820 |
Express 服务器端口 |
CLAUDE_DASHBOARD_PORT |
4820 |
Hook Handler 连接服务器使用的端口 |
DASHBOARD_TOKEN_FILE |
(未设置) | Docker/Kubernetes Secret 使用的文件型 Dashboard token |
DASHBOARD_HOOK_TOKEN / _FILE |
(未设置) | 远程 /api/hooks/* 采集的独立 token |
DASHBOARD_ENV_PATH |
仓库 .env |
Settings 持久化配置所用的可写 dotenv 路径 |
CCAM_DASHBOARD_URL |
本地发现 | 远程 Hook 目标;非 loopback 必须使用 HTTPS |
CCAM_HOOK_TOKEN / _FILE |
(未设置) | Hook handler 发送的凭据 |
DASHBOARD_STALE_MINUTES |
180(3 小时) |
一个仍为 active 的会话(包括正在等待中用户输入的会话——"等待中"是 active 行上的 UI 覆盖层,而非存储状态)在被自动标记为 abandoned 并从活跃列表中移除之前的无活动分钟数。由 15 秒看门狗和周期性维护清理(每 ¼ 该值运行一次,夹在 60 秒–5 分钟之间)执行。调低(例如 60)可获得更短的空闲超时 |
DASHBOARD_WORKING_IDLE_SECONDS |
120 |
用于恢复在任何输出之前以 Esc 取消(不会留下 Transcript 标记)回合的空闲工作超时。当主 Agent 处于 working、没有进行中的工具,且在此时长内既无 Hook 事件也无 Transcript 推进时,看门狗将会话转入等待中。调低可获得更迅捷的恢复,但代价是长时间静默思考的回合上偶尔出现误判(会自愈) |
DASHBOARD_LIVENESS_PROBE |
1(开启) |
设为 0 可禁用看门狗的死亡会话存活性回收(基于 ps/lsof 的探测,将匹配的本地 Claude Code 或 Codex CLI 进程已不存在的 active 会话标记为完成——恢复仪表盘停机期间丢失的 SessionEnd)。从另一台机器(家庭 Hook)转发来的会话会报告非 POSIX 的 cwd,会被回收自动跳过,因此混合的本地 + 转发部署不再需要关闭此项;仅在纯远程部署(本地进程无法证明任何事情)时才禁用它。在 Windows 和容器内自动禁用 |
DASHBOARD_LIVENESS_IDLE_SECONDS |
60 |
看门狗节拍存活性回收的空闲门槛:只有当会话的 Transcript 至少有这么长时间未被写入时(磁盘上没有 Transcript 时以最后一次 Hook 写入为后备时钟),才会将其标记为完成,因此回合中或刚 resume 的会话绝不会因一次瞬时的探测偏差而消失。启动时的回收跳过该门槛——boot 时由探测单独决定,因此启动前一刻退出的会话会立即清除 |
DASHBOARD_SESSION_SYNC_MS |
30000 |
持续 ~/.claude/projects 后台同步的轮询间隔(毫秒),用于显示启动后才加入、其会话从不经过 Hook 流入的项目。无论如何 fs.watch 监听器都会近乎即时触发;该轮询是安全兜底(监听器可能错过事件 / 在网络文件系统上不触发)。设为 0 可禁用轮询,同时让监听器保持运行 |
DASHBOARD_CODEX_HOME |
CODEX_HOME 或 ~/.codex |
可选的本地 Codex 状态目录。在设置中保存新位置会持久化此仪表盘专用覆盖、重新启用实时监视,并立即扫描新的 sessions/ 树。 |
DASHBOARD_CODEX_SYNC_MS |
4000 |
仅追加 Codex rollout 的安全兜底轮询间隔(毫秒)。Codex Hook 会立即触发同一个增量采集器;设为 0 仅禁用轮询,在可用时仍保留文件系统监听器。 |
DASHBOARD_TASK_SUMMARY_TTL_MS |
2000 |
任务进度缓存的宽限窗口(毫秒),作用于 include_task_progress 列表请求以及会话详情的 todo_snapshot。正在持续追加的转录文件几乎无法命中 size+mtime 缓存键,若无此下限,一连串列表刷新(例如仪表盘随 Hook 驱动的 WebSocket 事件刷新)会导致每个请求都完整重新解析数 MB 的活跃转录。窗口内改为返回刚解析的(略有滞后、仅用于展示的)结果;设为 0 恢复每次变更立即重新解析 |
DASHBOARD_REMOTE_SYNC_MS |
15000 |
远程数据源后台同步的间隔(毫秒),会独立拉取每个已启用远程的 ~/.claude/projects 和 ~/.codex/sessions(另含 Codex 的轻量 session_index.jsonl 标题索引),再分别通过本地导入器重新导入。新增或重新启用数据源时也会立即同步一次。设为 0 可禁用远程源轮询 |
DASHBOARD_REMOTE_ACTIVE_WINDOW_MS |
600000(10 分钟) |
远程数据源会话实时状态的新鲜度窗口。每次同步时,若远程 Claude Code 或 Codex 会话对应镜像 transcript 的 JSONL 最后事件在此窗口内,仍视为运行中(active);镜像停止推进超过该时长后,会话会被协调为 completed。远程会话不接收实时 Hook,因此按 provider 的镜像协调取代本地 liveness;失败、缺失或卡住的 provider 镜像会回退到常规 stale 扫描。链路较慢或空闲回合很长时可调大 |
DASHBOARD_REMOTE_SYNC_TIMEOUT_MS |
600000 |
每个远程源 scp 的超时时间 |
DASHBOARD_REMOTE_TEST_TIMEOUT_MS |
15000 |
到源的 SSH 连接探测超时时间 |
NODE_ENV |
development |
设为 production 以提供构建后的客户端 |
仪表盘的完整功能面同样可以在终端中使用——零依赖的 ccam CLI(bin/ccam.js),由 npm run setup 自动链接(失败即降级的 npm link)。CLI 通过 ~/.claude/.agent-dashboard.json(与 hook 处理器相同的注册表)自动发现正在运行的服务器,可用 CLAUDE_DASHBOARD_PORT/DASHBOARD_PORT 覆盖,默认 http://127.0.0.1:4820。
# 服务器
ccam status # ● 运行中 / ○ 未运行 指示器
ccam start [--port N] # 在后台启动服务器(分离进程)
ccam stop # 优雅地停止后台服务器
ccam repl # 交互式 shell(也可用 shell、i)
# 监控
ccam health # 仪表盘是否在运行?
ccam stats # 总量、今日事件、状态分布
ccam kanban # 会话 + agent 按状态列分组
ccam tail [--session <id>] # 终端里的实时事件流(Ctrl+C 停止)
# 数据
ccam sessions [--status s] [--q text] [--limit n]
ccam session <id> # 详情:agent 树、成本、最近事件
ccam agents [--status s] [--session id]
ccam events [--session id] [--limit n]
# 洞察
ccam analytics # token 总量、常用工具、agent 类型
ccam workflows [--session id] # 工作流智能统计与模式
ccam runs [--session id] # 动态 Workflow 工具运行
ccam cost [--session <id>] # 按模型细分的总预估成本
# (--session 限定为单个会话;显示服务器工具附加费用;
# 对有用量但无定价规则的模型发出警告)
# 告警 & webhook
ccam alerts [--unacked] # 触发告警流
ccam alerts ack <id> | ack-all # 确认告警
ccam rules # 告警规则列表
ccam webhooks # webhook 目标列表
ccam webhooks test <id> # 发送合成测试告警
# 价格
ccam pricing # 定价规则列表(含 fast-mode 与 intro 列)
ccam pricing set <pattern> --input N --output N [--cache-read N --cache-write N]
[--cache-write-1h N] [--fast-input N --fast-output N]
[--intro-input N --intro-output N … --intro-until YYYY-MM-DD]
ccam pricing delete <pattern>
ccam pricing reset
# 导入
ccam import rescan # 重新扫描 ~/.claude/projects
ccam import path <dir> # 导入目录下所有 .jsonl
# 管理
ccam doctor # 连接、hook 与数据库诊断
ccam info # 原始系统信息 JSON
ccam export [file.json] # 导出全部数据为 JSON
ccam import-data <file.json> # 恢复导出(幂等、非破坏性)
ccam cleanup --hours N --days M # 放弃滞留会话 / 清理旧会话
ccam reinstall-hooks # 重新安装 Claude Code hook
ccam update-check # 检出是否落后于 upstream?(打印更新命令)
ccam clear-data --yes # 删除全部数据(必须 --yes)
ccam open # 在浏览器中打开仪表盘
ccam version # 打印 CLI 版本(也可用 --version / -v)基于 API 的命令需要服务器在运行——未运行时,只读命令会自动回退为直接读取 data/dashboard.db(显示明确的 ⚠ Offline mode 横幅,且数据库中已死亡的 active 会话会用服务器看门狗所用的同一进程存活性探测在显示层校正),而无法在无服务器时正确运行的命令(实时 tail、分析/成本计算、写操作)会打印 ○ Dashboard server is NOT running 指示、具体原因和启动命令;ccam start 可在后台拉起生产服务器。读取类命令始终安全;唯一的破坏性命令(clear-data)没有显式 --yes 时拒绝执行。输出是完整的终端 UI——带右对齐数字列的框线表格、状态图标(● active、○ waiting、✔ completed、✖ error)、stats/analytics/cost 的内联条形图,以及真正的 ├─/└─ 代理树——ANSI 颜色在 TTY 上自动启用、管道输出时自动关闭,并可通过 --no-color / NO_COLOR / FORCE_COLOR 控制。若需持续监控,ccam repl(别名 shell / i)会打开一个交互式 shell,你可以在其中输入命令而无需 ccam 前缀——带有 CCAM 欢迎横幅、Tab 补全、可持久化的方向键历史、实时服务器状态提示符(● host 在线 / ○ offline 离线)、分组的 help / help <cmd> 菜单,以及可自动刷新任意命令的 watch [秒] <命令> 内置命令(例如 watch 5 kanban);每一行都作为独立子进程运行,因此离线拒绝或阻塞的 tail 都不会拖垮 shell。若 ccam 不在 PATH 上,在仓库根目录运行一次 npm link。完整参考——标志、服务器发现顺序、REPL、安全模型、退出码——见 docs/CLI.md。
| 命令 | 描述 |
|---|---|
npm run setup |
安装根目录、客户端、扩展与 MCP 依赖,构建 MCP 并链接 ccam |
npm run dev |
同时启动服务端(watch 模式)+ 客户端(Vite HMR) |
npm run dev:server |
仅启动 Express 服务器(--watch) |
npm run dev:client |
仅启动 Vite 开发服务器 |
npm run build |
构建 React 客户端到 client/dist/ |
npm start |
启动生产服务器(提供构建后的客户端) |
npm run install-hooks |
在 ~/.claude/settings.json 中配置 Claude Code Hook |
npm run seed |
用示例数据填充数据库 |
npm run import-history |
从 ~/.claude/ 导入历史会话(启动时也会运行) |
npm run reconcile-tokens |
刷新已导入会话的 Token 总计(不会降低已有的总计) |
npm run repair-tokens |
为每个 Transcript 仍在磁盘上的 Claude 会话(在 ~/.claude/projects/ 中查找,或按会话已保存的 transcript_path)重新推导非 workflow 的 Token 总计,并将上下文压缩基线清零;workflow 与 Codex 行保持不变。这是针对因 v2.0.9 之前按记录累加用量而虚高的数据库的一次性修复。请先停止 Dashboard |
DASHBOARD_TOKEN_REPAIR |
1(启用) |
npm run clear-data |
删除所有会话、Agent、事件和 Token 用量 |
npm run mcp:install |
安装本地 MCP 包(mcp/)的依赖 |
npm run mcp:build |
构建 MCP 服务器 TypeScript 到 mcp/build/ |
npm run mcp:start |
启动 MCP 服务器(stdio 传输 — 用于 MCP 宿主) |
npm run mcp:start:http |
启动 MCP 服务器(HTTP + SSE 传输,端口 8819) |
npm run mcp:start:repl |
启动 MCP 服务器(带 Tab 补全的交互式 REPL) |
npm run mcp:dev |
以开发模式运行 MCP 服务器(tsx,stdio) |
npm run mcp:dev:http |
以开发模式运行 MCP 服务器(tsx,HTTP + SSE) |
npm run mcp:dev:repl |
以开发模式运行 MCP 服务器(tsx,交互式 REPL) |
npm run mcp:typecheck |
类型检查 MCP 源码,不生成构建输出 |
npm run mcp:docker:build |
用 Docker 构建 MCP 容器镜像(agent-dashboard-mcp:local) |
npm run mcp:podman:build |
用 Podman 构建 MCP 容器镜像(localhost/agent-dashboard-mcp:local) |
npm run desktop:install |
在 desktop/ 工作区安装 Electron + electron-builder(为 Electron 的 ABI 重新编译 better-sqlite3);预检原生 better-sqlite3 构建,失败时打印可操作的安装帮助(含无工具链的替代方案) |
npm run desktop:build |
预构建校验 + tsc,编译 Electron 主进程到 desktop/out/ |
npm run desktop:dev |
构建后启动 Electron,加载本地桌面应用 |
npm run desktop:test |
运行桌面应用冒烟测试(启动 Electron 并探测 /api/health) |
npm run desktop:dmg |
macOS: 构建两个按架构的 DMG(arm64 + x64)— 用于发布,构建较慢 |
npm run desktop:dmg:arm64 |
macOS: 构建 Apple Silicon 专用 DMG — 快速 |
npm run desktop:dmg:x64 |
macOS: 构建 Intel 专用 DMG — 快速 |
npm run desktop:dmg:universal |
macOS: 构建一个合并的通用(universal)DMG(arm64 + x86_64,单个文件)——可选,最慢,不是发布版本附带的内容。 |
npm run desktop:win |
Windows: 构建 NSIS 安装包 .exe(x64)— 在 Windows 上运行 |
npm run desktop:win:portable |
Windows: 构建免安装便携版 .exe(x64)— 在 Windows 上运行 |
npm run monitoring:install |
在 monitoring/ 中运行 npm install — 通过 postinstall 下载 Prometheus + Grafana |
npm run monitoring:setup |
monitoring:install 的别名 |
npm run monitoring:up |
在后台启动 Prometheus(:9090)+ Grafana(:3000)(无需 Docker) |
npm run monitoring:down |
停止 npm 管理的监控栈 |
npm run monitoring:start |
前台启动监控栈(Ctrl+C 停止两者) |
npm run monitoring:docker:up |
通过 Docker Compose 启动 Prometheus + Grafana |
npm run monitoring:docker:down |
关闭 Docker 监控栈 |
npm run docker:up |
启动 Dashboard 容器 |
npm run docker:down |
停止 Dashboard 容器 |
npm run docker:full:up |
Dashboard + 认证 MCP + Nginx + Prometheus + Grafana |
npm run docker:full:down |
停止完整容器栈 |
npm run deploy:validate |
验证 Docker、Compose、Nginx、Helm、Kustomize、Terraform 与单 writer 约束 |
本仓库包含 Claude Code 和 Codex 的完整扩展层:
- Claude Code:
CLAUDE.md、.claude/rules/、.claude/skills/ - Claude 子 Agent:
.claude/agents/ - Codex:
AGENTS.md、.codex/rules/、.codex/agents/、.codex/skills/
graph TD
USER["开发者"]
CLAUDE["Claude Code"]
CODEX["Codex"]
MEMORY["CLAUDE.md + .claude/rules/*"]
C_SKILLS[".claude/skills/*"]
AGENTS_MD["AGENTS.md"]
X_RULES[".codex/rules/*.rules"]
X_AGENTS[".codex/agents/*.toml"]
X_SKILLS[".codex/skills/*"]
USER --> CLAUDE
USER --> CODEX
CLAUDE --> MEMORY
CLAUDE --> C_SKILLS
CODEX --> AGENTS_MD
CODEX --> X_RULES
CODEX --> X_AGENTS
CODEX --> X_SKILLS
- 持久上下文:
- 路径作用域规则:
- 技能:
repo-onboardingship-featureversion-releasemcp-operationsdebug-live-issue
- 子 Agent:
backend-reviewerfrontend-reviewermcp-reviewer
- 持久上下文:
- 执行策略:
- 自定义子 Agent 模板:
- 技能:
- 设置:
Tabby 是一只固定在每个页面右下角的可爱 SVG 小猫伴侣。它会订阅实时会话 WebSocket 流,并据此做出反应——既为仪表盘增添一丝活力,又提供随手可用的状态概览与快捷操作。它完全构建在现有的 WebSocket 流之上:无需新增后端、无需 API 密钥。
Tabby 基于实时会话流呈现 8 种情绪——空闲(idle)、观察(watching)、开心(happy)、担忧(worried)、卡住(stuck)、思考(thinking)、睡觉(sleeping)、断开连接(disconnected)。它的眼睛会追踪光标,每种情绪都有专属动画,让小猫始终反映当前的会话状态。
在值得关注的事件发生时(会话开始 / 结束、出现错误、运行完成),Tabby 会弹出气泡台词。台词带有节流,并且可以静音。
点击小猫,或按 ⌘B / Ctrl+B 打开面板(按 Esc 关闭)。面板包含:
- 实时状态行:N 个进行中 · M 个出错 · 连接状态。
- 快捷操作:跳转到 Run Claude / 活动 / 会话 / 出错的会话,静音,清除提醒。
- Ask 提问框:在本地回答简单的状态类问题;其他问题则交给现有的 Run Claude 页面(
/run?prompt=...),以启动一个真正的 Claude Code 会话。无需新增后端、无需 API 密钥。
Tabby 完全构建在现有的 WebSocket 流之上,支持键盘操作、aria-live,并尊重 prefers-reduced-motion 设置。可在「设置」中随时启用或禁用 Tabby。相关代码位于 client/src/components/Tabby/。
仪表盘会为实时会话活动提供轻柔的音频反馈,因此你可以把它放在副屏上,仍然能听到某次运行完成或失败。声音默认开启,也可以一键完全关闭。
仓库中没有任何 .mp3 或 .wav 资源,package.json 里也没有音频库。每个提示音都在播放时由 Web Audio API 生成:一小组振荡器(正弦或三角波),各自带指数增益包络,经主增益节点与低通滤波器混合,使声音退到你的工作之后而不是刺穿它。整个引擎只有一个文件:client/src/lib/sound.ts。
| 提示音 | 触发时机 | 听感 |
|---|---|---|
sessionStart |
出现新会话 | 上行纯五度(C5 → G5) |
sessionComplete |
会话回复完成(Stop)或关闭(SessionEnd) |
大三和弦解决音(E5 → G5 → C6) |
sessionError |
会话进入 error 状态 |
三角波上轻柔的下行小三度——能察觉,但不刺耳 |
subagentSpawn |
子代理启动 | 单次短促拨弦 |
notification |
Claude Code 发出 Notification 事件 |
失谐音对,如同小铃铛 |
connected / disconnected |
仪表盘 WebSocket 恢复或断开 | 双音升 / 降 |
click |
按下按钮、链接、标签页或开关 | 几乎听不见的滴答声 |
所有提示音都落在 C 大调音集内,因此叠加的尾音不会不协和;每个包络都以指数衰减而非硬切断,避免了硬停带来的爆音。
三重保护让音频不至于变成噪音:
- 单个提示音冷却——同一提示音在约 350 毫秒内不会重复(交互滴答声为 45 毫秒)。
- 全局突发预算——任意 1.2 秒窗口内最多启动 4 个提示音,因此导入历史或断线重连时,大量 WebSocket 消息不会变成一连串提示音。
- 自动播放策略——按浏览器规则,在你首次进行指针、按键或触摸交互之前不会播放任何声音;之前的提示音会被静默丢弃,而不是排队。
如果浏览器完全不支持 Web Audio,每次调用都是安全的空操作——仪表盘只是保持静音。
设置 → 声音提供总开关、音量滑块,以及每种提示音的独立开关。打开某个开关会立即播放该提示音,让你清楚听到刚刚启用的是什么;试听按钮可随时播放完成提示音。偏好设置保存在 localStorage 的 agent-monitor-sound 键下,在整个应用内即时生效——无需重新加载。该面板支持英文、中文、越南语、韩语和西班牙语。
默认情况下,会话开始、会话完成、会话出错、Claude Code 通知和交互滴答声为开启;子代理启动和连接变化为关闭(它们最为频繁)。实现位于 client/src/lib/sound.ts(引擎与偏好设置)和 client/src/hooks/useSoundCues.ts(事件总线接线),在 client/src/App.tsx 中挂载一次。
本项目在 mcp/ 目录下包含一个本地生产级 MCP 服务器,将 Dashboard 操作暴露为 AI Agent 的工具。支持三种传输模式以适应不同的集成场景。
flowchart LR
subgraph Transports["传输模式"]
STDIO["stdio\n(默认)"]
HTTP["HTTP + SSE\n(端口 8819)"]
REPL["交互式 REPL\n(终端 CLI)"]
end
subgraph Protocols["线路协议"]
P1["JSON-RPC\nstdin/stdout"]
P2["Streamable HTTP (2025-11-25)\n传统 SSE (2024-11-05)"]
P3["直接调用\nTab 补全 + 彩色输出"]
end
STDIO --> P1
HTTP --> P2
REPL --> P3
style STDIO fill:#6366f1,stroke:#818cf8,color:#fff
style HTTP fill:#f59e0b,stroke:#fbbf24,color:#000
style REPL fill:#a855f7,stroke:#c084fc,color:#fff
| 模式 | 命令 | 使用场景 |
|---|---|---|
| stdio | npm run mcp:start |
Claude Code、Claude Desktop、IDE MCP 宿主 |
| HTTP | npm run mcp:start:http |
远程 MCP 客户端、Web 集成、多会话 |
| REPL | npm run mcp:start:repl |
运维调试、手动工具调用、本地管理 |
graph LR
HOST["MCP 宿主<br/>(Claude Code / Claude Desktop)"]
HTTP_CLIENT["远程 MCP 客户端"]
OPERATOR["操作员 CLI"]
MCP_STDIO["MCP 服务器<br/>stdio"]
MCP_HTTP["MCP 服务器<br/>HTTP :8819"]
MCP_REPL["MCP 服务器<br/>REPL"]
API["Dashboard API<br/>Express /api/*"]
DB["SQLite<br/>data/dashboard.db"]
HOST -->|"stdin/stdout"| MCP_STDIO
HTTP_CLIENT -->|"POST /mcp · GET /sse"| MCP_HTTP
OPERATOR -->|"交互式 CLI"| MCP_REPL
MCP_STDIO --> API
MCP_HTTP --> API
MCP_REPL --> API
API --> DB
style HOST fill:#6366f1,stroke:#818cf8,color:#fff
style HTTP_CLIENT fill:#f59e0b,stroke:#fbbf24,color:#000
style OPERATOR fill:#a855f7,stroke:#c084fc,color:#fff
style MCP_STDIO fill:#0f766e,stroke:#14b8a6,color:#fff
style MCP_HTTP fill:#0f766e,stroke:#14b8a6,color:#fff
style MCP_REPL fill:#0f766e,stroke:#14b8a6,color:#fff
style API fill:#339933,stroke:#5cb85c,color:#fff
style DB fill:#003B57,stroke:#005f8a,color:#fff
graph TD
ROOT["MCP 工具"]
OBS["可观测性<br/>health, stats, analytics,<br/>system info, export, snapshot"]
SES["会话<br/>list/get/create/update"]
AGT["Agent<br/>list/get/create/update"]
EVT["事件和 Hook<br/>list events, ingest hook events"]
PRC["定价和成本<br/>规则 CRUD, 总成本/会话成本, 重置默认"]
MNT["维护<br/>cleanup, reimport, reinstall hooks, clear-all(受保护)"]
WFL["工作流<br/>统计、运行、下钻、编排"]
ALT["告警<br/>规则与触发记录"]
WHK["Webhook<br/>提供方、目标与投递"]
IMP["导入<br/>指南、扫描、上传、恢复"]
CFG["配置<br/>Claude/Codex 文件与备份"]
RUN["Run<br/>模型、目录、启动与控制"]
SET["设置<br/>更新、Home 与 Hook"]
DET["会话详情<br/>Transcript、图片与工作流"]
PSH["推送<br/>订阅、取消与发送"]
ROOT --> OBS
ROOT --> SES
ROOT --> AGT
ROOT --> EVT
ROOT --> PRC
ROOT --> MNT
ROOT --> WFL
ROOT --> ALT
ROOT --> WHK
ROOT --> IMP
ROOT --> CFG
ROOT --> RUN
ROOT --> SET
ROOT --> DET
ROOT --> PSH
flowchart TD
CALL["tools/call"] --> VALIDATE["zod 输入验证"]
VALIDATE --> TYPE{"工具类型?"}
TYPE -->|只读| EXEC["执行"]
TYPE -->|变更| M_FLAG{"ALLOW_MUTATIONS?"}
M_FLAG -->|否| DENY1["❌ 拒绝"]
M_FLAG -->|是| DEST{"破坏性?"}
DEST -->|否| EXEC
DEST -->|是| D_FLAG{"ALLOW_DESTRUCTIVE?"}
D_FLAG -->|否| DENY2["❌ 拒绝"]
D_FLAG -->|是| TOKEN{"confirmation_token?"}
TOKEN -->|无效| DENY3["❌ 拒绝"]
TOKEN -->|有效| EXEC
EXEC --> RESULT["返回工具结果"]
style EXEC fill:#339933,stroke:#5cb85c,color:#fff
style DENY1 fill:#dc2626,stroke:#f87171,color:#fff
style DENY2 fill:#dc2626,stroke:#f87171,color:#fff
style DENY3 fill:#dc2626,stroke:#f87171,color:#fff
- 只读模式(默认):
MCP_DASHBOARD_ALLOW_MUTATIONS=false - 管理模式:
MCP_DASHBOARD_ALLOW_MUTATIONS=true - 认证:
MCP_DASHBOARD_API_TOKEN/_FILE应与 Dashboard token 一致;MCP_HTTP_AUTH_TOKEN/_FILE保护 HTTP/SSE client - 传输防护:直接回环 HTTP 可携带 Token;容器主机别名必须使用 HTTPS;所有重定向都会被拒绝
- 负载防护:历史上传单文件 50 MiB、每次调用合计 100 MiB、二进制响应 10 MiB、备份恢复 25 MiB
- 破坏性模式:需要同时满足:
MCP_DASHBOARD_ALLOW_MUTATIONS=trueMCP_DASHBOARD_ALLOW_DESTRUCTIVE=true- 工具输入
confirmation_token: "CLEAR_ALL_DATA"
完整详情:mcp/README.md
所有端点返回 JSON。错误响应遵循格式 { error: { code, message } }。
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/openapi.json |
原始 OpenAPI 3.0 规范 |
GET |
/api/docs |
交互式 Swagger UI 文档 |
GET |
/api/redoc |
ReDoc 参考文档(针对阅读优化的三栏式 API 文档)。自托管:捆绑包从本地 /api/redoc/redoc.standalone.js 提供,不依赖 CDN,可离线使用 |
OpenAPI 文档由 server/openapi.js 生成,Swagger UI 由后端直接提供。
仓库根目录还提交了一份 openapi.yaml,它镜像实时规范,并通过 npm run openapi:yaml 重新生成(唯一可信来源为 server/openapi.js,切勿手动编辑)。
API 文档现已全面覆盖:每个后端路由都有文档说明(共 82 个路径条目),包含参数、Schema、字段描述与示例;新增文档的路由组包括 /api/push、/api/cc-config、/api/run、/api/workflows/runs、/api/sessions/facets 与 /api/settings/claude-home。
GET /api/metrics 以 Prometheus 文本暴露格式(text-exposition format)导出 Dashboard 的实时计数器——按状态划分的会话/Agent、事件与 Token 总数、已连接的实时客户端、已配置的远程数据源、进程运行时长/内存,以及构建版本——因此 CCAM 可被抓取(scrape)到你自己的可观测性栈中。一套开箱即用的 Prometheus + Grafana 组合,自动配置四个仪表盘(默认首页:CCAM — Overview),位于 monitoring/。
npm(无需 Docker / Homebrew):
npm start # dashboard on :4820
npm run monitoring:install # 一次性:npm postinstall 拉取二进制
npm run monitoring:up # Grafana 在 :3000(仅 npm 本地为 admin/admin)Docker / Podman(当 Dashboard 在容器中运行,或你偏好 Compose 时):
DASHBOARD_ALLOWED_HOSTS=host.docker.internal npm start # 或在 agent-monitor 服务上设置
npm run monitoring:docker:up
📊 Grafana · CCAM — Overview — 默认首页仪表盘(自动配置四个看板):舰队快照、数据库累计总量、分解图与速率 — 全部来自实时 /api/metrics 抓取
🔥 Prometheus · CCAM 控制台 — /consoles/index.html 预置落地页,直接查询 Prometheus 显示抓取状态、会话/事件/Token 总量及 Graph 钻取链接
📈 Prometheus · Graph — 对已抓取的 CCAM 指标运行 PromQL(如 sum(ccam_sessions)、ccam_events_total),可从 CCAM 控制台与 monitoring/README.md 的快捷链接打开
完整指标列表以及抓取/认证细节,请参见 docs/API.md → Metrics。
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/health |
返回 { status: "ok", timestamp } |
| 方法 | 路径 | 查询参数 | 描述 |
|---|---|---|---|
GET |
/api/sessions |
status、q、limit、offset |
列出会话(含 Agent 计数与每会话费用)。q 对 id / name / cwd 做不区分大小写搜索;limit 默认 50,最大 10000;响应包含 total 字段供分页器使用 |
GET |
/api/sessions/:id |
-- | 会话详情(含 Agent 和事件) |
GET |
/api/sessions/:id/stats |
-- | 会话详情概览面板使用的聚合计数:事件总数、按类型分类的事件、Top 工具用量、错误数、按类型/状态的 Agent 数、子 Agent 类型分布、Token 总量、时间范围 |
GET |
/api/sessions/:id/transcripts |
-- | 列出会话的可用 JSONL 转录文件(主 + 子 Agent + 压缩) |
GET |
/api/sessions/:id/transcript |
agent_id、limit、offset、after、before |
从指定转录文件流式读取消息,使用游标分页 |
POST |
/api/sessions |
-- | 创建会话(基于 id 幂等) |
PATCH |
/api/sessions/:id |
-- | 更新会话状态/元数据 |
| 方法 | 路径 | 查询参数 | 描述 |
|---|---|---|---|
GET |
/api/agents |
status、session_id、limit、offset |
列出 Agent(支持筛选) |
GET |
/api/agents/:id |
-- | 单个 Agent 详情 |
POST |
/api/agents |
-- | 创建 Agent |
PATCH |
/api/agents/:id |
-- | 更新 Agent 状态/任务/工具 |
| 方法 | 路径 | 查询参数 | 描述 |
|---|---|---|---|
GET |
/api/events |
session_id、limit、offset |
列出事件(最新优先) |
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/stats |
聚合计数、状态分布、WS 连接数 |
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/analytics |
用于图表和趋势视图的 Token / 工具 / 会话聚合数据 |
| 方法 | 路径 | 描述 |
|---|---|---|
POST |
/api/hooks/event |
接收并处理 Claude Code Hook 事件 |
Hook 事件载荷:
{
"hook_type": "PreToolUse",
"data": {
"session_id": "abc-123",
"tool_name": "Bash",
"tool_input": { "command": "ls -la" }
}
}| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/pricing |
列出所有定价规则 |
PUT |
/api/pricing |
创建或更新定价规则 |
DELETE |
/api/pricing/:pattern |
删除定价规则 |
GET |
/api/pricing/cost |
所有会话的总成本 |
GET |
/api/pricing/cost/:id |
指定会话的成本明细 |
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/workflows |
按 provider/source 聚合的工作流数据(编排、已记录工具、模式、Codex 压缩)。`?status=active |
GET |
/api/workflows/session/:id |
按 provider/source 的单会话 drill-in(agent 树、已记录工具时间线、事件) |
GET |
/api/workflows/session/:id |
按会话下钻(Agent 树、工具时间线、事件) |
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/settings/info |
系统信息、数据库统计、Hook 状态 |
POST |
/api/settings/clear-data |
删除所有会话、Agent、事件、Token 用量 |
POST |
/api/settings/reinstall-hooks |
重新安装 Claude Code Hook |
POST |
/api/settings/install-hooks |
安装 Claude Code、Codex 或两者的 Hook;保留无关 Hook |
POST |
/api/settings/reset-pricing |
将 Claude、Codex 或两者的定价重置为默认值 |
GET |
/api/settings/export |
以 JSON 下载方式导出所有数据 |
POST |
/api/settings/import |
从 /export 恢复一个不超过 25 MiB 的导出包(multipart file 或 JSON { path })。幂等且非破坏性——已存在的会话会被整体跳过 |
POST |
/api/settings/cleanup |
废弃过期会话、清除旧数据 |
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/remote-sources |
列出已配置的远程数据源 |
POST |
/api/remote-sources |
添加新的远程源 |
PATCH |
/api/remote-sources/:id |
更新某个远程源 |
DELETE |
/api/remote-sources/:id |
删除某个远程源 |
POST |
/api/remote-sources/:id/test |
测试到该源的 SSH 连接 |
POST |
/api/remote-sources/:id/sync |
立即触发该源的 scp + 导入 |
通过 Settings → Import History 中的提供方标签导入已有的
Claude Code 或 Codex 历史。Claude Code 使用
~/.claude/projects 的共享 JSONL 解析器;Codex 对
~/.codex/sessions 使用与实时监控相同的追加式 rollout 摄取器,
其中包含 Token 快照、response-item 工具、生命周期状态,以及提供
session_index.jsonl 时的原生 /rename 标题。重复导入是幂等的:
Claude 保留 compaction baseline,Codex 保留字节游标,因此两者都不会
重复计算用量或成本。文件夹和浏览器上传的 Codex 历史会在临时文件清理
之前复制到仪表板自有存储中。
flowchart LR
subgraph 来源
A1["默认文件夹<br/>~/.claude/projects"]
A2["自定义文件夹<br/>任意绝对路径"]
A3["上传文件<br/>.jsonl / .meta.json /<br/>.zip / .tar(.gz) / .gz"]
end
A1 -->|POST /api/import/rescan| R["server/routes/import.js"]
A2 -->|POST /api/import/scan-path| R
A3 -->|POST /api/import/upload<br/>multipart| R
R -->|解压 + 路径穿越防护<br/>+ zip-bomb 限额| X["server/lib/archive.js"]
R -->|递归遍历| I["importFromDirectory<br/>(scripts/import-history.js)"]
X --> I
I -->|与实时 Hook 采集<br/>相同的管线| P["parseSessionFile +<br/>importSession"]
P -->|预处理语句,<br/>单事务| D[("SQLite<br/>sessions / agents / events /<br/>token_usage")]
I -.->|import.progress<br/>已节流| W["WebSocket /ws"]
W -.-> U["Settings → Import History<br/>进度条 + 结果卡片"]
style A1 fill:#6366f1,stroke:#818cf8,color:#fff
style A2 fill:#6366f1,stroke:#818cf8,color:#fff
style A3 fill:#6366f1,stroke:#818cf8,color:#fff
style R fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style X fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style I fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
style P fill:#f59e0b,stroke:#fbbf24,color:#000
style D fill:#10b981,stroke:#34d399,color:#fff
style U fill:#a855f7,stroke:#c084fc,color:#fff
API 路由
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/api/import/guide |
按提供方返回路径、打包命令和说明(?provider=claude|codex) |
POST |
/api/import/rescan |
重新扫描所选默认路径({ provider }) |
POST |
/api/import/scan-path |
使用 { path, provider } 扫描任意绝对路径;递归遍历 |
POST |
/api/import/upload |
带 provider 字段的多部分上传;Codex 文件会被快照 |
支持的输入。 独立的 .jsonl 会话转录、配套的 .meta.json
元数据文件,以及包含任意嵌套目录结构的归档文件(.zip、.tar、
.tar.gz/.tgz、.gz)。Claude Code 的两种官方布局都会被自动识别:
<project>/<sessionId>/subagents/agent-*.jsonl(默认)和
<project>/subagents/<sessionId>/agent-*.jsonl(备选)。
准确性保证。 会话按 UUID 去重;重复导入始终安全。compaction 的
baseline_input / baseline_output / baseline_cache_read /
baseline_cache_write 列保留了压缩之前的 Token 总量,因此重新导入
压缩后的 JSONL 永远不会抹掉历史成本。
安全性。 归档解压会对每个条目进行路径穿越校验(绝对路径和 ..
路径段会被拒绝)。可配置的解压尺寸上限
(CCAM_IMPORT_MAX_EXTRACT_BYTES,默认 4 GB)可阻止 zip/tar/gzip
炸弹。上传大小按单文件(CCAM_IMPORT_MAX_BYTES,默认 1 GB)与单次
请求(CCAM_IMPORT_MAX_FILES,默认 2000)分别限制。每个请求使用
独立的临时目录,finally 中会被回收——即使 multer 提前拒绝了所有
文件也会被清理。
进度。 导入活动通过现有的 WebSocket 以 import.progress 消息广播
(phase:start / scan / extract / parse / complete /
error),并进行节流以避免在大批量导入时刷屏。
UI。 在 Settings → Import History 面板中使用拖放式向导,查看 分步指引、实时进度,以及导入完成后的结果卡片(imported / enriched / skipped / errors 计数)。
连接 ws://localhost:4820/ws 接收实时推送消息:
{
"type": "agent_updated",
"data": { "id": "...", "status": "working", "current_tool": "Edit" },
"timestamp": "2026-03-05T15:43:01.800Z"
}消息类型: session_created、session_updated、agent_created、agent_updated、new_event、remote_source.status
stateDiagram-v2
[*] --> Connecting: 组件挂载
Connecting --> Connected: onopen
Connected --> Closed: onclose / onerror
Closed --> Connecting: setTimeout(2000ms)
Connected --> [*]: 组件卸载
Closed --> [*]: 组件卸载
Dashboard 处理以下 Claude Code Hook 类型:
| Hook 类型 | 触发时机 | Dashboard 操作 |
|---|---|---|
SessionStart |
Claude Code 会话开始 | 创建会话和主 Agent。盖上 awaiting_input_since(附带 awaiting_reason=session_start),使新会话立即落入等待中——但 compact 来源的 SessionStart(回合中自动压缩)不改动标志,使正在工作的会话保持活动。重新激活恢复的会话。废弃无活动超过 DASHBOARD_STALE_MINUTES(默认 180)的孤立会话 |
UserPromptSubmit |
用户在提示符前按下回车 | 清除等待标志并将主 Agent 提升为 working — 文本响应回合开始的唯一可靠信号,因为它们不发出 PreToolUse |
PreToolUse |
Agent 开始使用工具 | 清除等待标志,设置 Agent 为 working,设置 current_tool。如果工具是 Agent,创建子 Agent 记录 |
PostToolUse |
工具执行完成 | 清除等待标志(用于处理用户在工具运行期间批准权限提示的场景)。清除 current_tool。Agent 保持 working |
Stop |
Claude 完成响应 | 非错误:主 Agent → waiting — Claude 完成本回合,主动权交给用户。stop_reason=error:将 Agent 和会话标记为 error。后台子 Agent 继续运行 |
SubagentStop |
后台 Agent 完成 | 通过描述、类型或任务匹配并完成子 Agent。故意不清除等待标志 — 子 Agent 完成不能说明用户是否已响应。触发 fire-and-forget 的 JSONL 扫描(scanAndImportSubagents),在子 Agent 自己的 agent_id 下为每个 tool 发出 PreToolUse + PostToolUse 事件,使 Timeline 显示子 Agent 运行的所有 tool,而不仅仅是 spawn 标记 |
Notification |
Agent 通知 | 记录事件。权限/输入提示消息将 Agent 设为 waiting 并盖上 awaiting_input_since(附带 awaiting_reason=notification,按模式匹配:permission、waiting for input、needs your approval 等)。压缩通知标记为 Compaction 事件。如果启用,触发浏览器通知 |
SessionEnd |
Claude Code CLI 进程退出 | 清除等待标志。如果会话已处于 error 状态,则保留错误状态;否则将所有 Agent 和会话标记为 completed |
Compaction |
JSONL 中检测到 /compact |
创建压缩子 Agent(类型 compaction)和 Compaction 事件。通过 Transcript JSONL 中的 isCompactSummary 条目检测。也可由周期性扫描器对活跃会话检测 |
APIError |
JSONL Transcript 中的 API 错误 | 从 isApiErrorMessage 条目(配额、速率限制、invalid_request)和原始 type: "error" 响应中提取。立即将会话和 Agent 标记为 error — 之前仅记录事件而不更改状态。存储为包含错误详情的事件 |
Interrupted |
用户取消的回合(Esc) | 由看门狗合成 —— Esc 不触发任何 Hook,因此从 Transcript 的 [Request interrupted by user] 标记,或当 Esc 发生在任何输出之前时从空闲工作超时(DASHBOARD_WORKING_IDLE_SECONDS)检测出卡住的 working 会话。会话转入等待中(与正常 Stop 相同) |
TurnDuration |
JSONL Transcript 中的回合计时 | 从 system 子类型 turn_duration 消息中提取,含 durationMs。存储为回合级计时分析事件 |
ToolError |
JSONL 中的工具结果错误 | 从 toolUseResult.is_error 条目中提取。追踪工具级失败用于错误传播分析 |
Dashboard 支持通过 Web Push (VAPID) 实现持久化浏览器通知。即使 Dashboard 标签页未聚焦或浏览器处于后台,也能提供实时警报。
- 启用 — 在设置页面通过主开关启用通知
- 授权 — 在浏览器提示时授予权限 — 这将注册一个 Service Worker 并创建一个推送订阅
- 配置 — 选择哪些事件触发通知:
| 事件 | 默认 | 描述 |
|---|---|---|
| 新会话开始 | 开 | 新 Claude Code 会话创建时触发 |
| Claude 完成响应 | 关 | Claude 完成响应回合时 Stop 事件触发 |
| 会话关闭 | 关 | CLI 进程退出时 SessionEnd 触发 |
| 会话错误 | 开 | 会话以错误结束时触发 |
| 子 Agent 生成 | 关 | 后台子 Agent 创建时触发 |
此外,来自 Claude Code 的任何 Notification Hook 事件都会触发浏览器通知(只要主开关启用),不受按事件开关影响。
- VAPID 管道: 服务端使用
web-push进行安全消息传递。VAPID 密钥自动生成并存储在data/vapid-keys.json。 - Service Worker: 专用 Worker (
client/public/sw.js) 处理传入的push事件,并以silent: false显示通知,以确保在 macOS 上播放音效。 - 订阅: 浏览器特定的端点存储在 SQLite 的
push_subscriptions表中。 - 持久性: 由于 Service Worker 在后台运行,即使浏览器已关闭,通知仍能送达。
- 测试通知: 设置页面中的按钮可让你验证 VAPID 管道和音效播放。
Dashboard 会监视自身的 git 检出,当规范默认分支领先于 HEAD 时弹出模态框。支持分支与 fork: 若配置了 upstream 远程(fork 的常规约定),则优先于 origin;所选远程的 master/main/HEAD 即为对比引用。manual_command 会根据用户处境调整——只有在本地分支真正跟踪规范引用时才用 git pull --ff-only,否则用 git fetch(fork 场景再加上 fast-forward 合并),命令永不撒谎。用户得到的是要在终端里执行的确切命令——服务端永远不会自动拉取或重启自己,这样机制在开发会话、pm2/systemd/launchd/Docker 等进程管理以及远程部署中都保持可移植性。
flowchart LR
S["服务器启动"] --> SCHED["更新调度器<br/>每 5 分钟"]
SCHED --> PICK["选择规范远程<br/>upstream 优先, 否则 origin"]
PICK --> FETCH["git fetch remote prune<br/>execFile 120 秒超时"]
FETCH --> CMP["rev-list HEAD vs<br/>remote master main HEAD"]
CMP --> FP["指纹是否变化?"]
FP -->|是| WS["广播<br/>update_status"]
FP -->|否| IDLE["跳过广播"]
WS --> CLIENT["UpdateNotifier<br/>+ 侧边栏徽标"]
CHECK["POST updates check"] --> FETCH
STATUS["GET updates status"] -.-> CMP
style WS fill:#6366f1,stroke:#818cf8,color:#fff
style CLIENT fill:#10b981,stroke:#34d399,color:#fff
单次检查开销很小(针对所选规范远程的 git fetch <remote> --prune——若配置了 upstream 则优先使用,否则用 origin),使用 execFile(不经 shell)封装并设有 120 秒超时。各种失败场景——离线、非 git 安装、未配置远程、无法解析上游引用——都会返回软失败载荷(例如 fetch_error: "...")而非抛错,因此不稳定的远程永远不会阻塞 Dashboard。
| 位置 | 行为 |
|---|---|
模态框 (client/src/components/UpdateNotifier.tsx) |
当 update_available === true 且用户尚未针对当前 remote_sha 关闭过时出现。显示落后的提交数、所追踪的引用、可复制的命令,以及三个按钮:复制命令(主按钮)、立即检查、关闭。ESC 与点击背景也可关闭。基于 remote_sha 在 localStorage 中持久化,上游出现更新提交时会自动重新弹出。 |
侧边栏按钮 (client/src/components/Sidebar.tsx) |
常驻在底部的"检查更新"按钮。落后时显示翠绿边框与绿色徽标点,最近一次检查失败时为琥珀色。点击会清除之前的"关闭"状态,并触发 POST /api/updates/check。 |
| 服务器终端 | 当调度器状态从"最新"变为"落后"时,会向 stdout 打印一段带框的命令块,便于无头运行的用户也能看到。 |
| 端点 | 作用 |
|---|---|
GET /api/updates/status |
只读检查:对规范远程运行 git fetch,比较 HEAD 与其默认分支,返回载荷。 |
POST /api/updates/check |
相同的检查,但会同时通过 WebSocket 广播 update_status,让所有连接的客户端同步更新。 |
两个端点返回相同的载荷结构:
{
"git_repo": true,
"update_available": true,
"repo_root": "/Users/you/Claude-Code-Agent-Monitor",
"remote_ref": "upstream/master",
"canonical_remote": "upstream",
"current_branch": "master",
"tracking_upstream": "origin/master",
"tracks_canonical": false,
"situation": "fork_or_diverged_tracking",
"local_sha": "abc1234...",
"remote_sha": "def5678...",
"commits_behind": 3,
"manual_command": "cd \"/...\" && git fetch upstream && git merge --ff-only upstream/master && npm run setup",
"situation_note": "You're on 'master' tracking 'origin/master'. This command fast-forwards your branch from upstream/master (the canonical default).",
"message": "3 commit(s) on upstream/master not in your checkout."
}situation 取值:tracking_canonical(典型克隆,本地分支跟踪规范引用——git pull --ff-only 即可);fork_or_diverged_tracking(本地分支名与规范一致但跟踪了不同的远程,例如 fork——git fetch <remote> && git merge --ff-only <ref>);feature_branch(不在规范默认分支上——只 fetch,由用户决定如何整合);detached_head。
这里没有 POST /api/updates/apply,也没有自重启脚本——这是有意为之。在没有外部进程管理的情况下让进程自我替换并不可靠:npm run dev(concurrently)、npm start、pm2、systemd、launchd、Docker 各自需要不同的重启逻辑,而 git pull / npm install 在一个即将退出的进程里失败时没有干净的回滚路径。只做检测能让行为在所有进程管理器、所有操作系统、所有分支状态下都保持可预测,同时仍然解决"什么时候需要拉取?"的信息缺口;实际的更新操作由用户在自己的 shell 中完成。
| 环境变量 | 默认值 | 说明 |
|---|---|---|
DASHBOARD_UPDATE_CHECK |
启用 | 设为 0 / false / off 可完全禁用调度器。 |
DASHBOARD_UPDATE_CHECK_INTERVAL_MS |
300000(5 分钟) |
两次自动检查的间隔。下限为 60 000 毫秒——低于此值会被钳制。 |
点击侧边栏底部的 Live / Disconnected 标签,可打开一个关于 Dashboard WebSocket 传输的小型详情面板。它会显示当前的 ws:// 端点、本次连接保持的时长、累计接收的事件数、以横向条形图展示的高频事件类型、最近 60 秒的吞吐量折线图,以及最近 8 个事件的活动列表。累计统计(总数、类型分布、最近列表)通过 localStorage 中的 sidebar-connection-stats 键持久化,可在刷新后保留;滚动折线图和"已连接时长"则有意保持临时性。底部的 Reset 按钮可一键清空所有数据。
Claude Code Agent Monitor 现已作为官方 VS Code 扩展提供,让你无需离开编辑器即可监控 AI Agent。
- 实时侧边栏:专用的 Activity Bar 视图,实时显示 Agent 状态(工作中、等待中、已完成、错误)。
- 使用分析:直接在侧边栏追踪总 Token 消耗、实时美元成本和事件计数。
- 状态栏集成:底部状态栏显示活跃会话和 Agent 的实时脉搏。
- 深度导航:一键访问特定的 Dashboard 页面(看板、分析、设置)或近期会话。
- 集成标签页:作为原生 VS Code Webview 标签页打开完整的监控面板。
- 打开 vscode-extension 目录。
- 从 Marketplace 安装或使用
vsce package自行打包安装。 - 确保本地 Dashboard 服务器正在运行(
npm run dev)。 - 点击 VS Code Activity Bar 中的 雷达图标 即可开始使用。
有关详细的开发人员配置,请参阅 .vscode 和 vscode-extension 目录。
Tip
Extension on VS Code Marketplace: Claude Code Agent Monitor
Dashboard 现在还提供一个可选的原生桌面应用,将现有的服务端 + 客户端打包进单个应用,安装一次即可长期使用:macOS 版为一个 .app(以 .dmg 分发),Windows 版为一个 .exe(一个 NSIS 安装包,外加一个免安装的便携版)。你在浏览器 localhost:4820 看到的全部内容都运行在这个窗口里,并在其上叠加了原生操作系统的生命周期能力:托盘图标、应用菜单、开机自启集成,以及一个能干净关闭服务器的「退出」按钮。
🍎🪟 桌面应用 —— 原生外壳:菜单栏 / 通知区域(托盘)图标、登录项自启动、单实例锁。同一套 Dashboard,运行在真正的操作系统窗口里(图为 macOS)。
🪟 同一套 Dashboard 作为原生 Windows 应用运行 —— 通知区域(托盘)图标、原生窗口菜单与登录项自启动。
状态: v1,支持 macOS 与 Windows。Linux 构建作为后续工作跟踪 —— Electron 让它实现起来并不难,但每个平台都需要各自的 QA。自动更新(auto-updater)同样不在 v1 范围内,当前的更新方式是重新下载最新的安装包。
desktop/ 是与 client/、server/、mcp/、vscode-extension/ 平级的同级工作区,使用 Electron 35 构建。它以进程内方式嵌入现有的 Express 服务器——直接 require() server/index.js,运行在与 Electron 主进程相同的 Node 运行时中,没有子进程、没有 IPC——并在 BrowserWindow 中渲染已构建好的 React 客户端。
#144 引入的 PWA 让 Dashboard 可以在 Chromium 系浏览器中安装,适合已经让服务器常驻运行的用户。桌面应用解决的是另一个正交问题:无需终端窗口即可启动并保持服务器运行。
| 能力 | PWA | 桌面应用 |
|---|---|---|
| 安装到 Dock / 应用程序文件夹 | ✅ | ✅ |
| 管理 Express 服务器 | ❌ —— 需用户单独 npm start |
✅ —— 进程内嵌入 |
| 开机自启 | ❌ | ✅ —— macOS 登录项 / Windows 启动项 |
| 菜单栏 / 通知区域(托盘)图标常驻状态 | ❌ | ✅ |
| 原生应用菜单(⌘ 快捷键等) | ❌ | ✅ |
| 浏览器重启后仍存活 | ✅ |
两者可以共存 —— 按你的工作流选择即可。
桌面应用本身不改动任何其他工作区的运行时行为。desktop/ 之外唯一的改动是对 server/index.js 做了一次保持行为不变的重构:监听端口后的引导逻辑(更新调度器、Claude Code 配置监视器 cc-watcher、孤儿运行对账)被抽取为一个导出的 startBackgroundServices(),使嵌入式服务器与 node server/index.js 运行完全相同的逻辑。独立服务器的运行路径在功能上没有任何变化。
flowchart TD
subgraph repo["Claude-Code-Agent-Monitor (repo root)"]
server["server/<br/>Express API · SQLite · WebSocket"]
client["client/<br/>React + Vite SPA"]
scripts["scripts/<br/>hook installer/handler, import, seed"]
mcp["mcp/<br/>local MCP server"]
vscode["vscode-extension/"]
desktop["desktop/<br/>★ Electron shell"]
end
desktop -- "require() in-process" --> server
desktop -- "loads built SPA from" --> client
desktop -- "auto-installs hooks via" --> scripts
server -- "serves static" --> client
style desktop fill:#6366f1,stroke:#818cf8,color:#fff
style server fill:#10b981,stroke:#34d399,color:#fff
方式 A —— 下载预构建的安装包(推荐):
从 Releases → latest 下载(公开,无需登录 GitHub)。每当 master 上的 package.json 版本号被提升时,CI 都会自动发布一个新的 vX.Y.Z,因此该链接始终指向当前版本:
| 平台 | 资源文件 | 说明 |
|---|---|---|
| macOS(Apple Silicon) | ClaudeCodeMonitor-<ver>-arm64.dmg |
拖入 /Applications |
| macOS(Intel) | ClaudeCodeMonitor-<ver>-x64.dmg |
拖入 /Applications |
| Windows(安装版) | ClaudeCodeMonitor-Setup-<ver>-x64.exe |
按用户安装,无需管理员权限 |
| Windows(便携版) | ClaudeCodeMonitor-<ver>-x64-portable.exe |
无需安装即可运行 |
若需要 每次提交的最新构建,可改用 CI 产物(需登录,保留 14 天):来自 🍎 macOS Desktop (DMG) 作业的 ClaudeCodeMonitor-dmg,以及来自 🪟 Windows Desktop (EXE) 作业的 ClaudeCodeMonitor-win。
安装:
macOS:
-
双击
.dmg将其挂载。 -
将 Claude Code Monitor.app 拖入你的
/Applications(应用程序)文件夹。 -
DMG 默认采用临时签名(ad-hoc signed),因此首次启动时 macOS Gatekeeper 会发出警告("Apple could not verify…")。清除隔离属性:
xattr -cr "/Applications/Claude Code Monitor.app"或者打开 系统设置 → 隐私与安全性,点击仍要打开(Open Anyway)。
-
启动应用。托盘图标出现,Dashboard 窗口打开。
Windows:
- 运行
ClaudeCodeMonitor-Setup-<ver>-x64.exe。它会按用户安装到%LOCALAPPDATA%\Programs\Claude Code Monitor(无需管理员提权)并允许你选择安装目录;或运行*-portable.exe无需安装即可启动。 - 安装包默认未签名,因此首次启动时 Windows SmartScreen 可能弹出「Windows 已保护你的电脑」("Windows protected your PC")—— 点击更多信息(More info)→ 仍要运行(Run anyway)。
- 从开始菜单 / 桌面快捷方式启动。通知区域(托盘)图标出现,Dashboard 窗口打开。
Windows 安装包 · 第 1 步 —— 选择安装选项(按用户「仅为我」对比全部用户)。
Windows 安装包 · 第 2 步 —— 选择安装位置(默认指向按用户的 %LOCALAPPDATA%\Programs)。
Windows 安装包 · 第 3 步 —— 完成安装(结束并启动应用)。
方式 B —— 本地构建:
# 在项目根目录,git clone 之后:
npm run setup # 安装根目录 + 客户端依赖、构建客户端、安装 Hook
npm run build # 构建 React 客户端(client/dist)
npm run desktop:install # 在 desktop/ 中安装 Electron + electron-builder(预检原生依赖;失败时打印安装帮助)
npm run desktop:dmg:arm64 # macOS: 快速的单架构 DMG → desktop/release/ClaudeCodeMonitor-<ver>-arm64.dmg
npm run desktop:win # Windows:NSIS 安装包 → desktop/release/ClaudeCodeMonitor-Setup-<ver>-x64.exeNote
DMG 在 macOS 上构建,Windows .exe 在 Windows 上构建 —— electron-builder 针对宿主操作系统打包。macOS 的 npm run desktop:dmg 构建有意设计得很慢(它会按架构把应用构建两次,产出两个按架构的 DMG——ClaudeCodeMonitor-<ver>-arm64.dmg 与 ClaudeCodeMonitor-<ver>-x64.dmg,并不做任何合并——发布时即随附这两个按架构的 DMG);为自己的 Mac 构建时请使用单架构的 desktop:dmg:arm64 / desktop:dmg:x64。在 Windows 上,npm run desktop:install 会把 better-sqlite3 作为 Electron 预编译二进制拉取,因此常见情况下无需 Visual Studio C++ 工具链。若构建确实失败(没有预编译二进制,或缺少 C++ 工具链),desktop:install 会打印准确的分平台修复步骤外加一个无工具链的替代方案,并显式失败(fail loudly),而非留下一个损坏的安装。
npm run desktop:install 会运行 scripts/install.js,它在重新编译 better-sqlite3(依赖树中唯一的原生模块)之前先做一次预检。若该原生构建失败,它会打印分平台的工具链前置条件,并以非零状态退出(绝不让你误以为安装成功);桌面构建的 prebuild.js 也会以同样的方式提前失败(fail fast)。打印出的指引包含两类常见原因与一个无工具链的替代方案:
- 缺少 C++ 构建工具链,模块无法从源码编译:
- Windows: 安装带 「Desktop development with C++」 工作负载的 Visual Studio Build Tools。
- macOS:
xcode-select --install - Linux: 安装
build-essential+python3。
- 你的 Node.js 比任何已发布的
better-sqlite3预编译二进制都新 —— 改用 Node LTS(20 或 22),它们自带预编译二进制,可完全避免编译。
或者,跳过源码编译、直接拉取 Electron 的预编译二进制(无需 C++ 工具链):
cd desktop
npm install --ignore-scripts
node node_modules/electron/install.js
npx electron-builder install-app-deps安装包默认未签名 / 临时签名,因此首次启动时操作系统可能会发出警告。
macOS —— DMG 默认采用临时签名(ad-hoc signing),在没有付费 Apple Developer ID 的情况下这是项目能提供的最高级别。macOS 首次打开时会警告「Apple 无法验证…」。两种绕过方式:
# 最简单:在打开前去掉隔离属性。
xattr -cr ~/Downloads/ClaudeCodeMonitor-*.dmg
# 或者在拖入「应用程序」之后去掉应用的隔离属性:
xattr -cr "/Applications/Claude Code Monitor.app"也可以打开 → 系统设置 → 隐私与安全性,滚动到被拦截的项目,点击仍要打开。
Windows —— 安装包默认未签名,因此首次启动时 SmartScreen 可能弹出「Windows 已保护你的电脑」("Windows protected your PC")—— 点击更多信息(More info)→ 仍要运行(Run anyway)。
- Electron 主进程挑选一个空闲端口 —— 优先 4820,其次回退到 4821–4829,若都被占用则使用一个随机的高位端口。
- 如果端口 4820 上已有进程响应
/api/health(例如你已在终端运行npm start),桌面应用会直接采用(adopt)那个服务器,不再启动第二个,避免重复绑定端口与 SQLite 争用。被采用的服务器不归应用所有 —— 退出应用时它仍会继续运行。 - 否则,应用直接
require()server/index.js在进程内启动 —— 与主进程同一个 Node 运行时、同一块内存,启动通常在两秒以内。 - 在首次由应用自有(owned)的服务器启动时,应用会自动安装 Claude Code Hook(写入
~/.claude/settings.json),并启动后台服务(更新调度器、cc-watcher配置监视器、孤儿运行对账)—— 这样仅安装应用的用户无需从代码检出运行npm run install-hooks即可让事件流转。- (macOS) 应用还会恢复你登录 Shell 的
PATH,使「运行 Claude」(Run Claude)功能能够找到并启动claudeCLI —— 从 Finder/Dock 启动的应用否则只会继承 launchd 提供的极简PATH,会漏掉~/.local/bin、/opt/homebrew/bin、版本管理器目录等位置的 CLI。(在 Windows 上,进程已继承用户PATH。)
- (macOS) 应用还会恢复你登录 Shell 的
- Dashboard 窗口打开 —— 除非应用是在登录时被启动的(macOS 通过登录项;Windows 通过带标记的
HKCU\…\Run项),此时它会保持仅托盘模式。 - 托盘(macOS 菜单栏 / Windows 通知区域)出现一个图标,菜单包含:打开 Dashboard、在浏览器中打开、重启服务器、查看日志、开机自启(开关)、退出。
flowchart TD
launch["App launch"] --> lock{"single-instance<br/>lock acquired?"}
lock -->|no| focus["focus existing window<br/>and exit(0)"]
lock -->|yes| probe{"healthy server<br/>already on :4820?"}
probe -->|yes| adopt["adopt it<br/>(ownedByUs = false)"]
probe -->|no| pick["pick free port<br/>4820 → 4821-4829 → random"]
pick --> boot["require() server/index.js<br/>in-process"]
boot --> bootstrap["auto-install hooks +<br/>startBackgroundServices()"]
adopt --> win
bootstrap --> win{"launched at login?"}
win -->|yes| tray["tray-only, dock hidden"]
win -->|no| show["open dashboard window"]
style adopt fill:#f59e0b,stroke:#d97706,color:#fff
style boot fill:#6366f1,stroke:#818cf8,color:#fff
style bootstrap fill:#10b981,stroke:#34d399,color:#fff
- 托盘图标 —— 常驻状态面板(macOS 菜单栏 / Windows 通知区域)。左键单击切换 Dashboard 窗口的显示/隐藏;右键单击打开上下文菜单,包含打开 Dashboard、在浏览器中打开、重启服务器、查看日志、开机自启(开关)与退出。macOS 使用着色的模板图标;Windows 使用彩色的
icon.ico(纯黑模板图标在深色任务栏上会看不见)。 - 窗口与任务栏图标 ——
BrowserWindow已绑定彩色的应用 Logo(Windows 上为icon.ico,其他平台为icon.png),因此标题栏 / 任务栏显示的是真正的 Claude Code Monitor 图标 —— 即便是未打包的npm run desktop:dev运行,也不再显示通用的 Electron 图标。 - 原生应用菜单 —— 标准的
About/File/Edit/View/Window/Help菜单,带⌘/Ctrl快捷键。其中 File → Open Dashboard(⌘1)项仅在 macOS 上可用:macOS 在窗口隐藏后仍保留全局菜单栏,因此该项能重新打开窗口 —— 而在 Windows/Linux 上,菜单是依附于窗口的,窗口隐藏时菜单快捷键无法触发,所以请改从托盘的 Open Dashboard 重新打开(即便窗口已最小化或被其他窗口遮挡,它也能可靠地将窗口调到前台)。 - 关闭窗口只是隐藏它。 服务器继续运行,托盘图标保留。点击托盘即可重新调出窗口。
- 退出(⌘Q / Ctrl+Q,或托盘 → 退出) 会优雅关闭嵌入式服务器、干净关闭 SQLite(完成 WAL checkpoint),然后退出。
- 开机自启开关: 在托盘菜单(或应用菜单)中切换开机自启。在 macOS 上,它通过
SMAppService/ServiceManagement框架注册 —— 你会在 → 系统设置 → 通用 → 登录项 中看到该条目;在 Windows 上,它写入一个按用户的HKCU\Software\Microsoft\Windows\CurrentVersion\Run项,可在任务管理器 → 启动中看到。当应用在登录时被启动时,它以仅托盘模式启动,不会有窗口突然弹到用户面前。 - 单实例锁: 重复启动只会聚焦已有窗口,不会产生第二个服务器,也不会发生端口冲突。(适用于所有平台。)
- 「在浏览器中打开」「重启服务器」「查看日志」 均可从托盘菜单直接触发。日志位于
~/Library/Logs/Claude Code Monitor/desktop.log(macOS)或%APPDATA%\Claude Code Monitor\logs\desktop.log(Windows)(菜单中的查看日志会打开该位置)。 - 你的数据(SQLite 数据库与 VAPID 密钥)保存在按用户的应用数据目录中,位于应用包 / 安装目录之外 —— macOS 为
~/Library/Application Support/Claude Code Monitor/data/,Windows 为%APPDATA%\Claude Code Monitor\data\,因此能够在应用重装与更新后继续保留。已打包的应用包是只读的,把数据库写在其中会导致「历史导入」(History Import)与事件持久化失败;保存在应用数据目录修复了这一点,并意味着你导入的历史在替换或升级应用时不会受影响。(Windows 的 NSIS 卸载程序默认会保留这些数据。) claudeCLI:在 macOS 上,应用在启动时会恢复你登录 Shell 的PATH—— 因此即便从 Finder/Dock 启动的 macOS 应用通常只会继承 launchd 提供的极简PATH,「运行 Claude」(Run Claude)功能依然能找到并启动claudeCLI。(在 Windows 上,所继承的用户PATH已包含它。)
所有命令都可从仓库根目录运行。每个负责打包的脚本都会先运行 npm run build,因此你无需手动调用 electron-builder。
| 命令 | 作用 |
|---|---|
npm run desktop:install |
在 desktop/ 中安装 Electron + electron-builder;为 Electron 的 ABI 重新编译 better-sqlite3;预检原生 better-sqlite3 构建,失败时打印可操作的安装帮助(含无工具链的替代方案) |
npm run desktop:build |
预构建校验 + tsc,编译主进程到 desktop/out/ |
npm run desktop:dev |
构建后启动 Electron 加载本地应用 |
npm run desktop:test |
冒烟测试(启动 Electron 并探测 /api/health),同样在 CI 上运行 |
npm run desktop:dmg |
macOS: 构建两个按架构的 DMG(arm64 + x64)。用于发布。构建较慢。 |
npm run desktop:dmg:arm64 |
macOS: 构建 Apple Silicon 专用 DMG。快速。 |
npm run desktop:dmg:x64 |
macOS: 构建 Intel 专用 DMG。快速。 |
npm run desktop:dmg:universal |
macOS: 构建一个合并的通用(universal)DMG(arm64 + x86_64,单个文件)——可选,最慢,不是发布版本附带的内容。 |
npm run desktop:win |
Windows: 构建 NSIS 安装包 .exe(x64)。 |
npm run desktop:win:portable |
Windows: 构建免安装的便携版 .exe(x64)。 |
Note
DMG 在 macOS 上构建,Windows .exe 在 Windows 上构建 —— electron-builder 针对宿主操作系统打包。macOS 的 npm run desktop:dmg 构建有意设计得很慢(它会按架构把应用构建两次,产出两个按架构的 DMG——ClaudeCodeMonitor-<ver>-arm64.dmg 与 ClaudeCodeMonitor-<ver>-x64.dmg,并不做任何合并——发布时即随附这两个按架构的 DMG);为自己的 Mac 构建时请使用单架构的 desktop:dmg:arm64 / desktop:dmg:x64。在 Windows 上,npm run desktop:install 会把 better-sqlite3 作为 Electron 预编译二进制拉取,因此常见情况下无需 Visual Studio C++ 工具链。
- 为自己的 Mac 构建 → 使用
desktop:dmg:arm64(Apple Silicon)或desktop:dmg:x64(Intel)。单架构、无合并,大约 1 分钟即可完成。 - 为所有人构建发布产物 → 使用
desktop:dmg(产出两个按架构的 DMG:arm64 + x64),并预期它会耗时较久。CI 已经会构建 macOS DMG 与 Windows.exe并分别上传为ClaudeCodeMonitor-dmg与ClaudeCodeMonitor-win产物,因此你很少需要在本地构建它们。 - 无论哪种方式,macOS DMG 体积约为 80 MB / 安装后约 250 MB,Windows 安装包体积相当 —— 这是标准的 Electron 体积成本。
better-sqlite3:依赖树中唯一的原生模块。桌面工作区在postinstall中通过electron-builder install-app-deps为 Electron 的 ABI 重新编译一份桌面专用的better-sqlite3,因此不会干扰仓库根目录为系统 Node 构建的那一份(npm run test:server仍可用)。若重新编译失败,服务器会回退到 Node 内置的node:sqlite,应用依然能启动。- 贡献者注意:构建 DMG 会针对目标架构重新编译
better-sqlite3,可能让其不再匹配本机 CPU 架构。桌面应用的预构建(prebuild)步骤会自动为本机修复(auto-heal)这一情况,因此后续的desktop:dev/desktop:test无需手动处理。 - 代码签名:macOS DMG 默认临时签名(
package脚本设置CSC_IDENTITY_AUTO_DISCOVERY=false,确保不会误用钥匙串里已有的证书)。提供CSC_LINK(base64 编码的.p12)与CSC_KEY_PASSWORD时启用真正的 Developer ID 签名。Windows 构建默认未签名(首次启动时 SmartScreen 可能弹出 —— 更多信息 → 仍要运行);仅当通过CSC_LINK+CSC_KEY_PASSWORD显式提供证书时才启用 Authenticode 签名。 - 公证(notarization):可选启用。当
APPLE_ID、APPLE_TEAM_ID、APPLE_APP_SPECIFIC_PASSWORD三者都设置时,desktop/scripts/notarize.js(electron-builder的afterSign钩子)会执行公证;否则它什么也不做。
.github/workflows/ci.yml 中有两个经过路径过滤的桌面作业(一个 changes 作业用 dorny/paths-filter 检测 desktop/** 的改动;这些作业也会在任何 push 时、或 PR 带有 desktop 标签时运行):运行在 macos-latest 上的 🍎 macOS Desktop (DMG) 作业会构建两个按架构的 DMG(arm64 + x64;对偶发的 hdiutil detach 失败会重试)并上传为 ClaudeCodeMonitor-dmg 产物(两个单架构 DMG);运行在 windows-latest 上的 🪟 Windows Desktop (EXE) 作业会构建并上传为 ClaudeCodeMonitor-win 产物(NSIS 安装包 + 便携版)。在向 master 推送版本号提升时,release 作业会把 macOS DMG 与 Windows .exe 都附加到所发布的 vX.Y.Z GitHub Release。Windows 图标(desktop/assets/icon.ico)已提交到仓库中(可用 npm run build:win-icon 从 icon.png 重新生成,基于 PowerShell + .NET,无需额外工具)。
| 现象 | 原因 / 解决方法 |
|---|---|
| 首次启动时 macOS 提示「Apple 无法验证…」 | DMG 默认临时签名。运行 xattr -cr ~/Downloads/ClaudeCodeMonitor-*.dmg(或对已安装的 .app 执行),或在系统设置 → 隐私与安全性中点击仍要打开 |
| 首次启动时 Windows SmartScreen 提示「Windows 已保护你的电脑」 | 安装包默认未签名。点击更多信息 → 仍要运行即可启动 |
「运行 Claude」提示 claude 不在 PATH 上 |
(macOS)从 Finder/Dock 启动的应用只会继承 launchd 的极简 PATH,而非你的 Shell PATH。已修复 —— 应用在启动时会恢复登录 Shell 的 PATH。若问题仍存在,请确认 claude 是真正的可执行文件(而非 Shell 别名或函数),并位于你的 Shell PATH 上。在 Windows 上,所继承的用户 PATH 已包含它 |
| 更新应用后导入的历史 / 会话消失 | 早期构建把数据库存放在(可被替换的)应用包内部。已修复 —— 数据现保存在 ~/Library/Application Support/Claude Code Monitor/data/(macOS)或 %APPDATA%\Claude Code Monitor\data\(Windows),可在重装与更新后保留。从修复前的旧版本升级后,请再执行一次 Import History → Rescan |
desktop:dev / desktop:test 报 ERR_DLOPEN_FAILED |
之前的 DMG 构建留下了为另一 CPU 架构编译的 better-sqlite3。预构建步骤会在下次构建时自动修复;如有需要可运行 npm run desktop:install |
更多细节请参阅面向用户的 DESKTOP.md,以及面向贡献者 / 架构的 desktop/README.md。
- 引擎: SQLite 3,通过
better-sqlite3(可选)或 Node.js 内置node:sqlite - 位置:
data/dashboard.db - 日志模式: WAL(写入期间支持并发读取)
- 重置: 删除
data/dashboard.db清除所有数据
erDiagram
sessions ||--o{ agents : owns
sessions ||--o{ events : owns
sessions ||--o{ token_usage : tracks
agents ||--o{ events : generates
agents ||--o{ agents : spawns
sessions {
TEXT id PK "UUID"
TEXT name "可读标签"
TEXT status "active|completed|error|abandoned"
TEXT cwd "工作目录"
TEXT model "Claude 模型 ID"
TEXT started_at "ISO 8601"
TEXT ended_at "ISO 8601 或 NULL"
TEXT metadata "JSON 数据"
TEXT awaiting_input_since "ISO 8601 或 NULL — 设置时表示等待中"
TEXT awaiting_reason "notification|stop|session_start|interrupted or NULL"
}
agents {
TEXT id PK "UUID 或 session_id-main"
TEXT session_id FK
TEXT name "主 Agent — {会话名} 或子 Agent 描述"
TEXT type "main|subagent"
TEXT status "working|waiting|completed|error"
TEXT current_tool "当前工具或 NULL"
TEXT awaiting_input_since "ISO 8601 或 NULL — 补充性等待时间戳"
TEXT awaiting_reason "notification|stop|session_start|interrupted or NULL"
}
events {
INTEGER id PK "自增"
TEXT session_id FK
TEXT agent_id FK
TEXT event_type "PreToolUse|PostToolUse|Stop|等"
TEXT tool_name "触发事件的工具"
TEXT created_at "ISO 8601"
}
token_usage {
TEXT session_id PK "与 model 的复合主键"
TEXT model PK "模型标识符"
INTEGER input_tokens
INTEGER output_tokens
INTEGER cache_read_tokens
INTEGER cache_write_tokens
}
model_pricing {
TEXT model_pattern PK "SQL LIKE 模式"
TEXT display_name "可读名称"
REAL input_per_mtok "每百万输入 Token 的美元成本"
REAL output_per_mtok "每百万输出 Token 的美元成本"
REAL cache_read_per_mtok "每百万缓存读取的美元成本"
REAL cache_write_per_mtok "每百万缓存写入的美元成本"
}
CCAM 为 Claude Code 和 Codex 提供 14 个共享插件、66 个插件技能、18 个 Claude 子 Agent、34 个 Claude 命令、3 个 CLI 工具、3 个 Hook 配置和 2 个支持 MCP 的插件。skills.sh CLI 可发现 76 个仓库技能。
claude plugin marketplace add hoangsonww/Claude-Code-Agent-Monitor
codex plugin marketplace add hoangsonww/Claude-Code-Agent-Monitor# 查看全部 76 个技能,不执行安装
npx skills add hoangsonww/Claude-Code-Agent-Monitor --list
# 在当前项目中为 Claude Code 和 Codex 安装一个技能
npx skills add hoangsonww/Claude-Code-Agent-Monitor \
--skill mcp-server \
--agent claude-code \
--agent codex \
--yes
# 验证、更新和移除项目级技能
npx skills list --json
npx skills update --project --yes
npx skills remove mcp-server --yes
# 添加 --global 以执行用户级安装,并显式管理全局范围
npx skills add hoangsonww/Claude-Code-Agent-Monitor \
--skill mcp-server \
--agent claude-code \
--agent codex \
--global \
--yes
npx skills list --global --json
npx skills update --global --yes
npx skills remove --global mcp-server --yes项目级安装使用 .agents/skills/ 及各 Agent 的链接。Claude Code 全局技能默认位于 ~/.claude/skills/,设置 CLAUDE_CONFIG_DIR 后位于其 skills/ 子目录。Codex 全局技能默认位于 ~/.codex/skills/,设置 CODEX_HOME 后位于其 skills/ 子目录。多 Agent 安装可能通过共享存储去重,并链接到这些目标目录。skills.sh CLI 可发现 76 个仓库技能,其中包括 66 个插件技能和仓库维护技能。
| 插件 | 安装命令 | 技能 |
|---|---|---|
| ccam-analytics | claude plugin install ccam-analytics@claude-code-agent-monitor-plugins |
session-report、cost-breakdown、usage-trends、productivity-score |
| ccam-cost-guard | claude plugin install ccam-cost-guard@claude-code-agent-monitor-plugins |
budget-set、spend-forecast、cost-alert、model-savings、daily-budget-check |
| ccam-productivity | claude plugin install ccam-productivity@claude-code-agent-monitor-plugins |
daily-standup、weekly-report、sprint-summary、workflow-optimizer |
| ccam-devtools | claude plugin install ccam-devtools@claude-code-agent-monitor-plugins |
session-debug、hook-diagnostics、data-export、health-check |
| ccam-insights | claude plugin install ccam-insights@claude-code-agent-monitor-plugins |
pattern-detect、anomaly-alert、optimization-suggest、session-compare |
| ccam-sessions | claude plugin install ccam-sessions@claude-code-agent-monitor-plugins |
session-search、session-timeline、transcript-replay、cwd-rollup、session-cleanup |
| ccam-workflows | claude plugin install ccam-workflows@claude-code-agent-monitor-plugins |
dag-map、delegation-audit、concurrency-report、error-propagation、fleet-runs |
| ccam-quality | claude plugin install ccam-quality@claude-code-agent-monitor-plugins |
error-scan、api-error-report、hook-failure-audit、slo-check、regression-alert |
| ccam-config | claude plugin install ccam-config@claude-code-agent-monitor-plugins |
config-audit、memory-review、skill-inventory、mcp-audit、hook-inventory |
| ccam-dashboard | claude plugin install ccam-dashboard@claude-code-agent-monitor-plugins |
dashboard-status、quick-stats + MCP 服务器 |
| ccam-runner | claude plugin install ccam-runner@claude-code-agent-monitor-plugins |
run-agent、run-history |
| ccam-integrations | claude plugin install ccam-integrations@claude-code-agent-monitor-plugins |
alert-management、webhook-management、remote-collection |
| ccam-platform | claude plugin install ccam-platform@claude-code-agent-monitor-plugins |
config-explorer、history-portability、hook-setup、mcp-server |
| ccam-reports | claude plugin install ccam-reports@claude-code-agent-monitor-plugins |
executive-report、cost-report、reliability-report、workflow-report |
ccam-stats— 终端 Dashboard(会话、成本、Token 含压缩基线)ccam-doctor— 系统诊断(API、数据库、Hook、数据新鲜度)ccam-export— 数据导出(JSON、CSV)用于会话、事件、分析、成本
# 安装插件后在 Claude Code 中:
/ccam-analytics:session-report latest
/ccam-analytics:cost-breakdown this week
/ccam-productivity:daily-standup today
/ccam-insights:pattern-detect tools
/ccam-dashboard:quick-stats📖 完整文档:docs/plugins.md
Claude Code 的独立 CLI 状态栏工具,显示模型名称、用户、工作目录、Git 分支、上下文窗口使用率条和 Token 计数 — 全部使用 ANSI 转义序列彩色编码。
Sonnet 4.6 | nguyens6 | ~/agent-dashboard/client | main | ████████░░ 79% | 3↑ 2↓ 156586c
| 段 | 颜色 | 示例 |
|---|---|---|
| 模型 | 青色 | Sonnet 4.6 |
| 用户 | 绿色 | nguyens6 |
| 工作目录 | 黄色 | ~/agent-dashboard |
| Git 分支 | 品红色 | main |
| 上下文条 | 绿色 / 黄色 / 红色 | ████████░░ 79% |
| Token | 暗色 | 3↑ 2↓ 156586c |
参见 statusline/README.md 了解安装说明。
graph TD
INDEX["server/index.js<br/>Express 应用 + HTTP 服务器"]
DB["server/db.js<br/>SQLite + 预编译语句"]
WS["server/websocket.js<br/>WS 服务器 + 广播"]
HOOKS["routes/hooks.js<br/>Hook 事件处理"]
SESSIONS["routes/sessions.js"]
AGENTS["routes/agents.js"]
EVENTS["routes/events.js"]
STATS["routes/stats.js"]
ANALYTICS["routes/analytics.js"]
PRICING["routes/pricing.js<br/>成本计算"]
SETTINGS["routes/settings.js<br/>系统管理"]
WORKFLOWS["routes/workflows.js<br/>工作流可视化"]
INDEX --> DB & WS
INDEX --> HOOKS & SESSIONS & AGENTS & EVENTS & STATS & ANALYTICS & PRICING & SETTINGS & WORKFLOWS
HOOKS --> DB & WS
SESSIONS --> DB & WS
AGENTS --> DB & WS
EVENTS --> DB
STATS --> DB
ANALYTICS --> DB
PRICING --> DB
SETTINGS --> DB
WORKFLOWS --> DB
style INDEX fill:#6366f1,stroke:#818cf8,color:#fff
style DB fill:#003B57,stroke:#005f8a,color:#fff
style WS fill:#10b981,stroke:#34d399,color:#fff
graph LR
ROOT["/ (首页)"] --> DASH["Dashboard<br/>统计 + Agent + 事件"]
K["/kanban"] --> KANBAN["KanbanBoard<br/>Agent / 会话 切换"]
S["/sessions"] --> SESS["Sessions<br/>可筛选表格"]
D["/sessions/:id"] --> DETAIL["SessionDetail<br/>Agent + 时间线 + 成本"]
A["/activity"] --> ACT["ActivityFeed<br/>流式事件日志"]
AN["/analytics"] --> ANALYTICS["Analytics<br/>Token + 热力图 + 趋势"]
WF["/workflows"] --> WORKFLOWS["Workflows<br/>D3 可视化 + 下钻"]
ST["/settings"] --> SETTINGS["Settings<br/>定价 + 通知 + Hook + 导出"]
NF["/*"] --> NOTFOUND["NotFound<br/>404 兜底页"]
ALL["所有路由"] --> LAYOUT["Layout 包装器<br/>(Sidebar + Outlet)"]
style ALL fill:#6366f1,stroke:#818cf8,color:#fff
style LAYOUT fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
flowchart TD
START["Claude Code 触发 Hook"] --> STDIN["读取 stdin 至 EOF"]
STDIN --> PARSE{"解析 JSON?"}
PARSE -->|成功| POST["POST 到 127.0.0.1:4820<br/>/api/hooks/event"]
PARSE -->|失败| WRAP["将原始输入包装为 JSON"]
WRAP --> POST
POST --> RESP{"响应?"}
RESP -->|200 OK| EXIT0["exit(0)"]
RESP -->|错误| EXIT0
RESP -->|超时 3s| DESTROY["销毁请求"] --> EXIT0
SAFETY["安全网: setTimeout 5s"] --> EXIT0
style EXIT0 fill:#10b981,stroke:#34d399,color:#fff
style START fill:#6366f1,stroke:#818cf8,color:#fff
我们支持开发和生产两种部署模式,使用不同的进程架构:
graph LR
subgraph dev["开发模式 — 2 个进程"]
D_CMD["npm run dev"] --> D_SRV["Express :4820<br/>node --watch"]
D_CMD --> D_VITE["Vite :5173<br/>HMR"]
D_BROWSER["浏览器"] --> D_VITE
D_VITE -->|"代理 /api + /ws"| D_SRV
end
subgraph prod["生产模式 — 1 个进程"]
P_BUILD["npm run build"] --> P_DIST["client/dist/"]
P_START["npm start"] --> P_SRV["Express :4820<br/>静态文件 + API"]
P_BROWSER["浏览器"] --> P_SRV
end
style D_VITE fill:#646CFF,stroke:#818cf8,color:#fff
style D_SRV fill:#339933,stroke:#5cb85c,color:#fff
style P_SRV fill:#339933,stroke:#5cb85c,color:#fff
style P_DIST fill:#646CFF,stroke:#818cf8,color:#fff
可选的本地 MCP Sidecar(支持 stdio、HTTP+SSE 和 REPL 传输):
graph LR
subgraph "MCP 传输选项"
M_STDIO["MCP 服务器 (stdio)<br/>npm run mcp:start"]
M_HTTP["MCP 服务器 (HTTP)<br/>npm run mcp:start:http<br/>:8819"]
M_REPL["MCP 服务器 (REPL)<br/>npm run mcp:start:repl"]
end
H["MCP 宿主"] -->|"stdin/stdout"| M_STDIO
RC["远程客户端"] -->|"POST /mcp · GET /sse"| M_HTTP
OP["操作员"] -->|"交互式 CLI"| M_REPL
M_STDIO --> D["Dashboard 服务器<br/>:4820"]
M_HTTP --> D
M_REPL --> D
style M_STDIO fill:#0f766e,stroke:#14b8a6,color:#fff
style M_HTTP fill:#0f766e,stroke:#14b8a6,color:#fff
style M_REPL fill:#0f766e,stroke:#14b8a6,color:#fff
deployments/ 可部署到任何兼容 Kubernetes 的平台,包括 EKS、GKE、AKS、OKE 和自建集群。CCAM 使用 SQLite,因此所有受支持的清单都强制 每个持久卷只有一个活动 Dashboard writer,并采用 Recreate 更新。只要 SQLite 仍是持久化后端,就不支持 HPA、active-active、多副本、蓝绿或金丝雀。
- Helm: Schema 拒绝多副本/HPA,支持镜像 digest、保留 PVC、Ingress 或 Gateway API、外部 Secret、NetworkPolicy、可选 MCP 与 ServiceMonitor。
- Kustomize: Restricted PSS 基础、dev/staging/production overlay,以及 MCP、监控、Gateway API、CSI Snapshot 组件。
- Terraform: 将经过验证的 Helm Chart 部署到现有 Kubernetes 集群;云网络、身份、CSI、TLS 与 Secret 同步由平台层负责。
- 运维: SQLite 在线备份、完整性检查、SHA-256、scale-to-zero 恢复、部署/回滚/拆除前备份、带认证的健康检查。
- CI 供应链: app 与 MCP 镜像会被扫描,发布 amd64/arm64,并附带 SBOM、SLSA provenance 和 Cosign keyless 签名。
npm run deploy:validate
REGISTRY="ghcr.io/$(gh repo view --json owner -q .owner.login)"
IMAGE_TAG="$(git rev-parse --short HEAD)"
helm upgrade --install agent-monitor deployments/helm/agent-monitor \
--namespace agent-monitor-production --create-namespace \
--values deployments/helm/agent-monitor/values-production.yaml \
--set image.registry= \
--set image.repository=${REGISTRY}/claude-code-agent-monitor \
--set image.tag=${IMAGE_TAG} \
--atomic --wait --timeout 10mNote
Secrets、Docker/Podman、Gateway API、Terraform、备份、恢复与回滚详见 DEPLOYMENT.md 和 deployments/README.md。
agent-dashboard/
|-- CLAUDE.md # Claude Code 项目记忆和工作约定
|-- AGENTS.md # Codex 项目指令
|-- package.json # 根脚本(Dashboard + MCP 辅助)+ 服务端依赖
|-- .claude/
| +-- rules/ # 路径作用域的 Claude 规则
| +-- skills/ # Claude 可复用项目技能
| +-- agents/ # Claude 自定义子 Agent
|-- .claude-plugin/
| +-- marketplace.json # Claude Code 插件市场清单(14 个插件)
|-- .agents/plugins/
| +-- marketplace.json # Codex 插件市场清单(14 个插件)
|-- plugins/
| |-- ccam-analytics/ # 分析:会话报告、成本明细、使用趋势、生产力评分
| | |-- .claude-plugin/plugin.json
| | |-- skills/ (4) # session-report, cost-breakdown, usage-trends, productivity-score
| | |-- agents/ # analytics-advisor(Sonnet 模型)
| | |-- hooks/hooks.json # Stop + SubagentStop 事件日志
| | +-- bin/ccam-stats # 终端 Dashboard CLI
| |-- ccam-productivity/ # 生产力:站会、报告、冲刺、工作流优化
| |-- ccam-devtools/ # 开发工具:调试、诊断、导出、健康检查
| |-- ccam-runner/ # Run Agent:启动、跟进、停止、恢复与历史
| |-- ccam-integrations/ # 集成:告警、Webhook、推送与远程采集
| |-- ccam-platform/ # 平台:配置、导入/恢复、Hook 与 MCP 管理
| | +-- bin/ # ccam-doctor + ccam-export CLI
| |-- ccam-insights/ # 洞察:模式、异常、优化、比较
| |-- ccam-cost-guard/ # 成本护栏:预算、支出预测、成本告警、模型节省
| |-- ccam-sessions/ # 会话取证:搜索、时间线、转录回放、按 cwd 汇总、清理
| |-- ccam-workflows/ # 工作流编排:DAG 映射、委派审计、并发、舰队运行
| |-- ccam-quality/ # 可靠性与 SLO:错误扫描、API 错误报告、Hook 失败审计、SLO 检查
| |-- ccam-config/ # 配置与记忆治理:配置审计、记忆审查、技能/MCP/Hook 清单
| +-- ccam-dashboard/ # Dashboard 连接器:状态、快速统计、MCP 集成
| +-- .mcp.json # MCP 服务器配置
|-- server/
| |-- index.js # Express 应用、HTTP 服务器、静态文件服务
| |-- db.js # SQLite Schema、迁移、预编译语句
| |-- websocket.js # WebSocket 服务器(含心跳)
| +-- routes/
| |-- hooks.js # Hook 事件处理(事务性)
| |-- sessions.js # 会话 CRUD
| |-- agents.js # Agent CRUD
| |-- events.js # 事件列表
| |-- stats.js # 聚合统计
| |-- analytics.js # Token、工具和趋势分析
| |-- workflows.js # 聚合工作流数据和按会话下钻
| |-- pricing.js # 模型定价 CRUD 和成本计算
| +-- settings.js # 系统信息、数据管理、导出、清理
| +-- lib/
| +-- transcript-cache.js # 基于 stat 的 JSONL Transcript 缓存,增量读取。采用 4 MiB 分块的同步字节流读取器并按行解析,避免一次性将整个文件加载为 JS 字符串,因此即使 JSONL 大于 V8 的最大字符串长度(64 位 Node 20 约 512 MiB)也能解析,不会让进程崩溃于 "FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal"。提取 Token、压缩、API 错误、回合耗时、思考块和用量附加信息(service_tier、speed、inference_geo)
| +-- compat-sqlite.js # node:sqlite 兼容性封装(better-sqlite3 的后备方案)
|-- client/
| |-- package.json # 客户端依赖
| |-- index.html # HTML 入口
| |-- vite.config.ts # Vite + 代理配置
| |-- tailwind.config.js # 自定义暗色主题
| |-- tsconfig.json # 严格 TypeScript
| +-- src/
| |-- main.tsx # React 入口
| |-- App.tsx # 路由 + WebSocket Provider
| |-- index.css # Tailwind + 自定义工具类
| |-- lib/
| | |-- types.ts # 共享 TypeScript 接口
| | |-- api.ts # 类型化 fetch 客户端
| | |-- format.ts # 日期/时间格式化工具
| | +-- eventBus.ts # WebSocket 分发的发布/订阅
| |-- hooks/
| | |-- useWebSocket.ts # 自动重连 WebSocket hook
| | +-- useNotifications.ts # WebSocket 事件触发的浏览器通知
| |-- components/
| | |-- Layout.tsx # 带 Sidebar + Outlet 的外壳
| | |-- Sidebar.tsx # 导航 + 连接指示器
| | |-- AgentCard.tsx # Agent 信息卡片(含状态)
| | |-- StatCard.tsx # 指标卡片
| | |-- StatusBadge.tsx # 彩色编码状态标签
| | |-- EmptyState.tsx # 空列表占位符
| | +-- workflows/ # D3.js 工作流可视化组件
| | |-- OrchestrationDAG.tsx # Agent 生成模式的水平 DAG
| | |-- ToolExecutionFlow.tsx # 工具到工具转换的 d3-sankey 图
| | |-- AgentCollaborationNetwork.tsx # 力导向 Agent 管道图
| | |-- SubagentEffectiveness.tsx # 带 SVG 成功率环的记分卡网格
| | |-- WorkflowPatterns.tsx # 自动检测的编排序列
| | |-- ModelDelegationFlow.tsx # 通过 Agent 层级的模型路由
| | |-- ErrorPropagationMap.tsx # 按层级深度的错误聚类
| | |-- ConcurrencyTimeline.tsx # 泳道式并行 Agent 执行
| | |-- SessionComplexityScatter.tsx # D3 气泡图(耗时 vs Agent vs Token)
| | |-- CompactionImpact.tsx # Token 压缩事件和恢复
| | |-- WorkflowStats.tsx # 聚合工作流统计
| | +-- SessionDrillIn.tsx # 按会话的 Agent 树、工具时间线、事件
| +-- pages/
| |-- Dashboard.tsx # 概览页
| |-- KanbanBoard.tsx # Agent / 会话切换的状态列
| |-- Sessions.tsx # 会话表格
| |-- SessionDetail.tsx # 单会话深入查看
| |-- ActivityFeed.tsx # 实时事件流
| |-- Analytics.tsx # Token 使用、热力图、趋势
| |-- Workflows.tsx # D3.js 工作流可视化和会话下钻
| |-- Settings.tsx # 模型定价、通知、Hook、导出、清理
| +-- NotFound.tsx # 404 兜底页
|-- scripts/
| |-- hook-handler.js # 轻量级 stdin-to-HTTP 转发器
| |-- install-hooks.js # 自动配置 ~/.claude/settings.json
| |-- import-history.js # 从 ~/.claude/ 导入会话,含增强 JSONL 提取(API 错误、回合耗时、入口点、权限模式、思考块、用量附加信息、工具错误、子 Agent JSONL 文件)。重新导入完全增量:在每次导入前按事件类型查询 `MAX(created_at) GROUP BY event_type` 作为基准,只插入 `ts > cutoff[type]` 的 JSONL 条目,长跨度会话即使 transcript 在多天内持续追加,也能在每次重跑时继续接收 Stop / PostToolUse / TurnDuration / ToolError 事件;同时在 JSONL 推进时前向更新 `sessions.ended_at`,并刷新消息计数元数据
| +-- seed.js # 示例数据生成器
|-- mcp/
| |-- package.json # MCP 包脚本 + 依赖
| |-- README.md # MCP 设置、宿主配置、工具目录、安全模型
| |-- src/
| | |-- index.ts # MCP 运行时入口(传输路由器)
| | |-- server.ts # MCP 服务器组装
| | |-- clients/ # 带重试/退避的 Dashboard API 客户端
| | |-- config/ # 环境/CLI 配置解析
| | |-- core/ # 日志器、工具注册、结果辅助
| | |-- policy/ # 变更/破坏性守卫
| | |-- tools/ # 16 个领域模块注册 97 个工具
| | |-- transports/ # HTTP+SSE 服务器、REPL、工具收集器
| | |-- ui/ # ANSI 横幅、颜色、格式化器、表格
| | +-- types/ # 共享 MCP 类型定义
| +-- build/ # 构建后的 MCP 运行时输出
|-- deployments/
| |-- README.md # 生产部署参考
| |-- nginx/ # Rootless Nginx 边缘与可选 Hook/MCP 策略
| |-- secrets/ # Git 忽略的 Compose token/password 文件
| |-- terraform/ # 将 Helm 部署到现有 Kubernetes 集群
| |-- kubernetes/ # 单 writer Kustomize 基础与环境 Overlay
| | |-- base/ # Restricted PSS、Recreate Deployment、PVC、Service、Ingress
| | |-- overlays/ # dev、staging、production 命名空间与资源
| | +-- components/ # MCP、ServiceMonitor、Gateway API、VolumeSnapshot
| |-- helm/agent-monitor/ # Schema 强制安全的 Helm Chart 与环境 values
| +-- scripts/ # validate、deploy、backup、restore、rollback、health、teardown
|-- .codex/
| |-- config.toml # Codex 运行时配置
| |-- README.md # Codex Agent 和技能设置指南
| |-- rules/ # Codex 执行策略规则
| |-- agents/ # Codex 自定义 Agent 模板
| +-- skills/ # Codex 项目技能
|-- desktop/
| |-- README.md # 桌面应用贡献者 / 架构参考
| |-- electron-builder.yml # DMG 打包配置;签名 / 公证钩子
| |-- src/
| | |-- main.ts # 主进程入口 —— 生命周期、对话框、装配
| | |-- server-host.ts # 进程内 Express 启动、端口发现、服务器采用、SQLite 关闭
| | |-- window.ts # BrowserWindow + 持久化窗口几何状态
| | |-- menu.ts # 原生应用菜单(File ▸ Open Dashboard 仅在 macOS 上可用)
| | |-- tray.ts # 菜单栏(托盘)图标 + 上下文菜单
| | |-- login-item.ts # macOS 登录项(SMAppService)开机自启
| | +-- logger.ts # 写入 desktop.log 的文件日志器
| |-- scripts/ # prebuild 校验、build-icons、notarize 钩子
| +-- tests/smoke.test.mjs # 启动 Electron 并探测 /api/health 的冒烟测试
|-- statusline/
| |-- README.md # 状态栏安装和使用指南
| |-- statusline.py # 渲染状态栏的 Python 脚本
| +-- statusline-command.sh # Claude Code statusLine 配置的 Shell 包装
+-- data/
+-- dashboard.db # SQLite 数据库(gitignored)
| 问题 | 解决方案 |
|---|---|
better-sqlite3 安装失败 |
这是非致命错误 — 服务器会自动回退到 Node.js 内置的 node:sqlite(Node 22+)。在旧版 Node 上,安装 Python 3 和 C++ 构建工具,然后运行 npm rebuild better-sqlite3 |
| Hook 未触发 | 运行 npm run install-hooks 并重启 Claude Code。验证 ~/.claude/settings.json 中存在 Hook 配置 |
| Dashboard 无数据 | 确保服务器正在运行(npm run dev)后再启动 Claude Code 会话。检查 http://localhost:4820/api/health |
| WebSocket 断开连接 | 客户端每 2 秒自动重连。检查端口 4820 未被防火墙阻止 |
| 重启后数据过期 | 数据库在重启间持久化。运行 npm run seed 获取新的演示数据,或删除 data/dashboard.db 重置 |
| MCP 工具连接失败 | 确认 Dashboard API 在 MCP_DASHBOARD_BASE_URL 上正常运行,并重新构建/启动 MCP(npm run mcp:build、npm run mcp:start) |
MIT。详见 LICENSE。







