Plugins & Skills
Updated June 6, 2026
Claude Code and Codex both load a fixed bundle of context into every API call: system prompt, tool definitions, walked-up agent files, and the frontmatter of every installed plugin and skill. None of it is optional per turn. It costs tokens whether you use it or not.
crystl lets you scope that bundle per gem. A Vercel project doesn’t need Shopify or Cloudflare loaded; a Swift project doesn’t need either. The plugin and skill management surfaces in crystl turn that one-size-fits-all global config into something tuned per project.
The eager-load surface
Every turn, your agent sends:
- The agent’s system prompt (Claude Code’s or Codex’s)
- All tool definitions: built-in tools and every connected MCP server
- Walked-up
CLAUDE.md/AGENTS.mdfiles - Every installed plugin’s manifest and the frontmatter of skills bundled inside those plugins
- User-level skill frontmatter:
~/.claude/skills/*/SKILL.mdfor Claude,~/.agents/skills/*/SKILL.mdfor Codex
The frontmatter and manifests are how the model “knows” a skill exists so it can decide to invoke one. That discoverability is exactly why they’re eager-loaded, and exactly why they cost tokens on every turn even when nothing in the session needs them.
See Context Load Tracking for how crystl measures the size of that bundle live.
Two surfaces, one setting
crystl gives you two places to toggle plugins and skills. Both write to the same underlying config:
- Context Load Panel (per-shard): opens from the
~N turns leftbutton in the status bar. Shows the live token cost of every plugin and skill so you can disable the expensive ones in-session. - New Gem / Gem Settings panel (per-gem): a checkbox grid for everything available. Applied when you save the gem.
Both surfaces edit the same files. Toggling something off in the context-load panel and then opening Gem Settings will show that entry unchecked.
What crystl writes
Claude Code
Per-gem state lives in <gem>/.claude/settings.json under two keys:
{
"enabledPlugins": {
"vercel@claude-plugins-official": false
},
"skillOverrides": {
"my-personal-skill": false
}
}
A false value tells Claude Code to skip loading that plugin or skill for sessions started in this directory. Re-enabling strips the entry entirely rather than writing true, so crystl-managed settings stay minimal and don’t drift from upstream defaults.
When a setting needs to apply globally (a user-level skill that should never load anywhere), crystl writes the same shape into ~/.claude/settings.json instead.
Codex
Codex doesn’t have per-project plugin scoping. crystl writes to the global config at ~/.codex/config.toml:
[plugins."vercel-plugin@plugins-cli"]
enabled = false
Flipping the entry back to enabled = true re-enables it everywhere. There’s no project-level override to layer on top.
Platform differences
| Claude Code | Codex | |
|---|---|---|
| Per-gem scope | yes (<gem>/.claude/settings.json) | no (global only) |
| User skill location | ~/.claude/skills/ | ~/.agents/skills/ |
| Mid-session apply | yes (crystl injects /reload-plugins automatically) | no (requires manual codex restart) |
| Re-enable | strips entry from settings.json | flips enabled = false to true |
If you mix agents in one gem, expect Codex changes to leak across all your projects. This is a Codex limitation, not a crystl one.
Mid-session reloads
After you toggle plugins or skills for a Claude shard, crystl writes the settings file and then injects /reload-plugins into the active shard. Claude Code picks up the new config without restarting, and the next turn runs against the trimmed context.
Codex has no equivalent reload command. crystl leaves a hint in the shard reminding you to restart codex for the change to take effect.
Auto-detect on new gem creation
When you create a new gem in a directory that already has files, crystl scans for known stack markers and proposes a tailored plugin config before the gem is saved.
The current marker set:
| Marker | Suggestion |
|---|---|
vercel.json, next.config.* | Vercel |
shopify.app.toml | Shopify |
wrangler.toml / wrangler.jsonc | Cloudflare |
supabase/config.toml | Supabase |
.sentryclirc / sentry.properties | Sentry |
Package.swift | swift-lsp + code-review |
Multiple matches union into a single suggestion: a Next.js project on Cloudflare Workers with Sentry wired up gets all three plugins proposed. The dialog gives you three buttons:
- Accept: enable the suggested set and disable everything else
- Customize: open the New Gem panel’s plugin grid pre-checked with the suggestions, edit before saving
- Skip: create the gem with whatever plugins are currently enabled globally
Skipping is a one-time choice. You can always open Gem Settings later to revisit.
The context load panel
The panel doubles as a live budget for the shard’s eager-load surface. Each plugin and skill appears with:
- Token cost: the size of that entry’s manifest or frontmatter as Claude actually sees it
- Source: global (
~/.claude/), per-gem (<gem>/.claude/), or plugin-bundled - Enabled toggle: left-click flips the entry
Disabling an entry from the panel is the fastest way to free up context without leaving the shard. crystl writes the change, fires /reload-plugins, and the indicator in the status bar updates on the next turn.
The gem settings panel
Opening Gem Settings from the gem menu (the ⋮ on a gem tab, or a double-click on its tile in the Crystal Rail → settings), or via the New Gem panel during creation, shows a Plugins section and a Skills section. Each lists every entry crystl knows about (bundled, user-level, and plugin-installed) with a checkbox.
Unchecking is the same as setting enabled: false for that scope. The panel batches changes and writes once on save, so toggling a dozen entries doesn’t thrash the settings file.
The grid is split by source so you can see at a glance which entries are user-level (will affect every gem unless overridden) and which are plugin-bundled (already scoped). For Claude this lets you scope at any level; for Codex the grid is informational only, since the underlying toggle is global.
Working with plugin manifests
crystl doesn’t install plugins itself. It reads whatever claude plugins or the Codex equivalent have already installed. Adding a new plugin to a marketplace registry (or installing one with claude plugins install) makes it appear in crystl’s grid on the next gem open.
For plugins bundled with skills, the per-skill toggles are independent: you can keep a plugin enabled (so its slash commands work) while disabling a few of its bundled skills you never use.
Best practices
Default to disabled, opt back in. A clean global config with most plugins off is usually cheaper than the inverse. Use auto-detect on new gems to switch the right ones back on per project.
Audit the context-load panel weekly. Plugin authors update frontmatter all the time; an entry that was cheap last month may have ballooned. The panel shows the current cost, not the cost at install.
Don’t enable everything “just in case.” Every enabled plugin and skill subtracts from your usable window for actual work. The model can be told about a skill mid-session via documentation; the eager-load surface is for skills it should always know exist.
Codex needs care. Because Codex toggles are global, the safest pattern is to keep its global plugin set lean and put project-specific instructions in AGENTS.md instead.
Related docs
- Context Load Tracking: per-shard token budgets and the
~N turns leftindicator - Agent Instruction Files:
CLAUDE.md,AGENTS.md, and the broader agent file system - MCP Servers: tool servers, which are also part of the eager-load surface
- Gems & Shards: creating gems and the New Gem panel