十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CodeCompanion Rules 配置指南:为 Neovim 聊天注入持久化 LLM 指令与项目上下文

CodeCompanion Rules 配置指南:为 Neovim 聊天注入持久化 LLM 指令与项目上下文 CodeCompanion Rules 配置指南为 Neovim 聊天注入持久化 LLM 指令与项目上下文【免费下载链接】codecompanion.nvim✨ AI Coding, Vim Style项目地址: https://gitcode.com/GitHub_Trending/co/codecompanion.nvim导读CodeCompanion 的 Rules规则机制借鉴了 Cursor Rules 与 Claude Code 的思路为每次新建的聊天会话自动注入系统级指令与项目级上下文两类信息——前者约束 LLM 的行为与输出风格后者把仓库内既有的事实与偏好如CLAUDE.md、AGENTS.md、.cursorrules等文件持续带入对话。本文以 doc/configuration/rules.md 为骨架结合仓库源码与测试完整讲解规则组Rule Groups的配置方式、autoload 自动加载策略、Prompt Library 联动以及 claude / CodeCompanion / none 三类内置解析器的底层原理读完即可在自己的 Neovim 配置中落地一套可复用、可按项目切换的规则体系。为什么需要 RulesLLM 在两次会话之间不保留任何记忆因此每次开启新聊天时用户的编码偏好、项目技术栈约定、常用工具链信息都必须重新注入。Rules 正是为解决这一痛点而设计它在聊天缓冲区中承担两个核心职责提供系统级指令以system角色的消息注入聊天持续约束 LLM 的行为提供持久化项目上下文把项目目录乃至用户主目录下约定的规则文件作为上下文附加到会话中。从源码实现看lua/codecompanion/interactions/shared/rules/helpers.lua 中的add_context函数会把每个规则文件包装成Sharing:\n\n---\ncontent\n---的上下文块并附带context.id rules .. path .. /rules去重标识确保同一文件不会在会话中被重复注入若解析器提取出了system_prompt则会先以role system的消息加入对话见 helpers.lua。这正是两条目的在代码层面的落点。启用 RulesRules 功能默认并未关闭插件开箱即用。最简配置如下完整默认值见 lua/codecompanion/config.luarequire(codecompanion).setup({ rules { default { description Collection of common files for all projects, files { .clinerules, .cursorrules, .goosehints, .rules, .windsurfrules, .github/copilot-instructions.md, AGENT.md, AGENTS.md, { path CLAUDE.md, parser claude }, { path CLAUDE.local.md, parser claude }, { path ~/.claude/CLAUDE.md, parser claude }, }, is_preset true, }, opts { chat { autoload default, -- The rule groups to load enabled true, }, }, }, })启用后每次创建聊天缓冲区插件都会尝试加载这个通用default规则集合。is_preset true标记该组为内置预设默认组中涵盖了当前生态最主流的规则文件命名——Claude Code 的CLAUDE.md、GitHub Copilot 的.github/copilot-instructions.md、Cursor 的.cursorrules、Windsurf 的.windsurfrules、Cline 的.clinerules、Goose 的.goosehints以及AGENT.md/AGENTS.md。注意default组中的CLAUDE.md系列文件显式指定了parser claude用于处理其中的文件引用语法详见下文Parsers章节。按条件启用enabled若只想在特定场景下启用 Rules可以给opts.chat.enabled传入一个回调函数。以下示例仅当聊天使用 HTTP 适配器即走真实 API 的适配器而非 ACP 等协议时才启用规则require(codecompanion).setup({ rules { default { description Collection of common files for all projects, files { -- Omitted for brevity }, }, opts { chat { ---param chat CodeCompanion.Chat ---return boolean condition function(chat) -- In this example, only enable rules for chats -- that are using http adapters return chat.adapter.type http end, }, }, }, })从 config.lua 的类型标注可见enabled支持boolean | fun(chat: CodeCompanion.Chat): boolean两种形态。在加载回调中helpers.lua只有当rules.enabled为真且配置了autoload时回调才会被挂载到聊天的on_created事件上。Rule Groups把规则组织成可复用集合规则组Rule Groups是一组文件或目录的集合可以整体加载进聊天缓冲区。它带来了极大的灵活性可以为使用 Claude Code 的场景单独建一组也可以为某个特定项目建一组专用规则。基础组Literal Paths最基本的组就是一系列字面路径可以是绝对路径或相对 cwd 的路径require(codecompanion).setup({ rules { my_project_rules { description Rule files for My Project, files { -- Literal file paths (absolute or relative to cwd) ~/.claude/CLAUDE.md, CLAUDE.md, CLAUDE.local.md, }, }, }, })条件组enabled 回调通过enabled函数可以控制某组规则是否出现在选择器picker中。下面的示例让my_project_rules只有在 cwd 包含my_project字样时才可见require(codecompanion).setup({ rules { my_project_rules { description Rule files for My Project, ---return boolean enabled function() -- Dont show this group unless in a specific dir return vim.fn.getcwd():find(my_project, 1, true) ~ nil end, files { ~/.claude/CLAUDE.md, CLAUDE.md, CLAUDE.local.md, }, }, }, })该回调的消费逻辑位于 helpers.luaenabled为false时直接跳过为函数时则调用cfg.enabled(chat)决定是否展示。目录扫描Directoriesfiles里也可以放目录配置用path files的组合指定在某个目录下按文件名模式扫描require(codecompanion).setup({ rules { my_project_rules { description Rule files for My Project, files { -- Specify dirs to search in (supports glob patterns and literals) { path vim.fn.getcwd(), files { .clinerules, .cursorrules, *.md } }, { path ~/.config/rules, files *.md }, -- Mix with literal file paths ~/.claude/CLAUDE.md, CLAUDE.md, CLAUDE.local.md, }, }, }, })文件模式File Patternsfiles数组支持五种书写形态覆盖了从单文件到通配符的全部需求require(codecompanion).setup({ rules { my_project_rules { description Rule files for My Project, files { -- 1. Literal file paths CLAUDE.md, ~/.claude/CLAUDE.md, -- 2. File path with parser { path CLAUDE.local.md, parser claude }, -- 3. Directory with file patterns { path ., files { .clinerules, *.md } }, -- 4. Directory with parser { path ~/.config/rules, files *.md, parser claude }, -- 5. Glob patterns (searches filesystem) docs/**/*.md, .github/*.md, }, }, }, })这五种形态与Rules:resolve_paths()lua/codecompanion/interactions/shared/rules/init.lua的解析逻辑一一对应字面路径直接vim.fs.normalize后检查存在性若是目录则递归扫描其下全部文件带 parser 的文件解析路径时记录文件级 parser供后续read_files阶段匹配见 init.lua目录 patterns调用file.scan_directory(normalized_dir, { patterns file_spec.files })按模式扫描目录glob 模式通过vim.fn.glob展开通配符源码用tostring(path):match([%*%?%[])判断是否含*、?、[命中目录则继续递归扫描解析过程中通过seen表对所有路径做vim.fs.normalize后的去重避免同一文件被重复收集。嵌套组Nested Groups规则组还可以嵌套父组的parser会被子组继承从而对多个子组统一施加同一解析器require(codecompanion).setup({ rules { my_project_rules { description Rule files for My Project, parser claude, files { [mcp] { description The MCP implementation in My project, files { .rules/mcp/mcp.md, }, }, }, }, }, })嵌套组的意义在于一个条件管多组、保持配置整洁。插件自己就是最佳范例——config 中内置了名为CodeCompanion的组其下按模块细分了adapters、chat、acp、code-review、rules、tests、tools等子组见 config.lua便于贡献者在开发特定模块时把对应.codecompanion/*.md上下文快速分享给 LLM且该组通过enabled函数限定仅在 cwd 包含 codecompanion 时才展示。展开逻辑在 helpers.lua 的expand_rules_group遇到数组形式的files就把整组作为可选条目加入 picker否则递归进入子组并以parent/child形式拼接展示名。因此在使用 Action Palette 或 slash 命令时嵌套组会被扁平化提取并显示在Chat with rules ...菜单中。Autoload自动加载规则组默认情况下你还可以指定哪些组在每次新建聊天时自动加载-- 单个组 require(codecompanion).setup({ rules { opts { chat { autoload my_project_rules, }, }, }, })-- 多个组 require(codecompanion).setup({ rules { opts { chat { autoload { my_project_rules, another_project }, }, }, }, })-- 按条件动态决定 require(codecompanion).setup({ rules { opts { chat { ---return string|string[] autoload function() if vim.fn.getcwd():find(another_project, 1, true) ~ nil then return { my_project, another_project } end return my_project end, }, }, }, })autoload的类型为string | table | function见 config.lua。其消费逻辑在 helpers.lua函数形态必须返回字符串或字符串数组否则会assert报错随后遍历每个组名通过callbacks_extend把on_created回调挂到聊天创建事件上最终调用add_to_chat_from_config完成注入若组名不存在则记录Could not find ... rules警告日志。Prompt Library 中的规则默认情况下Prompt Library 的 prompt永远不会自动加载规则组——除非 prompt 通过自身的rules字段显式指名。要改变这一行为让未指定规则的 prompt 也享受 autoload 组require(codecompanion).setup({ rules { opts { chat { autoload default, autoload_groups_in_prompt_library true, }, }, }, })开启后prompt 若未声明任何rules则会把rules.opts.chat.autoload指定的组加载进聊天若 prompt 自己指名了规则则使用它自己的规则。autoload_groups_in_prompt_library的默认值为false见 config.lua。prompt 中的rules字段会随 prompt 定义被保留见 lua/codecompanion/prompt_library/init.lua 及 Markdown frontmatter 解析 lua/codecompanion/prompt_library/markdown.lua。Parsers解析器如何改写规则解析器允许 CodeCompanion 对规则内容做变换从而影响规则在聊天缓冲区中的分享方式。内置解析器注册在 config.lua解析器说明claude按 Claude Code 的方式把规则中引用的文件导入聊天要求规则为 markdown 文件CodeCompanion与claude行为一致但额外支持通过 H2 标题## System Prompt提取系统提示词cli供 CLI 交互使用只解析文件路径、不解析内容none空解析器可用于覆盖默认规则组上已设置的解析器claude 解析器解析文件引用lua/codecompanion/interactions/shared/rules/parsers/claude.lua 实现了该解析器它先用 treesitter 解析 markdown遍历所有段落节点找出以开头的行line:match(^%s*(%S))将这些路径收集进included_files非绝对路径不以/或~开头会基于源文件所在目录做相对解析vim.fs.joinpath(source_dir, path)并校验文件确实存在。解析结果通过meta.included_files返回。随后在 init.lua 的add_to_chat中这些被引用的文件会经 helpers.lua 的add_files_or_buffers注入聊天——如果该文件正作为 buffer 打开就直接读取 buffer 内容并遵循rules.opts.chat.default_params的all/diff同步策略否则按普通文件读取。注入仍使用rules...的 ID 去重因此一个文件即使同时被显式列出又被引用也只会注入一次。CodeCompanion 解析器提取 System Promptlua/codecompanion/interactions/shared/rules/parsers/codecompanion.lua 在 claude 解析器基础上增加了一个能力识别 H2 标题## System Prompt将其下的内容跳过引用行提取为system_prompt其余部分照常作为用户内容引用同样被解析为included_files。提取出的system_prompt最终以role system的消息注入对话见 helpers.lua这是提供系统级指令的直接实现。应用解析器组级与文件级解析器可以施加在组级组内所有文件统一生效也可以施加在文件级更细粒度控制文件级优先-- 组级整组使用 claude 解析器 require(codecompanion).setup({ rules { claude { description Rules for Claude Code users, parser claude, files { CLAUDE.md, CLAUDE.local.md, ~/.claude/CLAUDE.md, }, }, }, })-- 文件级每个文件单独指定 require(codecompanion).setup({ rules { claude { description Rules for Claude Code users, files { { path CLAUDE.md, parser claude }, { path CLAUDE.local.md, parser claude }, { path ~/.claude/CLAUDE.md, parser claude }, }, }, }, })-- 禁用用 none 覆盖默认规则组上的解析器 require(codecompanion).setup({ rules { claude { description Rules for Claude Code users, parser none, -- Disable parsing for the entire group files { CLAUDE.md, CLAUDE.local.md, ~/.claude/CLAUDE.md, }, }, }, })解析优先级在 lua/codecompanion/interactions/shared/rules/parsers/init.lua 的parse函数中清晰可见文件级 parser 优先于组级 parser两者都缺失时返回原样内容。resolve函数同文件第 14-68 行则支持三种解析器来源配置内置名、可调用返回 parser 表的工厂函数、以及用户磁盘上的自定义 parser 文件先尝试require失败则loadfile加载。若想编写自己的解析器可参考仓库指南 doc/extending/parsers.md其中介绍了自定义解析器的接口与注册方式内置解析器各有对应测试如 tests/interactions/shared/rules/parsers/test_claude_parser.lua 与 tests/interactions/shared/rules/parsers/test_parsers.lua可作为行为基准。规则的实际加载链路把以上模块串起来一次规则加载的完整调用链为聊天创建时add_callbackshelpers.lua读取autoload字符串/表/函数为每个组名注册on_created回调回调调用Rules.add_to_chat_from_config(chat, args)init.lua创建Rules实例并执行makemakeinit.lua依次执行resolve_paths()路径解析与去重→read_files()读取内容并匹配文件级 parser→parse_files()组级/文件级 parser 变换→add_to_chat()注入 system 消息、上下文块与被引用的文件。结语通过 Rules 机制CodeCompanion 把LLM 无记忆这一天然缺陷转化为可配置、可复用的工程实践default预设开箱即覆盖主流规则文件Rule Groups提供从字面路径、目录扫描、glob 到嵌套组的丰富组织形态autoload与autoload_groups_in_prompt_library精确控制加载时机而claude/CodeCompanion/none三类解析器则决定了规则内容最终以何种形态进入对话。掌握这些配置项你就能让每个聊天会话自动携带准确的编码约定与项目事实减少反复粘贴上下文的时间成本。【免费下载链接】codecompanion.nvim✨ AI Coding, Vim Style项目地址: https://gitcode.com/GitHub_Trending/co/codecompanion.nvim创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表