持续学习 v2.1 - 基于习惯的架构 是做什么的?
一个高级学习系统,通过原子化的“习惯”——带有置信度评分的小型学习行为——将你的 Claude Code 会话转化为可复用的知识。
v2.1 新增了项目级作用域习惯 —— React 模式保留在 React 项目中,Python 约定保留在 Python 项目中,而通用模式(如“始终验证输入”)则在全局范围内共享。
何时激活
- 为 Claude Code 会话设置自动学习
- 通过钩子配置基于习惯的行为提取
- 调整学习行为的置信度阈值
- 查看、导出或导入习惯库
- 将习惯演进为完整的技能、命令或智能体
- 管理项目级与全局习惯
- 将习惯从项目级提升至全局级
v2.1 的新功能
| 特性 | v2.0 | v2.1 |
|---|---|---|
| 存储 | 全局 (~/.claude/homunculus/) | 项目级 (${XDG_DATA_HOME:-~/.local/share}/ecc-homunculus/projects/<hash>/) |
| 作用域 | 所有习惯作用于所有地方 | 项目级 + 全局 |
| 检测 | 无 | git 远程地址 / 仓库路径 |
| 提升 | 不适用 | 当在 2+ 个项目中出现时,项目→全局 |
| 命令 | 4 个 (status/evolve/export/import) | 6 个 (+promote/projects) |
| 跨项目 | 存在污染风险 | 默认隔离 |
v2(对比 v1)的新功能
| 特性 | v1 | v2 |
|---|---|---|
| 观察 | 停止钩子(会话结束) | PreToolUse/PostToolUse(100% 可靠) |
| 分析 | 主上下文 | 后台智能体 (Haiku) |
| 粒度 | 完整技能 | 原子化“习惯” |
| 置信度 | 无 | 0.3-0.9 加权 |
| 演进 | 直接到技能 | 习惯 → 聚类 → 技能/命令/智能体 |
| 共享 | 无 | 导出/导入习惯 |
习惯模型
一个习惯是一个小型的学习行为:
---
id: prefer-functional-style
trigger: "when writing new functions"
confidence: 0.7
domain: "code-style"
source: "session-observation"
scope: project
project_id: "a1b2c3d4e5f6"
project_name: "my-react-app"
---
# 偏好函数式风格
## 动作
在适当的情况下使用函数式模式而非类。
## 证据
- 观察到 5 次函数式模式偏好
- 用户在 2025-01-15 将基于类的方案修正为函数式
属性:
- 原子化 —— 一个触发器,一个动作
- 基于置信度加权 —— 0.3 = 尝试性,0.9 = 几乎确定
- 领域标记 —— 代码风格、测试、git、调试、工作流等
- 有据可查 —— 追踪哪些观察创建了它
- 作用域感知 ——
project(默认)或global
工作原理
会话活动(在 git 仓库中)
|
| 钩子捕获提示 + 工具使用(100% 可靠)
| + 检测项目上下文(git 远程 / 仓库路径)
v
+---------------------------------------------+
| projects/<project-hash>/observations.jsonl |
| (提示、工具调用、结果、项目) |
+---------------------------------------------+
|
| 观察智能体读取(后台,Haiku)
v
+---------------------------------------------+
| 模式检测 |
| * 用户修正 → 习惯 |
| * 错误解决 → 习惯 |
| * 重复工作流 → 习惯 |
| * 作用域决策:项目级或全局级? |
+---------------------------------------------+
|
| 创建/更新
v
+---------------------------------------------+
| projects/<project-hash>/instincts/personal/ |
| * prefer-functional.yaml (0.7) [项目级] |
| * use-react-hooks.yaml (0.9) [项目级] |
+---------------------------------------------+
| instincts/personal/ (全局) |
| * always-validate-input.yaml (0.85) [全局] |
| * grep-before-edit.yaml (0.6) [全局] |
+---------------------------------------------+
|
| /evolve 聚类 + /promote
v
+---------------------------------------------+
| projects/<hash>/evolved/ (项目级) |
| evolved/ (全局) |
| * commands/new-feature.md |
| * skills/testing-workflow.md |
| * agents/refactor-specialist.md |
+---------------------------------------------+
项目检测
系统自动检测你当前的项目:
CLAUDE_PROJECT_DIR环境变量(最高优先级)—— 作为显式覆盖值,即使目录不是 git 仓库(通过其绝对路径哈希)也会被认可git remote get-url origin—— 通过哈希创建可移植的项目 ID(不同机器上的同一仓库获得相同 ID)git rev-parse --show-toplevel—— 回退使用仓库路径(机器特定)- 全局回退 —— 如果未检测到项目,习惯将归入全局范围
每个项目获得一个 12 字符的哈希 ID(例如 a1b2c3d4e5f6)。注册文件位于 ${XDG_DATA_HOME:-~/.local/share}/ecc-homunculus/projects.json,用于将 ID 映射为人类可读的名称。
数据目录
持续学习 v2 将观察数据存储在 ~/.claude 之外,这样 Claude Code 的敏感路径守卫不会阻塞后台习惯写入:
- 设置了绝对路径时的
CLV2_HOMUNCULUS_DIR $XDG_DATA_HOME/ecc-homunculus$HOME/.local/share/ecc-homunculus
数据仍在 ~/.claude/homunculus 的现有用户可以一次性迁移:
bash skills/continuous-learning-v2/scripts/migrate-homunculus.sh
快速开始
1. 启用观察钩子
如果作为插件安装(推荐):
不需要额外的 settings.json 钩子块。Claude Code v2.1+ 会自动加载插件的 hooks/hooks.json,并且 observe.sh 已经在那里注册了。
如果你之前将 observe.sh 复制到了 ~/.claude/settings.json 中,请移除重复的 PreToolUse / PostToolUse 块。重复插件钩子会导致双重执行和 ${CLAUDE_PLUGIN_ROOT} 解析错误,因为该变量仅在插件管理的 hooks/hooks.json 条目中可用。
如果手动安装到 ~/.claude/skills,请将其添加到你的 ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "~/.claude/skills/continuous-learning-v2/hooks/observe.sh"
}]
}],
"PostToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "~/.claude/skills/continuous-learning-v2/hooks/observe.sh"
}]
}]
}
}
2. 初始化目录结构
系统会在首次使用时自动创建目录,但你也可以手动创建它们:
# 全局目录
mkdir -p "${XDG_DATA_HOME:-$HOME/.local/share}/ecc-homunculus"/{instincts/{personal,inherited},evolved/{agents,skills,commands},projects}
# 项目目录在钩子首次在 git 仓库中运行时自动创建
3. 使用习惯命令
/instinct-status # 显示已学习的习惯(项目级 + 全局)
/evolve # 将相关习惯聚类为技能/命令
/instinct-export # 将习惯导出到文件
/instinct-import # 从他人处导入习惯
/promote # 将项目习惯提升到全局范围
/projects # 列出所有已知项目及其习惯数量
命令
| 命令 | 描述 |
|---|---|
/instinct-status | 显示所有习惯(项目级 + 全局)及其置信度 |
/evolve | 将相关习惯聚类为技能/命令,建议提升 |
/instinct-export | 导出习惯(可按作用域/领域过滤) |
/instinct-import <file> | 导入习惯并控制作用域 |
/promote [id] | 将项目习惯提升到全局范围 |
/projects | 列出所有已知项目及其习惯数量 |
配置
编辑 config.json 以控制后台观察者:
{
"version": "2.1",
"observer": {
"enabled": false,
"run_interval_minutes": 5,
"min_observations_to_analyze": 20
}
}
| 键 | 默认值 | 描述 |
|---|---|---|
observer.enabled | false | 启用后台观察智能体 |
observer.run_interval_minutes | 5 | 观察者分析观察结果的频率 |
observer.min_observations_to_analyze | 20 | 分析运行前的最小观察次数 |
其他行为(观察捕获、习惯阈值、项目范围界定、提升标准)通过 instinct-cli.py 和 observe.sh 中的代码默认值配置。
观察者平台支持
后台观察者需要 WSL2、Linux 或 macOS。在原生 Windows(Git Bash / MSYS2)上,它会启动并报告成功,但当生成的钩子退出且其作业对象关闭时,进程会被终止,因此不会运行任何分析 —— 在那里设置 observer.enabled: true 实际上是空操作(参见 issue #2489)。
observe.sh 在随后的钩子调用中检测到这一点,并且在观察者连续多次未能存活后,会将一条解释性警告写入 observer-start.log。
| 环境变量 | 默认值 | 描述 |
|---|---|---|
ECC_OBSERVER_NOSURVIVE_WARN_AFTER | 3 | 记录警告前连续不存活的次数 |
文件结构
${XDG_DATA_HOME:-~/.local/share}/ecc-homunculus/
+-- identity.json # 你的个人资料、技术等级
+-- projects.json # 注册表:项目哈希 -> 名称/路径/远程
+-- observations.jsonl # 全局观察(回退)
+-- instincts/
| +-- personal/ # 全局自动学习习惯
| +-- inherited/ # 全局导入习惯
+-- evolved/
| +-- agents/ # 全局生成的智能体
| +-- skills/ # 全局生成的技能
| +-- commands/ # 全局生成的命令
+-- projects/
+-- a1b2c3d4e5f6/ # 项目哈希(来自 git 远程 URL)
| +-- project.json # 每个项目的元数据镜像(id/name/root/remote)
| +-- observations.jsonl
| +-- observations.archive/
| +-- instincts/
| | +-- personal/ # 项目特定的自动学习
| | +-- inherited/ # 项目特定的导入
| +-- evolved/
| +-- skills/
| +-- commands/
| +-- agents/
+-- f6e5d4c3b2a1/ # 另一个项目
+-- ...
作用域决策指南
| 模式类型 | 作用域 | 示例 |
|---|---|---|
| 语言/框架约定 | 项目级 | “使用 React 钩子”、“遵循 Django REST 模式” |
| 文件结构偏好 | 项目级 | “测试在 __tests__/”、“组件在 src/components/” |
| 代码风格 | 项目级 | “使用函数式风格”、“偏好 dataclasses” |
| 错误处理策略 | 项目级 | “使用 Result 类型处理错误” |
| 安全实践 | 全局 | “验证用户输入”、“清理 SQL” |
| 通用最佳实践 | 全局 | “先写测试”、“始终处理错误” |
| 工具工作流偏好 | 全局 | “Grep 前先 Edit”、“Read 前先 Write” |
| Git 实践 | 全局 | “约定式提交”、“小而聚焦的提交” |
习惯提升(项目级 → 全局)
当同一个习惯在多个项目中出现并具有高置信度时,它就有资格提升到全局范围。
自动提升条件:
- 在 2+ 个项目中存在相同的习惯 ID
- 平均置信度 >= 0.8
如何提升:
# 提升特定的习惯
python3 instinct-cli.py promote prefer-explicit-errors
# 自动提升所有符合条件的习惯
python3 instinct-cli.py promote
# 预览而不做更改
python3 instinct-cli.py promote --dry-run
/evolve 命令也会建议提升候选。
置信度评分
置信度随时间变化:
| 分数 | 含义 | 行为 |
|---|---|---|
| 0.3 | 尝试性 | 建议但不强制执行 |
| 0.5 | 中等 | 在相关时应用 |
| 0.7 | 强 | 自动批准应用 |
| 0.9 | 几乎确定 | 核心行为 |
置信度增加当:
- 模式被重复观察到
- 用户没有纠正建议的行为
- 来自其他源的类似习惯一致
置信度降低当:
- 用户明确纠正该行为
- 模式长时间未观察到
- 出现矛盾证据
为什么选择钩子而非技能进行观察?
“v1 依赖技能进行观察。技能是概率性的——它们根据 Claude 的判断,大约 50-80% 的时间会触发。”
钩子 100% 的时间 确定性触发。这意味着:
- 每次工具调用都被观察到
- 没有模式被遗漏
- 学习是全面的
向后兼容性
v2.1 与 v2.0 和 v1 完全兼容:
- 现有的全局习惯可以通过
scripts/migrate-homunculus.sh从~/.claude/homunculus/instincts/迁移 - v1 现有的
~/.claude/skills/learned/技能仍然有效 - 停止钩子仍然运行(但现在也会输入 v2)
- 逐步迁移:并行运行两者
隐私
- 观察数据 本地保存 在你的机器上
- 项目级习惯按项目隔离
- 只有习惯(模式)可以被导出——而不是原始观察数据
- 不共享任何实际的代码或对话内容
- 你控制什么被导出和提升
相关
- ECC-Tools GitHub App - 从仓库历史中生成习惯
- Homunculus - 启发 v2 基于习惯架构的社区项目(原子化观察、置信度评分、习惯演进管道)
- 长篇指南 - 持续学习章节
基于习惯的学习:教会 Claude 你的模式,一次一个项目。