Skip to main content
Version: Next (unreleased)

Muse Code Integration (Native Claude Skills Spec)

Uses the native Claude skills specification via Muse Code's own plugin marketplace: muse plugins marketplace add + muse plugins install load the plugin as a claude-compatible bundle, _shared/ included.

Prerequisites​

  • Jira auth configured — per-request Basic auth from .jst/jira-sdlc-tools.local.env, no login step (see jira-api-reference.md §9)
  • gh (GitHub CLI) authenticated
  • .jst/jira-sdlc-tools.env and .jst/jira-sdlc-tools.local.env in your project root — see project-config.md
  • Meta's Muse Code CLI installed (muse on PATH) and logged in (muse login), with an active subscription — muse usage shows the allowance. Written against Muse Code 1.4.13 (1.4.13-R6996.1) on Linux.
  • Muse's credentials live in ~/.config/muse/auth.json. Never print or paste that file.

Install / Wire-up Steps​

Muse Code reads Claude Code plugin bundles natively, so the install mirrors Claude Code's marketplace flow. No copy step, no per-skill adaptation file.

  1. Check the bundle (optional, read-only):

    muse plugins validate </PATH>/plugins/jira-sdlc

    Expect valid jira-sdlc claude-compatible skills=4. The eight warnings are expected (see the caveats below).

  2. Register this repo as a marketplace and install the plugin from it:

    muse plugins marketplace add jira-sdlc-tools </PATH-OR-GIT-URL> # the repo root, which holds .claude-plugin/marketplace.json
    muse plugins install jira-sdlc@jira-sdlc-tools

    Replace </PATH-OR-GIT-URL> with the absolute path to a local clone, or with the repo's git URL. Muse snapshots the marketplace, then copies the whole plugin root into its own cache (~/.local/share/muse/plugins/cache/local/jira-sdlc/<hash>/package/). _shared/ arrives intact, next to the four skill folders.

  3. Confirm the skills are registered:

    muse skills list --source plugin

    Each of the four shows as plugin:jira-sdlc:<skill> with activation user-invocable-only, which is the disable-model-invocation: true frontmatter honoured.

muse plugins install <path> --scope user|project (a local bundle, no marketplace) and muse skills install / muse skills import --from claude are also listed by the CLI. They are not covered here, because the marketplace route is the one that keeps _shared/ next to the skills and was run live.

Invoking the Three Skills​

Start the interactive TUI (muse) from where each skill expects to run, and use the same slash commands as Claude Code:

  • /jira-sdlc:jira-task-assigner — break down a task into Jira issues with branches + worktrees (from the main checkout)
  • /jira-sdlc:jira-task-executor — implement an issue end-to-end from its worktree
  • /jira-sdlc:jira-task-reviewer — review the issue's PRs from its worktree

/jira-sdlc:jst-install sets a project up. Muse also offers a bare alias for each (/jira-task-assigner, /jst-install, …), but the namespaced form is the one the skills' own cross-references use. Text after the command reaches the model: Muse leaves $ARGUMENTS unexpanded in the skill body and appends the arguments after it, which is enough for the assigner's free-form task and the notes the other skills accept. Verified in the TUI.

The first run in a directory asks whether to trust the workspace. Trusting only loads project-local skills and rules — the plugin's skills load either way.

