DeepSeek Harness 插件

dsh-zotero-wiki

A DeepSeekHarness plugin that turns your Zotero library into a citation-aware Obsidian wiki: sync, MinerU PDF parsing, DeepSeek notes, topic reviews and query tools.(英文原文)

跳到安装方式

来源信息

GitHub 仓库
Wechsels/dsh-zotero-wiki
最近更新
2026年8月15日
分类
文档与渲染
GitHub stars
3
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/Wechsels/dsh-zotero-wiki
插件名:dsh-zotero-wiki
作者:Wechsels

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

dsh-zotero-wiki

> 中文 | [English](#english)

DeepSeekHarness(dsh)× Zotero 插件:自动同步 Zotero 文献库,用 MinerU 解析 PDF、用 DeepSeek 阅读全文,把文献编译成可检索的 Obsidian Wiki,并让 Agent 在回答时附带可追溯的文献引用。

[![][node-badge]][node-link] [![][license-badge]][license-link] [![][repo-badge]][repo-link]

[node-badge]: https://img.shields.io/badge/Node.js-%3E%3D22.19-339933?logo=node.js&logoColor=white [node-link]: https://nodejs.org [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg [license-link]: ./LICENSE [repo-badge]: https://img.shields.io/badge/GitHub-Wechsels%2Fdsh--zotero--wiki-181717?logo=github [repo-link]: https://github.com/Wechsels/dsh-zotero-wiki

---

项目定位(范围)

是什么:一个 Node/Cordis 风格的 dsh 插件 + 独立 CLI。它把你的 Zotero 文献库变成一座持续更新的 Obsidian 知识库,并暴露原生工具供 Agent 检索。

完整链路

Zotero(本地库 / Web API)
  └─ sync:增量同步元数据 → .zotero-sync/sync.db(SQLite 状态库)
      └─ parse:MinerU 官方平台解析 PDF → raw/<topic>/<bundle>/ 原文 + DeepSeek 笔记(<key>-note.md 同束存放)
          └─ compile:主题综述(_index.md)、索引、交叉链接、归档标记
              └─ query:Agent 通过 query_zotero_wiki 检索 raw 笔记,回答附 [Zotero key, §章节] 引用

明确不做(保持轻量):向量数据库、自动聚类、多用户服务端、定时后台服务、Web UI、Zotero 注释(高亮/批注)同步、引用页码提取。

---

特性

| 能力 | 说明 | |---|---| | 双源同步 | 本地 zotero.sqlite(临时副本只读打开,不干扰 Zotero 进程)或 Zotero Web API(version 游标增量) | | 交互式范围 | 全部 / 指定 Collection(含子级)/ 标签过滤,选择结果持久化,启动时静默复用 | | PDF 智能解析 | MinerU 官方开放平台(上传→轮询→Zip),解析产物落为 raw/ bundle(Markdown + images/),原始 PDF 不落盘 | | DeepSeek 全文笔记 | deepseek-chat 全文直读(100K token 上限、尾部截断),产出中文结构化笔记(摘要/方法/结论/创新点/局限/关键引用) | | 优雅降级 | 无 PDF 或解析失败 → 基于标题+摘要生成简版笔记;后续补 PDF 自动升级全文笔记 | | 配额与并发 | 单轮解析上限 MAX_PARSE_PER_SYNC(默认 50),并发 3,失败记库、下轮可重跑;支持 topic/collection/keys/limit 过滤(keys > collection > topic 优先级) | | 解析预览 | parse_zotero_wiki 无参数调用只返回候选统计与样本(pending/failed/placeholder-upgrade,MinerU 零调用),确认后再执行 | | Wiki 编译 | 主题综述(LLM 增量改写)、index/authors/years 索引(index 表格含作者/DOI/Updated 列)、See Also 交叉链接(bundle 间相对路径)、归档标记(不删笔记)、追加式 log(## [YYYY-MM-DD] <op> | <summary>) | | LINT 自检 | 四类确定性检查(索引一致性 / 内部链接 / raw 引用 / 图片链接与孤儿图),compile 末尾自动 auto-fix,CLI 可单独运行 lint [--report-only] | | 查询归档 | archive_zotero_query 工具把问答归档为 wiki 归档页(含参考文献表格),联动更新 index 与 log | | Agent 查询 | minisearch 内存全文检索 + 中文 bigram 分词,返回片段与 [key, §章节] 章节级引用;无命中明确告知,不编造 |

---

当前状态与路线图

里程碑内容状态
M1Zotero 双源读取与增量同步✅ 已落地并通过真实库验收
M2MinerU 解析 + DeepSeek 笔记生成✅ 已落地并通过真实环境验收(7 篇全文笔记 + 37 篇摘要降级,0 失败)
M3主题归类与 Wiki 生成✅ 已落地并通过真实环境验收(deepseek-v4-flash 综述生成 + 幂等二跑)
M4dsh 插件集成与查询工具✅ 已落地并通过 dsh 真机联调
M5测试、打包、文档完善进行中
改进方案 1wiki 职责收窄(bundle 双文件写盘)、archive/LINT/migrate、parse 过滤与预览、首次配置向导✅ 已落地(阶段 A–E,typecheck + 120 单测 + CLI 冒烟)

路线图中(不阻塞使用):向量检索增强、Zotero 注释同步、引用页码提取、术语表、定时同步。问题与建议请提 Issues

---

架构

┌────────────────────┐      ┌─────────────────────────────────────────┐
│  Zotero 桌面端      │ ───▶ │ dsh-zotero-wiki                          │
│  / Zotero Web API  │      │                                          │
└────────────────────┘      │  sync 引擎 ──▶ SQLite 状态库             │
                            │  parse 管道 ─▶ MinerU + DeepSeek        │
┌────────────────────┐      │  compile 器 ─▶ 综述/索引/链接/归档       │
│ MinerU 官方平台     │ ◀──▶ │  query 索引 ─▶ minisearch + bigram      │
│ DeepSeek API       │      │                                          │
└────────────────────┘      │  dsh 工具:query / sync / parse          │
                            └────────────────┬────────────────────────┘
                                             ▼
                            ┌─────────────────────────────────────────┐
                            │ Obsidian Vault                           │
                            │  raw/(解析源文件) wiki/(笔记与索引)   │
                            │  references/(模板) .zotero-sync/(状态)│
                            └─────────────────────────────────────────┘

生成的 Vault 结构:

<Vault>/
├── raw/<topic>[/<subtopic>]/YYYY-MM-DD-<slug>/
│   ├── <key>.md            # 原文(全文或占位,frontmatter status: pending|fulltext)
│   ├── <key>-note.md       # LLM 笔记(type: note)
│   └── images/             # MinerU 图片(如有)
├── references/             # 5 个模板(只补缺不覆盖)
├── wiki/                   # 仅 compile 与 query 产物
│   ├── index.md / authors.md / years.md / log.md
│   └── <topic>/
│       ├── _index.md       # 主题综述(compile,含文献列表 + 参考文献表格)
│       └── <slug>.md       # archive 归档页(query 按需生成,仅 type: archive)
└── .zotero-sync/sync.db    # 同步游标、条目、处理状态(不入 git)

---

安装

环境要求

  • Node.js ≥ 22.19(使用内置 node:sqlite
  • Zotero 本地库或 Web API Key
  • (parse 阶段)MinerU Token(mineru.net API 管理页申请)与 DeepSeek API Key

从源码安装(MVP 阶段推荐)

git clone https://github.com/Wechsels/dsh-zotero-wiki.git && cd dsh-zotero-wiki
npm install
cp .env.example .env     # 然后按需编辑,见下方配置
npm run build

注册为 dsh 插件(本地路径安装)

npx -y @deepseek-ai/dsh plugin --profile web add file:/path/to/dsh-zotero-wiki

插件加载后:dsh 启动时自动静默增量同步并重建查询索引;聊天中即可调用三个原生工具。

---

配置

所有配置在插件目录下的 .env(参见 .env.example)。首次运行任意 CLI 命令时,若缺少必要配置会自动弹出交互式配置向导--no-wizard 可跳过,此时打印缺失清单并退出):

必填默认说明
ZOTERO_MODElocallocal / web
ZOTERO_DATA_DIRlocal 可选自动探测zotero.sqlitestorage/ 的目录
ZOTERO_API_KEY / ZOTERO_USER_ID / ZOTERO_GROUP_IDweb 必填Web API 凭据(Group 优先于 User)
OBSIDIAN_VAULT_PATHVault 根目录
SYNC_SCOPE_JSON交互选择持久化同步范围,如 {"mode":"all","collectionKeys":[],"tags":[]}
MINERU_TOKENparse 必填MinerU 官方平台 Token
MINERU_MODEL_VERSIONpipeline可选 vlm(质量更高)
MINERU_TIMEOUT_MS1200000单文件解析超时
DEEPSEEK_API_KEYparse/综述必填DeepSeek API Key
DEEPSEEK_MODELdeepseek-chat全文笔记生成模型
REVIEW_MODELdeepseek-v4-flash主题综述生成模型(compile)
NOTE_TOKEN_LIMIT100000每篇全文截断上限(按字符保守估算)
MAX_PARSE_PER_SYNC50单轮最多上传解析篇数(保护 MinerU 免费额度)
PARSE_CONCURRENCY3解析并发上限
REVIEW_REGEN_THRESHOLD5综述累计新增 N 篇后全量重生成
REVIEW_NOTE_CHARS2000综述生成时每篇笔记送入 LLM 的字数上限

---

用法

CLI(完整能力,首次配置入口)

node dist/cli.js sync                  # 增量同步;首次弹交互选择范围并持久化
node dist/cli.js sync --interactive    # 重新选择同步范围

node dist/cli.js parse --dry-run       # 预览待解析候选(≈ 预览模式,零外部调用)
node dist/cli.js parse --topic T       # 限定主题目录(支持两级如 A/B)
node dist/cli.js parse --collection C  # 限定 Collection(名称/key,含子合集)
node dist/cli.js parse --keys K1,K2    # 限定 Zotero key 列表(最精确)
node dist/cli.js parse --limit N       # 本次解析篇数上限(与配额取小)
node dist/cli.js parse                 # MinerU 解析 + DeepSeek 笔记生成

node dist/cli.js compile               # 综述/索引/交叉链接/归档标记(末尾自动 LINT)
node dist/cli.js compile --no-review   # 跳过 LLM 综述(无需 DEEPSEEK_API_KEY)

node dist/cli.js lint                  # LINT 检查 + auto-fix
node dist/cli.js lint --report-only    # 仅报告,不修改文件

node dist/cli.js migrate               # 存量迁移 dry-run(旧 wiki 单篇页 → raw bundle 计划表)
node dist/cli.js migrate --apply       # 执行迁移(写入 bundle 笔记、删除旧页面),随后运行 compile 重建索引
# 任意命令加 --no-wizard 可跳过首次配置向导(打印缺失清单并退出)

dsh 原生工具(Agent 侧)

工具说明
query_zotero_wiki(query, topic?, max_results?)检索 Wiki,返回片段、元数据与 [Zotero key, §章节] 引用;无命中返回"当前 Wiki 中没有找到相关文献"
sync_zotero_wiki()手动增量同步并重建索引
parse_zotero_wiki(topic?, collection?, keys?, limit?)无参数时仅返回候选预览(零 MinerU 调用)请用户确认;带参数执行解析与笔记生成(受配额限制)并重建索引
archive_zotero_query(title, body, topic?, source_keys?)把查询回答归档为 wiki 归档页(含参考文献表格),联动更新 index 与 log

典型对话:*"帮我总结荧光材料方向这几年的进展"* → Agent 调用 query_zotero_wiki → 基于命中片段与引用编制回答。

同步行为约定

  • 启动自动同步按上次持久化的范围静默执行;交互选择只在首次或手动 --interactive 时出现
  • 已有 bundle 更新/扩充,新文献新增,log.md 追加;永不物理删除笔记——Zotero 中删除的条目在笔记中标记 status: archived,恢复后自动复原
  • 未归入任何 Collection 的文献跳过,待用户在 Zotero 中分类后下轮处理
  • 一篇文献属于多个 Collection:每个主题各生成一份自包含 bundle(raw/<topic>/…/),processed.note_paths 记录各主题笔记的 raw 相对路径

---

开发

npm run typecheck   # tsc --noEmit
npm test            # vitest(18 个测试文件 / 82 个用例)
npm run build       # vite → dist/cli.js + dist/plugin.js
npm run dev         # 监听构建
src/
├── cli.ts          # CLI(sync / parse / compile)
├── plugin.ts       # dsh 集成层(工具注册 + 启动 sync,依赖注入可测)
├── config.ts       # .env 加载与回写
├── sources/        # Zotero 双源(local sqlite / Web API)
├── sync/           # 同步引擎与 scope 过滤
├── parse/          # MinerU 客户端、Zip 解包、单篇 pipeline(bundle 写盘)
├── llm/            # DeepSeek 客户端、prompts、截断
├── compile/        # 综述、索引、See Also、归档、参考文献表格、日志
├── query/          # minisearch 索引(raw 笔记 + _index/archive)、bigram 分词、检索
├── wiki/           # topic 映射、bundle 写盘(<key>.md + <key>-note.md)、frontmatter、模板
└── state/          # SQLite 状态库
dsh/index.js        # 插件薄壳 → dist/plugin.js

---

常见问题

Q:启动时提示 "SYNC_SCOPE_JSON 未配置"? 在终端运行一次 node dist/cli.js sync 完成交互式范围选择;dsh 运行环境无交互终端,首次配置必须走 CLI。

Q:首次运行提示缺少配置? CLI 在交互终端会启动配置向导逐项引导(Zotero 模式、数据目录/API Key、Vault 路径、MinerU/DeepSeek Token);非交互环境(含 dsh 工具)返回结构化缺失清单(configured: false + missing[],含 where_to_get 指引)。

Q:本地模式提示找不到 Zotero 数据目录?.env 显式设置 ZOTERO_DATA_DIR 指向含 zotero.sqlite 的目录(如 D:\ZoteroLibrary)。

Q:parse 很慢 / 部分篇目一直是 pending? MinerU 免费额度为每日 2000 页高优先级,超出后排队降速;调小 MAX_PARSE_PER_SYNC 分多轮执行即可。

Q:中文查询效果不理想? 当前为 bigram 分词的关键词检索(零原生依赖);可尝试更具体的关键词或加 topic 过滤。向量检索增强在路线图中。

Q:npx @deepseek-ai/dsh 报 'dsh' 不是内部或外部命令? npx 在部分 Windows 环境下无法生成可执行 shim。改用本地 dsh 源码仓的 CLI 入口即可:node <dsh 仓库>/apps/cli/lib/bin.js plugin --profile web add file:/path/to/dsh-zotero-wiki

Q:dsh 启动报 Cannot find module .../dist/plugin.js? 本地 file: 安装时 pnpm 打包会遵守 .gitignore;确保 package.jsonfiles 字段显式包含 dist(本仓库已配置)。

Q:能在 Obsidian 里手动编辑笔记吗? 可以。只有 ## See Also 章节、索引页(index/authors/years)与归档提示块会被自动重写,其余内容不受影响。

许可证 / License

[MIT](./LICENSE)

--- ---

<a id="english"></a>

dsh-zotero-wiki

> [中文](#dsh-zotero-wiki) | English

A DeepSeekHarness (dsh) plugin for Zotero: automatically syncs your Zotero library, parses PDFs with MinerU, reads full texts with DeepSeek, compiles everything into a searchable Obsidian wiki, and lets your agent answer questions with traceable literature citations.

---

Positioning & Scope

What it is: a Node/Cordis-style dsh plugin plus a standalone CLI that turns your Zotero library into a continuously updated Obsidian knowledge base, exposing native tools for agent retrieval.

Full pipeline:

Zotero (local DB / Web API)
  └─ sync: incremental metadata sync → .zotero-sync/sync.db (SQLite state)
      └─ parse: MinerU PDF parsing → raw/<topic>/<bundle>/ originals + DeepSeek notes (<key>-note.md co-located in the bundle)
          └─ compile: topic reviews (_index.md), indexes, cross-links, archive marks
              └─ query: agents search raw notes via query_zotero_wiki, answers cite [Zotero key, §section]

Explicitly out of scope (kept lightweight): vector databases, automatic clustering, multi-user server, scheduled background services, Web UI, Zotero annotation/highlight sync, page-number citations.

Constitution deviation: topic directories are kept to two levels (A/B; deeper nesting collapses into the second level), unlike the full-path convention in CLAUDE.md; see the raw//wiki/ layout below.

---

Features

| Feature | Description | |---|---| | Dual-source sync | Local zotero.sqlite (read-only temp copy, never blocks Zotero) or Zotero Web API (version-cursor incremental) | | Interactive scope | All / specific Collections (incl. children) / tag filter; the choice is persisted and silently reused at startup | | PDF parsing | MinerU official open platform (upload → poll → zip); results stored as raw/ bundles (Markdown + images/); original PDFs are never persisted | | DeepSeek notes | deepseek-chat full-text reading (100K-token cap, tail truncation) producing structured Chinese notes (abstract / method / conclusions / contributions / limitations / key quotes) | | Graceful degradation | No PDF or parse failure → concise note from title + abstract; automatically upgraded to a full-text note once a PDF is added | | Quota & concurrency | Per-run parse cap MAX_PARSE_PER_SYNC (default 50), concurrency 3, failures recorded and retryable next run; topic/collection/keys/limit filters (keys > collection > topic priority) | | Parse preview | parse_zotero_wiki with no args returns candidate stats & samples (pending/failed/placeholder-upgrade, zero MinerU calls); execute after confirmation | | Wiki compile | LLM topic reviews (incremental rewrite), index/authors/years pages (index table with author/DOI/Updated columns), See Also cross-links (bundle-relative), archive marks (no note deletion), append-only log (## [YYYY-MM-DD] <op> | <summary>) | | LINT self-check | Four deterministic checks (index consistency / internal links / raw refs / image links & orphans); auto-fix at the end of compile; standalone lint [--report-only] CLI | | Query archiving | archive_zotero_query tool archives an answer as a wiki archive page (with a reference table) and updates index + log | | Agent query | minisearch in-memory full-text search with Chinese bigram tokenization; returns snippets with [key, §section] citations; explicitly reports "not found", never fabricates |

---

Status & Roadmap

MilestoneScopeStatus
M1Zotero dual-source reading & incremental sync✅ landed, verified against a real library
M2MinerU parsing + DeepSeek note generation✅ landed, verified in a real environment (7 full-text notes + 37 abstract fallbacks, 0 failures)
M3Topic compilation & wiki generation✅ landed, verified in a real environment (deepseek-v4-flash reviews + idempotent re-run)
M4dsh plugin integration & query tools✅ landed, verified with a real dsh installation
M5Testing, packaging, documentationin progress
Improvement plan 1Narrowed wiki role (bundle dual-file writes), archive/LINT/migrate, parse filters & preview, first-run config wizard✅ landed (stages A–E; typecheck + 120 unit tests + CLI smoke)

On the roadmap (non-blocking): vector retrieval, Zotero annotation sync, page-number citations, glossary, scheduled sync. Please file issues and suggestions on GitHub Issues.

---

Installation

Requirements

  • Node.js ≥ 22.19 (uses built-in node:sqlite)
  • A local Zotero library or a Zotero Web API key
  • (for parse) a MinerU token (from mineru.net) and a DeepSeek API key

Install from source (recommended during MVP)

git clone https://github.com/Wechsels/dsh-zotero-wiki.git && cd dsh-zotero-wiki
npm install
cp .env.example .env     # then edit; see Configuration below
npm run build

Register as a dsh plugin (local-path install)

npx -y @deepseek-ai/dsh plugin --profile web add file:/path/to/dsh-zotero-wiki

Once loaded, dsh silently runs an incremental sync at startup and rebuilds the query index; the three native tools become available in chat.

---

Configuration

All settings live in .env inside the plugin directory (see .env.example). On first run, any CLI command with missing required settings launches an interactive setup wizard (add --no-wizard to skip and print the missing list instead). Key entries:

KeyRequiredDefaultPurpose
ZOTERO_MODEyeslocallocal / web
ZOTERO_DATA_DIRlocal, optionalauto-detectDirectory containing zotero.sqlite and storage/
ZOTERO_API_KEY / ZOTERO_USER_ID / ZOTERO_GROUP_IDwebWeb API credentials (Group wins over User)
OBSIDIAN_VAULT_PATHyesVault root
SYNC_SCOPE_JSONnointeractivePersisted sync scope, e.g. {"mode":"all","collectionKeys":[],"tags":[]}
MINERU_TOKENparseMinerU official platform token
MINERU_MODEL_VERSIONnopipelinevlm for higher quality
DEEPSEEK_API_KEYparse/reviewsDeepSeek API key
DEEPSEEK_MODELnodeepseek-chatModel for full-text note generation
REVIEW_MODELnodeepseek-v4-flashModel for topic review generation (compile)
NOTE_TOKEN_LIMITno100000Per-paper truncation cap (conservative char-based estimate)
MAX_PARSE_PER_SYNCno50Max uploads per run (protects MinerU free quota)
PARSE_CONCURRENCYno3Parse concurrency
REVIEW_REGEN_THRESHOLDno5Regenerate a topic review after N accumulated new notes

---

Usage

CLI (full capabilities; first-run configuration entry point)

node dist/cli.js sync                  # incremental sync; interactive scope picker on first run
node dist/cli.js sync --interactive    # re-select sync scope

node dist/cli.js parse --dry-run       # preview pending candidates (≈ preview mode, zero external calls)
node dist/cli.js parse --topic T       # restrict to a topic directory (two levels, e.g. A/B)
node dist/cli.js parse --collection C  # restrict to a collection (name/key, includes children)
node dist/cli.js parse --keys K1,K2    # restrict to the given Zotero keys (most precise)
node dist/cli.js parse --limit N       # cap items parsed this run (min with quota)
node dist/cli.js parse                 # MinerU parsing + DeepSeek note generation

node dist/cli.js compile               # reviews / indexes / cross-links / archive marks (auto-LINT at the end)
node dist/cli.js compile --no-review   # skip LLM reviews (no DEEPSEEK_API_KEY needed)

node dist/cli.js lint                  # LINT checks + auto-fix
node dist/cli.js lint --report-only    # report only, no file changes

node dist/cli.js migrate               # legacy migration dry-run (old wiki paper pages → raw bundle plan)
node dist/cli.js migrate --apply       # execute migration (write bundle notes, delete old pages), then run compile
# any command accepts --no-wizard to skip the first-run config wizard (prints the missing list and exits)

dsh native tools (agent side)

ToolDescription
query_zotero_wiki(query, topic?, max_results?)Search the wiki; returns snippets, metadata and [Zotero key, §section] citations; replies "nothing found in the wiki" when empty
sync_zotero_wiki()Manual incremental sync + index rebuild
parse_zotero_wiki(topic?, collection?, keys?, limit?)With no args returns a candidate preview (zero MinerU calls) for confirmation; with args runs parse & note generation (quota-limited) + index rebuild
archive_zotero_query(title, body, topic?, source_keys?)Archive an answer as a wiki archive page (with a reference table), updating index + log

Sync behavior contract

  • Startup sync silently reuses the last persisted scope; interactive selection only happens on first run or with --interactive
  • Existing bundles are updated/extended, new items create new bundles, log.md is append-only; notes are never physically deleted — items removed from Zotero get status: archived on the note and are auto-restored if they come back
  • Items without any Collection are skipped until classified in Zotero
  • An item in multiple Collections: one self-contained bundle per topic (raw/<topic>/…/); processed.note_paths tracks each topic note's raw-relative path

---

Development

npm run typecheck   # tsc --noEmit
npm test            # vitest (18 test files / 82 cases)
npm run build       # vite → dist/cli.js + dist/plugin.js
npm run dev         # watch build

---

FAQ

Q: Startup says "SYNC_SCOPE_JSON not configured"? Run node dist/cli.js sync once in a terminal to complete the interactive scope selection; the dsh runtime has no interactive TTY, so first-time configuration must go through the CLI.

Q: First run complains about missing settings? On an interactive t