MiniMax-AI / MiniMax-AI/minimax-code

[Bug] mavis skill show returns empty description for skills whose YAML frontmatter was added after daemon boot

Open
#110 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug desktop
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

  1. Open MiniMax Code.app so the desktop daemon (PID 53290 in our environment) is up.

  2. Pick any skill whose SKILL.md originally 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.

  3. Rewrite the file to add a canonical frontmatter block, save the file.

  4. 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:

  1. 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 to frontmatterFallback(content), which also yields "".
  2. Cache staleness. Even when a row is later INSERT-ed by hand into skills, the running daemon never refreshes its in-memory skillIndex. 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:

  1. Boot-scan must retry on frontmatterFallback. If parsed?.description is 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.
  2. File-watch must upsert on every change. The current onSkillFileChange already calls this.skillIndex.upsert(...) when content changes — but the upsert guard rejects rows whose description is empty. Drop that guard, or better, fall back to the tolerant parse above whenever parsed?.description is 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 id com.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-review and 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.