aujurd22/dsh-flymemory ↗★ 1

dsh-flymemory

运行本地FlyMemory MCP服务实现长期记忆 适合需要在本机保存长期记忆,并自动记录和召回历史上下文的DSH用户。

套件
dsh-flymemory
相容性
待驗證
版本
1.0.0
授權
MIT
最近更新
2026年9月30日

安裝

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:aujurd22/dsh-flymemory

dsh-flymemory

English | 中文

Long-term memory for DeepSeek Harness.

This is a plugin (a DSH bundle) that runs FlyMemory as a local MCP service and plugs it into the harness. You end up with 15 memory tools, plus a pair of hooks that quietly record what you've been working on and pull the relevant bits back when they matter — so you stop re-explaining the same context every session.

Everything stays on your machine. The service listens on 127.0.0.1:8791, the library is a single file under your DSH home, and nothing is sent anywhere.

DSH session ──┬── mcp__flymemory__*   15 tools the model can call
              └── hooks               recall before a turn, store after it
                        │
                        ▼
              FlyMemory service on 127.0.0.1:8791
                        │
                        ▼
              $DSH_HOME/flymemory-data/flymemory_v3.pkl

What you get

Fifteen tools, all under the mcp__flymemory__ prefix:

ToolWhat it's for
flymemory_rememberStore a decision or finding. Near-duplicates are merged automatically. compartment groups entries by topic; state_key/state_value track "the current value of X" and retire the old one.
flymemory_recallSearch. Dense embeddings and keyword matching are fused, older entries fade, and results come back with id, age and where they came from. include_superseded digs into history.
flymemory_autoRecall and store in one call. This is what the hooks use.
flymemory_recall_index / flymemory_get_memoryLook first, read later: a one-line index, then the full text of whatever looks interesting.
flymemory_supersedeSay "this old entry is out of date, that one replaces it".
flymemory_state_lookup / flymemory_state_historyCurrent value for an entity key, or the whole history of it.
flymemory_consolidateFold several entries into one conclusion; the originals stay as evidence.
flymemory_find_conflicts / flymemory_insightsPairs that look contradictory; valuable entries that are fading.
flymemory_forget / flymemory_cleanupDelete one entry, or sweep everything that has decayed past a threshold.
flymemory_session_packA short pack of the recent trail and the latest conclusions.
flymemory_statsCounts, ages, access counts.

And two hooks that work on their own:

  • On every prompt — the prompt is stored, and memories that match it get appended to the turn. No model call, just local search.
  • On session start — a recovery pack of recent activity, so a fresh session isn't starting from nothing.

Both hooks are silent when the service is down, and neither can block a turn.

Requirements

  • DeepSeek Harness with @deepseek-ai/dsh-mcp-client and @deepseek-ai/dsh-hooks-claude-code available. Built and tested against 0.2.0-rc.2.

  • Node 20+ (the add-on and its CLI).

  • Python 3.10+ with the engine's dependencies:

    pip install torch sentence-transformers "mcp>=1.30,` |
    

| flymemory-hooks | @deepseek-ai/dsh-hooks-claude-code | Runs the two hook scripts on the right events |

When the harness starts, the first row checks 127.0.0.1:8791. If a FlyMemory service is already answering there, it's reused — two harness windows share one engine and one library. If the port is free, the bundled engine starts in the background and the row waits for it before letting the next row connect. If something else owns the port, the plugin says so and leaves it alone; it never kills a process it didn't start.

Cold starts are slow: the engine imports torch before it can listen, which takes 15–20 seconds. The row waits up to 25 seconds by default, and the mcp-client reconnects on its own if it has to.

If the engine can't start at all — no interpreter, missing dependency, port conflict — the harness still boots. You just don't get the tools, and the reason is in the log.

Settings

Environment variables, read before the harness starts:

VariableDefault
FLYMEMORY_MCP_PORT8791Service port
FLYMEMORY_MCP_URL`http://127.0.0.1:
/mcp`Full endpoint
FLYMEMORY_DATA_DIR$DSH_HOME/flymemory-dataLibrary, logs, hook config, pid file
FLYMEMORY_PYTHONauto-detectedInterpreter for the engine
FLYMEMORY_DEVICE / FLYMEMORY_MODELcpu / multilingual MiniLMPassed to the engine

