Keeps notes as local Markdown files grouped by directory under a root folder you choose, with a sidebar page, AGENTS-style rule files surfaced as writing context, and six agent tools.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:suomir1995/dsh-notes
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
English | 中文
A DeepSeek Harness plugin (bundle) that keeps your notes as local Markdown files, grouped by directory.
It is a DSH bundle in two halves:
- Host half (
index.js, plain ESM, no build step) — the read/write service for your notes. Choose a local directory as the root (default<DSH_HOME>/dsh-notes; switchable inside the page and remembered, no restart required); a direct subdirectory of the root is a group (second-level directory, created automatically when missing); an md file inside a group is a note; rule md files under the root or a group — AGENTS.md / CLAUDE.md / *.rules.md / *规则.md and the like — are read as convention context. Loopback + same-origin guarded routes serve the Web UI, and six agent tools are registered:note_root/note_list/note_rules/note_create/note_read/note_delete. - Client half (
src/client/*, built tolib/client.js) — the sidebar entry 「笔记」 opens a page: group list, rule viewer, note create (paste text) / view / edit / rename / delete, and switching the root directory.
Storage model (a directory is a group, an md file is a note)
<root>/ ← the local directory you chose (level 1)
AGENTS.md ← root-level rule file (optional, matched case-insensitively)
<group>/ ← level-2 directory = a group (created automatically if missing)
AGENTS.md ← that group's rule file (optional)
<note>.md ← one note (every other .md counts as a note)
Rule files = md files whose name matches (case-insensitive): AGENTS.md,
AGENTS.local.md, CLAUDE.md, *.rules.md, *规则.md / *規則.md. A note with the same
name cannot be created (that name is reserved for rules). Tolerant parsing: hand-written
plain Markdown can be dropped into a group as a note — a missing title falls back to the
file name, a missing group to the directory name; pasting a complete md file that already
carries front matter stores it verbatim and never wraps it twice.
Each note the plugin creates:
---
title: useState 笔记
group: 前端
created: 2025-01-01T00:00:00.000Z
updated: 2025-01-01T00:00:00.000Z
---
Body (any Markdown).
Features
- Groups = second-level directories under the root: list / create; writing a note creates the directory when the group does not exist.
- Notes: paste text or organized content → stored as
<group>/<note>.md; view / edit / rename / delete; the body is any Markdown. - Rule context: the AGENTS-style rule md files of the root and of each group are shown as
chips — click one to read it in full; before writing, the model can read the conventions
with
note_rulesand then file the note. - Root directory: switched inside the page, effective immediately and remembered (the
host stores the current path in
<DSH_HOME>/dsh-notes/.notes-root; an explicitrootDirin the config file takes precedence). - Agent tools:
note_root— view / switch the root directory;note_list— list the group overview, or list the notes inside one group;note_rules— read the root rules (plus a given group's rules) as writing context;note_create— create / update a note (the group is created automatically;update: trueoverwrites);note_read— read one note in full;note_delete— delete one note (removes only that md, never the group directory).
- Chinese UI; the sidebar entry DOM and visual language follow the skill center (36px
rounded row + 24px icon box, shell
--dsw-alias-*tokens, collapsible sidebar).
Layout
| Path | Purpose |
|---|---|
index.js |
Host half: group/note/rule read-write + agent tools + guarded routes |
cordis.patch.yml |
Bundle layer: host row notes |
src/client/* |
Browser half: sidebar entry + notes page overlay (React) |
lib/client.js |
Built client artifact (exports["./client"]) |
tsdown.config.ts |
Client build (closure-factory __ModuleLoader__ format) |
scripts/smoke-host.mjs |
Host-half smoke (md parsing/CRUD/rules/tools, isolated DSH_HOME) |
scripts/loader-boot.mjs |
Real Loader + webServer HTTP route smoke |
scripts/smoke-client.mjs |
Client artifact smoke (executes the closure in a stub browser) |
Build
The client half needs a build; the host half ships as plain ESM:
npm run build:client # tsdown → lib/client.js (+ map)
The tsdown binary comes from the DeepSeek Harness checkout. React is resolved through the
shell's module table (react, react-dom/client) and is never bundled. The smoke scripts
need @deepseek-ai/* to be resolvable locally (a temporary
ln -s ~/.dsh/profiles/node_modules node_modules, removed afterwards, is enough).
Install
dsh plugin --profile web add ./dsh-notes
This appends a dsh-notes layer; restart the profile afterwards (both host and client
changes require a restart):
pnpm dsh web
After the restart a「笔记」entry appears in the left sidebar. The default root directory is
<DSH_HOME>/dsh-notes (created automatically); use "switch directory" in the page to point
it at any absolute local path (~ is supported; leave it empty to restore the default).
Plugin config
All optional (defaults shown); override in the profile's own cordis.patch.yml:
- id: notes
config:
rootDir: '' # explicit root dir (absolute path / ~/…); empty = use the remembered one
maxRuleBytes: 524288 # single rule-file read limit
maxNoteBytes: 2097152 # single note read limit
maxBodyBytes: 1048576 # submitted note body limit
Host routes (all loopback + same-origin guarded)
| Route | Method | Purpose |
|---|---|---|
/api/notes/state |
GET | Root state (current path / config-pinned / exists) |
/api/notes/root |
PUT | Switch the root (empty = restore default) |
/api/notes/groups |
GET | Group overview (note count + rule file names in the group) |
/api/notes/group |
POST | Create a group directory |
/api/notes/rules?group= |
GET | Root (or group) rule file list |
/api/notes/rule?group=&file= |
GET | Read one rule file in full |
/api/notes/notes?group= |
GET | Note list of one group |
/api/notes/note?group=&file= |
GET / DELETE | Read / delete a note |
/api/notes/note/create |
POST | Create a note (group created automatically; duplicate name 409) |
/api/notes/note/update |
POST | Update a note (keeps created, refreshes updated) |
/api/notes/note/rename |
POST | Rename a note file |
Security boundaries
The browser reaches data only through the guarded routes above and never touches the disk
directly; group and note names are sanitized first (path-traversal characters and hidden
files rejected) and then, after resolve, checked to still be inside the root; switching
the root writes a dedicated pointer file; every Markdown write goes through a temp file +
atomic rename with a single-writer queue against concurrent corruption; a missing directory
is created automatically. Rule and note reads are byte-capped (413 when exceeded).
Remove
dsh plugin --profile web remove dsh-notes
Verification record
scripts/smoke-host.mjs(isolated DSH_HOME + temp root, no network) — all passed: front matter / note parsing and idempotent round-trips, tolerant parsing of hand-written md, a pasted whole md file stored verbatim (no double wrapping), name sanitizing and rejection of reserved rule names (AGENTS/CLAUDE/*rules/*规则), rule-file detection (root/group), group CRUD (duplicate name 409, auto-creation), note add/read/duplicate-name 409/in-place update (keepscreated)/rename (implicit title follows)/delete/repeat-delete 404, over-limit body 413,note_list/note_rules(root + group rule text) /note_create(auto-creates the group) /note_read/note_delete/note_root.scripts/loader-boot.mjs(real Cordis Loader +dsh-host-webserver, isolated DSH_HOME) — all passed: row loading, webServer binding, state/root switching and persistence, HTTP CRUD for groups/rules/notes, rule text reading, foreign-host 403, wrong method 405, unknown route 404, malformed JSON 400, invalid group name 400, deleting a missing note 404.scripts/smoke-client.mjs— all passed:lib/client.jsregistersdsh-notesas a__ModuleLoader__closure and exportsname: notes-ui / inject / apply; no machine paths leak; only module-table externals (the react family) are resolved.- Static preflight:
node …/dsh-plugin-development/scripts/check-artifact.mjs bundle .→ PASS, 0 warnings.
Links
More in this category
vectorize-io/hindsight#coding-agents★ 54464
Hindsight, agent memory that learns: long-term project memory with auto recall and retain, knowledge pages, deep reflection, and per-repo memory banks.
volcengine/OpenViking#examples/dsh-memory-plugin★ 40976
OpenViking memory and context bundle for DeepSeek Harness: pre-step auto-recall and profile injection, session capture, `viking://` URI guarding, and recall/write memory tools backed by an OpenViking server.
MemTensor/MemOS#memos-local-plugin★ 12136
Local-first memory plugin for DeepSeek Harness: layered L1/L2/L3 memory with automatic capture, manual memos_* retrieval tools, and a built-in memory viewer.
agentscope-ai/ReMe#dsh★ 3702
Connects DeepSeek Harness to ReMe's local-first, self-evolving personal knowledge base: automatically captures completed main-agent conversations as user-owned Markdown memory, searches conversations and source material through reme_search with BM25, optional embeddings, and wikilink expansion, and schedules daily memory consolidation.
zilliztech/memsearch#MemSearch★ 2802
Shared Markdown memory for DSH and other coding agents, with automatic capture, pre-step context injection, searchable recall, and memory-to-skill self-evolution through a review panel.
vshulcz/deja-vu#extensions/dsh★ 1321
Reads the session files forty-two other coding agents on this machine already wrote (Claude Code, Codex, Cursor, VS Code Copilot Chat, opencode, OpenClaw, Hermes, Kimi, Cline, Zed and more), including sessions from before it was installed: six tools (deja_recall, deja_session, deja_blame, deja_fix, deja_how, deja_remember), a /deja command, and optional automatic recall added to the runtime context. Local BM25 index, no LLM, no embeddings, no network (dsh plugin --profile web add dsh-deja).
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.