Releases: Emasoft/claude-menu-system
v0.2.0
v0.1.6
v0.1.5
[0.1.5] — 2026-05-17
Bug Fixes
- Correct \.git→\.git doubled-backslash in _current_repo_slug regex
Documentation
- Add version badge for publish.py auto-update
Features
- Install canonical CPV pipeline + fix all validate findings
Miscellaneous Tasks
- Sync uv.lock to v0.1.4
Styling
- Ruff format publish.py + suppress upstream-template lint noise
Generated by git-cliff
v0.1.4
Fixed
-
Critical install bug —
.claude-plugin/plugin.jsondeclared
"hooks": "./hooks/hooks.json", which pointed the manifest override
at the auto-discovered default file. Claude Code rejects this with
Duplicate hooks file detectedAND silently disables the plugin's
hooks (and any sibling MCP servers). v0.1.3 and earlier would not
load on any Claude Code instance. Fix: remove thehooksfield
entirely — the canonicalhooks/hooks.jsonis auto-discovered.This is empirical plugin-loading bug #2 catalogued by CPV
(claude-plugins-validation) under RC-PLUGIN-LOAD-002. The very
bug-class that motivated CPV's loader-audit rules. Ironic.
Changed
- README rewritten to lead with the value proposition: "The
AskQuestion prompt is not good for a big number of choices. Just
run this command and you get a nice menu with as many entries as
you need." Followed by a single copy-paste snippet. ~240 lines
trimmed to ~80.
v0.1.3
Removed
skills/render-menu/SKILL.md— the skill path is gone. Benchmarks
in v0.1.2 (underCLAUDE_CODE_EFFORT_LEVEL=maxopus) showed the skill
fork took 15-25 seconds end-to-end vs 25 ms for direct Bash to
menu_write.py, dominated by extended-thinking model inference no
skill-frontmatter knob could escape.effort: low, removingmodel:,
removingallowed-tools:, removingcontext: fork— none helped on
a max-effort session. No user would wait that long for a menu.
Changed
- README rewritten to lead with Option 1 (direct Bash invocation).
Plugin authors callpython3 $CLAUDE_PLUGIN_ROOT/scripts/menu_write.py spec.json
from any Bash block in their orchestrator. ~25 ms. Reliable. No fork. commands/menu-test.mdupdated to invokemenu_write.pydirectly
instead of the skill.commands/menu-render.mdupdated to invokemenu_write.pydirectly
instead of the skill.- Plugin now ships only hooks + scripts + commands + examples.
Why
The skill existed for the use case "consumer wants to delegate menu
rendering to a fork so the parent doesn't pay any tokens". In practice:
(a) the fork's wall time was unacceptable, (b) the parent was going to
spend Bash-tool tokens anyway, and (c) direct Bash is a 25 ms call —
faster than any fork could be. The skill was solving the wrong problem.
Migration for consumers
If you were using Skill({skill: "claude-menu-system:render-menu", args: "spec.json"}):
# Replace with:
python3 "$CLAUDE_PLUGIN_ROOT/scripts/menu_write.py" "spec.json"If your plugin is in another marketplace, resolve the cache path:
CMS_ROOT=$(ls -d ~/.claude/plugins/cache/emasoft-plugins/claude-menu-system/*/ | sort -V | tail -1)
python3 "$CMS_ROOT/scripts/menu_write.py" spec.jsonv0.1.2
Fixed
- Critical UX bug — emitted
systemMessagenow prepends a\nso
the menu box starts on its own line beneath Claude Code'sStop says:
banner. v0.1.1 emitted the box's first row inline with the banner,
shifting every subsequent row right and breaking visual alignment.
Regression-pinned bytest_systemMessage_always_starts_with_newline. - render-menu skill body — rewritten to NOT rely on the
$ARGUMENTSplaceholder (slash-command syntax, not skill syntax).
The haiku fork now receives explicit instructions to take the user
message as the path and invoke the Bash tool with it. v0.1.1's
body left the fork describing what it would do rather than actually
executing the script.
v0.1.1
Added
/menu-testslash command — self-test that renders a demo menu so
users can verify the plugin is wired correctly after install./menu-render <spec-path>slash command — ad-hoc rendering from any
JSON spec file on disk; useful for plugin authors testing their specs.scripts/menu_test_specs.py— helper script that produces canonical
demo specs for all 8 modes. Used by/menu-testand re-used to seed
theexamples/gallery.examples/directory with 8 canonical JSON specs (one per render
mode) — plugin authors can copy-paste these as starting points.
Notes
- All changes additive — no behavior change to v0.1.0 hooks / skill /
renderer. Consumer plugins built against v0.1.0 work unchanged on v0.1.1.
v0.1.0
Initial release. First-class, reusable menu rendering for Claude Code
plugins via the systemMessage-from-Stop-hook pattern empirically
proven against Emasoft/token-reporter-plugin.
Added
render-menuskill (context: fork,model: haiku,
agent: general-purpose) — other plugins invoke via
Skill({skill: "claude-menu-system:render-menu", args: "<spec>"}).Stop/StopFailurehooks that emit the queued menu as
systemMessageat main-session turn end.SubagentStophook that no-ops (systemMessage from subagent-stop
routes to AI context, not the user terminal — documented).- 8 render modes:
menu,summary,breakdown,status_table,
panel,multi_box,progress,confirm. - 5 box styles:
heavy(default for menus),rounded(default for
panels),light,double,ascii. Auto-downgrade toasciiwhen
the terminal can't render unicode box-drawing. - Semantic ANSI palette (border / header / value / success / warning /
error / info / muted + severity tiers). Auto-strip whenNO_COLOR=1,
CLAUDE_MENU_COLOR=0, orTERM=dumb. - Display-width-aware padding via
unicodedata.east_asian_width—
correct alignment for emoji + CJK + box-drawing glyphs. - ANSI-safe text wrapping that preserves color state across continuation
lines (ported from token-reporter_wrap_ansi). - Auto-terminal-width detection (
COLUMNSenv →shutil.get_terminal_size
→ 80 default, capped atCLAUDE_MENU_MAX_WIDTHdefault 120). - 10K hook-output cap with tiered truncation (SMALL untouched / BIG
row-dropped / OVERFLOW title-stubbed) and line-safe truncation
(cut only at\nboundaries, never mid-ANSI-escape). - Session-isolated queue dir
(${TMPDIR}/claude-menu-system/<session_id>/). flock-protected concurrent emit (multiple Stop hooks don't race).- TTL-based stale cleanup (default 60s, configurable via
CLAUDE_MENU_TTL_SEC). - 188 tests (≥95% line coverage on every module), all running in
under 1 second viapytest-xdist.
Notes
- Runtime dependency: stdlib only (no third-party deps).
- Plugin-scoped hooks — picked up by
/reload-plugins, no full session
restart needed. - Consumer plugins must hard-require
claude-menu-systemto be enabled.
Pre-flight check pattern in the README.