dsh-memory: A local memory pool shared by all DSH sessions

Preface

DSH’s philosophy is “everything is a plugin,” but there is no shared memory between multi-turn conversations by default: changing a session or workspace makes the model forget previous preferences, project conventions, and environmental facts. Therefore, the common practice is to repeatedly paste important information back into the prompt, which wastes tokens and is prone to copying errors or omissions. octidote/dsh-memory solves this: a persistent memory pool shared by all DSH conversations on the local machine, automatically recalled when relevant topics are mentioned. It does not connect to the internet, does not call embedding models, and completes storage and recall locally.

What is this

  • Plugin Name: dsh-memory
  • Maintainer: Octidote
  • Directory Category: Memory
  • Version: 0.17.0
  • License: MIT
  • Runtime: Node >= 20

One-sentence positioning: A local-first shared memory pool to replace manually stuffing background into the prompt every time. The difference is it only saves structured compressed summaries, injecting only a small amount of relevant content when hit, rather than stuffing the entire dialogue text into the context. The README introduction is “Shared local memory pool for DeepSeek Harness conversations.”

Core Capabilities

Local Shared Pool and Zero Token Compression

All sessions and workspaces share $DSH_HOME/storages/dsh-memory/memories.json. The actual user input prompt and the assistant’s final reply are only locally structured extraction-style compressed and stored: single entry ≤ 420 characters, merged rounds ≤ 760 characters, preserving the opening conclusion, point list, and ending conclusion. Full dialogue is not saved, and no model is called. Plugin-injected runtime context, skill directories, time snapshots, and tool call intermediate steps will not be mistakenly stored. Before storage, sensitive fragments like private keys, API keys, GitHub tokens, JWT, Bearer, passwords, etc., are automatically masked, and code blocks, long links are replaced with placeholders.

Encrypted Disk Storage and Single-Writer Protection

The memory pool is written to the memories.json snapshot encrypted with AES-256-GCM. Daily add/delete/recall events are appended to memories.json.journal.jsonl (one independent encrypted event per line), compacted into a new snapshot every 200 entries or 512 KB. The key is saved in key.bin in the same directory (32 bytes, readable only by the current user). Old plaintext data is automatically migrated to ciphertext on first load. Only one writer is allowed for the same data directory: a lock file records the writer’s PID and instance ID; the second process automatically enters read-only mode, allowing viewing and recall but not overwriting data. Model calls to memory save/forget, panel feedback/classification/delete/clear, etc., explicit write operations wait for disk confirmation; on write failure, success is not returned, and the event stays in the queue with a retry starting at 5 seconds and a max 60 seconds backoff. Every 6 hours, an encrypted snapshot is retained on startup. A forced backup is kept before migration, clearing, or restoring, retaining the most recent 16.

When manually backing up or migrating, memories.json, memories.json.journal.jsonl, and key.bin must be preserved together; without the key, old memories cannot be recovered.

Restrained Automatic Recall

Default “Classic Mode”: Local BM25-style keyword matching + synonym concept expansion + local feature hash vector cosine + classification context weighting. Synonym rewrites (“dark/dark mode”, “meeting/meeting”) and minor spelling differences (kubernetis/kubernetes) can also hit. Injection only happens if relevance is high enough: max 2 entries, total length ≤ 760 characters, appears only once in the first step of the turn, and the same session does not re-inject the same memory.

In the panel “Settings” → “Recall”, you can switch to “Hybrid Mode”: using RRF to fuse BM25, vector, and tag/classification sorting, adding confidence interval, MMR diversity, and intent bias. Classic mode is still the default; the switch result is written to config.json and can be switched back at any time. The 70 annotated query results given in the README: Hybrid Mode Hit@1 91.7%, Hit@2 100%, MRR 0.958, False Recall Rate 10%; Classic Mode is 86.7% / 98.3% / 0.929 / 10%. These numbers are reproduced by tools/eval-recall.mjs.

Turn Memory and Explainable Recall

The assistant’s reply, within 15 minutes, is merged with the previous user message of the same session into one episode to avoid storing one for the user and one for the assistant; the summary preserves the “points” list and “conclusion” structure. In “Settings” → “Recall”, input a query to see each candidate’s score / bm25 / vector / coverage / reasons for every candidate, without calling the model or injecting dialogue. Expanding the list row allows pinning ★, blocking ⊘, or giving feedback; blocked memories are no longer automatically recalled.

Core Memory, Project Context, and Injection Protection

Entries marked with ★ as Core Memory are automatically brought into the first step of every new session (max 2), even if the current question has no keyword hits. Automatically recorded memories extract project from the session working directory, and memories of the same project get slight weighting when recalled. The memory text spliced into the model prompt first removes pseudo-system tags, {{variables}}, and injection patterns like “Ignore previous instructions/Enter developer mode”. The original text saved in the database remains unchanged; only the version the model actually sees is purified.

Quality Feedback and Automatic Organization

