# Recollect

[中文](README.md) · [npm](https://www.npmjs.com/package/@kirkchinese/dsh-recollect) · [Changelog](CHANGELOG.md) · [Issues](https://github.com/kirkchinese/DSH-Recollect/issues) · Sibling project: [CiteCiter](https://github.com/kirkchinese/CiteCiter)

![Recollect](assets/hero/recollect-hero.png)

**Switch models and keep your memory.**

Recollect is a plugin for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) that provides a **Claude-Code-compatible memory system**. It follows Claude Code's conventions: layered `CLAUDE.md` files, `@import`, `.claude/rules`, and a persistent memory with `MEMORY.md` as its index. Every model (DeepSeek, GPT, Qwen, Claude, …) gets the same complete memory guidance, with no downgrade for models outside a vendor's own catalog.

## Why

In Claude Code, the memory-writing guidance depends on the model. Models outside its catalog get a short version that drops the long-term duty, the "save immediately when asked" rule and all examples, so they rarely write memories on their own. Recollect gives every model guidance written independently for this project (in Chinese and English) together with the same file conventions, so that any model:

- **records** who the user is, feedback on how they want work done, project context and pointers to external resources, at the right moments;
- sees the memory index in each new session and reads or recalls memory bodies when relevant;
- verifies a memory before recommending from it, because memories go stale.

## Compatibility with Claude Code

| Area | Status |
| --- | --- |
| Instruction files | **Reads the same files**: `~/.claude/CLAUDE.md`, `~/.claude/rules/`, project `CLAUDE.md`, `.claude/CLAUDE.md`, `.claude/rules/`, `CLAUDE.local.md`, `@import`, `/etc/claude-code`, plus `AGENTS.md` |
| Memory format | **Same**: one file per memory with frontmatter (`name`, `description`, `metadata.type`), four types, `MEMORY.md` as the index |
| Memory storage | **Separate by default**: Recollect writes to `~/.dsh/memory/projects/<slug>/`, Claude Code to `~/.claude/projects/<slug>/memory/`, with the same slug rule |
| Existing Claude Code memories | Copy them with `/memory-import` (`all` for every project, `--dry-run` to preview). The source is only read, existing files are never overwritten, and index lines are merged by link |
| One shared memory | Optional globally (`memory.shareWithClaudeCode: true`) or per project (`memory.shareProjects`). The panel's **Share this project with Claude Code** switch controls the current project; **Preview import → Confirm import** copies memories once instead. Sharing lets both programs edit the same files, including Claude Code's background consolidation |
| Not implemented | Team memory (`CLAUDE_MEMORY_STORES`), account memory, `#` quick capture |

## Install

| DSH version | Recollect version |
| --- | --- |
| `0.2.0-rc.2` and later (including the official Desktop; tested with `0.2.1-rc.2` and `0.2.1-rc.5`) | `0.5.0` |

**Official Desktop:** on the Plugins page, install the npm package `@kirkchinese/dsh-recollect`, or enter `https://github.com/kirkchinese/DSH-Recollect.git` as the Git address, then restart when prompted.

**CLI and Web:**

```sh
dsh plugin --profile web add @kirkchinese/dsh-recollect@0.5.0
# or a release tag from the repository
dsh plugin --profile web add "git+https://github.com/kirkchinese/DSH-Recollect.git#v0.5.0"
```

Restart DSH and reload the page. New sessions use Recollect. It takes over instruction-file loading and filters out what DSH's built-in AGENTS.md loader injects, so no file is loaded twice.

### Installing on Windows

Install the npm package from PowerShell (the official Desktop also accepts this npm package on its Plugins page):

```powershell
dsh plugin --profile web add "@kirkchinese/dsh-recollect@0.5.0"
```

Restart DSH and reload the page. Known platform differences:

- Background extraction and dream helpers only allow bash read-only commands (plus restricted memory deletion). DSH uses pwsh on Windows, so these helpers cannot run shell commands there. Both features are off by default; ordinary memory reads/writes, sharing and imports are unaffected.
- `instructions.managedDirs` defaults to `/etc/claude-code`, which normally does not exist on Windows. Set a real absolute directory if organization policies are needed.
- Slugs follow Claude Code's rule: `C:\Users\me\proj` becomes `C--Users-me-proj`, so per-project sharing resolves to the same memories.

### Version support policy

`engines.dsh` sets only the lower bound `>=0.2.0-rc.2`, and DSH peer dependencies use open ranges. New DSH release candidates therefore are not blocked by installation checks. If a host interface changes, the affected feature may fail rather than the entire plugin being rejected because of a version ceiling. CI covers the two tested host versions above and Linux / Windows; an open range is not a promise that future interfaces never change.

## What it does

