claude-obsidian 的 ZCode 主机集成:AGENTS.md 契约、用户级技能安装与 Vault 事务边界
【免费下载链接】claude-obsidianSelf-organizing AI second brain for Obsidian + Claude Code. Drop any source and Claude reads, links, and files it into one connected knowledge graph of plain Markdown you own. AI note-taking, personal knowledge management (PKM), and an open-source Notion alternative. Based on Karpathy's LLM Wiki pattern.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-obsidian
ZCODE.md 是 claude-obsidian 仓库中面向 ZCode 这一 Agent 主机的接入说明文档,它规定了 ZCode 如何复用仓库的中立契约AGENTS.md、如何通过一次性安装命令把全部 15 个 Agent Skills 发布到用户级目录~/.zcode/skills/,以及 ZCode 会话在操作知识库(vault)时必须遵守的产品/数据边界与共享事务协议。读完本文,你可以独立完成 ZCode 环境下的技能发现安装(含 dry-run 预览与冲突处理)、正确解析并选定用户 vault,并按claude-obsidian.transaction.v1事务协议安全地执行共享变更。
ZCODE.md 的文档定位:一份“主机适配层”契约
ZCODE.md 篇幅不长,但它承担的是一个明确的角色:主机适配层声明。claude-obsidian 同时支持多个 Agent 宿主(仓库中还有 GEMINI.md 等结构相同的兄弟文档),每个宿主文档都不重复定义产品行为,而是做三件事:
- 声明中立契约的唯一来源:
Read AGENTS.md as the canonical host-neutral contract——所有跨宿主一致的行为规则只定义在 AGENTS.md 里; - 指明可移植代码的落点:技能在
skills/<name>/SKILL.md,可移植核心在claude_obsidian/(标准库实现,无第三方依赖); - 给出该宿主特有的发现机制与安装命令。
从仓库结构看,这种分层是刻意设计的:AGENTS.md 开头即声明 "host hooks never define knowledge behavior"(宿主钩子从不定义知识行为),即宿主适配文档(ZCODE.md)只解决"宿主如何找到并调用"的问题,"调用之后做什么"完全由中立契约和可移植核心决定。
ZCode 的原生发现机制:AGENTS.md 与用户级技能目录
ZCODE.md 指出 ZCode 有两条原生的发现路径,因此不需要镜像规则文件(no mirrored rules file is needed):
- 规则文件:ZCode 原生地在 workspace 与 user 两个作用域读取
AGENTS.md。这意味着同一份中立契约无需为 ZCode 复制一份zcode-rules.md之类的变体; - 技能文件:用户级技能在
~/.zcode/skills/<skill-name>/SKILL.md被自动发现。仓库内置的 15 个技能(wiki、save、wiki-ingest、wiki-query、wiki-lint等核心工作流,以及autoresearch、canvas、wiki-retrieve等扩展)全部位于 skills/ 目录下,每个技能只使用可移植的 Agent Skills frontmatter 子集——恰好是name和description两个字段,这与 AGENTS.md 中 "Canonical skills" 一节的约束一致。
用户级(而非项目级)安装带来的直接收益是:每个 ZCode 工作区都可以直接调用这些技能,无需逐项目配置。这是 ZCODE.md 与 Cursor/Windsurf 等需要--workspace指向项目目录的主机在安装语义上的关键区别。
安装技能到 ZCode:setup-multi-agent.sh 的两段式流程
ZCODE.md 给出的安装命令是标准的"先预览、后应用"两段式:
bash scripts/setup-multi-agent.sh --host zcode bash scripts/setup-multi-agent.sh --host zcode --apply第一条命令只预览将要创建的符号链接,第二条命令才真正落盘。结合 scripts/setup-multi-agent.sh 的源码,这套流程的完整参数与安全语义如下:
参数与模式
脚本支持的模式与目标主机为:
Usage: scripts/setup-multi-agent.sh [--check|--dry-run|--apply] [--host codex|opencode|gemini|zcode|cursor|windsurf|all] [--workspace PATH]--dry-run(默认):仅输出PLANNED <host> <destination>计划,结尾提示 "Dry run only. Repeat with --apply to create the planned links.",不做任何写入;--check:与 dry-run 相同但以退出码 1 表示存在待安装项,适合放进 CI 或 Agent 自检流程;--apply:实际执行创建符号链接,输出CREATED;--host zcode:ZCode 是显式 opt-in 主机。不指定--host时,脚本默认只安装 Codex、OpenCode、Gemini 三家(见脚本第 50–52 行的默认主机展开逻辑);--workspace PATH:仅 Cursor/Windsurf 必需(它们安装到<workspace>/.<host>/skills/),ZCode 固定安装到$HOME/.zcode/skills(脚本中destination_root="$HOME/.zcode/skills",见 setup-multi-agent.sh)。
安全语义:绝不覆盖、冲突即失败
脚本头注释即声明 "Install portable skill links without overwriting existing host configuration"。其inspect_link函数实现了严格的冲突判定(setup-multi-agent.sh):
- 目标路径已是符号链接且指向本仓库对应技能目录 → 输出
READY(幂等成功); - 目标路径是指向别处的符号链接,或目标已存在为普通文件/目录 → 输出
CONFLICT ...,保留原文件,整体退出码置为 2; - 不存在任何目标 →
dry-run下计划、apply下mkdir -p父目录后ln -s创建。
这些行为不是口头约定,而是有隔离式(hermetic)测试锁定的实现事实。tests/test_setup_multi_agent.py 通过重写HOME环境变量在临时目录中执行真实脚本:
- test_zcode_host_installs_global_links:
--apply --host zcode后断言~/.zcode/skills/下恰好是 15 个符号链接、每个链接的resolve()都指回仓库skills/<name>/,且默认主机(如~/.agents/skills)未被顺带安装;重复执行时 15 个链接全部报告READY,证明幂等; - test_zcode_host_conflict_is_preserved:预先在
~/.zcode/skills/wiki/放入用户自有文件后执行--apply,断言退出码为 2、用户文件原样保留("preserve"内容未变),同时其余 14 个技能仍正常安装——即单点冲突不会阻塞其余链接,但会让本次运行以失败码收场。
工作区主机为何多一层 symlink 防护
对 Cursor/Windsurf 这类安装到工作区内的主机,脚本还实现了"父目录符号链接逃逸"检查:若<workspace>/.<host>或其父级是符号链接,apply也会被拒绝(parent is a symlink,退出码 2),见 test_workspace_parent_symlinks_cannot_redirect_apply。ZCode 安装目标在$HOME下不经过这层工作区禁闭逻辑,但该机制说明了这个安装器的整体安全基调:任何可能把写入重定向到预期路径之外的结构,一律 fail-closed。
产品源与用户 Vault 的边界:先解析、后读取
ZCODE.md 明确警告:"This repository is product source, not the default user vault"。仓库是产品源代码,不是默认的用户知识库。这条边界有三层落地:
vault 的形态:按 AGENTS.md,用户 vault 是包含
.claude-obsidian.json、wiki/和.raw/的目录,"可变状态永远属于那里";仓库根部的wiki/、.raw/、.vault-meta/是贡献者状态,被排除在公开发布物之外,templates/vault/才是可分发的种子模板;新建/接管走 dry-run-first 命令:ZCODE.md 要求用 dry-run 优先的
init命令创建独立 vault,或用adopt接管既有 vault。对应的确定性命令(见 skills/wiki/SKILL.md 的完整示例)为:python3 "$CORE" init /absolute/path/to/vault \ --generated-at <ISO-UTC> --operation-id init-reviewed python3 "$CORE" init /absolute/path/to/vault \ --generated-at <ISO-UTC> --operation-id init-reviewed \ --approved-plan-sha256 <reviewed-sha256> --apply第一条输出初始化计划(
initialization-plan.v1),只有人工审查过计划摘要后,第二条才携带--approved-plan-sha256真正执行。adopt对既有 vault 走同样的"计划 → 审查 → 应用"路径(见 claude_obsidian/cli.py 中command_init/command_adopt);解析顺序 fail-closed:ZCODE.md 要求"在读取
wiki/hot.md或运行任何技能之前先解析 vault"。这一顺序在源码中由resolve_vault_root精确实现(claude_obsidian/paths.py),优先级为:显式--vault→ 环境变量CLAUDE_OBSIDIAN_VAULT→ 向上查找最近的.claude-obsidian.json工作区配置 → 当前目录及其祖先中无歧义的已初始化 vault。任何一步失败都抛出VaultSelectionError(如VAULT_NOT_FOUND:"no vault selected; pass --vault or set CLAUDE_OBSIDIAN_VAULT"),即选不出 vault 就拒绝工作,而不是回退到产品仓库自身。同文件的assert_not_plugin_tree还会显式拒绝把可变 vault 状态写入已安装的产品树内(PLUGIN_ROOT_IS_NOT_VAULT),从机制上堵死"在插件缓存里误建 vault"的错误。
wiki/hot.md本身按 AGENTS.md 的 vault 约定是"有界最近上下文,绝非转录";若要把它注入会话上下文,还需要用户显式设置CLAUDE_OBSIDIAN_SESSION_CONTEXT=1作为同意信号,且工作区外的 vault 必须同时给出精确的CLAUDE_OBSIDIAN_SESSION_CONTEXT_VAULT路径——绝不允许自动设置。
共享变更协议:一个经过审查的事务 bundle
ZCODE.md 对 ZCode 会话的变更纪律表述为:所有共享变更使用唯一一个经过审查的claude-obsidian.transaction.v1bundle;并行工作者只产出草稿;禁止直接共享写、自动提交和已弃用的按文件锁助手;远程出站(remote egress)与破坏性操作需要用户明确同意。
这些约束在可移植核心中都有对应的实现实体:
- bundle 模式名:
claude_obsidian/transaction.py第 41 行定义BUNDLE_SCHEMA = "claude-obsidian.transaction.v1",与 ZCODE.md 中的字符串逐字一致; - 操作类型即权限边界:同一模块的
OPERATION_TYPES声明了base、save、ingest、autoresearch、lint-fix、capture、generic等类型,源码注释强调 "an operation type is an authority boundary, not merely an audit label"——每种类型能写的路径域是声明式的,.raw/原始载荷是 create-only(仅可创建),实现上通过_WIKI_ONLY_OPERATIONS、_WIKI_AND_RAW_OPERATIONS等集合把权限域钉死; - 实现层面为何不是"原子文件系统操作":transaction.py 的模块注释解释了设计动机——多文件更新在常见文件系统上不可能真正原子,因此提供一套"诚实的更强契约":进程持有的变更锁、前置哈希(precondition SHA-256)、持久日志(journal)、逐文件原子替换(临时文件 +
os.replace+ 父目录 fsync,见_atomic_vault_write),以及针对整个操作的确定性回滚/恢复; - 审查摘要与冲突语义:claude_obsidian/cli.py 中,
transaction apply缺少--approved-plan-sha256会直接报错 "transaction apply requires --approved-plan-sha256 from transaction inspect";若重新生成的事务与已审查计划不一致,则报 "the regenerated transaction differs from the reviewed plan"。运行期发现目标文件在审查后已被改动时,抛出TransactionConflict,其退出码固定为 75(transaction.py),与临时/可重试错误区分开; - 规模上限:单事务单文件上限 64 MiB、总量 128 MiB、写操作数 1024(
MAX_TRANSACTION_*常量组,transaction.py),防止事务日志本身成为不可控状态。
"弃用的按文件锁助手"指scripts/wiki-lock.sh——它在仓库中仍然存在(并有配套测试 tests/test_wiki_lock.sh 验证其行为),但 AGENTS.md 的 Mutation protocol 明确将其列为不得再使用的历史方案,transaction.v1bundle 是唯一的共享变更通道。
端到端工作流小结
把 ZCODE.md 的条款串起来,一个 ZCode 会话操作 claude-obsidian 知识库的完整合规流程是:
| 阶段 | 动作 | 依据 |
|---|---|---|
| 1. 一次性安装 | bash scripts/setup-multi-agent.sh --host zcode预览,确认后加--apply,把 15 个技能符号链接到~/.zcode/skills/ | ZCODE.md、setup-multi-agent.sh |
| 2. 读取契约 | ZCode 原生读取AGENTS.md(workspace/user 作用域),无需镜像规则文件 | ZCODE.md、AGENTS.md |
| 3. 解析 vault | 按--vault→CLAUDE_OBSIDIAN_VAULT→ 最近.claude-obsidian.json→ cwd 祖先发现;选不出即失败;新库先init、老库adopt(均 dry-run-first) | paths.py、skills/wiki/SKILL.md |
| 4. 加载上下文 | vault 解析成功后才静默读取wiki/hot.md;注入会话需显式环境变量同意 | AGENTS.md |
| 5. 执行变更 | 并行工作者只产草稿 → 合并为单个claude-obsidian.transaction.v1bundle →transaction inspect审查 → 带--approved-plan-sha256应用 → 汇报操作 ID 与精确变更路径 | transaction.py、cli.py |
| 6. 高风险动作 | 远程出站、破坏性修复、规范研究合并一律要求用户明确同意 | ZCODE.md、AGENTS.md |
最后一点与发布流程相关:AGENTS.md 的 Verification 一节要求行为变更后运行make test(覆盖全部 Python/shell 测试套件与产品、能力、包、钩子、清单契约,见 Makefile),且任何 Agent 未经所有者批准不得推送、打标签或发布版本——这也解释了为什么 ZCODE.md 的"同意门槛"从文件安装到 vault 写入再到远程出站是一以贯之的。
【免费下载链接】claude-obsidianSelf-organizing AI second brain for Obsidian + Claude Code. Drop any source and Claude reads, links, and files it into one connected knowledge graph of plain Markdown you own. AI note-taking, personal knowledge management (PKM), and an open-source Notion alternative. Based on Karpathy's LLM Wiki pattern.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-obsidian
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考