Anything else goes on the row itself, in your profile's cordis.patch.yml. A patch entry replaces the whole config, so write out everything you need:

- id: flymemory
  name: 'dsh-flymemory'
  config:
    port: 8791
    dataDir: 'D:\dsh-memory'
    libraryPath: 'D:\dsh-memory\my-lib.pkl'
    pythonExe: 'C:\Python313\python.exe'
    device: cpu
    readinessTimeoutMs: 25000   # 0 = don't wait, let the tools show up later
    shutdownOnDispose: true     # stop the engine this activation started
    writeHooksConfig: true
    seedFromUpstream: false     # don't import another library implicitly
    upstreamLibrary: ''         # set both to import one, once
    autostart: true

The rest of the options are documented in resolveOptions() in lib/index.js. Unknown keys are ignored.

Where your memory lives

$DSH_HOME/flymemory-data/flymemory_v3.pkl — one file, plain data, easy to back up or delete. Alongside it:

  • hooks.json — regenerated on every activation; describes the two hooks
  • engine.log — stdout/stderr of the engine process
  • server.log — the engine's own log
  • server.pid — so flymemory stop knows what to kill

To run the service on its own, without the harness:

node bin/flymemory.mjs start
node bin/flymemory.mjs stop
node bin/flymemory.mjs log -n 40

After installing the bundle, the same CLI is linked into the profile at /node_modules/.bin/dsh-flymemory.

About the hooks

They're on by default, because automatic memory is the whole point of the thing. Worth knowing exactly what that means:

  • Every prompt you send is written to the memory file. It's local and cheap, but it is a record of what you typed.
  • Recalled memories are appended to the turn, which costs some context — in practice around 1.5 KB per turn.
  • Credential-shaped text never gets stored: the engine rejects things like ghp_, github_pat_, sk-ant-, AKIA and private key headers.

If you'd rather have the tools and no automation:

plugin_manager(action: "set_plugin", target: "include:flymemory-hooks", enabled: false)

Importing a library you already have

Nothing is imported unless you ask. If you have a FlyMemory library from somewhere else and want to move it in, point the plugin at it once:

- id: flymemory
  name: 'dsh-flymemory'
  config:
    port: 8791
    upstreamLibrary: 'D:\path\to\flymemory_v3.pkl'
    seedFromUpstream: true

On the next activation the file is copied into place if the target doesn't exist yet. The original is left alone. The format is the same in both directions, so you can move it back out later.

Working on it

node --check lib/index.js    # syntax
npm test                     # unit tests, no Python needed, ~0.3 s
node tests/engine_smoke.mjs  # end-to-end against the real engine (needs torch)
python tests/http_smoke.py   # protocol check against a running service

npm test covers the parts that are easy to get wrong: port and library defaults, config precedence, the generated hook file, endpoint probing. The engine smoke test runs apply() in a throwaway directory against a real Python engine — it needs torch and sentence-transformers, and prints SKIP if they aren't there. CI runs the syntax check and the unit tests on Linux, macOS and Windows across Node 20, 22 and 24.

lib/index.js        Host half: port probing, engine supervision, hook config
bin/flymemory.mjs   CLI built on the same helpers
cordis.patch.yml    the three rows this bundle inserts
python/             vendored FlyMemory engine (server, hooks, engine package)
locale/{en,zh}.json title and description for the Plugins page
tests/              unit tests, engine smoke test, protocol smoke test

Rough edges

  • The first start takes 15–20 seconds. That's torch loading. Set readinessTimeoutMs: 0 if you'd rather the harness start immediately and have the tools appear a few seconds later.
  • The Python dependencies are heavy. The plugin won't install them for you; doctor tells you what's missing.
  • DSH has no PreCompact hook, so the recovery pack runs at session start rather than right after a compaction.
  • Tool names are long. mcp__flymemory__flymemory_recall is what the mcp-client naming rule produces — mcp____ — and it's stable, just not pretty.
  • One engine per port. Two harnesses share it; a third instance needs its own port and its own library, set explicitly.
  • Recall gets slower as the library grows. Upstream measured ~11 ms per query at about 1,400 entries on CPU.

License

MIT. See LICENSE.

The bundled FlyMemory engine is MIT as well, Copyright (c) 2026 Junrong Du. THIRD_PARTY_NOTICES.md lists exactly which files were copied, which were adapted, and why.