Passer au contenu principal
S

dsh-notes

suomir1995/dsh-notes

Conserve des notes Markdown locales, classées par dossier sous une racine choisie, avec une page dans la barre latérale. Les fichiers de règles de type AGENTS sont proposés comme contexte de rédaction ; six outils Agent sont inclus.

Installer

dsh plugin --profile web add github:suomir1995/dsh-notes

README

dsh-notes — Notes

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 to lib/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_rules and 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 explicit rootDir in 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: true overwrites);
    • 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

PathPurpose
index.jsHost half: group/note/rule read-write + agent tools + guarded routes
cordis.patch.ymlBundle layer: host row notes
src/client/*Browser half: sidebar entry + notes page overlay (React)
lib/client.jsBuilt client artifact (exports["./client"])
tsdown.config.tsClient build (closure-factory __ModuleLoader__ format)
scripts/smoke-host.mjsHost-half smoke (md parsing/CRUD/rules/tools, isolated DSH_HOME)
scripts/loader-boot.mjsReal Loader + webServer HTTP route smoke
scripts/smoke-client.mjsClient 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)

RouteMethodPurpose
/api/notes/stateGETRoot state (current path / config-pinned / exists)
/api/notes/rootPUTSwitch the root (empty = restore default)
/api/notes/groupsGETGroup overview (note count + rule file names in the group)
/api/notes/groupPOSTCreate a group directory
/api/notes/rules?group=GETRoot (or group) rule file list
/api/notes/rule?group=&file=GETRead one rule file in full
/api/notes/notes?group=GETNote list of one group
/api/notes/note?group=&file=GET / DELETERead / delete a note
/api/notes/note/createPOSTCreate a note (group created automatically; duplicate name 409)
/api/notes/note/updatePOSTUpdate a note (keeps created, refreshes updated)
/api/notes/note/renamePOSTRename 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 (keeps created)/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.js registers dsh-notes as a __ModuleLoader__ closure and exports name: 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.

Plugins associés