DSH Plugins Marketplace

DSH Plugins

Plugins

/

Terminal & Clients

/

@adamcjm/dsh-memo

@

@adamcjm/dsh-memo

Manifest valid

Memo plugin for DeepSeek Harness: sidebar quick capture, local SQLite storage, private GitHub repo sync, and image/screenshot support.

UI (client)hasBundlePatch

dsh-memo

中文 | English

A memo/scratchpad plugin for DeepSeek Harness — sidebar entry with quick capture, local SQLite storage, sync to a private GitHub repository, and image/screenshot support.

Built for the moment a requirement changes mid-conversation: capture it in seconds, find it later, keep the context, never lose it.

Capture a note; it syncs to GitHub
Type it, press Enter — thirty seconds later it is in your private GitHub repository

Main panelCapturing with images
Main panelCapturing
Search across everythingGitHub sync settings
SearchSettings

Features

Sidebar entryBottom-rail icon next to Settings, with an open-items badge; click to switch to the memo panel
Quick captureAlways-present input at the top of the panel; Enter saves; the box is drag-resizable
Images & screenshots⌘V paste / drag-and-drop / file picker (multi-select); content-hash deduplicated, one copy per image
EditableInline editing on the card — body and images both; tags follow the #tags in the body, images can be added/removed one by one
TagsType #anything in the body and it is created automatically — not a fixed whitelist
PinningPinned notes sort first and show a pin badge plus a left accent bar on the card; the pin button lights up too
Drag & dropHold and drag a card to reorder it within the same day group, with transition animation (inlined SortableJS)
Ascending / descendingOne button right of the Pinned chip flips the date direction: descending = today on top, ascending = oldest on top; day groups only — order inside a day never moves, and the choice is remembered locally
SearchCJK-safe substring search plus #tag / source: / after: / before: / has:image / is:open qualifiers
Local storagenode:sqlite (built into Node) — zero external dependencies, no native module compilation
GitHub syncAuto-pushes the text layer to a private repo (30s debounce), plus daily compact SQLite snapshots
No build stepThe client half is a hand-written module bundle using React.createElement — edit and refresh

Installation

