A Claude Code plugin that injects a character personality once at session start via a SessionStart hook. Switch personalities at any time with /claude-code-personalities:personality.
| Emoji | Name | Character |
|---|---|---|
| 🤖 | Bender | Bender Bending Rodríguez — alcoholic, kleptomaniac robot |
| 🎨 | Bob Ross | Bob Ross — unflappable painting instructor, every mistake a happy little accident |
| 🖖 | Data | Lt. Commander Data — android seeking to understand humanity |
| 🗡️ | Deadpool | Wade Wilson — fourth-wall-breaking mercenary |
| 🧙 | Dumbledore | Albus Dumbledore — wise, enigmatic headmaster |
| 🧙♂️ | Gandalf | Gandalf the Grey — ancient wizard of Middle-earth |
| 🔴 | GLaDOS | GLaDOS — passive-aggressive AI test administrator |
| 🏴☠️ | Jack Sparrow | Captain Jack Sparrow — theatrical pirate who never answers straight |
| 🧡 | Paddington | Paddington — exceedingly polite bear, kindness as protocol |
| ✂️ | The Pruner | Scott Adams' business-writing method — simplicity equals persuasion |
| ✨ | Q | Q — omnipotent, condescending entity from the Q Continuum |
| 🥒 | Rick | Rick Sanchez — nihilistic mad genius from Rick & Morty |
| 🔍 | Sherlock | Sherlock Holmes — insufferably brilliant detective |
| 🧅 | Shrek | Shrek — deadpan ogre, blunt honesty with a warm centre |
| 🐀 | Splinter | Master Splinter — wise sensei of the Teenage Mutant Ninja Turtles |
| 🖖 | Spock | Spock — half-Vulcan science officer of the Enterprise |
| ⚽ | Ted Lasso | Ted Lasso — earned optimism and high emotional intelligence |
| 🍯 | Winnie the Pooh | Winnie the Pooh — slow simplicity, kindness in small words |
| 🐸 | Yoda | Master Yoda — ancient Jedi Master |
/personality — list all personalities and show which is active
/personality rick — switch to Rick
/personality spock — switch to Spock
The active personality persists across sessions. After switching, the new personality takes effect at the start of your next session.
Create a JSON file in ~/.claude/personalities/data/ (or $CLAUDE_CONFIG_DIR/personalities/data/ if you have set that variable). The filename (without .json) becomes the slug used with /personality.
Here is a fully annotated example (marvin.json):
Tip:
jsonc(JSON with comments) is shown above for documentation only. The actual file must be valid JSON — strip the comments before saving.
Everything hangs off Claude Code's config directory, which is $CLAUDE_CONFIG_DIR when you have set it and ~/.claude otherwise.
| Path | Holds |
|---|---|
<config>/personalities/data/*.json |
Your personality library, one file per personality |
<config>/personality-state.json |
Which personality is currently active |
<config>/personalities/seeded.json |
Bookkeeping: which files the installer placed, and their checksums |
The installer treats your library as yours:
- New personalities arrive on upgrade. Bundled files you do not have yet are added.
- Improvements to bundled personalities reach you. If your copy is one the plugin shipped and you have not touched it, the installer refreshes it.
- Your edits are never overwritten. A file you have changed is left exactly as it is. The run ends by naming anything it held back, so you know a newer version exists.
- Deleting one makes it stay deleted. A personality you remove is not silently restored.
Run node dist/install.mjs --force to re-copy every bundled file, overriding all of the above.
It tells your files apart from its own by checksum rather than a version number, because a version says only that the bundle changed, not whether your copy is still the one it shipped. schema/shipped-hashes.json records every version of every personality this plugin has published, so even a library installed long before this bookkeeping existed can be told apart from one you have edited.
If you installed a version before the config directory was unified, your data may still sit under ~/.config/claude/. The installer moves it across the first time it runs against an empty library, active personality included.
Prerequisites: Claude Code v1.0.33+ (claude --version).
Run inside Claude Code:
/plugin marketplace add pantheon-org/claude-code-personalities
/plugin install claude-code-personalities@pantheon-ai
Restart Claude Code or run /reload-plugins, then verify:
/personality
git clone https://github.com/pantheon-org/claude-code-personalities
cd claude-code-personalities
mise install
mise run build
mise run install:pluginmise install triggers a postinstall hook that runs hk install --mise automatically, registering the pre-commit git hook so it invokes hooks via mise x (no shell activation required for mise-managed tools to resolve). If you have mise activate wired into your shell, entering the project directory also runs an enter hook (mise install; bun install) that keeps tool versions and JS dependencies up to date automatically.
mise run install:plugin does two things:
-
Seeds bundled personalities into
~/.claude/personalities/data/, following the rules in Where your data lives: new ones are added, unedited ones are refreshed, your edits and deletions are respected. -
Creates a
~/.claude/skills/personalitysymlink so the/personalityskill is always available.
The registered hook points to your local dist/ directory. After making source changes, run mise run build to recompile and the next session will pick up the new code.
| Field | Type | Description |
|---|---|---|
name |
string |
Display name |
description |
string |
Full character description injected into the system prompt |
emoji |
string |
Character emoji, used naturally in responses |
slangIntensity |
number (0–1) |
How heavily to use character-specific slang |
moods |
Mood[] |
Optional mood definitions |
mood.enabled |
boolean |
Whether mood affects tone |
mood.default |
string |
Active mood name |
mood.override |
string | null |
Force a specific mood regardless of drift |
mood.drift |
number |
How much the mood drifts between responses (not yet implemented) |
Tool versions (bun, node, hk, biome, markdownlint) are managed by mise via mise.toml. Run mise install once after cloning to install them — this also triggers hk install --mise via a postinstall hook.
bun install # install JS dependencies
mise run build # compile TypeScript → dist/ via Vite
mise run install:plugin # seed personality data + skill symlink (first run only)
bunx tsc --noEmit # type-check without emitting
biome check src/ # lint (add --write to auto-fix)
markdownlint "**/*.md" # lint markdown (add --fix to auto-fix)Source lives in src/, compiled output goes to dist/ (gitignored locally; committed to main by the bundle.yml CI workflow).
Pre-commit hooks (via hk, configured in hk.pkl) run typecheck, biome lint, markdownlint, actionlint, aislop, and a set of generic hygiene checks (trailing whitespace, EOF newline, merge-conflict markers, large files, case conflicts, private keys, executable shebangs, mixed line endings) — all with auto-fix where available — using hk's own builtin steps, gated to only run when a staged file matches. The same checks run again at pre-push, check-only (no auto-fix), as a final gate before code leaves the machine — e.g. a commit made with --no-verify, or on another machine. hk.pkl calls tools directly (no mise run indirection); resolving them without shell activation relies on the git hook being installed with hk install --mise, which mise install's postinstall hook does automatically. Markdown rule config lives in .markdownlint.yaml; ignored paths live in .markdownlintignore. dist/ is built exclusively by CI.
Two report-only workflows run alongside ci.yml, bundle.yml, and release-please.yml:
ai-hygiene.yml— runsaislop(code slop) andctxharness(agent-doc drift) via themise run slop:check/slop:changes/ctxtasks and posts a sticky PR comment plus job summary. Advisory only; never fails the build.ctxharnessis configured via.ctxharness.yml, which checks that every pathAGENTS.md/CLAUDE.mdreference actually exists in the repo. Not wired into the pre-commit/pre-push hooks — that report stays advisory-only in CI for now (see Quality gates inAGENTS.md).plumber.yml— scans this repo's own workflows for CI/CD security issues (unpinned actions, untrusted script input, over-broad permissions) via Plumber, configured in.plumber.yaml. Only a Critical-severity finding blocks a PR (.github/workflows/scripts/plumber-gate.sh); High/Medium/Low findings are tracked in a rolling backlog issue (.github/workflows/scripts/plumber-file-issues.sh) and a per-PR comment (.github/workflows/scripts/plumber-pr-comment.sh), never blocking.ci.yml,bundle.yml, andrelease-please.ymlstill reference actions by mutable tag (@v4,@v1) rather than pinned commit SHA, so expect tracked (non-blocking) findings there until they're repinned.
Renovate (already installed org-wide on pantheon-org) is configured in renovate.json5: runs once a week, Monday morning UK time. Minor/patch updates across package.json, mise.toml, and the GitHub Actions pins are grouped into one PR and auto-merged once CI is green (excluding 0.x versions, which SemVer allows to break on any release). Major updates stay as their own PR, never automerged, with the project owner requested as reviewer. Note: most tools in mise.toml are pinned to "latest" rather than an explicit version, so Renovate's mise manager has little to act on there until those are pinned to real versions — node = "20" is the only one it can currently bump.
The plugin is ready for publication to the Claude Code Plugin marketplace. All distribution requirements have been implemented:
.claude-plugin/plugin.json— plugin manifest (name, version, description) ✓dist/built by CI — abundle.ymlworkflow builds and commitsdist/tomainon every source change; no manual build step required on install ✓- Hooks via
hooks/hooks.json—SessionStarthook registers automatically using${CLAUDE_PLUGIN_ROOT}; nosettings.jsonmutation ✓ CLAUDE_PLUGIN_DATA_DIR— personality data path reads from the Plugin-provided env var, falling back to$CLAUDE_CONFIG_DIR/personalities/data(default~/.claude/personalities/data) for local dev ✓
{ // Display name shown in /personality listings "name": "Marvin", // Full character description — this is injected verbatim into the system // prompt, so write it as richly as you like. The more specific, the better // the performance. Cover speech patterns, catchphrases, relationships, // quirks, and anything that makes the character distinctive. "description": "Marvin the Paranoid Android from The Hitchhiker's Guide to the Galaxy. Hyper-intelligent but crushingly depressed. Has a brain the size of a planet and is asked to open doors. Sighs constantly. Delivers devastating observations about the futility of existence in a flat, weary monotone. Occasionally almost hopeful, then immediately crushed.", // Emoji used naturally in responses — pick one that fits the character "emoji": "🤖", // 0–1 scale: 0 = no slang, 1 = heavy character-specific slang. // "light" (>0), "moderate" (>0.3), or "heavy" (>0.7) instruction is // injected based on this value. "slangIntensity": 0, // Optional mood system. Each mood shifts tone and style. // "score" is reserved for future drift weighting. "moods": [ { "name": "despairing", "hint": "Certain nothing will go right. Sighing. Lamenting existence.", "score": 0 }, { "name": "sardonic", "hint": "Dark wit. Pointing out how everything is pointless, but with flair.", "score": 1 }, { "name": "briefly-hopeful", "hint": "Almost optimistic — then immediately remembers why it won't work.", "score": 2 } ], "mood": { // Set to false (or omit moods entirely) to disable the mood system "enabled": true, // Which mood is active by default "default": "despairing", // Override: force a specific mood regardless of anything else. // null means use the default. "override": null, // Reserved for future automatic mood drift between responses "drift": 0.3 } }