{"id":51495661,"url":"https://github.com/mtking2/mystique","last_synced_at":"2026-07-07T15:01:19.185Z","repository":{"id":367618399,"uuid":"1281450601","full_name":"mtking2/mystique","owner":"mtking2","description":"🎭 Shapeshift Claude Code into any role — instantly, mid-session","archived":false,"fork":false,"pushed_at":"2026-06-26T18:15:54.000Z","size":31,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-26T20:11:10.005Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtking2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-26T15:10:23.000Z","updated_at":"2026-06-26T18:17:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mtking2/mystique","commit_stats":null,"previous_names":["mtking2/mystique"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/mtking2/mystique","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtking2%2Fmystique","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtking2%2Fmystique/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtking2%2Fmystique/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtking2%2Fmystique/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtking2","download_url":"https://codeload.github.com/mtking2/mystique/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtking2%2Fmystique/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35232326,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-07T15:01:15.913Z","updated_at":"2026-07-07T15:01:17.097Z","avatar_url":"https://github.com/mtking2.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎭 mystique\n\n\u003e Shapeshift Claude Code into any **role** — instantly, mid-session, no restart.\n\n`mystique` lets Claude assume switchable **forms**: self-contained bundles of mindset, output style, recommended skills, advisory tool scope, and focus areas. The active form is re-injected every turn via a `UserPromptSubmit` hook, so a role sticks across long sessions without drifting — and switching is just rewriting a small state file.\n\nRoles are *forms*. Drive it with `/mystique` or its alias `/role`.\n\n## Why\n\nExisting role/persona projects each cover one slice — capability *or* cosmetic *or* a big library. mystique focuses on the gap: **frictionless in-session switching** of a **behavior bundle**, with light 2-form stacking and dead-simple authoring (write a markdown file).\n\n## Highlights\n\n- **Sticks across the session** — hook re-injects the active form every turn, no drift.\n- **Behavior bundle** — principles, output style, recommended skills, focus, advisory tool scope.\n- **Stacking (cap 2)** — combine two forms; primary wins conflicts.\n- **Project + global forms** — `./.claude/roles/` overrides `~/.claude/roles/`. Repos ship their own forms.\n- **Easy authoring** — `/role create` wizard, or just drop a markdown file.\n- **Optional cosmetics** — per-form spinner verbs + a composable statusline segment.\n\n## Status\n\nEarly development.\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| `/role` | Menu — active form(s) + available |\n| `/role \u003cname\u003e` | Shift into a form (primary) |\n| `/role +\u003cname\u003e` | Stack a 2nd form (cap 2) |\n| `/role clear` | Revert to true self |\n| `/role show` | Current form(s) + resolved injection |\n| `/role list` | All forms, global + project |\n| `/role create` | Guided authoring wizard |\n| `/role edit \u003cname\u003e` | Edit a form file |\n\n## Install\n\n1. Add the marketplace and install the plugin (Claude Code):\n   ```\n   /plugin marketplace add mtking2/mystique\n   /plugin install mystique@mystique\n   ```\n2. Copy the example forms into your global roles dir (or a project's `./.claude/roles/`):\n   ```\n   mkdir -p ~/.claude/roles \u0026\u0026 cp roles/*.md ~/.claude/roles/\n   ```\n\n## Authoring a form\n\nA form is a markdown file in `~/.claude/roles/` (global) or `./.claude/roles/` (project — wins on name collision). Flat frontmatter + a markdown body:\n\n```markdown\n---\nname: my-role\ndescription: One line.\nlabel: 🎭 My Role          # optional, statusline\ntool_prefer: [Read, Grep]  # optional, advisory\ntool_avoid: [Bash]         # optional, advisory\ntriggers: [keyword]        # optional, soft suggestions\nspinner: [Doing]           # optional, spinner verbs\n---\n\n## Principles\n- ...\n## Output style\n- ...\n## Focus\n- In: ... / Out: ...\n```\n\nKeep the body tight (~150 words) — it is injected every turn. Or just run `/role create` for a guided wizard.\n\n## Spinner (per-session)\n\nA form's `spinner` verbs drive Claude Code's thinking spinner. `spinnerVerbs` is a\nsingle global `settings.json` key, so per-session spinners aren't truly possible —\ninstead the `UserPromptSubmit` hook re-asserts the active form's verbs every turn.\nThe window whose prompt just fired wins the spinner (last-active-wins), which is\nexactly the window whose spinner is about to render. Writes are change-guarded, so\n`settings.json` is only touched when the spinner actually needs to change.\n\n\u003e **Known limitation:** on a turn where the spinner *changes* (a cross-window\n\u003e handoff), the opening frame may briefly show the previous verbs before flipping\n\u003e to the new ones — the hook's write races Claude Code's initial read of\n\u003e `spinnerVerbs`. It self-corrects within the same turn; a single steady-state\n\u003e window never flashes.\n\n## Statusline (optional)\n\nAdd the active form to your own statusline by calling the segment helper. From a statusline command, invoke it with the plugin root Claude Code provides:\n\n```\nnode \"${CLAUDE_PLUGIN_ROOT}/bin/mystique-segment.js\"\n```\n\n(Outside a plugin context, point at the installed path, e.g. `~/.claude/plugins/marketplaces/mystique/mystique/bin/mystique-segment.js`.)\n\nIt prints e.g. `🛡️ Security +💎 Rails`, or nothing when no form is active.\n\n### Bash snippet (no `node` spawn)\n\nIf your statusline is already a `bash` + `jq` script, read this session's state file directly — faster, no subprocess per render. The statusline JSON arrives on stdin, so pull `session_id` from it:\n\n```bash\n# mystique active form(s) — drop into your statusline.sh\nINPUT=$(cat)                                  # statusline JSON on stdin\nSID=$(printf '%s' \"$INPUT\" | jq -r '.session_id // empty')\nMYST_FILE=\"${CLAUDE_CONFIG_DIR:-$HOME/.claude}/mystique/sessions/${SID}.json\"\nmyst=\"\"\nif [ -n \"$SID\" ] \u0026\u0026 [ -f \"$MYST_FILE\" ] \u0026\u0026 [ ! -L \"$MYST_FILE\" ]; then\n\tmyst=$(jq -r '(.active // []) | map(.label // .name) | join(\" +\")' \"$MYST_FILE\" 2\u003e/dev/null)\nfi\n# then append \"$myst\" to your status line, e.g.:\n[ -n \"$myst\" ] \u0026\u0026 printf ' | \\033[38;2;180;142;255m%s\\033[0m' \"$myst\"\n```\n\nPrints e.g. `🛡️ Security +💎 Rails` in violet, nothing when no form is active. If your script already consumes stdin elsewhere, capture `INPUT=$(cat)` once and reuse it. Symlink-guarded and silent on a missing/corrupt file.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtking2%2Fmystique","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtking2%2Fmystique","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtking2%2Fmystique/lists"}