claude-obsidian Windows 与 WSL 平台指南:只读原生、全能力 WSL 与排障实战
【免费下载链接】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
本篇基于仓库中的 Windows/WSL 官方指南,讲清楚 claude-obsidian 在 Windows 生态下的能力边界:原生 Windows 是“只读平台”,WSL 才是“全能力平台”。读完后你将掌握各平台能力矩阵、UNSUPPORTED_PLATFORM/UNSAFE_VAULT_IDENTITY/PLAN_CHANGED三类错误的源码级成因、Claude Code hooks 在 Windows 上依赖python3的机制,以及一套可复用的 WSL 排障清单与跨边界工作流。
平台能力矩阵:哪些命令能在哪跑
官方指南(docs/windows-wsl.md)给出的支持矩阵如下,本文所有结论均以此为准:
| 能力 | WSL / Linux / macOS | 原生 Windows(含 Git Bash) |
|---|---|---|
| 检查、dry-run 预览、检索(retrieval) | 支持 | 支持 |
Vault 写入(transaction apply、init、adopt、migrate、capture apply、mode set) | 支持 | 不支持 — 拒绝并报错UNSUPPORTED_PLATFORM |
Capture 队列命令(包括只读的capture queue list) | 支持 | 不支持 — 当前一律拒绝;上游已在 issue #151 跟踪 |
Git 检查点(checkpoint) | 仅 Linux 和 macOS | 不支持 |
| Bash 安装脚本与 shell 测试套件 | 支持 | 不支持(POSIX 专属) |
Claude Code hooks(SessionStart、Stop) | 支持(开箱即用) | 部分支持:要求python3在PATH上,见下文 |
也就是说,在原生 Windows 上你可以放心做“看”的操作(inspect、dry-run 预览、retrieve),但所有“改”的操作都会被平台门禁(platform gate)在产生任何副作用之前直接拒绝;WSL 里则是全功能。
稳定文件身份是 Vault 的硬性前提
除了操作系统本身的限制,Vault 所在文件系统的“文件身份”稳定性也决定写入是否被放行:
- NTFS 可以;
- FAT/exFAT 卷(典型如 U 盘)和部分网络共享卷会被拒绝,错误码为
UNSAFE_VAULT_IDENTITY——解决办法是把 Vault 移到 NTFS 卷,或放进 WSL 内部文件系统操作。
从源码看,这条拒绝来自 claude_obsidian/transaction.py 中的_require_stable_identity():当stat结果的st_ino为 0(说明文件系统不暴露稳定的 inode 身份)时,抛出UNSAFE_VAULT_IDENTITY,错误信息明确提示 “FAT/exFAT/some network shares; use an NTFS volume or WSL”。同一错误码还覆盖了“无法 pin 住 Vault 父目录”“无法枚举 Vault 父目录”等身份不可信的情形(见 transaction.py 中的多处抛出点),即任何一步无法确认“这个目录始终是这个目录”,写入都会 fail closed。
Claude Code hooks 与 Windows 上的 python3
claude-obsidian 通过 hooks/hooks.json 注册了SessionStart与Stop两个 Claude Code 生命周期钩子,配置形态如下(exec-form 命令钩子):
{ "type": "command", "command": "python3", "args": [ "${CLAUDE_PLUGIN_ROOT}/scripts/claude-obsidian.py", "hook", "session-start" ], "timeout": 5 }关键点在于"command": "python3"加一个args数组:Claude Code 会像可执行文件一样直接在PATH上解析python3并 spawn,没有 shell 参与,因此.batshim、shell alias 函数、shell profile 全部不会被参考。
- WSL 与大多数 Linux/macOS 的 Python 安装默认提供
PATH上的python3,所以那些环境下 hooks 无需额外配置即可工作。 - 原生 Windows 常常没有,常见有两种情形:
- python.org 官方安装包:装出来的是
python.exe而不是python3.exe。对策有三种任选:在解释器之前的PATH位置放一个python3.exeshim;安装提供python3.exe的发行版;或者干脆从 WSL 里运行 Claude Code,让 hooks 解析到 WSL 的python3。 - Microsoft Store 版 Python:其
python3应用执行别名(app execution alias)可能只是一个会打开商店的 stub,而不是真正的解释器。需要在 Windows 设置中禁用python3应用执行别名,然后从 python.org 安装 Python 或在 WSL 中安装,并确认真正的解释器在PATH上。
- python.org 官方安装包:装出来的是
还有一个值得注意的失败语义:当python3无法被解析时,Claude Code 根本起不了钩子进程,claude-obsidian 自己的代码永远不会执行,因而也无法输出任何诊断信息。此时SessionStart的上下文注入和Stop的恢复警告都会“安静地缺席”。但这只影响可选的 hook 路径——skills 与 CLI 本体不受影响。
为什么写入必须在 WSL 里进行:目录描述符围栏
文档中“writes require WSL”一节的技术依据,可以从仓库源码完整印证。
能力探测:supports_confined_dirfd()
平台门禁的底层判断位于 claude_obsidian/paths.py 的supports_confined_dirfd():
def supports_confined_dirfd() -> bool: """True when the POSIX openat-style confinement primitives all exist.""" return ( os.name != "nt" and hasattr(os, "O_DIRECTORY") and os.open in os.supports_dir_fd and os.mkdir in os.supports_dir_fd and os.rename in os.supports_dir_fd and os.stat in os.supports_dir_fd and os.unlink in os.supports_dir_fd )从源码结构看,该函数要求 POSIX 的 openat 风格围栏原语全部齐备:O_DIRECTORY标志、open/mkdir/rename/stat/unlink对dir_fd的支持,且明确排除os.name == "nt"。其 docstring 说明得很直白——原生 Windows 完全缺少O_DIRECTORY与dir_fd支持,调用方在这些平台上走基于路径的降级分支,而不是描述符围栏。
写入门禁:UNSUPPORTED_PLATFORM
对 Vault 的一切变更操作,写入前都会经过 claude_obsidian/transaction.py 中的_require_write_platform():
- 该函数在任何副作用(目录创建、备份暂存)发生之前调用,保证一次被拒绝的
--apply不会留下任何残留; - 它调用
_require_lock_dirfd_support()探测能力,若平台不满足则抛出专门的_PlatformConfinementUnavailable(errno.ENOTSUP),再映射为TransactionValidationError("UNSUPPORTED_PLATFORM", ...); - 专用异常类型的设计用意在于:Linux 上
ENOTSUP与EOPNOTSUPP是两个不同的 errno 值,如果混用,平台门禁自身抛出的 ENOTSUP 可能会把“受支持宿主上真实文件系统返回的 EOPNOTSUPP”一并吞掉。
面向用户的拒绝信息是(transaction.py):
vault writes require directory-descriptor confinement (WSL/Linux or supported macOS); on native Windows run this command inside WSL — read-only inspection and dry-runs work natively; if WSL itself misbehaves, see docs/windows-wsl.md
同样的门禁也覆盖 capture 路径:claude_obsidian/capture.py 在打开受围栏的.vault-meta/capture运行时目录时捕获_PlatformConfinementUnavailable,抛出CaptureValidationError("UNSUPPORTED_PLATFORM", ...)——这解释了能力矩阵中“连只读的capture queue list也拒绝”的现象:队列命令需要先把运行时目录 pin 住,而这一步在无 dirfd 的原生 Windows 上无法完成。
围栏到底防什么
变更安全性被绑定到 POSIX 目录描述符:整个写入期间,vault 根目录与每个运行时目录都被“钉住”(pinned)在打开的目录描述符上,后续mkdir/rename/unlink等一律通过dir_fd相对定位,不跟随任何路径组件上的符号链接。因此,一个并发被掉包的符号链接或被替换的文件夹不会把写入重定向到别处,而会直接失败(fail closed)。配套的别名检查(如CASEFOLD_PATH_ALIAS、UNSAFE_VAULT_IDENTITY的 parent pin 校验,见 transaction.py)进一步保证“你看到的 vault 名字”与“被锁住的那个 vault 对象”是同一个东西。原生 Windows 无法提供这些原语,所以写入选择在入口处被明确拒绝,而不是静默降级到更弱的保证。
指南同时说明:一个“降级写入模式”——默认关闭、由显式的“降低保证”开关控制——正在 issue #151 中讨论;如果你被 WSL 卡住,那是表达立场的地方。
这条路径的验证覆盖位于 tests/test_windows_compat.py:该测试在 POSIX 上通过禁用 dirfd 能力探测、移除os.O_DIRECTORY来模拟降级平台(每个测试文件独立进程,操作安全),验证同一套降级分支的行为;而真正的 Windows 行为(CRT 文本模式O_BINARY、os.open拒绝打开目录、junction/reparse 语义、NTFS stat 身份等)由真实的 windows-smoke CI 任务覆盖——文件头注释明确列出了模拟无法证明的部分,这也是理解其证据边界的关键。
WSL 排障:症状、检查与清单
“WSL 已安装”不等于“WSL 能正常工作”。下面先给出指南中的症状-检查对照表,再给出建议按序执行的检查清单。
症状对照表
| 症状 | 检查方法 |
|---|---|
wsl --install完成了,但wsl --status或wsl -l -v无限挂起 | 该现场报告的挂起目前没有确认的根因。按 Microsoft 官方的 WSL 挂起诊断与上报流程处理(见下文清单第 5 步)。 |
wsl报内核或版本错误 | 依次执行wsl --update、wsl --shutdown,然后重试。 |
| WSL 之前正常,一次更新或软件变更之后停止工作 | 不要先入为主归因。先更新 Windows 与 WSL,再走 Microsoft 的 WSL 排障流程。 |
原生 dry-run 得到的审批哈希在 WSL 里 apply 时失败,报PLAN_CHANGED | 这是设计使然:审批哈希绑定了审阅环境中的文件系统身份。如果 apply 将发生在 WSL 中,就在 WSL 里跑被审阅的 dry-run;原生环境产出的approved_plan_sha256无法在 WSL 中重放。 |
写入失败,UNSAFE_VAULT_IDENTITY提到稳定文件身份 | Vault 位于 FAT/exFAT 卷或不受支持的网络共享上。移到 NTFS,或保留在 WSL 文件系统内部。 |
关于PLAN_CHANGED的“按设计”,源码层面的证据是变更锁获取阶段对“被审阅身份”的复核:claude_obsidian/transaction.py 中,MutationLock会用os.fstat(root_fd)取当前被 pin 住目录的设备号与 inode,与审批计划中记录的expected_vault_identity(device/inode)逐一比对,不一致即抛出PLAN_CHANGED(“the selected vault object changed before locking”);对尚不存在的 vault,则比对父目录的parent_device/parent_inode与leaf。由于 NTFS 卷与 WSL 内的同一目录在两个环境里的设备/ inode 身份不同,跨环境重放审批哈希必然失败——这不是 bug,而是身份绑定的直接后果。
排障检查清单
按值得尝试的先后顺序:
- 从 Microsoft 官方 WSL troubleshooting 指南入手。
- 确认 BIOS/UEFI 中已启用虚拟化,并且“Virtual Machine Platform”与“Windows Subsystem for Linux”两个 Windows 功能均已启用;启用任一功能后需重启。
- 在提升权限的提示符中运行
wsl --update,然后wsl --shutdown,再重试wsl --status。 - 确认 hypervisor 启动设置已启用。如果安装了第三方 hypervisor,使用支持 Hyper-V 的较新版本,或在诊断冲突期间暂时关闭它。
- 若 WSL 仍挂起,按 Microsoft 官方的 WSL 挂起数据采集步骤收集诊断并提交给 WSL 项目。在没有诊断证据支持之前,不要把挂起归因于某个具体原因。
跨边界工作流:原生审阅,WSL 变更
官方支持的跨边界工作流可以概括为一句话:在原生 Windows 上检查与审阅,在 WSL 内变更。
- 由于审批哈希绑定产生它的环境,被审阅的 dry-run 必须与执行 apply 的环境一致。如果变更将落在 WSL 里,就在 WSL 里跑 dry-run、拿到审批哈希、再 apply;反之亦然。
- Vault 放在 WSL 内部文件系统(而不是挂载的 Windows 驱动器)能同时规避两类问题:上文“稳定文件身份”的坑,以及跨边界访问的性能开销。
- 原生 Windows 侧可用的能力(inspect、dry-run 预览、retrieve)可以照常用来做“读”的审阅;所有“写”的动作留在 WSL 中完成。
相关延伸阅读:围栏与 pin 机制的完整设计见 复合 Vault 指南,平台门禁与身份校验的其余实现细节可继续查看 claude_obsidian/transaction.py 与 claude_obsidian/capture.py。
小结
- 原生 Windows 的定位是只读 + 审阅:inspect、dry-run、retrieval 可用;写入类命令一律
UNSUPPORTED_PLATFORM拒绝,且拒绝发生在任何副作用之前。 - WSL 是全能力平台:事务写入、capture 队列、模式设置等都在这里完成;Git 检查点(
checkpoint)则仅限 Linux/macOS。 - 拒绝的根因在源码里清晰可见:
supports_confined_dirfd()的能力探测、_require_write_platform()的写入门禁、_require_stable_identity()对st_ino == 0的UNSAFE_VAULT_IDENTITY校验。 - hooks 在 Windows 上“静默失效”的唯一原因是
python3不在PATH上;CLI 与 skills 不受影响,排查时优先检查这一点。 - 跨边界时牢记:审批哈希绑定产生它的文件系统身份,dry-run 与 apply 必须同环境;Vault 留在 WSL 文件系统内部是最稳妥的布局。
【免费下载链接】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),仅供参考