dsh-joplin
Identified★ 1Joplin notes plugin for DeepSeek Harness: search, read and (opt-in) edit notes via the local Web Clipper API. Zero runtime dependencies.
dsh-joplin
Joplin notes plugin for DeepSeek Harness — let the agent read and write your local Joplin notes: search, full-text read, create, notebook management, backlinks. Read-only by default, zero runtime dependencies.
Features
- Zero dependencies: Node built-ins only (
node:http/node:fs) — no Python, no uv, no long-running sidecar, no build step. - 10 tools: search, read full text, create notes/notebooks, import Markdown, outgoing/back links, diagnostics.
- Least privilege by default: create on, update and delete off; when a capability is off the tool throws before any request is sent, so Joplin is never touched.
- Privacy first: connects only to the local address you configure, no uploads, no telemetry; it also installs a standing prompt rule that forbids sending note content anywhere else.
- Notebook paths: accept full paths such as
Work/ProjectA, ids, or unique titles; ambiguity is reported instead of guessed. - Search fallback: when Joplin's full-text endpoint hangs, the plugin falls back to a local scan and marks the result with
engine. - Write verification: every write is read back and compared, so a corrupted body fails loudly instead of silently.
Requirements
- Joplin desktop installed and running;
- The Web Clipper service enabled under "Tools → Options → Web Clipper" (default port
41184); - The API token copied from that same page;
- Node.js >= 20 on the DSH (DeepSeek Harness) host side.
Only Joplin desktop's Web Clipper data API is supported. Joplin Cloud and the mobile apps expose different APIs and do not work.
Install
Option 1: npm registry (dsh-joplin)
plugin_manager(action: "install_bundle", target: "dsh-joplin")
or:
dsh plugin --profile <profile> add dsh-joplin
Option 2: from GitHub
Have DSH install the repository into your profile directly:
plugin_manager(action: "install_bundle", target: "github:ddssh/dsh-joplin")
Option 3: local directory
git clone https://github.com/ddssh/dsh-joplin.git
Then pass that directory as target to install_bundle, or:
dsh plugin --profile <profile> add /absolute/path/to/dsh-joplin
The joplin_* tools are registered after install. This is a pure Host plugin with no client half, so a restart is usually unnecessary — but restarting is required after editing the plugin's JS (Node caches imported modules).
Configuration
Settings are resolved from three layers, highest priority first, and the first non-empty value wins:
| Priority | Source | Notes |
|---|---|---|
| 1 | ~/.dsh/joplin.json | Recommended: takes effect immediately, keeps the token out of your profile YAML |
| 2 | Env vars JOPLIN_TOKEN, JOPLIN_BASE_URL, JOPLIN_TIMEOUT_MS, JOPLIN_DEFAULT_NOTEBOOK, JOPLIN_ALLOW_CREATE / JOPLIN_ALLOW_UPDATE / JOPLIN_ALLOW_DELETE | Requires a Harness restart |
| 3 | Plugin config (Settings / cordis.patch.yml in the profile) | baseUrl, token, timeoutMs, defaultNotebook, allowCreate, allowUpdate, allowDelete |
Minimal setup:
cat > ~/.dsh/joplin.json <<'JSON'
{
"token": "your-web-clipper-token",
"baseUrl": "http://127.0.0.1:41184"
}
JSON
chmod 600 ~/.dsh/joplin.json
Optional fields: defaultNotebook (where new notes go, e.g. Work/ProjectA), timeoutMs, and allowCreate / allowUpdate / allowDelete.
Once configured, call joplin_status first: it reports which layer the token came from, whether the service is reachable, and how many notebooks exist.
Tools
| Tool | What it does | Default permission |
|---|---|---|
joplin_status | Diagnostics: token source, connectivity, notebook count, recent updates | read-only |
joplin_list_notebooks | Notebook tree with full paths and ids | read-only |
joplin_search_notes | Keyword search with snippets; empty query + notebook lists that notebook | read-only |
joplin_get_note | Full note: body, notebook, tags, internal links | read-only |
joplin_find_linked_notes | Outgoing and back links via internal links :/<id> | read-only |
joplin_create_note | Create a note (optionally in a notebook, optionally a todo) | allowCreate (on) |
joplin_create_notebook | Create a notebook or sub-notebook | allowCreate (on) |
joplin_import_markdown | Import a local .md file as a note | allowCreate (on) |
joplin_update_note | Change title/body/notebook/todo, only the fields you pass | allowUpdate (off) + user_confirmed |
joplin_delete_note | Delete; to trash by default, permanent with permanent: true | allowDelete (off) + user_confirmed |
Notebook arguments accept a 32-character id, a unique title, or a full path (Work/ProjectA); ambiguous input raises an error listing the candidates.
Permissions and privacy
Three write permissions (least privilege by default)
| Capability | Setting | Default |
|---|---|---|
| Create notes / notebooks / import Markdown | allowCreate | on |
| Modify existing notes (title/body/notebook/todo) | allowUpdate | off |
| Delete notes | allowDelete | off |
- When a capability is off, the tool throws without sending any write request.
- With update/delete enabled, the caller must additionally pass
user_confirmed: true, meaning the user explicitly asked for that note in this turn. - Resolution order is "config file > env vars > plugin config > defaults", so tightening a permission is never blocked by a stale setting.
{ "token": "…", "allowUpdate": true }
Privacy
- Connects only to the configured
baseUrl(defaulthttp://127.0.0.1:41184), no uploads, no telemetry. - Installs a standing prompt rule (
JOPLIN_NOTES) requiring note bodies and snippets to stay away from web search, the browser, subagents, and other tools. - Markdown imports send file contents only to the local Joplin instance.
Known issues (Joplin side)
Both were reproduced on Joplin desktop 3.7.18; the plugin works around them:
- Full-text search can hang:
GET /search?query=…may never return, whiletitle:search,/folders, and/notesstay fast. The plugin falls back to a local scan after 8 seconds (about 13 ms for 260 notes) and skips the stuck endpoint for 10 minutes;mode: "local"forces the local scan. - Large bodies get corrupted on write: when the request body contains raw multi-byte UTF-8 and is large enough, roughly one
U+FFFDappears per 16 KB of body text (client-independent; reproducible with Python as well). The plugin ASCII-escapes every outbound JSON payload (\uXXXX) and reads the note back after writing; a mismatch raisesWRITE_VERIFY_FAILEDinstead of silently corrupting the note.
Development and testing
npm test # starts an in-memory mock Joplin and exercises all 10 tools
The smoke test covers notebook tree/path resolution, keyword search, listing notes by notebook, full-text read, outgoing/back links, create/update/delete, sub-notebook creation, Markdown import, the three configuration layers, the permission gates (update/delete refused by default without touching disk, user_confirmed validation), search failure fallback, and ASCII escaping.
Layout
dsh-joplin/
├── package.json # bundle manifest: dsh.bundle.patch / icon / locale
├── cordis.patch.yml # inserts the Host plugin row (id: dsh-joplin)
├── index.js # Config (schemastery) + apply: tools and prompt rules
├── joplin-tools.js # settings resolution, notebook resolution, search/link graph, tool definitions
├── joplin-client.js # node:http client (timeouts, error translation, ASCII escaping)
├── icon.svg / locale/ # plugin card presentation
└── test/ # mock Joplin server + smoke test
Credits
The capability set follows dweigend/joplin-mcp-server (Python + FastMCP). This plugin is a native Node rewrite for DSH: it keeps CRUD, the notebook tree, Markdown import, and backlinks, and adds permission gates, search fallback, and write verification, while fixing the original's notebook-path degradation when the API returns a flat list.
License
Comments
Loading…
From the same category
by awesome-dsh-plugin
A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表
★ 20.7k
CC0-1.0
Python
Oct 25, 2026
by 0xsline
DeepSeek Harness (DSH) ecosystem: curated plugins, tools, and infrastructure from dsh-external/hub and the public dsh-plugin topic.
★ 1.3k
CC0-1.0
Python
Oct 16, 2026
by pax-beehive
Open-source CLI, schemas, resolver, and DSH agent tools for DSH Plugin Hub
★ 277
MIT
TypeScript
Oct 20, 2026
by xiajiajun516
DeepSeek Harness (DSH) backup & restore plugin — export, import, migrate and sync your complete DSH configuration, plugins, MCP servers, skills and workspace. One-click migration to another machine.
★ 245
MIT
TypeScript
Oct 25, 2026
dsh plugin --profile web add dsh-config-managerby Yuuyuko-uu
DSH 鱼的记忆:给会话一份会淡忘的长期记忆,每条都带时间
★ 210
MIT
JavaScript
Oct 25, 2026
dsh plugin --profile web add dsh-fish-memoryby yjh051108
推荐组件(非必须):DeepSeek Harness 运行时注入器;已随 dsh-routing-suite 单仓库化保留,本仓库继续维护/发布。
★ 167
TypeScript
Oct 16, 2026
dsh plugin --profile web add @dsh-external/dsh-super-injector