首页
/ opencode /learn 命令详解:把会话洞察沉淀进分层 AGENTS.md 知识体系

opencode /learn 命令详解:把会话洞察沉淀进分层 AGENTS.md 知识体系

2026-09-05 12:26:31作者:明树来

opencode 仓库自带一个名为 learn 的自定义命令(.opencode/command/learn.md),它的作用是在一次编码会话结束后,让 Agent 回顾整个会话、提取那些"不显而易见"的洞察,并把它们写入正确目录层级的 AGENTS.md 文件。本文完整拆解该命令的调用方式、学习条目的取舍标准与五步工作流程,并基于 指令注入服务源码 说明"读取文件时自动加载父目录 AGENTS.md"这一底层机制,帮助你建立一套可随项目生长、按消息去重、就近注入的仓库知识沉淀方案。

一、/learn 命令的定位与调用方式

learn.md 是一份标准的 opencode 项目级自定义命令定义文件,其 frontmatter 声明了命令用途:

---
description: Extract non-obvious learnings from session to AGENTS.md files to build codebase understanding
---

在 opencode 中,项目级命令通过 .opencode/command/ 目录下的 Markdown 文件提供,本仓库该目录下共包含 8 个命令(learn.mdcommit.mdchangelog.md 等)。从 命令注册服务Info Schema 可以看出,每个命令最终都会被解析为一条命令记录,包含 namedescriptionagentmodelsourcecommand / mcp / skill 三种来源)、templatehints 字段。

几个值得注意的实现细节:

  • $ARGUMENTS 占位符learn.md 的正文末尾保留了 $ARGUMENTS 占位符。hints() 函数 会扫描模板中的 $ARGUMENTS$1$N 编号占位符并生成命令提示,因此你可以直接执行 /learn,也可以追加参数(如 /learn 重点总结构建相关的坑),追加内容会替换掉模板中的 $ARGUMENTS
  • 命令模板的来源是多通道的Command 服务初始化逻辑 表明命令不仅来自配置文件 command 字段,还可以来自 MCP 服务的 prompt 和 skill 体系,.opencode/command/ 下的 Markdown 文件则以项目命令的形式参与注册,frontmatter 中的 description 会展示在命令列表中。
  • description 的意义learn 命令的描述明确点出目标——"build codebase understanding"(构建对代码库的理解)。这不是一个一次性的问答提示词,而是一个以**长期知识资产(AGENTS.md 文件)**为产出物的沉淀流程。

二、AGENTS.md 的分层放置策略:让洞察贴着代码住

learn.md 开篇就给出了一条核心原则:

AGENTS.md 文件可以存在于任意目录层级,而不只是项目根目录。当 Agent 读取某个文件时,其父目录链上所有 AGENTS.md 都会被自动加载进 read 工具的上下文。因此洞察应当尽可能靠近相关代码放置。

文档给出了三级放置建议:

洞察作用域 放置位置 典型内容
项目级(跨模块通用) 根目录 AGENTS.md 全局约定、统一的构建/发布流程、跨包约束
包/模块级 packages/foo/AGENTS.md 该包的内部架构、特有的构建命令
功能级 src/auth/AGENTS.md 某一功能目录内的实现细节与坑

这种"就近放置"策略的价值在于:它让知识按需加载、按目录隔离,避免把所有项目的细节堆在一个越来越长的根 AGENTS.md 里。opencode 仓库自身就采用了这种分层实践——除了根目录的 AGENTS.md 和已标记弃用的 CONTEXT.md 外,还存在着诸如 packages/opencode/src/session/llm/AGENTS.md 这样的深层目录级指令文件,覆盖 packages/apppackages/uipackages/llm 等多个包,正好印证了 learn 命令倡导的分层沉淀思路。

三、什么才算一条"学习":只收非显而易见的发现

learn.md 对"learning(学习)"的定义非常克制——只收录非显而易见的发现(non-obvious discoveries only),具体包括八类:

  1. 文件与模块之间的隐藏关系(Hidden relationships between files or modules)
  2. 执行路径与代码表象不一致的地方(Execution paths that differ from how code appears)
  3. 不显而易见的配置项、环境变量或标志位(Non-obvious configuration, env vars, or flags)
  4. 报错信息具有误导性、最终才找到真相的调试突破点(Debugging breakthroughs when error messages were misleading)
  5. API/工具的怪癖(quirks)与变通方案(API/tool quirks and workarounds)
  6. README 中没有记载的构建/测试命令(Build/test commands not in README)
  7. 架构决策与约束(Architectural decisions and constraints)
  8. 必须一起修改的文件(Files that must change together)

与之对应,文档明确列出了不应收录的内容:

  • 文档中显而易见的常识性事实(Obvious facts from documentation)
  • 标准语言/框架行为(Standard language/framework behavior)
  • AGENTS.md 中已经写过的内容(Things already in an AGENTS.md)
  • 冗长的解释性文字(Verbose explanations)
  • 仅与本次会话相关、不具备长期价值的细节(Session-specific details)

这套"白名单 + 黑名单"设计本质上是在控制 AGENTS.md 的信息熵:因为 AGENTS.md 的内容最终会注入模型上下文,每多一行废话都在稀释真正有价值的信号。

四、标准五步流程与输出契约

