最近在用 ZCode 时老分不清「这个东西该配在哪个文件」「同名配置到底谁生效」,于是把官方指南插件里六份文档通读了一遍,用自己的话整理成这一页。核心是五类扩展资源 + 一个指令文件,以及贯穿始终的「作用域优先级」思路。
一、总览:五类扩展资源 + AGENTS.md
| 资源 | 形式 | 一句话理解 |
|---|---|---|
| Skills 技能 | 目录 + SKILL.md | 给模型看的「说明书」,由模型自主决定何时调用 |
| Commands 命令 | .md 文件 | 斜杠菜单里的 /命令,用户主动触发 |
| MCP 服务器 | JSON 配置项 | 给模型接外部工具(数据库、浏览器、GitLab…) |
| Hooks 钩子 | hooks 配置 | 在固定事件点自动执行脚本,确定性介入 |
| Plugins 插件 | 目录 + plugin.json | 打包分发以上资源的容器 |
| AGENTS.md | Markdown 指令文件 | 注入模型上下文的行为规则,不是五类资源之一 |
一个重要的分工理解:Skill 靠模型自觉(描述写得好才会被触发),Command 靠人主动调用,Hook 是确定性执行。想要「必须发生」的事用 Hook,想要「按需可用」的能力用 Skill。
二、两个作用域与核心配置文件
- 用户级:在用户主目录下,对所有工作区生效;
- 工作区级:在仓库内,只对本项目生效,可随版本控制分享给团队。
| 文件 | 位置 | 管什么 |
|---|---|---|
| 用户配置 | ~/.zcode/cli/config.json | MCP、Hooks、插件启停、技能/命令禁用 |
| 工作区配置 | <repo>/.zcode/config.json(或 zcode.json) | 同上,但只对本仓库 |
| 用户指令 | ~/.zcode/AGENTS.md | 个人全局默认规则 |
| 工作区指令 | <repo>/AGENTS.md | 仓库级规则 |
选哪个位置的原则一句话:个人跨项目用的放用户级,团队共享、随仓库版本化的放工作区级。密钥永远不进版本库,用环境变量或本地配置。
三、AGENTS.md:先后注入,后者覆盖
- 两份都存在时,先注入
~/.zcode/AGENTS.md,再注入工作区的<repo>/AGENTS.md——后注入的工作区规则可以收窄或覆盖宽泛的个人默认值; - 工作区文件从当前目录向上逐级搜索直到项目根,所以子目录也能命中;
- 内置
/init命令针对的是当前工作区的 AGENTS.md(创建或更新仓库规则),不会动用户级文件; - 实践建议:个人偏好(语言、风格)放用户级;架构边界、测试要求、提交规范放工作区级。
四、Skills:一个目录一个 SKILL.md
技能 = 一个目录 + 一个 SKILL.md。frontmatter 里被识别的键是 name、description、when_to_use、license、metadata。几个决定成败的知识点:
- 加载失败 vs 不触发是两回事:frontmatter 缺
name或description、或description超过 1024 字符 → 技能整个被丢弃;没有 frontmatter → 能加载但description为空,模型无从判断何时使用; - 触发机制没有关键词匹配器:只有
name、description(呈现给模型时截断到约 250 字符)和when_to_use,模型自主决定是否调用——所以「什么时候用」要写在描述的前 250 字符里; - 发现顺序(先者生效):显式配置根 → 用户
~/.zcode/skills→ 用户~/.agents/skills→ 工作区.zcode/skills(从当前目录逐级到仓库根,越深越优先)→ 工作区.agents/skills→ 插件(最低);同层级内.zcode先于.agents; - 身份是文件路径:同名技能在不同路径都会被发现,但只有发现顺序第一个被加载,其余被遮蔽——「改了没生效」多半是改了被遮蔽的那份;
- 点开头的目录(
.system除外)和node_modules会被跳过。
跨工具复用的小技巧:想被 Claude、Codex、Cursor 共用的技能放 ~/.agents/skills/;只想在 ZCode 里覆盖同名技能时,放 .zcode/skills/(同层级先扫描,天然遮蔽)。
五、Commands:文件名即命令名
- 命令 = 一个
.md文件,文件名就是命令名,必须匹配^[a-z0-9][a-z0-9_:-]{0,63}$(小写开头、无空格和点、≤64 字符),违规直接丢弃; - 子目录映射为冒号:
review/code.md的命令是/review:code,不是/review/code; - frontmatter 认这些连字符键:
description、argument-hint、allowed-tools、model、skills、disable-noninteractive;拼错键不报错但字段不生效; - 必须有
description或非空正文,两者都没有则命令被丢弃;缺 description 时取正文第一行非空文本; - 参数替换用
$ARGUMENTS(完整参数串)和$1、$2(按位置,越界为空);有参数但正文没占位符时,参数会以「User arguments:」追加在末尾; - 正文里不支持
!`cmd`这类动态 shell 展开;同名命令「第一个生效」(本地永远压过插件);与内置斜杠命令重名的会在/菜单里被过滤。
六、MCP:键名有差异,配置即信任
- 配置位置:用户级
~/.zcode/cli/config.json的mcp.servers;工作区<repo>/.zcode/config.json同样字段。.agents/mcp.json只是兼容回退——同一作用域内.zcode有任何 MCP 服务器时,.agents那份被整体忽略; - 键名不一样:
.zcode系列用嵌套的mcp.servers,.agents/mcp.json用顶层的mcpServers——粘贴配置时最容易错的就是这个; - 覆盖顺序:CLI 参数 → 环境变量 → 用户级 → 工作区级 → 系统默认,同名服务器用户级压过工作区级;插件提供的服务器是底层,会被显式配置覆盖;
- 全部作用域自动连接:用户级、工作区级、插件、环境的服务器在会话启动时都会受信任并自动连接(工作区级早先需要手动授权,现在不用了)。推论:只打开你信任的项目;
- stdio 型必填
command(可选args、cwd、env),http/sse 型必填url(可选headers);schema 是严格的,出现未知键整个服务器被静默丢弃; - 默认超时 30000ms,启动慢的服务器可加
timeoutMs; - 配置文件里的 MCP 不展开
${...}模板变量(那是插件 MCP 才有的能力)→ 配置文件里老老实实写绝对路径; - 排查入口:客户端 Settings → MCP 看每个服务器的连接状态与内联报错;stdio 服务器的完整报错流在 ZCode 日志里。
七、Hooks:恰好七个事件
支持的事件有且只有七个:SessionStart、UserPromptSubmit、PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、Stop。(Notification、SubagentStop 这类名字不受支持。)
- 配置文件钩子默认关闭:必须写
"hooks": { "enabled": true, ... }才会跑;但只要任何一个插件带了钩子,钩子运行器会自动启用; - matcher 是大小写敏感的正则,工具类事件匹配工具名(
Bash、Edit…),写成"bash"匹配不上;省略 matcher = 匹配一切;非法正则则永远匹配不上(且不报错); - 超时单位是经典坑:
command型的timeout单位是秒,process型的timeoutMs是毫秒(优先级更高)——timeout: 500是 500 秒不是 500 毫秒; command走 shell(Windows 上 POSIX 语法会挂,跨平台优先选process型,参数向量不经 shell);- 退出码约定:0 通过,2 阻止(PreToolUse/PermissionRequest 里等于拒绝),其他非零视为报错;
async: true目前没有运行时效果,钩子总是内联执行,别指望它做后台任务;- 模板变量:
${ZCODE_PROJECT_DIR}/${CLAUDE_SESSION_ID}等在命令和参数中展开;插件钩子额外可用${ZCODE_PLUGIN_ROOT}。
八、Plugins:最小清单只有一个 name
- 插件目录带清单
.zcode-plugin/plugin.json(兼容.claude-plugin/、.codex-plugin/旧名),最小合法清单只需name一个字段; - 清单里能真正生效的组件字段:
commands、skills、hooks、mcpServers、agents;channels、lspServers、outputStyles、settings只被记录、不执行; - 管理入口:Settings → Plugin Management(Installed / Discover 两个标签页);启停状态存在
~/.zcode/cli/config.json的plugins下;内置插件可停用但不可卸载; - 市场(marketplace)可以来自 GitHub 仓库、Git URL、本地目录或文件;
- 注意:插件的钩子与本地钩子一样直接执行,没有额外的「信任门」。
九、排错速查:症状 → 去哪看
| 症状 | 先查什么 |
|---|---|
| 技能不出现 / 不触发 | Settings → Skills 和 / 菜单;再按发现顺序查有没有同名高优先级副本遮蔽、frontmatter 是否缺 name/description、description 是否超 1024 字符 |
/命令 不存在或跑的不是我改的 | 确认在扫描根下的 .md、文件名合法;同名「第一个生效」,查高优先级副本;嵌套名用冒号 |
| MCP 连不上 / 工具不出现 | Settings → MCP 看状态;查键名(mcp.servers vs mcpServers)、未知键、command 是否在 PATH、是否忘了绝对路径 |
| 钩子不触发 | 配置钩子是否 enabled: true;事件名是否七个之一;matcher 大小写;timeout 单位秒/毫秒 |
| 插件没列出 / 组件缺失 | Plugin Management 里看启停;清单是否合法、组件字段是否属于「可生效」名单 |
| 改了 AGENTS.md 没反应 | 确认改对了作用域:用户级先注入、工作区后注入可覆盖;工作区文件从当前目录向上找 |
官方这套指南本身也做成了技能,排错时可以直接点名调用:diagnosing-skills、diagnosing-commands、diagnosing-mcp、diagnosing-hooks、diagnosing-plugins,每个都提供「症状 → 原因 → 检查 → 修复」的固定流程。
十、我的整理理由
这一页表面上是「配置知识」,其实核心是一套优先级心智模型:用户级压工作区级、.zcode 压 .agents、深目录压仓库根、本地压插件、先发现者生效。记住这一句,八成「改了没生效」的问题都能自己定位。之后写自己的 Skill 和命令时,我会从「把 when to use 写进 description 的前 250 字符」这条开始实践。
相关笔记:上一篇《Unity 放出 29 个官方 Skill》和《DeepSeek Harness 学习笔记》里聊的「技能」生态,正是基于本页这类机制运转的。
zcode-configuration-guide 与五个 diagnosing-* 技能。本页为个人要点整理,行为细节以本机客户端实际表现与官方文档为准。