| Feature | Default | Notes |
| --- | --- | --- |
| Instruction files | on | Loaded in this order: organization policy (`/etc/claude-code`); the user level (`~/.claude/CLAUDE.md`, `~/.dsh/AGENTS.md`, `~/.agents/AGENTS.md`, `~/.claude/rules`); then every directory from `/` down to the working directory (`CLAUDE.md`/`AGENTS.md` with `@import` expanded in place up to 4 levels, then `.claude/CLAUDE.md`, then rules as recursive `.md` files, then `CLAUDE.local.md`/`AGENTS.local.md`). All files are concatenated without truncation; a single file over 4 MiB is skipped |
| Persistent memory | on | The system prompt carries the full writing guidance: four types, what not to save, the two-step save procedure, and access and verification rules. The first message carries the `MEMORY.md` index, truncated with a warning beyond 200 lines or 25 000 characters |
| Refresh | on | On resume only changed files are shown. When compaction summarizes the instructions away, they are re-injected in full. Directory changes and pause/resume also refresh them |
| Subdirectory discovery | on | Touching a file in a subdirectory injects that directory's instruction files and any rule whose `paths:` frontmatter matches the file |
| Write checks | on | Right after a memory write, the model is warned about an oversized index, a file over the recall limit, a missing `description`, or `-2` continuation files |
| Recall | off | Up to 5 relevant memory bodies per question. `bm25` searches locally (Chinese, English, Japanese and Korean); `selector` uses one model call |
| Background extraction | off | After each turn, a forked helper saves what the main conversation missed. It can only write inside the memory directory |
| Consolidation (dream) | off | Merges, fixes and prunes the memory directory after 24 h and 5 sessions; `/dream` runs it on demand |
| Agent memory | off | Per-preset memory with `user`, `project` or `local` scope |

Memories live in `~/.dsh/memory/projects/<slug of the git root>/`, shared by all subdirectories and worktrees of a repository.

**Writes adapt to the sandbox.** When the sandbox allows writing the memory directory, the model uses the built-in `write`/`edit`. When it does not (for example `workspace-write`, where the directory is outside the workspace), Recollect mounts `memory_list/read/write/edit/delete` and switches the guidance to match. These tools write only `.md` files inside the memory directory and refuse secrets. Nothing is written in a read-only sandbox.

## Settings page

Two entry points share one form: the **Memory** section of the Settings dialog, and the Web sidebar's **Plugins** → Recollect → the `recollect` row. Adjust every option: memory on/off and write mode, the language of memory text, sharing with Claude Code, instruction wording and excludes, recall, background extraction and consolidation. Changes apply on save and are stored as a profile override; content already injected into a conversation updates at the next refresh.

The Memory section opens with **What is loaded**: pick a working directory (defaulting to the latest root session, excluding subagents) to list its injected instruction files and memory index with type and size, and its memory topic files with type, description and update time.

The panel also shows the Claude Code memory directory and topic count. **Share this project with Claude Code** saves the selection by Git root; turning it off removes every alias for that project. The switch is disabled when sharing globally, using a fixed `memory.directory`, or editing a read-only form. For an independent copy, choose **Preview import**, inspect copied/identical/conflicting counts, then **Confirm import**; conflicts keep existing files. Changing directory or configuration revision invalidates old previews. After import, root sessions using the target memory directory refresh on their next request.

## Commands

| Command | Purpose |
| --- | --- |
| `/memory` | Memory status, write mode, and every loaded instruction and memory file |
| `/pause-memory` | Pause or resume memory for this session (kept across restarts) |
| `/remember <text>` | Ask the model to save `text` to memory |
| `/memory-import [all] [--dry-run]` | Copy Claude Code memories; refuse a shared current project, skip per-project shares in `all`, and preview with `--dry-run` |
| `/dream` | Consolidate this project's memory now (requires dream to be enabled) |

Imports are refused while memory is disabled. Global sharing refuses `all`; a single-project import is refused only when that project actually shares memory. A fixed `memory.directory` overrides sharing: with only `shareProjects` configured, `all` imports every project into that fixed directory without skipping any. Sources stay read-only, existing target files are kept, and index lines are merged by link. Command output follows `language`.

## Configuration

You can also edit the profile's `cordis.patch.yml` by hand. A hand-written override replaces the whole config object; omitted fields keep their defaults.

```yaml
- id: recollect
  name: '@kirkchinese/dsh-recollect'
  config:
    language: en          # memory text and command output: zh / en
    memory:
      shareWithClaudeCode: false  # share all projects with Claude Code
      shareProjects: []          # absolute project directories matched by Git root
      directory: ""              # fixed directory overrides all sharing settings
      claudeHome: ""             # empty: $CLAUDE_CONFIG_DIR or ~/.claude
    recall: { enabled: true, method: bm25 }
    instructions:
      authority: strong   # strong: instruction files override default behavior (as in Claude Code); soft: guidance only
```

Precedence: fixed `memory.directory` → global `shareWithClaudeCode` → per-project `shareProjects` → independent `memory.root/projects/<slug>/`. Empty or incomplete `.git` directories are not repository roots; without a valid repository, the working directory is used.

Every field is listed in [lib/config.js](lib/config.js). `DSH_RECOLLECT_DISABLE_MEMORY=1` turns memory off (`0` forces it on), and `DSH_RECOLLECT_DISABLE_INSTRUCTIONS=1` turns instruction files off.

## Differences from Claude Code

- Every model gets the same complete guidance. Memory is never shortened or disabled based on the model name.
- All prompts are written independently for this project, with no Claude Code text, in Chinese and English. Recall uses an independent BM25F implementation.
- `AGENTS.md`, `.agents/rules` and `AGENTS.local.md` load alongside the `CLAUDE.md` family. Files with identical content in one directory are shown once.
- Invisible and control characters are stripped, and `</system-reminder>` in file content or paths is escaped.
- Adds `/remember`. Settings live on the Plugins page; `/memory` reports the current status and loaded files as text.

## Known limitations

- On a context overflow, DSH compacts and retries within the same step without the injection hook, so that single retry lacks the instruction block. The next step restores it.
- Headless mode exits right after the turn, so background extraction does not run there.
- The consolidation lock writes a PID and reads it back; it is not atomic. Do not run two host processes on one DSH home.

Recollect is not affiliated with Anthropic. "Claude Code" is used only to describe compatible file conventions.

## License

[MIT](LICENSE)
