Introduction¶
Large models start with a blank slate for every new session: the names discussed, preferences, and agreements from last time either have to be recounted from scratch or completely discarded. The common approach is to stuff memory into the context window, but the context is limited; stuffing too much is both expensive and suppresses the model’s performance; or one simply saves it to a database, thereby disconnecting it from code, versions, and diffs.
dsh-soul-forging offers a different approach: memory is stored in pure Markdown, purely local, zero-dependency, and runs on Python 3 alone without needing a server or a database. It is maintained by Fqingwan and is positioned as a memory plugin for DSH, with the slogan “Separate Vessels, One Heart · 异体同心” (Different Bodies, One Heart) — the same AI can have multiple entry points on a phone, in a group chat, or on a computer, but there is only one memory library. Whatever is written is appended to it, labeled by the source field.
Below is an introduction to its design, commands, and integration methods.
Three-Layer Memory, Not Three Features¶
This solution divides memory into three layers, each with different responsibilities, rather than stacking several features side-by-side:
| Layer | Location | Who Reads |
|---|---|---|
| Injection Layer | SOUL.md, identity/注释层.md, MEMORY.md, index.md, NOW.md |
Read every round, so it must be short |
| Retrieval Layer (Cerebellum) | brain/entries.json |
Only checked when needed |
| External Layer | docs/tech, docs/debug |
Not injected into context, only checked when errors occur |
Corresponding to the time dimension, there is another division of labor: short-term memory is written to NOW.md, with three sections flushed at the end of each session; medium-term memory goes into log.md, diary/, live.jsonl, written by soul write and slimmed down by soul-archive; long-term memory settles in SOUL.md, core/, identity/, established by Soul Forging and refined back into the comment layer by persona-sediment.
Forgetting is part of this design, not a flaw. The script attenuates memory intensity based on the salience field: 1 is almost never forgotten, 3 will fade away on its own, and things recalled repeatedly become more solid. There is a subtle detail here that is easy to confuse: “Forgetting” comes in two types with different meanings.
soul-forget # Only removes from the retrieval index, original text remains on disk (don't want to be dug up)
soul-forget --restore <id> # Retrieve and pin it
soul-purge "keyword" # Preview: which lines will actually be deleted
soul-purge "keyword" --apply # Actually delete + Git reinitialize
soul-forget means “don’t want to be dug up,” the original text is not deleted and can be retrieved at any time. soul-purge is true “forgetting,” deleting lines containing keywords from the file and reinitializing Git, leaving only a SHA256 fingerprint. The author explicitly states: it does not touch backups; cloud-based old volumes are the user’s own responsibility.
Personality Has Only Two Layers, Plus Raw Materials¶
The personality part is split into two layers to maintain because they change at different frequencies:
Essence (Static) Desires / Fears / Tug-of-war / Skeleton → SOUL.md
|
Comment Layer How I look right now, first-person, no bullet points → identity/注释层.md
|
Raw Materials Quoted words · Diary · Cerebellum · Base color.md Details
The Essence changes rarely, while the appearance can grow indefinitely; splitting the two layers means that if something is wrong, it’s easy to identify which layer is to blame. The Comment Layer has hard constraints, as stated in the template: first-person, no sub-sections, no labels, every sentence must anchor a quote. The README also specifically provides a negative example — “Step 4: Emotional Expression Guardrails (harshness, passive-aggressive, cold sarcasm)” — stating that this is an operation manual, not a person.
Installation and Activation¶
When the DSH plugin is installed, memory is automatically injected every round:
soul-init # Initialize empty memory library to ~/.soul-forging/memory
dsh plugin add dsh-soul-forging # Install into profile
# Restart DSH, and memory is automatically attached
If using the command line without installing the plugin:
git clone https://github.com/Fqingwan/dsh-soul-forging
cd dsh-soul-forging && bash install.sh
No server is required. To change the memory location, set MEMORY_DIR, or modify memoryDir in the plugin configuration.
There are two pitfalls worth knowing ahead of time during installation. Global installation requires sudo; if not granted, it will report EACCES: permission denied, mkdir '/usr/local/lib/node_modules'. If you don’t want to use sudo, switch to a user-level prefix. Another issue is that domestic mirror sources may lag; configuring mirrors like Taobao or Tencent Cloud and installing a new version may report No matching version found. At this point, specify the official source.
sudo npm i -g dsh-soul-forging
sudo npm i -g dsh-soul-forging --registry https://registry.npmjs.org
There is one thing more important than the command itself: Make sure to run soul series commands as a normal user daily, never use sudo. The code and data are separate; code is in node_modules/dsh-soul-forging/ (replaced entirely when upgrading), and data is in ~/.soul-forging/{memory,brain} (not touched when upgrading). sudo changes HOME to /root, so it looks for /root/.soul-forging, which looks like memory has been lost.
Three Installation Modes, Corresponding to Three Types of People¶
Not everyone wants a “personality AI,” so you can choose during initialization:
soul-init # Full set: memory + personality template
soul-init --memory-only # Memory only, no personality
soul-init --external # Personality belongs to your own agent, we only manage memory
| Mode | Injects | Suitable For |
|---|---|---|
full |
SOUL + MEMORY + index + NOW | Want to grow a personality from scratch |
memory-only |
MEMORY + index + NOW | Only want it to remember, don’t want to touch the persona |
external |
index + NOW | Agent already has its own prompt/persona |
There is an implementation detail worth mentioning here: Empty templates are never injected. A filled-out SOUL is full of “(to be filled)”, stuffing it into the context is worse than not stuffing it; the model will solemnly introduce “My name is (to be filled)”. Therefore, if a page has more than 3 placeholders, it is automatically skipped. --keep-empty can be used to force retention (for debugging).
Soul Forging: First, Clarify “Who Am I”¶
The first thing after installation isn’t to work, but to clarify “Who Am I.” Open memory/BOOTSTRAP.md, go through it item by item: name, personality, values, boundaries, who the master is, what kind of companionship is desired. The author emphasizes moving forward one item at a time — asking everything at once is a questionnaire, not a chat.
After writing back to the file, check the box. Once complete → status: complete + soul-sync. To start over, change status back to pending; existing memory will not be cleared: the re-forging is of the personality, not the memory.
Injection Has a Budget; Exceeding It Must Be Stated¶
The plugin configuration bootMaxChars (default 20,000 characters). After exceeding, it truncates sequentially from the end, and at the end of the injection block, it clearly states which segments were truncated and which were completely omitted.
The author’s explanation for this behavior is that silent truncation is the worst kind of confidence; the model will think it saw everything and then pretentiously guess based on half the memory.
Daily Usage¶
Commands are divided into groups by purpose. Writing, Retrieving, and Maintenance:
soul write "content" --kind chat --section subtitle # Write
soul-recall "keyword" # Retrieve from Cerebellum
soul-recall --topics # See what categories exist
soul digest # Wrap up: which four steps to do
soul-compact # Budget check: size of injection layer, what to compress
soul-archive # Timeline slimming, old ones go to archive but are still searchable
soul-sediment # Personality sedimentation: accumulate enough prompts to refine back into the Comment Layer
soul-review # Narrative refinement: connect fragments into "My journey"
Troubleshooting and Safety Nets:
soul-debug # Archive a debug record
soul-debug-recall "keyword" # Search previous debug archives
soul-debug-detail <filename> # View full text of an archive
soul-snapshot save "description" # Save a snapshot
soul-snapshot ls / restore / diff
Dual-ended:
soul-peer export # Export
soul-peer import # Import
Services and Wrap-up:
soul-serve # Start retrieval service, default 127.0.0.1:3013
soul-sync # Summarize → Slim → Build Index → Reload → Health Check
Integrating into Other Agents¶
This won’t grow on the model itself; you must feed memory into the system prompt at the beginning of every round:
soul-boot # Print injection block, splice to front of system prompt
soul-boot --budget 12000 # Limit length, truncate from end if exceeded, prioritize SOUL
It can also be used as a Python module. boot() is read-only and doesn’t modify any files. To write memory, you must explicitly call remember():
from soul import boot, recall, remember
system_prompt += boot()
context = recall("He said he cares about what", n=3)
remember("Today he said he wants to change direction", kind="chat")
Multi-Device Sync and Cloud Backup¶
The principle of multi-device sync is simple: whoever writes appends a line to live.jsonl, tagged with source to indicate origin. Syncing is simply copying over ids that the other side doesn’t have, skipping duplicates. No central server is needed; as long as both ends can see the same file, they can communicate.
soul-peer pull "ssh host cat ~/.soul-forging/brain/live.jsonl"
soul-peer push "ssh host 'cat >> ~/.soul-forging/brain/live.jsonl'"
For cloud backup, just set SOUL_BACKUP_CMD. Once set, soul-sync runs it alongside every time. If not set, it won’t run:
export SOUL_BACKUP_CMD='tar czf ~/soul-backup.tgz -C /path/to/repo memory'
Source and License¶
Plugin version 0.2.1, license MIT, requires preserving the copyright lines in LICENSE and NOTICE.md. Zero third-party dependencies at runtime, only Bash + Python standard library + DSH’s own plugin interface. One point to note: the underlying memory architecture comes from dsh-plugin-memory (v0.10.0 · MIT). This project is a rewrite based on that approach, without copying source files, and NOTICE.md is included with the package; the two can coexist.
Suitable Scenarios and Notes¶
Suitable for developers of agents who want “long-term memory but don’t want to introduce a database or cloud dependencies”; also suitable for scenarios with multiple entry points where different entry points should share the same personality. It explicitly supports single-user only; sharing the same memory library among multiple people will cause the personalities to get mixed up.
Two engineering reminders. First, the plugin runs with the permissions of the current DSH process. Before installing, open the source code and check to ensure the directories and commands it reads and writes behave as expected in your environment. Second, the license is MIT, but the underlying architecture comes from dsh-plugin-memory, NOTICE.md is included with the package, and the two can coexist.
The limitations listed in the README are worth copying over: retrieval is literal matching and doesn’t understand meaning; “My boss yelled at me today” and “Getting treated badly at work” may not find each other via search; semantic search requires vectors. “Can an empty shell be filled with personality?” has not been verified by humans. It is certain that the code runs, but whether it produces a person with personality or a resume, only humans who have tried it know.
Getting Started¶
- First, install the plugin:
soul-initto initialize the memory library, thendsh plugin add dsh-soul-forging. - Open
memory/BOOTSTRAP.md, clarify “Who Am I” item by item, and check the box after writing back. - Daily use
soul writeto record,soul-recallto check, andsoul-syncto wrap up. - When integrating with other agents, use
soul-bootto splice the injection block to the front of the system prompt.
Directory Page: https://www.skillhub.cn/plugins/Fqingwan/dsh-soul-forging
GitHub: https://github.com/Fqingwan/dsh-soul-forging