learn 命令规定的执行流程共五步:

  1. 复盘会话:Review session for discoveries, errors that took multiple attempts, unexpected connections —— 重点找那些"试了多次才解决的报错"和"意外的关联",这类事件正是高价值洞察的来源;
  2. 确定作用域:Determine scope —— 判断每条洞察适用于哪个目录,这是分层放置的前提;
  3. 读取现有文件:Read existing AGENTS.md files at relevant levels —— 先读再写,既避免重复收录,也为增量更新做准备;
  4. 创建或更新:在相应层级创建或更新 AGENTS.md;
  5. 控制篇幅:Keep entries to 1-3 lines per insight —— 每条洞察压缩到 1~3 行,保证文件可快速扫读。

流程末尾还有一个输出契约要求:

更新完成后,需总结创建/更新了哪些 AGENTS.md 文件、每个文件新增了多少条洞察

这使得 /learn 的执行结果是可审计的:你能在回复中直接看到知识的落盘位置与数量,而不是得到一段没有产出的闲聊。

五、源码深挖:AGENTS.md 是如何被"自动加载"的

learn.md 中那句"读取文件时父目录 AGENTS.md 自动进入上下文"并非空话,其实现位于 instruction.ts。理解这段代码,才能真正理解为什么"就近放置"是正确策略。

5.1 指令文件的识别与查找顺序

服务初始化时定义了候选指令文件列表(instruction.ts L60-L68):

const globalFiles = [
  path.join(global.config, "AGENTS.md"),
  ...(!flags.disableClaudeCodePrompt ? [path.join(global.home, ".claude", "CLAUDE.md")] : []),
]
const instructionFiles = [
  "AGENTS.md",
  ...(!flags.disableClaudeCodePrompt ? ["CLAUDE.md"] : []),
  "CONTEXT.md", // deprecated
]

可以看出:项目级查找顺序是 AGENTS.mdCLAUDE.md(可通过 disableClaudeCodePrompt 标志关闭)→ CONTEXT.md(源码注释明确标注 deprecated)。find() 函数 在给定目录内按此顺序取第一个存在的文件。

5.2 读取文件时向上遍历目录、按消息去重注入

核心机制在 resolve():当 read 工具读取某个文件时,服务会从该文件所在目录向上逐级遍历(源码注释原话:"Walk upward from the file being read and attach nearby instruction files once per message"),把沿途找到的 AGENTS.md 内容以 Instructions from: <filepath> 为前缀附加进上下文。遍历过程中有三层去重防线:

  • 系统级已加载的跳过:已作为系统提示注入的指令文件(sys.has(found))不会重复附加;
  • 本消息历史已加载的跳过extract() 会扫描该消息中所有已完成的 read 工具调用,从 part.state.metadata?.loaded 中取出此前已附加过的指令文件路径集合;
  • claims 记账:服务内部维护 Map<MessageID, Set<string>>L70-L77),记录每条助手消息已认领过的指令文件,保证同一文件在一条消息内只注入一次

这套"向上遍历 + 消息级去重"的设计意味着:learn 命令把洞察写到 src/auth/AGENTS.md 后,Agent 今后第一次读取 src/auth/ 下任何文件时就会自动获得这些知识,且不会在同一消息里反复注入同一个文件、撑爆上下文。

5.3 系统提示侧的"首个匹配胜出"策略

在系统提示注入侧,systemPaths() 采用不同策略:全局配置目录下的 AGENTS.md 命中即停;项目级则向上查找,首个命中的项目级指令文件胜出(源码注释:"The first project-level match wins so we don't stack AGENTS.md/CLAUDE.md from every ancestor"),避免把每一级祖先目录的 AGENTS.md 全部堆进系统提示。此外,配置中的 instructions 字段还可以追加额外的本地路径或 HTTP(S) URL 远程指令源(L135-L168),远程内容以 5 秒超时抓取。

把 5.2 与 5.3 对照就能理解分工:系统提示只承载"第一层"的指令文件,而更深层目录的 AGENTS.md 依靠 read 时的向上遍历实现按需注入——这正是 learn 命令鼓励多层级放置的机制基础。

六、实操建议:什么时候跑 /learn

结合命令设计与源码机制,以下场景是运行 /learn 的高价值时机:

  • 排查完一个误导性报错之后:错误信息与真实原因不符、试错多次才解决的调试过程,是"黑名单外"最典型的洞察来源,此时执行 /learn 让 Agent 把"真正的根因"而不是"表面报错"写进对应目录的 AGENTS.md;
  • 完成跨模块的关联修改之后:当发现"改 A 必须同时改 B"这类隐藏耦合时,把该约束写到两者公共上级目录(或各自目录)的 AGENTS.md 中;
  • 发现 README 与现实的偏差之后:比如实际使用的构建命令、隐藏的环境变量,这些属于文档明确认可的收录范围。

使用时注意两点:其一,参数可以聚焦方向(如 /learn 只沉淀与 pty 模块相关的发现),利用 $ARGUMENTS 占位符收窄复盘范围;其二,执行后务必核对命令要求输出的汇总——哪些文件被创建/更新、每文件几条洞察——并抽查条目是否都满足"1~3 行、非显而易见"的约束,防止 AGENTS.md 被低质量条目污染。

七、小结

opencode 的 /learn 命令是一个小而完整的知识管理闭环:以"非显而易见的发现"为唯一收录标准,以五步流程保证落盘质量,以分层放置让知识贴近代码,最终依托 指令服务 的"系统级首个命中 + 读取时向上遍历 + 消息级去重"三套机制,让每一条沉淀下来的洞察在后续会话中按需、自动、不重复地回到 Agent 的上下文里。AGENTS.md 因此从一份静态的项目说明,变成了随会话持续生长的活文档。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384