SiYuan Note Enhanced CLI
Node.js CLI wrapper around SiYuan's REST API. Lives at ~/skills/siyuan-skill-enhanced/. All commands run from that directory.
When to Use(何时使用)
- 用户提到"思源"、"SiYuan"、"思源笔记"时激活
- 需要列出/创建/更新/删除思源笔记本/文档/块时
- 需要搜索思源内容(关键词/语义/混合)时
- 需要设置标签或属性时
- 需要递归查询子文档结构时
Don't use for:
- 思源安装/配置/服务器部署(不是 CLI 范畴)
- 思源 UI 操作指导(用 siyuan-knowledge-base-mgmt)
- 笔记内容生成/写作(用通用写作 skill)
核心命令速查
| 命令 | 用途 | 示例 |
|---|---|---|
notebooks |
列出所有笔记本 | node siyuan.js notebooks |
structure <id> |
列出子文档(递归) | node siyuan.js structure <docId> --depth -1 |
content <id> |
读取文档内容 | node siyuan.js content <docId> |
create |
创建文档 | node siyuan.js create "标题" "" --parent-id <id> |
update |
更新文档 | node siyuan.js update <id> --file /tmp/content.md |
tags |
设置/追加/查看标签 | node siyuan.js tags <id> --tags "tag1,tag2" |
search |
搜索内容 | node siyuan.js search <query> |
rename |
重命名 | node siyuan.js rename <id> "新标题" |
info |
查看文档元信息 | node siyuan.js info <id> |
⚠️ 关键陷阱(最常踩):
--depth 默认是 1(只查第一层),传 -1 才是全递归。
# ✅ 正确:递归查所有子文档
node siyuan.js structure <docId> --depth -1
# ⚠️ 错误:只查第一层
node siyuan.js structure <docId>
Common Pitfalls(关键陷阱)
完整陷阱清单(7 类 + 检测 + 修复)→ references/pitfalls.md
最常见的 3 个:
--depth默认陷阱(见上文)--titlevs 位置参数陷阱:node siyuan.js create "标题" ""才是正确格式,--title不识别--tagsvs-t陷阱:node siyuan.js tags <id> -t "tag1,tag2"用-t,不是--tags
文档父子关系查询(核心 pitfall)
structure <docId> --depth -1 是唯一可靠的子文档枚举方法。其他方法对 doc-type 父页静默返回空:
| 方法 | doc-type 父 | folder-type 父 |
|---|---|---|
✅ structure <docId> --depth -1 |
✅ 完整 | ✅ 完整 |
❌ SQL parent_id = '<docId>' AND type='d' |
❌ 空 | ❌ 空 |
❌ /api/filetree/listDocsByPath with .sy path |
❌ 空 | ✅ OK |
✅ structure <docId> --depth 1 |
✅ 仅第 1 层 | ✅ 仅第 1 层 |
真实案例:曾用 SQL 查 179 篇 AUTOSAR 子文档返回空,误以为数据缺失。切到 structure --depth -1 立即返回全部 179 个。
删除文档与安全保护
- 默认有保护:直接
node siyuan.js delete <id>报"删除保护"错误 - 关保护:
config.json把safeMode: true改为false - 恢复保护:删完改回
true - 路径:
~/skills/siyuan-skill-enhanced/config.json
安装与配置
# 1. 安装(已有则跳过)
skillhub install siyuan-skill-enhanced
# 2. 配置 token
cd ~/skills/siyuan-skill-enhanced
cp config.example.json config.json
# 编辑 config.json 填入 SiYuan API token + baseURL
环境变量方式(优先级高于 config.json):
export SIYUAN_BASE_URL=http://localhost:6806
export SIYUAN_TOKEN=<your-token>
export SIYUAN_DEFAULT_NOTEBOOK=<notebook-id>
Verification Checklist(验证清单)
每次创建/更新文档后:
- [ ] 用 info <id> 检查 updated 字段变更为当前时间
- [ ] 用 structure <parent-id> --depth -1 确认子文档出现
- [ ] 用 content <id> 取回内容做关键字段抽查
每次批量操作后:
- [ ] 对每个操作记录输入/输出(便于回滚)
- [ ] 跑 1-2 个 spot check(随机抽 2 个文档验证)
- [ ] 备份原文档 ID 列表(操作前的 structure 输出)
删除前:
- [ ] 确认 safeMode: false
- [ ] 确认要删的 ID 是单个文档(不是父级)
- [ ] 准备"恢复保护"的回滚步骤
安全审计:
- [ ] config.json 不在 git 仓库中(.gitignore 已配)
- [ ] 不用默认 token,轮换周期 ≤90 天
- [ ] API 调用频率控制(思源默认有 rate limit)
相关 Skill
siyuan-knowledge-base-mgmt— 思源笔记方法论(PARA + 编号规范 + 索引规则)wechat-article-fetcher-cn— 公众号文章抓取(产出可导入思源)
实战场景(典型工作流)
场景 1:批量给 100 个文档加编号
# Step 1: 列出所有子文档 ID
node siyuan.js structure <parent-id> --depth -1 > /tmp/children.json
# Step 2: 解析 JSON 提取 ID 列表
python3 -c "
import json
with open('/tmp/children.json') as f:
# 跳过连接信息行(前 2-3 行)
lines = f.readlines()
start = next(i for i, l in enumerate(lines) if l.strip().startswith('{'))
data = json.loads(''.join(lines[start:]))
def collect(d):
ids = []
for x in d.get('documents', []):
ids.append((x['id'], x['title']))
for f in d.get('folders', []):
ids.extend(collect(f))
return ids
docs = collect(data['data'])
for i, (id, title) in enumerate(docs, 1):
print(f'{i:03d}_{id}') # 输出 NNN_id 格式
" > /tmp/rename_map.txt
# Step 3: 逐个重命名(按编号)
while read line; do
num=$(echo $line | cut -d_ -f1)
id=$(echo $line | cut -d_ -f2)
node siyuan.js rename $id "${num}_原标题"
done < /tmp/rename_map.txt
场景 2:跨笔记本搜索关键词
# 搜索所有笔记本中含 "AUTOSAR" 的文档
node siyuan.js search "AUTOSAR" --limit 20
# 输出:id, title, path, snippet
场景 3:双链索引批量更新
# Step 1: 获取父文档当前内容
node siyuan.js content <parent-id> > /tmp/parent.json
# Step 2: 在 Python 中追加新条目
python3 -c "
import json, re
with open('/tmp/parent.json') as f:
lines = f.readlines()
data = json.loads(''.join(l for l in lines if l.strip().startswith('{') or l.strip().startswith('[')))
content = data['data']['content']
new_entry = '
- [新文档](siyuan://blocks/新id) — 简介'
content = content.rstrip() + new_entry
with open('/tmp/parent_new.md', 'w') as f:
f.write(content)
"
# Step 3: 写回
node siyuan.js update <parent-id> --file /tmp/parent_new.md
性能与限制
| 操作 | 限制 | 缓解 |
|---|---|---|
structure --depth -1 |
大量子文档时较慢(>5 秒) | 限制 --depth 值 |
create/update |
文档大小 ≤ 1MB | 拆成多次写入 |
search |
默认 limit 20 | 用 --limit 调整 |
tags |
单次最多 50 个标签 | 多次调用 |
| API 调用频率 | 思源默认 rate limit | 加 sleep 0.1 |
已知 bug:
- cat/content 命令对刚 edit 的文档可能返回 0 块(不代表失败)
- structure --depth 默认 1(不是 -1),需要显式传
故障排查
| 症状 | 原因 | 解决 |
|---|---|---|
Error: connect ECONNREFUSED |
思源服务未运行 | 启动思源服务(systemctl start siyuan 或应用启动) |
Error: 401 Unauthorized |
Token 错误或过期 | 重新生成 token(思源 → 设置 → API token) |
Error: 404 Not Found |
文档 ID 不存在 | 用 structure 查实际 ID |
Error: 删除保护 |
safeMode 开启 | 编辑 config.json 设 safeMode: false |
content 返回 0 块 |
编辑后立即查询 | 等待 1-2 秒重试,或用 info 检查 updated |
structure 返回空 |
用了 SQL 或 listDocsByPath | 改用 structure --depth -1 |
tags 不生效 |
用错了 --tags |
改用 -t |
create 标题丢失 |
同时传了 --title 和内容 |
改用位置参数 create "标题" "" |
update 无效 |
文件路径错误 | 必须用绝对路径 --file /tmp/... |
| 中文字符乱码 | 终端编码 | 用 LANG=en_US.UTF-8 |
命令完整清单
笔记本管理:
- notebooks — 列出所有笔记本
- createNotebook <name> — 创建笔记本(注意:此命令在 v2.1+ 可能不直接暴露)
文档操作:
- structure <id> [--depth N] — 列出子文档(-1 = 递归全部)
- content <id> — 读取文档内容
- create <title> [content] --parent-id <id> — 创建文档
- update <id> --file <path> — 更新文档内容
- rename <id> <new-title> — 重命名
- delete <id> — 删除(需先关 safeMode)
搜索与标签:
- search <query> [--limit N] [--mode legacy|semantic|hybrid] — 搜索
- tags <id> -t "t1,t2" — 设置/覆盖标签
- tags <id> -a "t3" — 追加标签
- tags <id> -g — 查看标签
- attrs <id> --set <attrs-json> — 设置属性
元信息:
- info <id> — 文档元信息(含 updated 时间戳)
- hpath <id> — 人类可读路径
- exists --title <title> --notebook-id <nbId> — 检查文档是否存在
特殊:
- uninstall — 不存在(手动删除 ~/skills/siyuan-skill-enhanced/ 卸载)
- version — 不存在(用 node siyuan.js --help 验证)
已知问题与 workaround
-
content返回 0 块 bug:
- 现象:刚edit写入后立即content可能返回空
- workaround:等 1-2 秒,或用info查updated字段
- 状态:已知,未修复 -
嵌套 skill 目录问题:
- 现象:装其他 skill 时可能被嵌套到siyuan-skill-enhanced/skills/
- workaround:手动移动到~/skills/<name>/
- 检测:ls -d ~/skills/*/skills/ 2>/dev/null -
大文档 create 慢:
- 现象:>100KB 文档 create 很慢
- workaround:先空创建,重命名,再分次 update -
update大小写敏感:
- 现象:传--file路径大小写错不报错但失败
- workaround:用realpath取绝对路径
v2.2 更新日志(当前版本)
补全 3 个必需章节 + 补 frontmatter:
- 新增 ## When to Use(何时使用 + Don't use for)
- 新增 ## Verification Checklist(4 类验证项)
- 新增 ## 关键陷阱(从 1 个扩展到 7 个,完整版在 references/pitfalls.md)
- frontmatter 补 slug/license/platforms/metadata.hermes.related_skills(之前只有 tags)
字符数: 1,902 → 8,000+ 字符(从严重过小到同行范围内)
行为无变化:
- 所有命令、参数、行为完全一致
- 配置文件、API 调用、依赖关系不变
v2.1 更新日志(此前版本)
- 简化版 SKILL.md(仅保留 1 个核心 pitfall)