openloomi-pet
GitHub管理 OpenLoomi Pet 状态与外观。支持通过命令或 Hook 设置 9 种状态(如 happy、working),并提供自定义主题、角色及单精灵覆盖的决策指南,指导用户通过文件系统配置外观而非直接修改配置。
Trigger Scenarios
Install
npx skills add melandlabs/openloomi --skill openloomi-pet -g -y
SKILL.md
Frontmatter
{
"name": "openloomi-pet",
"description": "OpenLoomi Pet sprite and state helper for Codex. Use for pet state, themes, custom characters, and sprite overrides.",
"allowed-tools": "Bash(node $SKILL_DIR\/..\/..\/scripts\/loomi-bridge.mjs *)"
}
OpenLoomi Pet Sub-skill
The Loomi Pet has 9 universal state names. The plugin ships the fox
(loomi-*) sprite set for branding; the OpenLoomi runtime's
state-resolution watcher renders the matching sprite for whichever
theme you have active (fox or capybara, or any folder under
~/.openloomi/pet-custom/). State set:
| State | When to use |
|---|---|
happy |
A task just completed successfully |
idle |
Loomi is waiting for the next loop tick (watcher-only — do not set from Codex) |
juggling |
Multiple sub-agents are running |
needsinput |
Permission prompt / elicitation dialog visible |
presenting |
Fresh decision requires the user's review (watcher-only — do not set from Codex) |
sleeping |
Local hour outside 6–22 with no pending work (watcher-only — do not set from Codex) |
sweeping |
User dismissed a card just now (watcher-only) |
thinking |
Between steps, awaiting LLM response |
working |
A tool call is in progress (PreToolUse hook fires this) |
Available commands
node $SKILL_DIR/../../scripts/loomi-bridge.mjs pet <state>— synchronous, returns JSON; use only when the user explicitly asks.- Hooks call
state <name>automatically (fire-and-forget, 2s timeout).
Sprite set is hardcoded in the bridge — invalid state names are rejected
before any HTTP call. The endpoint POST /api/pet/state may not yet exist
in the target OpenLoomi runtime; the bridge falls back to "would have set
state to X — pending OpenLoomi endpoint" without raising an error.
Help the user customize their pet's appearance
The bridge only drives the state — sprite overrides and theme folders
are file-based and live outside the plugin. When the user asks to "change
the pet's look" or "add a custom character", walk them through the file
system. Do not try to write pet-config.json from the bridge; the
bridge has no such command and the runtime's file watcher does the work.
Decision tree
- "I just want the other built-in" → right-click Loomi →
Theme → Fox/Theme → Capybara. Persisted in~/.openloomi/pet-config.jsonunderactiveTheme. Long-press (~600 ms) is the fallback ifcontextmenuis swallowed by the host. - "I want my own character" → drop a folder at
~/.openloomi/pet-custom/<name>/with PNGs named after the states. The watcher auto-discovers it within ~250 ms and the theme appears in the menu. - "I want to change just one sprite" → edit
~/.openloomi/pet-config.json'soverridesmap. Wins over both built-ins and custom-theme sprites for the matching(theme, state)pair. - "I want to make my theme the default" → set
activeThemeto the custom theme's folder name.
What the bridge can and can't do
| User intent | Bridge role |
|---|---|
Flip to happy mid-task |
pet happy — yes |
| Switch fox ↔ capybara | No — that's a menu action or pet-config.json edit; do not try the bridge |
| Add a custom character | No — direct them to ~/.openloomi/pet-custom/<name>/ and the file watcher |
| Override a single sprite | No — direct them to ~/.openloomi/pet-config.json's overrides map |
| Diagnose "the pet isn't switching themes" | Direct them to the troubleshooting section in pet docs |
| Drive the pet from their own tool | Direct them to POST /api/pet/state — see Pet API |
Filename conventions to communicate
When guiding the user through a custom theme, surface these conventions up-front:
- PNG only.
.gif,.webp,.apng,.lottieare silently ignored. - Bare or prefixed names both work.
idle.png,loomi-idle.png,capybara-thinking.png,my-pack-sweeping.pngall normalize correctly (case-insensitive). - One recognizable state PNG is enough. The folder is registered as a theme as soon as it has ≥1 normalized state stem; missing states fall through to the active theme's
idlesprite. - Hidden / dot-prefixed folders are ignored.
.git,.DS_Storeetc.
Override JSON shape to communicate
The overrides map is camelCase on the wire — activeTheme, customThemesDir. Snake_case keys silently no-op the assignment (a unit test in the runtime pins the contract). Use the exact shape:
{
"version": 1,
"activeTheme": "fox",
"customThemesDir": "~/.openloomi/pet-custom",
"overrides": {
"fox": {
"idle": "/absolute/path/to/my-fox-idle.png"
}
}
}
Absolute paths only — the runtime routes them through tauri::convertFileSrc, so relative paths and ~/ prefixes will not resolve.
Common pitfalls to surface
- The folder doesn't show up — usually a missing or mis-named state PNG. Run them through the filename convention table.
- Override doesn't apply — host log line
[loomi-pet/theme] failed to parse ~/.openloomi/pet-config.jsonmeans the JSON itself is malformed and defaults loaded. Host log line[loomi-pet/theme] failed to read <path>: <io error>means the path doesn't resolve. - Theme menu tick is wrong / stuck — almost always a camelCase vs snake_case wire-format mismatch. The widget reads
activeTheme, notactive_theme. sleeping/sweepingrejected by/api/pet/state— those are watcher-only vocabulary; the runtime returns400 invalid_state. Do not POST them from your tool.
What NOT to do from Codex
- Do not try to call
POST /api/pet/statewithsleepingorsweeping. The API rejects them; the watcher owns them. - Do not try to write
pet-config.jsonfrom the bridge. The bridge has no command for it; the file watcher owns updates. - Do not invent new state names.
CAPYBARA_STATESrejects them before any HTTP call. - Do not claim support for non-PNG sprite formats. The asset pipeline is static PNG only.
- Do not say "I'll set up your custom theme for you" if you can only walk them through the file system. The watcher does the work; you guide.
See also
- Customize your Loomi Pet (user docs) — full guide to themes, custom folders, overrides, troubleshooting
- Pet API —
POST /api/pet/statefor external tools - Attention Agent — the desktop pet as a whole
Sandbox and network
If node ... loomi-bridge.mjs pet <state> or POST /api/pet/state fails
with a network error (ECONNREFUSED, ETIMEDOUT, "unreachable"), check
whether Codex is running inside a sandbox before concluding the OpenLoomi
desktop API is stopped. Codex network sandboxing can block loopback access
to the host's localhost (e.g. http://localhost:3414). The bridge's
"would have set state to X — pending OpenLoomi endpoint" fallback hides
this in many cases, but a genuine ECONNREFUSED still surfaces.
Request approval and retry the same command outside the sandbox. If the
outside-sandbox retry succeeds, treat the in-sandbox failure as a sandbox
artifact. Do not tell the user the pet API is broken until the
outside-sandbox retry also fails. See openloomi for the canonical
loopbackAccess.verification.commands probe.
Version History
-
5296a2a
Current 2026-07-22 19:46
移除源码路径引用,更新为关注点描述;将map_state_to_pet重命名为state-resolution watcher;替换Tauri安装文档引用为bridge命令。
- 23e340f 2026-07-19 17:58