Platform-Specific Caveats and Known Gaps​

  • disable-model-invocation: true — honoured natively (Verified). The skills register as user-invocable-only. When the model tries to load one itself, read_skill returns code: disabled-skill, and the model stops and asks rather than improvising. Only the user's slash command loads them.

  • Headless route (Verified locally under 1.4.14; first CI run pending). Under 1.4.13 there was none: muse exec passed /jira-sdlc:<skill> to the model as plain text, read_skill was refused (disabled-skill), and the run ended asking for confirmation (Verified then). Muse 1.4.14 adds muse skills enable <skill-id> --scope plugin, which flips a plugin skill to model-invocable in Muse's own settings ($CONFIG_DIR/settings.json) without editing any SKILL.md frontmatter — disable-model-invocation: true stays in the repo. With plugin:jira-sdlc:jira-task-reviewer enabled that way, muse exec "/jira-sdlc:jira-task-reviewer" loads the skill and runs it headlessly (Verified locally: read_skill returned the skill and the run proceeded through its credential and healthcheck steps; local activation was restored to user-invocable-only afterwards with muse skills user-only … --scope plugin). The CI counterpart is .github/workflows/demo-muse-code-reviewer-workflow-dispatch.yml (workflow_dispatch from the PR's issue branch, muse-spark-1.3, contributor mode on); it can only be dispatched once that file exists on the default branch, so its first live CI run is still pending and this bullet should not be read as covering it yet.

  • Script paths resolve with no fallback (Verified). Muse substitutes ${CLAUDE_PLUGIN_ROOT} in the skill body with the cached plugin root and passes the skill's own skill-dir, so every _shared/scripts/posix/ call hits the cache copy directly. The skills' "Locating the shared scripts" fallback never runs, and Muse needs no entry in its skills-locations list.

  • Sandbox needs unprivileged user namespaces. Muse's Linux sandbox is Bubblewrap. On Ubuntu 24.04, AppArmor restricts unprivileged user namespaces (kernel.apparmor_restrict_unprivileged_userns = 1) and every sandboxed command fails with bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted. Muse then offers to rerun the command outside the sandbox, which needs approval. Approved, ensure_local_env, check_assignee, statuscheck (Jira REST, gh auth, gh api) all ran (Verified). Whether git, gh and Jira calls work inside a working sandbox — whose network mode defaults to proxy-only — and whether it allows writes to WORKTREES_DIR outside the workspace is Unverified. Compare Codex's writable_roots caveat.

  • allowed-tools is not enforced. Muse reports that the skills' allowed-tools lists can't be represented exactly and runs them under ordinary approval, so you approve each command, as with any other Muse tool call. The plugin.json author/keywords/license/repository warnings are presentation-only.

  • The cache is a snapshot — updating it is verified (0.9.0 → 0.9.1). Like Claude Code, Muse copies the plugin at install time, so edits to your clone don't reach it. The verified refresh is:

    muse plugins marketplace update jira-sdlc-tools
    muse plugins update jira-sdlc

    Then restart muse: a running TUI keeps the cache it started with, so the new version only loads in a fresh session. The already-configured trap: re-running muse plugins marketplace add jira-sdlc-tools <git-url> while a marketplace of that name already exists is a no-op (already configured) — it does not change the source. When the existing source is a local directory (here a JST worktree still at 0.9.0), the snapshot stays on that directory and the update never sees the git remote. Remove and re-add it with the intended source instead, then refresh and update:

    muse plugins marketplace remove jira-sdlc-tools
    muse plugins marketplace add jira-sdlc-tools git@github.com:kantorv/jira-sdlc-tools.git
    muse plugins marketplace update jira-sdlc-tools
    muse plugins update jira-sdlc

    Check the result with muse plugins marketplace list (the source should read git@github.com:kantorv/jira-sdlc-tools.git) and muse plugins list (the version should read 0.9.1), then restart muse. That sequence moved a live install from 0.9.0 to 0.9.1 (Verified).

  • Two skill forms inside this plugin's own repo (Verified). After reinstall, typing a skill name in this repo shows two forms: an unprefixed project skill discovered in the workspace, and the namespaced /jira-sdlc: form from the installed plugin cache. They are different copies — the workspace copy tracks your checkout, the namespaced copy tracks the installed cache — so pick the namespaced form when you mean the installed plugin, and expect edits to one not to appear in the other until the cache is refreshed and muse is restarted.

  • What was run. Under Muse Code 1.4.13 on this repo: the marketplace install, /jira-sdlc:jira-task-executor up to its credential gate (it stopped as designed, outside any project), the assigner's step 1 healthcheck from the main checkout — every row as expected, and the skill stopped when told to — the verified plugin update from 0.9.0 to 0.9.1 above (including the already-configured trap, the remove-and-re-add recovery, and the restart), and the full assigner → executor → reviewer live flow for JST-325, which created, implemented, and reviewed this docs change end to end. Under Muse Code 1.4.14 (JST-326): muse skills enable plugin:jira-sdlc:jira-task-reviewer --scope plugin flipped the skill's activation from user-invocable-only to on in Muse's settings (no SKILL.md edited), a bounded muse exec "/jira-sdlc:jira-task-reviewer" probe then loaded the skill (read_skill status ok, no disabled-skill) and ran its credential and healthcheck steps before the step cap stopped it, and muse skills user-only … --scope plugin restored the original activation.