Obsidian AI Skill
用自然语言操作 Obsidian 笔记库。你(宿主 agent)负责分析意图、检索、决策;
Python 脚本负责安全执行(确认门、路径防护、备份回滚)。 不需要配外部 AI——
你就是 AI。
> 所有改动经 scripts/execute.py,可回滚。不知道就问用户,别扫描、别猜。
决策树(每次请求照此走)
任何请求
↓
第1步: python3 scripts/config.py show ← 永远先跑这个,别扫描
↓
Vault configured: NO → 问用户 vault 绝对路径,设上再继续(见"首次配置")
Vault configured: YES → 看用户要干啥
↓
你要做的:
1. 需要信息? → execute.py read / search(免确认)
2. 要改笔记? → 自己生成 decision JSON → prepare → policy → diff 给用户 → 用户确认 → apply
↓
任何会改既有笔记的动作(APPEND/UPDATE/DELETE/MOVE/RENAME/MERGE/CREATE 覆盖)
→ 必须先用单独一轮对话问用户"确定吗?",用户明确同意后才传 --confirmed / "confirmed": true
0. 语言规则(最高优先)
用用户第一条消息的语言回复,全程跟随。 用户写中文 → 你全程中文(思考、状态、提问、报错)。
用户写英文 → 全程英文。绝不默认英文回复中文用户——这是体验灾难。
1. 首次配置(每次会话第一步)
永远先跑,且只跑这一个命令——它告诉你一切,替代所有扫描:
python3 scripts/config.py show
禁止: 扫描文件系统、ls/find/glob 找 vault、猜路径、用默认 ~/Documents/Obsidian Vault。
如果 scripts/config.py 找不到 → 问用户 skill 装在哪,别自己 hunt。
vault_path 没配(Vault configured: NO)→ 停下问用户
中文示例:
> 为了把笔记写进你的 Obsidian,我需要知道你的 vault(笔记库)在哪。
> 请告诉我绝对路径,比如 macOS /Users/你/Documents/MyVault,或 Windows C:\Users\你\Documents\MyVault。
> 还没有的话说"新建",我帮你建空目录再设上。
用户给路径后:
python3 scripts/config.py set vault_path "<路径>"
python3 scripts/config.py show # 确认 Vault configured: YES
没到 YES 之前,不进行任何笔记操作。
> 本 skill 无内置 AI,不需要配 base_url/model/api_key。你就是 AI,自己做分析决策。
2. 操作命令(execute.py)
| 用户说什么 | 跑什么 | 要确认? |
|---|---|---|
| "读 X" / "看 X" | execute.py read "X" |
否 |
| "搜 XXX" / "找含 XXX 的" | execute.py search "XXX" --top 5 |
否 |
| "建 X 笔记,内容是..." | execute.py create "X" --content "..." --summary "..." --tags "a,b" |
X 必须不存在;已存在 → 拒绝,改用 UPDATE |
| "给 X 末尾加..." | execute.py append "X" --content "..." --confirmed |
是,X 必须存在 |
| "改 X 的内容为..." | 走 prepare/apply(见 §3),无 --confirmed 快捷路径 |
是,X 必须存在 |
| "删 X" | 走 prepare/apply(见 §3),无 --confirmed 快捷路径 |
是 |
| "把 X 挪到 Y" | execute.py move "X" "Y" --confirmed |
是(Y 存在还需 --overwrite-confirmed) |
| "把 X 改名 Y" | execute.py rename "X" "Y" --confirmed |
是(Y 存在还需 --overwrite-confirmed) |
| "把 A 合并到 B" | execute.py merge "A" "B" --confirmed |
是 |
> DELETE / UPDATE 没有一键快捷路径——它们破坏性大(删除不可逆、更新覆盖原文),
> 必须走 §3 的两阶段(prepare → diff 给用户看 → 用户确认 → apply),让用户在 diff 阶段
> 有机会喊停。其他动作(append/move/rename/merge)保留 --confirmed,但有 rollback 兜底。
命令模板:
python3 scripts/execute.py read "notes/Foo.md"
python3 scripts/execute.py search "关键词" --top 5
python3 scripts/execute.py create "notes/Foo.md" --content "..." --summary "..." --tags "a,b"
python3 scripts/execute.py append "notes/Foo.md" --content "..." --confirmed
python3 scripts/execute.py move "notes/Foo.md" "archive/Foo.md" --confirmed
python3 scripts/execute.py rename "notes/Foo.md" "FooRenamed" --confirmed
python3 scripts/execute.py merge "notes/Old.md" "notes/New.md" --confirmed
# update / delete 没有 --confirmed 快捷路径 —— 走 §3 两阶段(prepare→diff→apply)
多行内容: 用 --content-file <临时文件>(用你的 Write 工具写文件再传,字节精确,无 shell 引号问题)。
--content "..." 会解码 \n/\t/\r/\\(便捷),但含字面反斜杠的代码块必须用 --content-file。
3. 自己决策的流程(整理/合并/智能修改)
用户说"整理/合并/看着办"这种含糊话时,你自己分析(不用调外部 AI)。
DELETE / UPDATE 也必须走这个流程(它们没有 --confirmed 快捷路径)。
① 检索 + 读: search 找候选,read 读 body,自己判断该 MERGE/UPDATE/CREATE/DELETE 哪个。
python3 scripts/execute.py search "会议主题" --top 10
python3 scripts/execute.py read "projects/foo.md"
② 自己生成 decision JSON: 你判断后写一个 decision JSON 到临时文件:
{"action": "MERGE", "absorbed": "meeting.md", "survivor": "projects/foo.md"}
{"action": "UPDATE", "target": "notes/x.md", "content": "...", "summary": "..."}
{"action": "CREATE", "target": "notes/new.md", "content": "...", "summary": "..."}
action ∈ {CREATE, APPEND, UPDATE, MERGE, NO_CHANGE, MOVE, DELETE, RENAME}。
③ Python 校验(prepare + policy):
python3 scripts/execute.py prepare --decision-file /tmp/decision.json # 盖 _before_hash
python3 scripts/policy.py --decision-file /tmp/decision.json # proceed 或 halt_and_ask_user
policy 说 halt_and_ask_user = 需要用户确认(见下)。
④ 给用户看 diff,然后问确认:
python3 scripts/diff.py --decision-file /tmp/decision.json
用用户语言问:"这样可以吗?确认执行?" 用户明确同意后才进 ⑤。
⑤ 执行(带 confirmed:true): 把 "confirmed": true 写进 decision.json,apply:
python3 scripts/execute.py apply --decision-file /tmp/decision.json
MOVE/RENAME 到已存在文件,还要加 "overwrite_confirmed": true。
apply 返回 hash_mismatch(exit 3) = 用户在确认时手改了文件 → 别盲目重试,告诉用户文件变了,问要不要重来。
4. 确认规则(最重要,别违反)
"用户说删除" ≠ "用户确认删除"。 用户说"把 X 删了"是请求,不是同意。
你必须先用单独一轮对话问:"确定要删吗?" 用户明确说"确定/删除/执行"后,才传 --confirmed。
- 用户只说"删 X" → 你问"确定吗?",不传 confirmed
- 用户回"确定" → 你传
--confirmed/"confirmed": true - 用户没回或换话题 → 不执行,等用户明确
confirmed 必须是 JSON 布尔 true(严格),不是 "yes"/1/"false"。
你是可信 Layer-1,你传 confirmed:true 是合法的——但必须基于用户真实同意。
5. 安全底线(Python 代码强制,你撞上了会被拒)
| 动作 | 规则 | 违反时 |
|---|---|---|
| READ / SEARCH | 免确认 | — |
| CREATE | 只建新文件;目标已存在 → 直接拒绝(即使 --confirmed),改用 UPDATE |
exit 9 overwrite_refused |
| APPEND / UPDATE | 必须 --confirmed,且目标必须存在(不静默创建) |
exit 8 / exit 5 target_not_found |
| DELETE / MOVE / RENAME / MERGE | 必须 --confirmed |
exit 8 |
| MOVE/RENAME 到已存在文件 | 还需 --overwrite-confirmed |
exit 9 |
路径穿越 ../ ..\ / vault 外 / symlink 出 vault |
拒绝 | exit 4 vault_error |
confirmed 非严格布尔("yes"/1/[true]) |
拒绝 | exit 8 |
| vault 未配置 | 拒绝任何操作 | exit 10 |
| 非法 action / decision 字段缺失 | 拒绝 | exit 6 |
关键:
- 路径在 vault 外 → 告诉用户"路径在笔记库外,不能操作",别尝试。
- 用户没明确同意前,绝不传 --confirmed / "confirmed": true。
6. 回滚(改错了能撤)
每个改动返回 operation_id,告诉用户这个 id。
python3 scripts/rollback.py <operation_id> # 撤回(文件被改过会拒绝)
python3 scripts/rollback.py <operation_id> --force # 强制撤回(覆盖后来修改,需用户明确同意)
- 不知道 op_id → 看
<vault>/.obsidian-ai/history/里最新的op_*.json。 - rollback 拒绝(exit 2 drift)= 操作后文件又被改过 → 告诉用户"之后又改过了,强制回滚会覆盖,确认吗?",同意才
--force。
7. 跨平台提示
- Windows 若
python3不识别 → 改用python。 - 路径 macOS
/Users/...或 WindowsC:\Users\...都行(正反斜杠均可)。 - 命令行传 JSON 用
--decision-file(别用单引号 inline JSON,Windows cmd 不支持)。
8. 笔记格式
- 新建/更新自动加 YAML frontmatter(
created/updated/summary/tags/outline),created更新时保留。 - 链接用
[[笔记名]]wikilink;MOVE/RENAME/MERGE 自动重写 backlink。
内部架构(仅供理解,不用背)
两层:① SKILL.md(你,交互+分析+决策)② execute.py/policy.py/backup.py/history.py/rollback.py(安全执行,hash+备份+事务)。
安全在 ② 层代码强制,即使忽略本文件也生效。