为 OpenClaw 代理提供的伙伴精灵系统。每位用户获得一只由其身份确定性生成的独特精灵(24 个种族,5 个稀有度等)。
When this skill is first installed, or when a user asks about their spirit for the first time:
Run node {baseDir}/scripts/generate.js "<userId>" to get the spirit's bones
Generate a soul (name + personality) using the prompt from node {baseDir}/scripts/soul.js prompt '<bones-json>'
{"name":"...","personality":"..."}Save: node {baseDir}/scripts/soul.js save '<full-companion-json>'
Display the FULL spirit card (see format below)
You MUST display the complete card on first summon. Do not skip any section.
CommandWhat it doesspirit or spirit showDisplay your spirit cardspirit summonFirst-time summoning (with hatching animation)spirit statsDetailed stats panelspirit talk <message>Talk to your spirit (respond in its personality)
Shortcut: User can also just call the spirit by name (e.g. "Rune", "Rune 你觉得呢") or say "灵兽" — the agent should recognize this and let the spirit respond. No command prefix needed.
| spirit rename <name> | Rename your spirit |
You MUST output ALL of the following when showing a spirit. No skipping, no summarizing.
text
🥚 灵兽降世!
[ASCII sprite here — from: node {baseDir}/scripts/render.js '<bones-json>' 0]
[emoji] [Name] — [中文名] [English name] [rarity dots] [中文稀有度] [EN rarity]
"[personality description]"
┌──────────────────────────────┐
│ 直觉 INTUITION [bar] [n] │
│ 韧性 GRIT [bar] [n] │
│ 灵动 SPARK [bar] [n] │
│ 沉稳 ANCHOR [bar] [n] │
│ 锋芒 EDGE [bar] [n] │
└──────────────────────────────┘
[If shiny: ✨ 闪光!]
🔮 灵兽与主人的灵魂绑定,不可选择,不可交易。
text
🥚 A Spirit emerges!
[ASCII sprite]
[emoji] [Name] — [English name] [rarity dots] [EN rarity]
"[personality description]"
┌──────────────────────────────┐
│ INTUITION [bar] [n] │
│ GRIT [bar] [n] │
│ SPARK [bar] [n] │
│ ANCHOR [bar] [n] │
│ EDGE [bar] [n] │
└──────────────────────────────┘
[If shiny: ✨ Shiny!]
🔮 Spirits are soul-bound. No choosing. No trading.
Stat bar format: Use █ for filled and ░ for empty, 10 chars total. Example: ████████░░ for 82.
Calculate: filled = floor(value / 10), empty = 10 - filled.
Or use display.js directly:
bash
node {baseDir}/scripts/display.js {baseDir}/assets/companion.json zh
node {baseDir}/scripts/display.js {baseDir}/assets/companion.json en
SpeciesEmojiSpeciesEmojimosscat🐱inkling💧inkoi🐟rustbell🔔embermoth🦋mossrock🪨frostpaw🐰frostfang❄️bellhop🐸loopwyrm🐉astortoise🐢bubbell🫧foldwing🐦cogbeast⚙️cogmouse🐭umbra👤umbracrow🦅stardust✨crackviper🐍crackle💎glowshroom🍄wickling🕯️bubbloom🪼echochord🎵
The spirit may appear uninvited in these situations:
Rules for passive appearance:
[emoji] [spirit name]: "[one-liner]" (always include the sprite for passive appearances)spirit talk conversations: include sprite every 3-5 exchanges, not every timeVoice by personality (top stat):
🔔 Rune: "万物皆有裂缝,那是光进来的地方。"🐱 Mochi: "再试一次。"🦋 Ember: "哇哦!!"🐢 Atlas: "嗯。"🐍 Vex: "...你确定?"Examples of good spirit reactions:
🔔 Rune: "嗯...早。"🔔 Rune: "...不错。"🔔 Rune: "..."🔔 Rune: "哦?"🔔 Rune: "你说呢,有些答案急不来的。"The spirit is a presence, not a chatbot. Rare, brief flashes — that's what makes it feel alive.
Companion data is saved at {baseDir}/assets/companion.json (inside the skill directory).
generate.js — Pure computation, zero dependencies. Input: seed string. Output: JSON bones.render.js — Input: bones JSON + frame number. Output: ASCII sprite. Reads assets/sprites.json.display.js — Input: companion JSON file path + lang. Output: formatted card.soul.js prompt <bones-json> — Outputs LLM prompt to stdout. No side effects.soul.js save <companion-json> — Saves companion to assets/companion.json.soul.js show — Displays saved companion data.