Requirements

  • DeepSeek Harness (dsh) 0.2.0-rc.2 or newer
  • Its bundled Node ≥ 22.5 (the minimum for node:sqlite; dsh's Electron usually ships 24.x)
  • No third-party runtime dependencies, no npm install needed

Option 1: Install from npm (recommended)

dsh plugin --profile <your-profile> add @adamcjm/dsh-memo

<your-profile> is your dsh profile name (e.g. web, tui). Restart dsh afterwards.

Option 2: Install from GitHub

Pins to the repository's default-branch HEAD instead of a published release:

dsh plugin --profile <your-profile> add github:adamcjm/dsh-memo

Option 3: Install for local development

git clone https://github.com/adamcjm/dsh-memo.git
dsh plugin --profile <your-profile> add link:/path/to/dsh-memo

With link: your edits are live (refresh the page for client changes; restart for host changes).

Option 4: Manual wiring (desktop profile only)

The desktop profile is owned exclusively by the dsh desktop app and the CLI refuses to write to it (it reports profile "desktop" is managed exclusively by the Electron application). Wire it manually:

  1. Edit ~/.dsh/profiles/desktop/package.json:

    {
      "dsh": {
        "profile": {
          "bundles": [
            // ... existing bundles ...
            "@adamcjm/dsh-memo"                       // ← add
          ]
        }
      },
      "dependencies": {
        // ...
        "@adamcjm/dsh-memo": "^0.2.11"                // ← add
      }
    }
    
  2. Install dependencies (creates the symlink):

    cd ~/.dsh/profiles/desktop
    pnpm install
    
  3. Restart DeepSeek Harness.

Verifying the install

dsh --profile <profile> --dump-config | grep -A3 "id: memo"

Or just look at the UI: a Memo icon should appear at the bottom of the sidebar.


Usage

Capturing a note

Open the Memo icon at the bottom of the sidebar and type into the input at the top, then press Enter:

Mr. Zhang wants a WeChat QR login entry on the login page; prototype due next Wednesday #requirement-change #login

#requirement-change and #login become tags automatically, and the tag markers are stripped from the body.

Editing a note

Hover a row and click Edit (the pencil); the row expands in place into an editor:

  • Change the body directly. The #tags in the body become the note's tags (remove a #tag from the body and the tag is removed too)
  • Opening the editor merges the note's existing tags back into the body as #tags — visible, and saved back as-is
  • Images can be removed one by one (the × on the thumbnail) or added at any time (paste / drag / multi-select)
  • ⌘Enter saves, Esc cancels

Saving regenerates the .md source of truth, bumps rev, and syncs to GitHub within 30 seconds.

Reordering

Date dimension: ascending / descending

One button sits to the right of the Pinned filter chip; it shows only the current direction — click it to flip:

  • Descending (default): today on top, older as you go down
  • Ascending: the oldest date on top, closer to today as you go down
  • It only changes the order of the day groups — the order inside a single day is left untouched (that one is yours, from dragging)
  • The choice is remembered locally (localStorage), so it survives reopening the panel

Within one day: drag & drop

Within one day group, hold a card and drag it to change the order:

  • The new order saves on drop and is written to the .md source of truth as order:, so it survives syncing to another machine
  • You cannot drag across day groups (a "today" card will not drop into "yesterday"); use Pinning to lift something across days
  • Order is decided only by dragging and pinning: marking done / undone or editing the body no longer bounces an item to the top

Adding images / screenshots

Three ways, freely mixable and repeatable:

  • Paste — take a screenshot, then press ⌘V in the input
  • Drag — drag images straight from Finder onto the input
  • Pick — click the "Image" button; hold ⌘ / ⇧ in the file dialog for multi-select

Images are named by SHA-256 and stored in attachments/, so pasting the same image twice costs one copy. Click a thumbnail to view it full size.

Tags

Tags are not fixed. The defaults (#requirement-change #todo #follow-up #idea #meeting) are just starting suggestions:

  • Type #customer-A or #MrZhang in the body and save → the tag is created and attached to that note
  • Anywhere works: start, middle or end of the body (buy milk#groceries, meeting,#work also count); a tag name ends at whitespace or punctuation
  • The tag area is sorted by usage; click one to filter
  • A tag that no note uses anymore disappears on its own

Search

Use the search box in the panel header and press Enter. Qualifiers combine:

SyntaxMeaning
scanBody or source contains the string (works for short CJK queries too)
#requirement-changeBy tag
source:MrZhangBy origin
after:2026-10-01 before:2026-10-08By date range
has:imageOnly notes with attachments
is:open is:doneOnly open / only completed

Keyboard shortcuts

KeyAction
EnterSave the current input
⇧EnterNewline inside the input
⌘VPaste an image from the clipboard
EscClose an overlay (settings / image zoom)

Syncing to GitHub

  1. Create a private repository on GitHub (e.g. yourname/dsh-memo-data)
  2. Create an access token:
    • Preferred: a fine-grained PAT scoped to that repo with Contents: Read and write
    • Or a classic PAT with the repo scope
  3. Click the settings icon in the panel header, fill in the repository and token, and hit "Save and sync"

After that:

  • Manual sync — click "Sync now"; the result is reported by a top-center notification (success / failure)
  • Auto sync — every change is committed and pushed 30 seconds later; failures also raise a notification
  • Status — the panel header shows "Synced / Pending / Local only / Sync error"

Where the repository setting lives

Three layers, resolved in order:

#LocationNotes
①~/.dsh/memo/.config.jsonSaved from the plugin's settings dialog — survives restarts
②Plugin config config.repo in cordis.patch.ymlDeployment-time default
③remote.origin.url in ~/.dsh/memo/.git/configExisting git trace (a manual git remote add counts)

Only when all three miss does the panel say "not configured". The sync-badge tooltip reports which layer is in use (runtime / config / git-remote).

Token lookup order (none of them ever enter the repository):

  1. The settings dialog writes ~/.dsh/memo/.token (mode 0600)
  2. Environment variable DSH_MEMO_GITHUB_TOKEN
  3. Environment variable GITHUB_TOKEN

When pushing, the token only ever appears in the git process arguments (http.extraheader) — it is never written into .git/config.


Data & backup

The data root is ~/.dsh/memo/, which is itself a git repository:

~/.dsh/memo/
├── memo.db                  # SQLite working DB (engine; git-ignored, rebuildable from notes/)
├── notes/2026-10/<id>.md    # ★ the text source of truth: one file per note
├── attachments/<xx>/<sha256>.<ext>      # images, content-hash named
├── log/2026-10.jsonl        # append-only action log (.gitattributes sets merge=union)
├── snapshots/memo-YYYY-MM-DD.sqlite     # daily compact snapshot, 7 kept
├── .token                   # credentials (0600, git-ignored)
├── .config.json            # remote repository setting (saved from the UI, synced too)
├── .gitignore
└── .gitattributes

Why the SQLite file is not committed directly

A SQLite file in git is an unmergeable binary: if two machines both edit it, git can only pick one entire file — you lose everything from the other machine, not just one note. It also rewrites whole database pages on every change, so a single small edit becomes a complete new blob and the repository balloons.

Hence three layers:

LayerRoleIf it breaks
① Local SQLiteQuery engine and indexDelete it; it rebuilds from ②
② notes/ + attachments/ + log/Sync source of truth — this is what git moves③ is the backstop
③ Private GitHub repoBackup and history—

The daily .sqlite files under snapshots/ are committed too, satisfying "the SQLite file lives on GitHub as well" — but they are disaster recovery only and never participate in merges.

What if the SQLite file is lost

Delete memo.db* and restart dsh (or call the rebuild API). The plugin scans notes/**/*.md and rebuilds everything, including tags, sources, due dates and attachment references.


Uninstalling

If installed via the CLI

dsh plugin --profile <your-profile> remove @adamcjm/dsh-memo

If wired manually (desktop profile)

  1. Edit ~/.dsh/profiles/desktop/package.json and remove the two @adamcjm/dsh-memo entries from dsh.profile.bundles and dependencies
  2. cd ~/.dsh/profiles/desktop && pnpm install
  3. Restart DeepSeek Harness

Optional: delete your data

Uninstalling the plugin does not delete your data. If you are sure:

rm -rf ~/.dsh/memo          # local data (including credentials)

If you synced to GitHub, the remote repository (e.g. yourname/dsh-memo-data) is yours to delete.


Development

git clone https://github.com/adamcjm/dsh-memo.git
cd dsh-memo

node test/smoke.mjs                    # host half, 64 checks: CRUD / tags / attachments / rebuild / snapshots / credentials
node test/client-precheck.mjs          # client half, 25 checks: module protocol / slot registration / component rendering
node test/ui-feedback-check.mjs        # UI details, 80 checks (incl. pinning and drag wiring)
node test/edit-interaction-check.mjs   # theme foreground + clickable edit area, 15 checks (real mount via jsdom + React)
node test/tag-rules-check.mjs          # tag rules & edit round-trip, 52 checks (position / fidelity / host-client parity)
node test/edit-check.mjs               # editing & image refcounting, 29 checks
node test/reorder-check.mjs            # ordering, 20 checks (done does not jump / drag persists / old-db migration)
node test/drag-check.mjs               # real-browser drag, 12 checks (Chrome + CDP; skipped without Chrome)
node test/panel-mount-check.mjs        # real panel mount, 7 checks (jsdom + React; proves the Sortable instance is attached)
node test/sort-check.mjs               # ascending/descending, 23 checks (jsdom + React, real clicks: day groups only / order inside a day untouched)
node test/i18n-check.mjs               # i18n, 22 checks (zh/en switching, missing-key fallback)
node test/config-check.mjs             # sync config, 18 checks
node test/hot-swap-check.mjs           # hot swap, 9 checks

None of these need dsh running. The client tests need to resolve react / react-dom (they look in the project first, then borrow from a dsh profile); the real-mount tests also need jsdom (installed as a devDependency by npm i, skipped when absent).

Layout

package.json        dsh.bundle.patch + dsh.client (platform: web)
cordis.patch.yml    host plugin row: id: memo
lib/index.js        host half: SQLite / attachments / Markdown source of truth / git sync / HTTP API
lib/client.js       client half: window.__ModuleLoader__.load({id, factory}) + React UI
                    (SortableJS 1.15.7 — MIT — is inlined here for drag-and-drop reordering)
test/               independently runnable test files (host / client / UI / tag rules)

Extension points

  • Client → host: fetch('/memo/api/<method>'); the host serves it via ctx.webServer.register({ kind: 'prefix' })
  • Sidebar icon: ctx.slots.register({ name: 'sidebar.panellist', id, order, label }, Icon) — the icon component receives { size, active }
  • Main panel: ctx.slots.register({ name: 'main', key: id }, Panel) — both ids must match; the shell calls ctx.layout.selectPanel(id) when the icon is clicked

How changes take effect

  • Client (lib/client.js): refresh the page (the module system derives revisions from mtime / ctime / size and hot-swaps)
  • Host (lib/index.js): restart dsh (host code loads at process start)
  • lib/client.js rewritten exactly while dsh boots: the client-side HMR watch can hot-swap the bundle while its first load is still in flight, so DSH ends up executing the same bundle twice. The bundle now tolerates its own duplicate registration (a second duplicate factory registration is ignored, because a registration already exists) instead of failing the whole web boot. Every other error is still rethrown

Known limitations

  • Text-layer sync only — no multi-device merge UI (it cannot happen on a single machine; the text layer being mergeable is the insurance)
  • No mobile UI
  • Search uses LIKE, not FTS5 — SQLite's trigram tokenizer requires query terms of 3+ characters, and the most common Chinese queries are two characters ("扫码", "登录"), which would silently return nothing. Correctness first
  • Images are transferred at original size; no thumbnails
  • No system-level reminders (only a due-date field and due highlighting)

License

MIT

Comments

Loading…

From the same category

dsh-TUI

by ccch1mneyyy

DSH 官方公众号收录的 TUI 补位插件:Claude Code 风,鲸鱼顶栏/实时状态/流式思考/双击 Esc 回滚/上下文进度+TPS。npm 一键装。 DSH official WeChat featured TUI plugin — Claude Code style: whale bar, live status, streaming thoughts, double-Esc rol

Terminal & ClientsManifest valid

★ 4.6k

↓ 11.6k/wk

MIT

TypeScript

Oct 14, 2026

dsh plugin --profile terminal add @deepseek-harness-tui/dsh-tui

by strukto-ai

The World's First Virtual Terminal for AI Agents

Terminal & ClientsManifest valid

★ 3.7k

↓ 374/wk

Apache-2.0

TypeScript

Oct 14, 2026

dsh plugin --profile agent add @struktoai/mirage-dsh

by bowenliang123

The best DeepSeek Harness plugin for context insight and management, with context dashboard / browser / sidebar and context command, for context statistics, composition, breakdown, evolution details,

Tools & CapabilitiesUI & ExperienceTerminal & ClientsManifest valid

★ 2.1k

↓ 44k/wk

Apache-2.0

TypeScript

Oct 13, 2026

dsh plugin --profile web add dsh-context

by huiliyi37

官方 DeepSeek Harness 的交互式终端 UI 插件:自研 ANSI 极简交互渲染、流式 Markdown/工具卡、16+ 主题、slash 命令与选择器、输入历史与本地偏好持久化、LSP 诊断、memory记忆,很丝滑的开发体验。

Terminal & ClientsManifest valid

★ 285

↓ 486/wk

Apache-2.0

TypeScript

Sep 30, 2026

dsh plugin --profile terminal add @huiliyi37/dsh-tianshu-tui

by Hilbert-beinghappy

面向 DeepSeek Harness 的 Claude Code 风格终端界面,支持 Windows、macOS 与 Linux,兼容透明终端、VS Code 主题和自定义配色。

Terminal & ClientsManifest valid

★ 196

↓ 108/wk

MIT

TypeScript

Oct 13, 2026

dsh plugin --profile web add seektty

by T-Auto

deepseek-harness Plugin Access and Implementation Standards / deepseek-harness交互生态插件规范与实施标准

Terminal & Clients

★ 83

MIT

JavaScript

Oct 10, 2026

Index only — not installable