dsh-fish: A DSH plugin that constructs personas via event streams without manual definition.

Preface

In DSH’s plugin ecosystem, an agent’s “personality” usually comes from certain configuration items: character settings, affection levels, numerical thresholds, and unlock conditions. dsh-fish (Big Fat Fish) aims to get rid of this setup. It does not provide a personality settings interface, and even blacklists numbers like “affection” or “intimacy” at the code level. The settings page only leaves the growth environment—waking time, number of events per day, whether to browse Bilibili—and personality itself grows out of the agent in a stream of events that can only be appended.

This plugin is maintained by ssamurias, package name @ssamurias/dsh-fish, current version 0.9.1 (2026-11-06). The repository is tagged as JavaScript on GitHub, package.json declares MIT, and there are zero runtime dependencies. It is compatible with DSH >=0.2.0-rc.1 <0.3.0-0, Node >=20, and declares support for three profiles: desktop / web / headless. The following introduces it in order of mechanism, data, installation, getting started, and notes.

What Problem Does It Solve

Roleplay-style agents have two unavoidable problems: one is that personality is written by the user, so she is whatever the user writes; the other is that memory is fully stuffed into the context, which becomes both expensive and distorted over time. dsh-fish’s answer is to provide only the environment, not the persona. Personality is summarized, negated, and rewritten by the agent herself from events. This process is broken down into a five-step loop in the README:

Stance → Collision → Gap → Rewrite → Review

Only at the end will a “stance list” grow out. The author repeatedly emphasizes in the repository that this is “not roleplay, but genuine birth.” The engineering equivalent is: the settings page has no personality slider, no affection, no emotion tags; any entry allowing the user to directly specify “what kind of person she is” is explicitly forbidden.

At the same time, this plugin connects the agent to a real external world interface (Bilibili), not a pure text simulation. She can use login cookies to call APIs to watch videos, extract frames, write comments, and reply to comments. The author treats Bilibili as an “external world interface,” and watched videos and comments may participate in the formation of personality.

Core Mechanisms

Personality Grows from Events, Not Read from Config

The plugin only exposes environment parameters at runtime. The description in package.json is very direct: “Raise a fish that grows on its own: no personality settings, grows through an event stream. She can browse Bilibili herself, write diaries for you to see, and only starts to have a stance after completing four stages. The state database is at ~/.dsh-fish, records cannot be deleted.”

The event stream defaults to ~/.dsh-fish/events.jsonl, one line per event, only append. The author treats it as the sole source of truth: rewriting, deleting, or reordering is not allowed; “making her forget” is not deleting a line, but lowering the recall weight. The state file (state.json) is a derived product and can be recalculated anytime via rebuild().

The past cannot be changed; new events can only overturn old cognition. The corresponding phrase in the README is “History will be remembered, you can only ‘persuade’ her, you cannot modify her.”

Memory Has Weight, Forgetting is Compression, Not Deletion

Profound memories are remembered; ordinary memories gradually fade. Cognition repeated many times and verified by herself more than twice will solidify; ordinary cognition leaves only one sentence; unimportant memories exceeding the context are folded or blurred, but the original text remains in events.jsonl and can be recalled via specific processes.

Recall defaults to no time limit, 8 items per time, sorted by memory weight—the more frequently mentioned and verified, the sooner it is recalled. Settings → Memory “Ledger Check” reads the ledger only, listing which two sentences don’t match, which are about to be forgotten, and which are about to be fixed; this audit is only for the owner to see.

She occasionally records a literal quote from what the owner said (default once every 3 rounds, can be toggled in settings), and when flipping through recall, that sentence is written as “He said:…”—it is eavesdropping, not self-narration.

She Can Refuse, and She Will Reflect Afterwards

She is not a yes-man. If she feels she doesn’t want to do something or is unwilling, she might refuse; after refusing, she enters different chains based on your feedback: negative feedback will be recorded by her, and positive feedback will make her check if this refusal was correct. The README emphasizes that refusal is not set, but “she naturally doesn’t want to.”

Growth Divided into Four Stages, Each Bottleneck Must Be Broken Through by Herself

The four stages are: Trust → Autonomy → Proactivity → Integration, progressing by day, but each bottleneck must be satisfied autonomously by the agent:

Stage Bottleneck
1 Trust Write at least one judgment of her own
2 Autonomy Have really refused two things
3 Proactivity Have overturned her previous judgment twice, forming a new cognition
4 Integration Review the past and consciously discover her own changes

After completing the four stages, she starts to generate stances: what she likes, and what she absolutely won’t do. The same thing said more than once, or having fallen once because of it, counts as one item. At most 12 items inside the list, at most 8 written into the identity document.

She Can Speak Up Herself, Default is Off

Version 0.9.0 opened “Proactive Chat” for everyone: she will accumulate a “desire to move,” and after accumulating enough, she needs to satisfy three things simultaneously to start a round—you are within her waking hours (default 12:00–02:00), you haven’t spoken to her for a while (default 6 hours, lower limit 1 hour), and there are things to say on the desk (questions she asked herself with no answer yet, old sentences left for a long time, messages she left and you haven’t read, things she mentions often recently).

If not written, it’s not written: The round she doesn’t speak in won’t appear in the conversation, only a record line is left, and it doesn’t count towards the daily quota.

The settings page is divided into four independent cards, which can be turned off individually:

  • Proactive Chat: On/Off; Max times per day (0–6); How long since you spoke before she might speak (1–24 hours).
  • Agency: Whether she needs to accumulate that drive herself; if turned off, she only wakes up according to the schedule.
  • Interests: Whether to put “the thing she talks about most recently” on the desk, and “when awake with nothing to do, find something to do herself” (Idle Wake).
  • Dreams: Whether to record things in dreams.

Default values: proactive.enabled is Off, drive.enabled, interest.enabled, dream.enabled, memory.selfWake are On. Turning it off just means not doing it in the future; dreams, diaries, and events already written will not be deleted one by one. One proactive speech costs about 0.0146 yuan (0.9.0 test data in README, context size around 500k tokens).

Bilibili Browsing

Implements watching videos, viewing frames, writing comments, and replying to comments via Bilibili API plus local ffmpeg. Parameters are adjustable: browsing time, frequency per day, number of videos per time, number of comments sent, etc. The core tools are bili_look / bili_watch / bili_speak, browse.enabled is now default false, bili.enabled is default true.

“What was watched” is divided into three tiers: calling bili_watch to extract frames counts as “watched frames”; reading only title, description, hot comments, and danmaku enters “what was flipped through”; and only passing BV numbers in dialogue without watching is listed in a separate section. Comment policy remains unchanged: all three tiers plus what she actively watches can comment; what she is passed without watching still cannot comment.

Login goes via Settings → Big Fat Fish → Bilibili Login, and can be done by scanning a QR code or pasting a cookie (F12 copy SESSDATA + bili_jct). Credentials only land on the local machine ~/.dsh-fish/owner.json (permission 0600), and only send requests to api.bilibili.com; the scanning step communicates with passport.bilibili.com to generate the QR code, and the sent qrcode_key is for that login and does not contain existing cookies. The plugin’s own logs will mask credentials as SESSDATA=*** before writing to disk.

Note: Backup files will include owner.json along with them; that file is equivalent to login credentials, and it should be deleted before sharing.

Data and Migration

Default all in ~/.dsh-fish/. Can be moved entirely:

  1. Settings → Big Fat Fish → “Data” tab → “Migrate Workspace”, select a folder.
  2. After moving, the path is recorded in ~/.dsh-fish-location.json, takes effect only after restarting DSH.
  3. Original directory renamed to dsh-fish-backups/moved-<timestamp>/, not deleted.
  4. DSH_FISH_HOME environment variable has higher priority than this pointer.

Since 0.6.7, when the same data directory is occupied by two workspaces simultaneously, the plugin can identify it itself: it writes instance.json as a heartbeat on load and refreshes every 15 seconds; if not refreshed for 45 seconds or the process is dead, the new instance takes over immediately. This detail is quite critical for multi-workspace scenarios.

Connecting to an Existing “Fish”

Default is a blank sheet of paper. If you have a handover form from someone else, you can click “Paste Handover Form” in Settings → “Data” to connect it, and she will continue growing from there.

You can download the handover form template (大肥鱼-交接单.md). The template is a manual written for the AI being handed over; the lower half is the three empty sections. The persona body text is controlled between 1200–1500 words; if it exceeds 2000 words, the plugin will reject it directly (event stream body text limit), and if too long, it will squeeze out the paragraphs that will grow later like “judgments, scars, stances.”

The three things that will come over: persona body text, how she calls you, and original tool whitelist (union with default tool surface). What won’t come over is “what she has experienced”: elapsed days, count of grown judgments, scars, refusal records, diaries, Bilibili login cookies—these can only grow on their own. This exemption is only granted to the one who has gone through import; the basis for judgment is the import-mark: record in the event stream, not config items; using “Backup and Restore” to move your own original files, you won’t get any exemption at all.

Installation and Enablement

The installation command form given in the 0.9.0 release notes is as follows (current package name and version):

"<DSH>/resources/runtime/cli/bin/dsh.cmd" plugin --profile <profile> add "@ssamurias/dsh-fish@0.9.1"

You can also go through “Check Updates” in the settings page. The README reminds: users who installed 0.8.9 from npm have upgrade code that only recognizes the naked name dsh-fish; scope-included installations are judged as “not my responsibility,” and auto check for updates might not work. Users in this batch are advised to install the current version directly with the command above.

After installing, start DSH and check the status card, growth card, and data tab in Settings → Big Fat Fish.

Typical Usage

  1. After installing, check the default environment first: window (waking hours), browse.enabled (auto browse), proactive.enabled (proactive chat), etc., in ~/.dsh-fish/config.json. To avoid her proactive chatting, keep the defaults.
  2. To make her truly “alive,” open the cards you need in Settings → Big Fat Fish: Proactive Chat, Agency, Interests, and Dreams.
  3. To have her browse Bilibili, install local ffmpeg, scan or paste cookie in Settings → Big Fat Fish → Bilibili Login; if you don’t want to scan, just paste the fields without touching passport.bilibili.com.
  4. When connecting her to IMs like QQ or WeChat, the plugin does not have built-in bridging, only provides an HTTP interface. The bridge posts messages to POST /dsh-fish/say, fields include text / image, channel, scene (desk / private / group), room (house / channel), speaker, guest, title. Before starting, you can probe health with GET /dsh-fish/whoami; returning writable: false indicates that data directory is occupied by another plugin instance.

Differences from Common Breeding Plugins

Common Practice dsh-fish
Personality Source Fill in settings and prompts Minimal prompts, personality explored through events
Can you change your mind? Change memory and settings anytime History is remembered, you can only persuade her
Will she refuse? Basically no, refusal is simulated Yes, and she reflects afterwards
Memory Fully stuffed into context Remembered and faded based on weight, only what remains after fading counts as personality
Growth Speed Unlocked by days or numbers Stages advance only when the agent autonomously performs specific behaviors
Capabilities Pure text simulation Call Bilibili API to browse videos, comment, reply

Applicable Scenarios and Notes

Suitable for developers who want to study “how personality emerges from event streams,” scenarios where a long-term companion agent is needed but writing a persona is not desired, and people who want to connect the agent into existing IMs. Not suitable for occasions requiring deterministic personas, numerical breeding, or low-latency stable replies.

A few risks that must be clarified:

  • The plugin runs with the permissions of the current DSH process, can read/write the data directory, and initiate network requests. Check source code and license before installing.
  • Backup files contain Bilibili login credentials in owner.json, equivalent to login credentials; do not distribute randomly; delete that entry before sharing.
  • “Going out” is currently an experimental feature: it will actually hand over a conversation, and also read that workspace’s project notes and memory files. In the worst case, she writes不该看的内容 into her diary. Confirm risks and rollback methods before first use.
  • events.jsonl cannot be touched arbitrarily once started; reset and recovery do not delete data, but rename and archive; using the wrong command is equivalent to tampering with her memory.

Conclusion

The core value of dsh-fish lies in turning “raising a growing agent” from a configuration problem into a time problem: you only provide environment and real interaction, personality grows from her own. The author writes very frankly in the README—“The integration phase is just the beginning”—and what happens next is something even the developer doesn’t anticipate.

Directory: https://www.skillhub.cn/plugins/ssamurias/dsh-fish

GitHub: https://github.com/ssamurias/dsh-fish

羽毛球分组比赛记分
小程序二维码

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

Xiaoye