MiniMax-AI / MiniMax-AI/minimax-code
[Bug] mavis skill show returns empty description for skills whose YAML frontmatter was added after daemon boot
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.3k
- Forks
- 141
- Avg merge
- 2h 45m
- Merged PRs (30d)
- 46
Description
Summary
mavis skill show <name> returns "description": "" even when the on-disk SKILL.md has a clean YAML frontmatter block, the corresponding row exists in ~/.minimax/sqlite.db with the right description, and the agent tool can load the skill once prompted. The desktop daemon's in-memory skillIndex is populated only once at boot and is never refreshed when an already-indexed skill's file is rewritten.
Steps to reproduce
-
Open
MiniMax Code.appso the desktop daemon (PID 53290 in our environment) is up. -
Pick any skill whose
SKILL.mdoriginally lacked a YAML frontmatter block. The shipped bundle ships at least one (e.g.secure-by-design-review) and the legacy# Skill:header shape is easy to introduce by importing a marketplace bundle written before the YAML contract landed. -
Rewrite the file to add a canonical frontmatter block, save the file.
-
Re-run the same query without restarting the app:
$ mavis skill show secure-by-design-review | jq .description "" $ mavis skill ls mavis | jq '.skills[] | select(.name == "secure-by-design-review").description' null $ sqlite3 ~/.minimax/sqlite.db \ "SELECT length(description) FROM skills WHERE name='secure-by-design-review';" 142 $ # But the agent tool *can* load it: $ # claude /skill secure-by-design-review -> works
Expected
mavis skill show should return the on-disk description (or the row description, whichever wins) without a daemon restart.
Actual
show keeps returning "" until the daemon is restarted (launchctl kickstart -k gui/$UID/com.mavis.daemon on macOS). A clean restart sometimes still fails with Cannot find module 'better-sqlite3' in ~/.minavis/logs/launchd-stderr.log until MAVIS_SQLITE3_MODULE_PATH is exported to the app.asar.unpacked directory.
Root cause (reverse-engineered from MiniMax Code.app/Contents/Resources/resources/daemon/daemon.js)
In packages/skill/dist/skill.js (extracted from the bundled daemon.js):
async readSkill(req) {
const { skill_name, agent_name } = req;
// ... (fs lookup chain)
const meta = this.skillIndex.get(skill_name, actualAgentName); // in-memory cache
const fallback = meta ? null : this.frontmatterFallback(content);
const description2 = meta?.description ?? fallback?.description ?? "";
// ...
}
skillIndex is hydrated at daemon boot from ~/.minimax/sqlite.db. Two failure modes compound:
- Boot-scan skip. If the file lacks valid YAML frontmatter at boot time, the indexer silently drops the row (the description is empty string). Without a row in
skills, every later API hit falls through tofrontmatterFallback(content), which also yields"". - Cache staleness. Even when a row is later
INSERT-ed by hand intoskills, the running daemon never refreshes its in-memoryskillIndex. The skill is invisible to the agent tool until restart.
Workaround (validated end-to-end on 2026-07-04)
A community skill patch is already in flight — see MiniMax-AI/skills#107 which adds skill-hygiene plus a reference doc with three recovery paths. The cleanest one is:
mavis skill update <name> -a mavis --file <absolute-path-to-SKILL.md>
This invokes the file-watcher's onSkillFileChange handler in the daemon, which calls this.skillIndex.upsert(...) and brings the in-memory cache back in sync without restarting the desktop app.
A launchctl kickstart -k gui/$UID/com.mavis.daemon also works but forces the user to relaunch the whole UI; see workaround doc for MAVIS_SQLITE3_MODULE_PATH export if you go that route.
Proposed fix in the daemon
Two minimum-touch changes:
- Boot-scan must retry on
frontmatterFallback. Ifparsed?.descriptionis empty and the file has a# Skill:style header, attempt a tolerant fallback parse (regex over the first five lines, same algorithm as the community script) before giving up on the file. - File-watch must upsert on every change. The current
onSkillFileChangealready callsthis.skillIndex.upsert(...)when content changes — but the upsert guard rejects rows whosedescriptionis empty. Drop that guard, or better, fall back to the tolerant parse above wheneverparsed?.descriptionis empty.
A third, larger change is a mavis skill reindex [--agent <name>] [--skill <ref>] CLI command so contributors can recover from cache drift without a restart at all.
Environment
- Product:
MiniMax Code.app(bundle idcom.minimax.agent) - Daemon PID 53290 launched by the Electron app with
--port 15321 --owner electron --skip-pid-port - macOS 15.x, Apple Silicon
- ~/.minimax/sqlite.db size ~39 MB, schema includes
skills(PK name+agent_name),skill_hub,skill_hub_added - Reproduced on
secure-by-design-reviewand 48 other SKILL.md files in the bundled~/.minimax/skills/
Severity
Medium — the agent tool still loads the skill through available_skills once the user mentions it, but any tooling built on top of mavis skill show (publishing, marketplace linting, contribution checks) is silently broken until restart.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/skill/dist/skill.js as extracted from daemon.js, focusing on readSkill, skillIndex, and the onSkillFileChange path. Reproduce with mavis skill show and compare the result with the sqlite3 skills query after rewriting a SKILL.md frontmatter block. Done means the running daemon returns the on-disk or row description without requiring a restart.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, sqlite, typescript
- Domain
- backend, database, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100