dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Workspace-scoped long-term memory for DeepSeek Harness: plain Markdown, zero network, no automatic model calls.
Long-term memory for DeepSeek Harness (DSH), scoped by workspace directory. Sessions opened in the same directory share one memory store; sessions in a different directory see none of it, except for memories saved with the global scope. Every memory is a plain Markdown file on disk. No network requests, no automatic model calls, no database, no index files.
memory_save, memory_search, memory_get, memory_list, memory_forget@deepseek-ai/dsh-* 0.2.1-rc.2 (engines.dsh is pinned to >=0.2.1-rc.2 <0.2.2)@deepseek-ai/cordis 4.0.5From a local checkout:
pnpm install
pnpm build
dsh plugin --profile <name> add <path-to-repo>
Or directly from GitHub:
dsh plugin --profile <name> add git+https://github.com/Alexis-ray/dsh-memory-lite.git
Both forms register the plugin in the profile named by --profile (for example desktop) and append dsh-memory-lite to dsh.profile.bundles. Restart the client if a newly created session does not see the memory_* tools. Full instructions, including verification, upgrade, and uninstall, are in INSTALL.md (Chinese).
| Tool | Key inputs | Returns | Notes |
|---|---|---|---|
memory_save | title (<= 80 chars), body, scope? (project | global), tags?, confidence? | id, path, scope | Defaults to project. Rejects bodies that look like credentials. |
memory_search | query, scope? (both | project | global), limit? | hit list with snippets | Lexical scoring: title x3, tags x2, body x1. CJK text is matched as bigrams. Default limit 8, max 50. |
memory_get | id | full record | Errors when not found; never returns empty. |
memory_list | scope? | title index lines | Titles only; bodies are not read. |
memory_forget | id | archivedPath | Moves the file to .archive/; reversible by moving it back. |
memory_get and memory_forget only reach memories visible to the current workspace plus global; an id from another workspace cannot be read or archived.
sha256(normalizePath(cwd)).slice(0, 12). normalizePath lowercases the drive letter, converts \ to /, collapses repeated separators, and drops the trailing separator. Symlinks are not resolved, so renaming a directory means a new project.global memories are visible from every workspace. Set allowGlobalScope: false to disable writing them.| Key | Default | Meaning |
|---|---|---|
vaultPath | <DSH_HOME>/memory-vault (or %USERPROFILE%\.dsh\memory-vault when DSH_HOME is unset) | Root directory of the vault |
injectStanding | true | Inject the standing title index into the system prompt |
standingMaxItems | 8 | Max entries in the standing section (min 1) |
standingBudgetChars | 1200 | Character budget for the standing section (min 200) |
allowGlobalScope | true | Allow scope: global in memory_save |
redactSecrets | true | Reject writes whose body matches credential patterns (api_key, secret, password, token, private key blocks) |
maxFileBytes | 65536 | Max size of a single memory file (min 1024) |
autoSavePolicy | off | Whether to register a "write policy" system prompt section that nudges the agent to save notable facts proactively. hint enables the section; off registers nothing. |
Values are set through the plugin's config in cordis.patch.yml (either the file shipped with the plugin, or an id-targeted patch appended to your profile's cordis.patch.yml). Keys that are not written fall back to the schema defaults above.
The vault is a plain directory:
<vault>/
global/
<slug>-<id>.md global memories, visible everywhere
projects/
<key>/ key = sha256(normalizePath(cwd)).slice(0, 12)
project.json { "path": "<normalized cwd>", "name": "<dir name>" }
<slug>-<id>.md project memories, visible in that workspace only
.archive/
<slug>-<id>.md archived (soft-deleted) memories
One memory is one Markdown file with YAML front matter:
---
id: 20261020-1730-ab12
title: This repo uses pnpm
scope: project
projectPath: c:/work/demo
tags:
- toolchain
- conventions
confidence: medium
createdAt: 2026-10-20T09:30:00.000Z
updatedAt: 2026-10-20T09:30:00.000Z
---
Install dependencies, run tests, and build with pnpm. Do not use npm or
yarn; the lockfile is pnpm-lock.yaml.
Writes go through a temp file plus fsync plus rename, so a crash mid-write loses at most that one write and never leaves a truncated memory file. Files over maxFileBytes are rejected outright, not truncated. memory_forget moves the file into .archive/ and stamps archivedAt; moving it back restores it. There is no index file: listing and search always read the .md files directly, so there is nothing to rebuild or corrupt.
test/offline.test.ts stubs fetch, http.request, https.request, net.connect, and dns.lookup at runtime and asserts zero call attempts.memory_get.lib/ ships in the repository so the plugin can be installed straight from git without a build step.project.json records the old path).engines.dsh is pinned to a narrow range; a DSH upgrade outside >=0.2.1-rc.2 <0.2.2 skips the bundle until the range is updated (see INSTALL.md).pnpm install # install dependencies
pnpm typecheck # tsc --noEmit
pnpm test # vitest run
pnpm build # tsc -p tsconfig.json -> lib/
pnpm smoke # node --experimental-strip-types smoke.mjs
test/offline.test.ts runs the entire plugin with fetch, http.request, https.request, net.connect, and dns.lookup stubbed, and asserts that none of them was called even once. The other suites cover path normalization and project keys, slug generation, frontmatter round-trips, atomic writes leaving no .tmp- residue, archiving, search ranking, cross-workspace denial of get/forget by id, the tool contracts, and the standing section's 3+5 selection and budget trimming.
Read this page in Chinese: README.zh-CN.md