Each memory in the list can be clicked 👍 / 👎; feedback adjusts importance and recall ranking. Memories with 3 consecutive “Useless” and no “Useful” feedback stop automatic recall; clicking 👍 once restores them. New memories are automatically merged with highly similar near-duplicates upon storage (same type, same category, Jaccard ≥ 0.78). Each memory scores all classifications based on tags and local keywords, retaining the main classification, confidence, candidate sub-classifications, and scoring details; low confidence enters “Uncategorized” without forced bucketing; after expanding the list row, the classification capsule becomes a dropdown box, allowing manual change to any classification (manual result takes priority, confidence recorded as 100%), without calling the model or consuming extra tokens. Max 2500 entries, exceeding items are淘汰 (淘汰) based on importance, timeliness, type, and feedback quality; pinned memories are protected.

Panel and 3D Graph

Clicking the “Memory” button at the bottom of the sidebar opens the panel, with only two main views: “List” and “Graph”. Search, classification filtering, and memory body are visible by default; feedback, pinning, blocking, changing classification, deletion, and other operations are hidden in expanded rows. Recall mode, recall testing, data security, backup, and clear are unified in the top-right “Settings”. The graph is an independent 3D canvas: nodes represent a memory or a round; edge thickness and brightness are determined by relationship strength; node size increases with recall count, merge count, and pinning status. Layout is organized by classification clusters, supporting rotation, panning, zooming, auto-rotation, classification filtering, search highlighting, and details. Tags perform screen space collision detection, hiding minor tags automatically when crowded. The “Standalone Window” in the top-right of the graph opens a full view without the sidebar, which can be freely resized. Dialogue content automatically enters the pool by default; manual addition is not required.

Model Can Actively Maintain

The memory tool supports search / save / forget / feedback, suitable for saving stable preferences, environmental facts, and long-term project conventions. Simply saying “Remember…” to the model will cause the model to call this tool to save.

Installation and Enablement

The plugin is installed by cloning the repository and running the install script; do not use link: or directory linking: DSH’s ESM interception only works for real paths inside the profile, and symbolic links will cause an ERR_MODULE_NOT_FOUND: @deepseek-ai/dsh-llm error on startup.

git clone https://github.com/Octidote/dsh-memory.git
cd dsh-memory
node scripts/install.mjs desktop

The install script copies the plugin to the real directory <DSH_HOME>/profiles/desktop/node_modules/dsh-memory and appends dsh-memory to dsh.profile.bundles of that profile; restart DeepSeek Harness after completion.

Typical Usage

  1. Click “Memory” at the bottom of the sidebar to open the panel. The top dropdown filters by Preferences / Project / Environment / Facts / Plan / Characters / Dialogue / Uncategorized, and the search box matches body, tags, and category names simultaneously.
  2. “List” to view, search, expand, and delete memories. Each row shows classification, time, and summary; clicking open shows classification correction (+N indicates candidate sub-classifications), tags, recall count, pinned ★, blocked ⊘, 👍 / 👎, and delete. The list is loaded in batches of 120, max 1000.
  3. “Graph” view: Left-click drag to rotate, right-click drag to pan, scroll wheel to zoom, double-click to reset; click a node to see details, click the right-side classification legend to filter, and the search box highlights matching nodes.
  4. Click the top-right “⚙” to enter settings. “Recording” can pause/resume automatic recording; “Recall” can view/switch Classic and Hybrid modes, input queries to see local candidates and scores; “Data Security” shows single-writer/read-only status and backup count, allowing immediate backup, verification, export/import, or restore; “Maintenance” shows quality statistics and clear entry. These operations do not call the model or inject the current dialogue.
  5. Simply say “Remember…” to the model; the model will call the memory tool to save. Clear all is in “Settings” → “Maintenance”; before clearing and restoring, an encrypted backup is written first.

Applicable Scenarios and Notes

Suitable for developers who need to reuse preferences, project conventions, and environmental facts across multiple DSH sessions and workspaces, and those who want memory content to be controllable, explainable, correctable, and kept local.

A few points to note:

  1. The plugin runs with the current dsh process permissions; the read/write range of memory files depends on that process’s permissions. Check the source code and license (MIT) before installing.
  2. The repository is currently starred 0 times and is an early project; rely on README and local evaluation for features and recall effects; do not depend on a single default configuration in production.
  3. The backup trio (memories.json, memories.json.journal.jsonl, key.bin) must be kept together, otherwise the ciphertext cannot be decrypted.
  4. Recall is heuristic local matching, not calling the model; if more precise injection behavior is needed, switch modes in the panel and observe candidate scores.
  5. The repository comes with npm test (lock/persistence confirmation/JSONL and compaction/encryption/recall/graph) and npm run eval (70 annotated queries) which can serve as self-check measures after installation.

Conclusion

The value of dsh-memory lies in replacing “remembering background for each session individually” with “a shared, encrypted, explainable memory pool on the local machine,” injecting only small amounts of relevant content when hit, bypassing the burden of manually organizing prompts in daily operations. For further understanding, check the directory page and repository:

  • Directory Page: https://www.skillhub.cn/plugins/Octidote/dsh-memory
  • GitHub: https://github.com/Octidote/dsh-memory
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye