dsh-wildmon
野外怪物收集插件,将用户的实际工作转化为草丛,通过对话、工具调用和错误触发野生怪物出现,支持捕捉与组队。
AI 分析
核心用途是将 DSH 的日常使用转化为收集类冒险游戏。适合想要在枯燥的编码或调试工作中寻找随机惊喜的用户。零 Token 消耗,不影响 Agent 运行上下文。
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:swaylq/dsh-wildmon说明文档
阅读完整 README ↗dsh-wildmon
English | 中文
Your real work is the tall grass. Turns, tool calls and errors rustle it — wild critters pop out at random, you throw balls, fill a 28-slot dex, and walk with a team of six. The small hours wake nocturnal species, errors wake the glitch ones, and three legendaries each guard their own appearance condition.
Zero tokens, zero tools, zero context injection: the model never learns any of this exists.
野生的 绒电鼠 Volttuft 出现了!◈ 少见 · 常野原
(A wild Volttuft appeared! Uncommon · Field)
⟋⟍ ⟋⟍
(⚡ᴥ⚡)
c( )ɔ
⌁⌁
球 ×9 —— /mon throw to throw · /mon run to retreat

Why this exists
The DSH pet lane is busy: twenty-plus desk pets are state mirrors (agent thinks, pet does a thinking animation), and dsh-digipet added raising (one pet eats your work and evolves).
Collecting was still an empty slot: no encounters, no catching, no "looking forward to the next error because the dex wants it." As of 2026-08, searching the dsh-plugin topic (2,800+ repos) and all four curated awesome lists for pokemon / pokedex / catching / gacha returns zero hits. dsh-wildmon fills that slot — the complete collect-em-all loop (encounter → catch → dex → team) mounted on your actual workflow.
It complements digipet rather than replacing it: digipet is depth with one creature, wildmon is breadth across many. Both install side by side (different command, different save file).
How to play
/mon start— pick one of three starter-trio critters, get 8 balls.- Work normally. Every turn, message, tool call and error has a chance to rustle the grass; the longer nothing shows, the higher the odds (a pity mechanic).
/monto check. A wild one waits 10 minutes, then wanders off./mon throw. Rarer species are harder to catch; every miss improves your next throw — but it may also bolt.- Fill the dex, build the team: your first six catches auto-join, and slot 1's aura raises its home habitat's encounter rate ×1.5. Rearrange with
/mon swap.
Habitats: how you work decides who you meet
| Habitat | What rustles it | Residents |
|---|---|---|
| Field (常野原) | messages, turns, unclassifiable tools | Fluffgrub, Dotfinch, Volttuft… |
| Forge (锻造窟) | writing files, running commands | Malletclaw, Cogbadger, Coredrake… |
| Archive (墨书林) | reading code, searching docs | Markmoth, Indexowl, Tomewyrm… |
| Glitch ridge (故障岭) | failed tools, agent errors | Shardtoad, Tracepede, Panicray… |
| Night bound (夜阈) | anything between 00:00–05:59 | Lunasmudge, Dozetapir, Stardrift |
Plus the starter trio (the two you didn't pick roam the field) and three legendaries: one surfaces every 250 turns; one only answers a deep-night error; the last only visits collectors who completed the first 25 slots. Shinies exist, at 1/64.
Ball economy: 8 to start, +1 per finished turn (cap 30), and catching a species you already own trades the catch back for 2 balls — duplicate encounters are never a loss.

Install
dsh plugin --profile web add github:swaylq/dsh-wildmon
# or a local checkout
dsh plugin --profile web add /path/to/dsh-wildmon
Restart dsh. Pure JavaScript, zero dependencies, no prepare script — installing from git needs no build approval.
Already running dsh-digipet? Just install this too; they don't interact. If /mon collides with another plugin, override config.command in your profile patch.
Commands
| Command | Does |
|---|---|
/mon | Check the grass: encounter card (art, rarity, time left) or quiet status |
/mon start | Begin the journey (bare form lists the three candidates) |
/mon throw | Throw one ball at the live encounter |
/mon run | Back out of the standoff |
/mon dex | Collection: caught ● / seen ◐ / unknown ○; legendaries show only rumors |
/mon team | Party and box (its numbering feeds swap / name) |
/mon swap | Reorder the party or exchange with the box (slot 1 leads) |
/mon name | Nickname a caught partner (16 chars) |
/mon story | The journey log |
/mon about | Mechanics and the trust stance |
How it works
The whole plugin is four event taps and one slash command; the taps only roll dice:
| Tap | Base encounter rate |
|---|---|
agent/turn-stopping (also refills 1 ball) | 9% |
agent/inbox/claimed (your messages) | 5% |
tools/result (routed by tool name to forge/archive/field; failures → glitch) | 6% / 16% on failure |
agent/error | 20% |
On top: +0.8% per quiet event (capped at +25%), lead's home habitat ×1.5, and at night a 70% roll swaps in the night pool. Catch odds = rarity base (65% / 45% / 28% / 12%) + 12% per prior miss, capped at 95%; after a miss the wild one may flee at a rarity-scaled rate. Every number lives as a named constant at the top of core.js.
The save lives at $DSH_HOME/wildmon/state.json, written the way the official JSON storage backend writes: temp file + fsync + atomic rename, throttled to one write per 1.5 s no matter how busy the agent is.
The invariant that matters: model-visible means logged — and this plugin simply shows the model nothing. No tool registration (tool schemas are a per-request token tax), no agent.inject(), no session events. The whole game lives in command result cards and contributes zero bytes to every model request.
Trust stance
- Reads: only its own save file. Never your code, never conversation content — the listeners use only what kind of thing happened; message and tool payloads never touch the save.
- Writes: only
$DSH_HOME/wildmon/state.json. - Network: none.
- Model-visible surface: none. Zero token cost; KV cache untouched.
- Randomness: affects the game only. The listeners never veto, rewrite or delay real work (all hooks are notification-mode events).
- Blast radius: every listener is wrapped in try/catch and the command handler has its own catch — a collapsing grassland cannot land on your work.
Known limits
- One dex per DSH home; all profiles, sessions and subagents on the machine share (and rustle) the same grass — feature and limit at once.
- Concurrent dsh processes: last writer wins, same single-process stance as the official JSON backend.
- Encounters don't notify you (the price of a zero model-visible surface) — you check with
/mon; the wild ones wait 10 minutes and misses land in the story log. - Tool routing is a name-regex heuristic; oddly named third-party tools count as field.
- The night window is machine-local 00:00–05:59; travel across time zones and the nocturnals jet-lag with you.
- Rates and thresholds are not configurable: changed numbers would leave the dex and the save with no common language.
Verification record
Verified for real on dsh 0.1.0-rc.6 (macOS, web profile):
- Installed with
dsh plugin --profile web add; the wildmon layer shows in--dump-config; dsh webboots clean;- In a real browser,
/mon startpicks a partner and the send-off card renders (monospace, newlines kept); - Six plain messages without an API key — every model request fails, but
inbox/claimedandagent/errorare real events: the save recordedmessages:6, mishaps:6, and with pity at 10 the 6th round really spawned a Shardtoad (error event → glitch ridge, matching the table); /mon throwmissed once (the card showed the throw-bonus note), caught on the second — party 2/6, dex 2/28, balls ×6 = 8 − 2 throws; the save reconciles line by line with the observed events;- Observed caveat: on rc.6, MISSING_CREDENTIAL failure rounds do not fire
agent/turn-stopping, so the per-turn ball refill wasn't observable on a keyless machine (it needs turns that complete); that path is covered by unit tests; - 61 unit/integration tests (
node --test) covering pure logic, rendering, the store and a fake-ctx integration.
Homage and boundaries
The design pays homage to the collect-em-all genre's traditions (grass encounters, the three-shake catch, a dex, a starter trio, an electric rodent, shinies). Pokémon is a trademark of Nintendo / Creatures / Game Freak; this project is not affiliated with them in any way. All 28 species names, ASCII art and text are original; no official names, characters or assets appear. The ball is just a ball that wobbles — that belongs to everyone who loves collecting things.
License
MIT