ECC 仓库源码深度解析:/instinct-status 命令与 Continuous Learning v2 本能库状态可视化
导读
/instinct-status 是 ECC(Everything Claude Code)生态中 Continuous Learning v2 技能的核心诊断命令,用于在会话内以一条命令快速查看"当前项目已学会哪些本能(instincts)、全局积累了哪些本能、置信度如何"。本文以 .opencode/commands/instinct-status.md 为骨架,结合 instinct-cli.py、resolve-ecc-root.js 与 hooks/hooks.json 等仓库源码,逐层拆解该命令的调用链:从"如何在多插件根目录中准确定位 ECC 安装"的 walker 解析逻辑,到 CLI 后端的项目检测、范围合并、置信度可视化与 TTL 告警。读完你既能理解命令的真实运行机制,也能直接看懂其输出格式,并能在自己的 ECC 安装中复用这套定位器。
一、命令是什么:一条 OpenCode 斜杠命令的自我定位
在 ECC 中,.opencode/commands/ 目录存放面向 OpenCode 环境的斜杠命令定义,每个命令是一个带 YAML frontmatter 的 Markdown 文件。instinct-status.md 的元信息如下:
---
description: Show learned instincts (project + global) with confidence
agent: build
---
description声明命令用途,其中的$ARGUMENTS占位符表示用户输入参数(命令体会被 frontmatter 引擎替换后执行);agent: build指示该命令由build角色的 Agent 执行,属于工程/编码上下文而非安全审计或规划类上下文。
与之等价,commands/instinct-status.md(Claude Code 斜杠命令目录)中还有一份使用 command: true frontmatter 的副本,说明同一条能力被封装进了多个 harness(OpenCode 与 Claude Code),而执行逻辑完全一致。
命令的正文首页直接点明意图:
Show instinct status from continuous-learning-v2:
$ARGUMENTS
即它把用户输入透传给 continuous-learning-v2 技能下的 instinct CLI 执行。其背后是一个完整的"本能学习系统"——continuous-learning-v2/SKILL.md 中描述的 v2.1 架构把每条学习到的行为封装为原子化本能(instinct):一条本能 = 一个 trigger + 一个 action + 一个置信度分值,并按 project(项目作用域)或 global(全局作用域)存放。
二、核心执行逻辑:先定位 ECC 根,再跑 CLI
命令体是两行 bash,构成一条典型的两段式调用链:
ECC_ROOT="${CLAUDE_PLUGIN_ROOT:-$(node -e "var r=(function(){var p=require('path'),f=require('fs'),o=require('os');var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var d=p.join(o.homedir(),'.claude');function L(x){try{return require(p.join(x,'scripts','lib','resolve-ecc-root')).resolveEccRoot()}catch(_){return null}}var r=L(d);if(r)return r;var s=['ecc','ecc@ecc','marketplaces/ecc','everything-claude-code','everything-claude-code@everything-claude-code','marketplaces/everything-claude-code'];for(var i=0;i<s.length;i++){r=L(p.join(d,'plugins',s[i]));if(r)return r}try{var g=['ecc','everything-claude-code'];for(var j=0;j<g.length;j++){var c=p.join(d,'plugins','cache',g[j]);var O=f.readdirSync(c);for(var k=0;k<O.length;k++){var q=p.join(c,O[k]);var V=f.readdirSync(q);for(var m=0;m<V.length;m++){r=L(p.join(q,V[m]));if(r)return r}}}}catch(_){}return d})();console.log(r)")}"
python3 "$ECC_ROOT/skills/continuous-learning-v2/scripts/instinct-cli.py" status
第一行解析出当前活跃的 ECC 插件根目录,第二行以 status 子命令调用 instinct-cli.py(skill 内的 CLI 位于 skills/continuous-learning-v2/scripts/)。执行 CLI 时未对 $ARGUMENTS 做进一步解析——这与 Behavior Notes 中"v2.1 该命令不支持额外过滤器"的声明完全一致。
2.1 为什么必须先解析 ECC 根:规避 stale legacy 安装(#2037)
原文档用很大篇幅强调:解析根目录的 walker 必须与 hooks/hooks.json 使用的方式一致(环境变量 → 标准安装 → 已知插件根 → 插件缓存 → 回退)。原因是一个真实踩过的坑:当 CLAUDE_PLUGIN_ROOT 未设置、而用户机器上还残留着旧版本手工安装的 ~/.claude/skills/continuous-learning-v2/ 目录时,命令若直接按固定路径运行,会读到过期的旧版 CLI/旧数据目录,从而与当前活跃插件(可能安装在 ~/.claude/plugins/cache/... 下)产生路径分歧。这与 issue #2037 记录的问题对应。因此命令必须在运行时动态确认"到底哪一份 ECC 是活的"。
2.2 五级定位链的源码级解读
内嵌的 node -e 片段是一个经过压缩的内联定位器(即 resolve-ecc-root.js 中导出的 INLINE_RESOLVE 常量)。它的职责分两步:
- 快路径:若进程环境变量
CLAUDE_PLUGIN_ROOT已设置且非空,直接使用——Claude Code 为插件管理的 hooks 与命令都会注入该变量; - 慢路径:逐个探测候选目录,尝试
require(<候选>/scripts/lib/resolve-ecc-root).resolveEccRoot(),命中即把权威决策委托给完整模块,保持探测行为与 hooks 完全一致。
完整模块 resolveEccRoot() 按如下顺序判定候选根(测试覆盖见 tests/lib/resolve-ecc-root.test.js):
| 优先级 | 候选位置 | 说明 |
|---|---|---|
| 1 | CLAUDE_PLUGIN_ROOT |
环境变量,Claude Code 插件 hooks/命令注入 |
| 2 | ~/.claude/ |
标准手工安装(install.sh 直接复制到该目录) |
| 3 | ~/.claude/plugins/{ecc, ecc@ecc, marketplaces/ecc, everything-claude-code, everything-claude-code@everything-claude-code, marketplaces/everything-claude-code} |
6 个已知插件根路径段,兼容新旧 slug |
| 4 | ~/.claude/plugins/cache/{ecc, everything-claude-code}/<org>/<version>/ |
插件缓存自动探测:遍历 org → version 两级子目录 |
| 5 | ~/.claude/ |
回退(历史默认行为) |
值得注意的细节:对"技能类消费者",默认需要同时存在脚本树 scripts/lib/utils.js 和哨兵技能 skills/continuous-learning-v2 才算完整根(见 DEFAULT_SCRIPT_PROBE/DEFAULT_SKILL_PROBE),防止把"只复制了 scripts 的残缺安装"误判为完整 ECC 根(对应 #2544 回归用例)。而内联定位器之所以采用这种无 ... 展开、无嵌套数组字面量、无转义双引号的压缩写法,是为了能在 node -e "..." 的引号包裹下于各类 shell(含 Windows)安全执行,对应 #2368 修复。
三、后端实现:instinct-cli.py status 到底打印了什么
定位到根目录后,命令执行 python3 "$ECC_ROOT/skills/continuous-learning-v2/scripts/instinct-cli.py" status。cmd_status() 入口在 instinct-cli.py,处理流程可概括为四步,恰好呼应原文档 Behavior Notes 的行为约定。
3.1 项目检测(detect_project)
CLI 首先调用 detect_project() 确认"我当前在哪个项目里"。检测顺序(与 SKILL.md 及 shell 版 detect-project.sh 保持一致):
CLV2_NO_PROJECT=1环境变量 → 直接进入global作用域;CLAUDE_PROJECT_DIR显式指向的目录 → 取其 git 根(非 git 目录按绝对路径哈希,同样视为项目);git rev-parse --show-toplevel当前目录 git 根;- 都失败 → 回退
global。
项目 ID 是一个 12 字符的 SHA-256 截断哈希 _project_hash()(优先基于 git remote get-url origin 归一化后的 URL,其次基于仓库路径),这使得同一仓库在不同机器上得到相同的项目 ID、本能可移植;~/.local/share/ecc-homunculus/projects.json 注册表负责记录 ID → 名称/路径/远端地址的映射。
3.2 加载与合并:项目本能优先于全局本能
load_all_instincts()(instinct-cli.py)先读取项目作用域的 personal + inherited 两个子目录,再读取全局的两个子目录,去重规则正是原文档 Behavior Notes 中的第一条:当同一 ID 同时存在于项目与全局时,项目本能胜出、全局本能被丢弃——这与 v2.1"React 项目里的模式留在 React 项目"的设计目标一致,防止跨项目污染。
本能文件按扩展名过滤(.yaml/.yml/.md,见 ALLOWED_INSTINCT_EXTENSIONS),每个文件内部用成对的 --- 分隔多条 YAML frontmatter,由 parse_instinct_file() 解析,未通过 _validate_instinct_id() 的条目会被忽略。
3.3 空库时的兜底输出
若当前没有任何本能,命令不会报错,而是打印空态指引(No instincts found.),同时列出实际的数据目录位置,方便用户定位:
Project: my-app (a1b2c3d4e5f6)
Project instincts: <.../projects/<hash>/instincts/personal>
Global instincts: <.../instincts/personal>
四、输出格式拆解:domain 分组 + 置信度条 + 扩展状态
有本能时,输出先打印 60 字符分隔线组成的标题与统计区,再按作用域分两节(## PROJECT-SCOPED (<项目名>) 与 ## GLOBAL (apply to all projects)),这正是原文档"输出按 domain 分组并带置信度条"的落点:
============================================================
INSTINCT STATUS - 12 total
============================================================
Project: my-app (a1b2c3d4e5f6)
Project instincts: 8
Global instincts: 4
## PROJECT-SCOPED (my-app)
### WORKFLOW (3)
███████░░░ 70% grep-before-edit [project]
trigger: when modifying code
## GLOBAL (apply to all projects)
### SECURITY (2)
█████████░ 85% validate-user-input [global]
trigger: when handling user input
各字段的生成规则可以逐条对应到 _print_instincts_by_domain()(instinct-cli.py):
### DOMAIN (N):本能按domain字段分组,未标注时默认归入general;组内按confidence降序排列;- 置信度条:
_confidence_bar()将confidence(0.0–1.0)放大 10 倍取整,用█(满格)与░(空格)渲染 10 格条形;若终端编码无法输出 Unicode(如部分 Windows 管道场景),自动降级为#/.;相邻的百分比为int(conf*100); [project]/[global]:展示该本能的最终生效作用域标签;trigger::直接读取 frontmatter 中的 trigger;action::CLI 会从本能正文的## Action小节中正则抽取第一行并截断到 60 字符,作为行为的快速摘要。
随后 cmd_status 还会输出两类"扩展状态",这也是实战中非常有用的信息:
- 观测统计:
Observations: N events logged及observations.jsonl文件路径; - 待审本能告警:
pending本能超过 5 条时提示 "Unreviewed instincts auto-delete after 30 days"(PENDING_TTL_DAYS = 30);距到期 7 天内(PENDING_EXPIRY_WARNING_DAYS = 7)的条目逐条列出剩余天数。也就是说/instinct-status同时承担了本能库健康巡检的职责。
五、遗留数据检测:命令自带的"迁移哨兵"
cmd_status 最后调用 _warn_legacy_data():若发现旧版数据目录 ~/.claude/homunculus/ 存在非空数据、而当前活跃目录已经迁移到 XDG 风格的新路径($CLV2_HOMUNCULUS_DIR 或 $XDG_DATA_HOME/ecc-homunculus 或 $HOME/.local/share/ecc-homunculus),输出块会醒目地提示:
LEGACY DATA DETECTED
Active data directory: ...
Run the migration script to move your data:
bash "<...>/migrate-homunculus.sh"
Or set CLV2_HOMUNCULUS_DIR=<legacy> to use the legacy path.
这解释了数据目录选择逻辑(_resolve_homunculus_dir()):优先 CLV2_HOMUNCULUS_DIR(须为绝对路径)→ 其次 $XDG_DATA_HOME/ecc-homunculus → 默认 ~/.local/share/ecc-homunculus,规避 Claude Code 对 ~/.claude 的敏感路径保护,让后台 observer 能自由写入。老用户可在迁移后通过 migrate-homunculus.sh 一键搬移全局本能。
六、Behavior Notes 逐条对照:v2.1 的行为契约
原文档末尾的 Behavior Notes 是命令的"行为契约",可逐条与源码印证:
| 行为约定 | 源码依据 |
|---|---|
| 输出同时包含 project 与 global 本能 | load_all_instincts(project, include_global=True) 同时加载两种作用域 |
| ID 冲突时项目本能覆盖全局本能 | 去重时构建 project_ids 集合,同 ID 的全局条目被跳过 |
| 输出按 domain 分组、带置信度条 | _print_instincts_by_domain + _confidence_bar |
| v2.1 不支持额外过滤器 | 命令体只传固定 status 子命令,$ARGUMENTS 不参与解析 |
七、横向对比与排障提示
- 三种相关命令的区别:
/instinct-status只读查询;instinct-export/instinct-import 负责库的备份与共享;promote/projects/evolve/prune则覆盖"项目→全局晋升、项目清单、聚合进化、TTL 清理"等写操作——它们共享同一个instinct-cli.py入口,只是子命令不同; - 输出为空先别怀疑命令坏了:优先检查三处——当前目录是否在 git 仓库中(影响项目 ID 生成)、数据目录
$HOME/.local/share/ecc-homunculus/是否存在本能文件、是否残留旧~/.claude/skills/continuous-learning-v2/导致命中过期安装(此时应升级为插件安装并信任CLAUDE_PLUGIN_ROOT注入); - 终端乱码:若置信度条显示为
#/.而非█/░,是 CLI 检测到当前流无法编码 Unicode 的自动降级,不影响数据准确性; - 行为可配置项:observer 的
enabled、run_interval_minutes、min_observations_to_analyze可在 skills/continuous-learning-v2/config.json 中调整,而 status 相关的 TTL(30 天)与到期预警(7 天)阈值则以常量形式固化在 CLI 源码中。
结语
/instinct-status 是理解 ECC Continuous Learning v2 数据模型的最小入口:一条命令背后串联了插件根定位器(解决多安装路径分歧 #2037)、项目作用域检测(git remote/路径哈希)、本能解析与合并去重(项目覆盖全局)、置信度可视化与 TTL 健康巡检。无论你是想确认某条模式是否已被 Agent 记住,还是想排查"本能库为什么没生效",从读懂这份输出格式与调用链开始,就能准确地把问题定位到"安装路径、数据目录、还是本能文件本身"三层中的某一层。
相关深入阅读:continuous-learning-v2/SKILL.md(本能模型与作用域决策指南)、instinct-cli.py(全部子命令实现)、resolve-ecc-root.js(五级定位器与 INLINE_RESOLVE)、resolve-ecc-root.test.js(定位链测试)。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00