claude-code Documentation

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks,...

152,845 stars TypeScript TypeScript 1 file · ~49,052 tokens
RAW Doc

Technical Documentation: anthropics/claude-code

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

Claude Code

[

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows -- all through natural language commands. Use it in your terminal, IDE, or tag @claude on Github.

Learn more in the official documentation.

Get started

[!NOTE]
Installation via npm is deprecated. Use one of the recommended methods below.

For more installation options, uninstall steps, and troubleshooting, see the setup documentation.

  1. Install Claude Code:

    MacOS/Linux (Recommended):

    bash
    curl -fsSL https://claude.ai/install.sh | bash

    Homebrew (MacOS/Linux):

    bash
    brew install --cask claude-code

    Windows (Recommended):

    powershell
    irm https://claude.ai/install.ps1 | iex

    WinGet (Windows):

    powershell
    winget install Anthropic.ClaudeCode

    NPM (Deprecated):

    bash
    npm install @anthropic-ai/claude-code
  2. Navigate to your project directory and run claude.

Plugins

This repository includes several Claude Code plugins that extend functionality with custom commands and agents. See the plugins directory for detailed documentation on available plugins.

Reporting Bugs

We welcome your feedback. Use the /bug command to report issues directly within Claude Code, or file a GitHub issue.

Connect on Discord

Join the Claude Developers Discord to connect with other developers using Claude Code. Get help, share feedback, and discuss your projects with the community.

Data collection, usage, and retention

When you use Claude Code, we collect feedback, which includes usage data (such as code acceptance or rejections), associated conversation data, and user feedback submitted via the /bug command.

How we use your data

See our data usage policies.

Privacy safeguards

We have implemented several safeguards to protect your data, including limited retention periods for sensitive information, restricted access to user session data, and clear policies against using feedback for model training.

For full details, please review our Commercial Terms of Service and Privacy Policy.


Overview (`mods/README.md`)

Mods

A mod is a Claude Code plugin whose behaviour lives in a hooks module: one
register(on, options) entry that hooks the engine's events as functions
($, e, next). These four ship inside Claude Code; this folder is their
source, published as it is built into the binary.

Mod What it does Seated
sec-default Keeps an organization's classic hooks, prompt content, managed settings, tool policy, permission rules and pinned environment out of reach of the plugins a person installs; adds no policy of its own. Outermost, on a machine with managed settings or a managed-mcp.json, or for a Team or Enterprise organization, and from then on for the session, unless managed prependPlugins says otherwise
diff /diff: the session's uncommitted changes in a pane beside the transcript, file by file with their hunks, refreshed as Claude edits files and runs commands. Built in
telemetry Hooks $.telemetry's two events (log, mark), adding the noun in the engine.create fold where the engine has none, so a built-in plugin can record an event as a first-party analytics row, sent in batches; refuses installed plugins; sends nothing wherever Claude Code's analytics are off. Built in
agents-md AGENTS.md as project instructions, by one option: loaded where the project has no CLAUDE.md of its own (claude-md-or-agents-md, the default) or beside it (claude-md-and-agents-md), placed and framed exactly as the engine places CLAUDE.md, nested ones on a Read; or the project's and the person's instruction files dropped and the organization's kept (managed-only); or CLAUDE.md alone, as the engine reads it (claude-md). Built in

Each folder is a complete plugin: .claude-plugin/plugin.json, a
hooks/hooks.json naming the module, and TypeScript under hooks/ typed
against the declarations /plugin-types writes (import type … from 'claude-code'), kept here in types/. To read one running from source:

text
claude --plugin-dir mods/diff

Testing

A mod's tests are in its tests/ folder, and run with

text
claude plugin test mods/diff

A test gets the engine's own $ and a plugin's on. Each call on $ is one
the engine makes, through every hook of the mod loaded as it ships. The hooks
the test registers with on sit beneath the mod, where the rest of the world
would be, and nothing is beneath them: a call they leave unanswered throws,
naming its event.

A test file is named for what it covers under hooks/ (register.test.ts
beside hooks/register.ts, git.test.ts beside hooks/git/), and holds its
imports, the tier the mod loads in, and one describe titled with that name;
what several tests share sits under tests/fixtures/, one export a file.

ts
import { describe, expect, mock, test, tier } from 'claude-code/testing'

tier('builtin')

describe('register', () => {
  test('outside a git repository /diff says so, opens nothing', async ($, on) => {
    const opened: string[] = []
    mock.clock(on)
    on('session.start', ($, e) => ({ cwd: e.cwd }))
    on('command.register', ($, e) => ({ value: { command: e.name } }))
    on('process.run', () => ({
      value: { exitCode: 128, stdout: '', stderr: 'fatal: not a git repository' },
    }))
    on('ui.open', ($, e, next) => {
      opened.push(e.id)
      return next(e)
    })

    await $.session.start({ surface: 'terminal', isInteractive: true, cwd: '/work' })
    const { text } = await $.command.run({
      command: 'diff',
      args: '',
      origin: { kind: 'composer' },
    })

    expect(text).toContain("isn't in a git repository")
    expect(opened).toEqual([])
  })
})

The kit's mock answers the world beneath the mod from memory, noun by noun,
each member a plain function over on registering hooks where the test calls
it: mock.env(on, variables) for $.env, mock.store(on, entries) for
$.store, and mock.clock(on) for $.clock, whose advance(ms) resolves
every wait the mod asked for ($.clock.sleep, after, every) as the clock
crosses it. To see what a dispatch does before it answers, start it
unawaited, await clock.settle(), then look: the clock stays where it was.
$.ui.press({ plugin, key }) presses a Button the test rendered, as a
click in the terminal does.

tsc -p mods/tsconfig.json typechecks every mod's hooks and tests against
types/ and each mod's own types/ contract.

Composing mods: noun contracts

A mod that adds a noun to $ in the engine.create fold owns that noun's
types, and keeps them in one place: its types/index.d.ts, a declaration
file with no imports that exports the types the noun is made of, each named
for the noun, and declares the noun on EngineInterface in claude-code
(telemetry/types/index.d.ts exports Telemetry, TelemetryLogEntry,
TelemetryMarkEntry and the rest, and declares $.telemetry).

  • The contract is the only declaration of the noun. The mod's own hooks
    import its types from the folder (import type { Telemetry } from '../types'), and the value its engine.create hook returns is checked
    against EngineInterface['telemetry'], so the implementation cannot drift
    from what callers read.
  • A mod that calls another's noun reads the same file and never copies it:
    mods/tsconfig.json includes */types/**/*.d.ts, so $.telemetry.log(…)
    in diff types against telemetry's contract as it stands, and a helper
    that must name one of its types imports it from that folder by path.
  • A test of a mod that calls another's noun seats a provider for it, an inline
    plugin whose engine.create hook adds the noun, and answers the calls the
    way it answers the engine's: on('telemetry.log', ($, e) => ({ value: undefined })) runs above the provider's own method, its e typed by the
    contract. With no provider loaded the $ build refuses the hook, naming the
    noun nobody provides.

A plugin outside this repository that depends on a mod's noun points its
tsconfig include at that mod's types/ folder for now; once the engine
writes the contracts of the plugins a session has installed, /plugin-types
will put them beside claude-code.d.ts and the include goes away.

Early access: hooks modules load only where function hooks are enabled, and
the API these mods are written against may change between releases without
notice. They are not listed in this repository's marketplace; the copies that
matter are the ones already in your Claude Code.


Overview (`plugins/README.md`)

Claude Code Plugins

This directory contains some official Claude Code plugins that extend functionality through custom commands, agents, and workflows. These are examples of what's possible with the Claude Code plugin system—many more plugins are available through community marketplaces.

What are Claude Code Plugins?

Claude Code plugins are extensions that enhance Claude Code with custom slash commands, specialized agents, hooks, and MCP servers. Plugins can be shared across projects and teams, providing consistent tooling and workflows.

Learn more in the official plugins documentation.

Plugins in This Directory

Name Description Contents
agent-sdk-dev Development kit for working with the Claude Agent SDK Command: /new-sdk-app - Interactive setup for new Agent SDK projectsAgents: agent-sdk-verifier-py, agent-sdk-verifier-ts - Validate SDK applications against best practices
claude-opus-4-5-migration Migrate code and prompts from Sonnet 4.x and Opus 4.1 to Opus 4.5 Skill: claude-opus-4-5-migration - Automated migration of model strings, beta headers, and prompt adjustments
code-review Automated PR code review using multiple specialized agents with confidence-based scoring to filter false positives Command: /code-review - Automated PR review workflowAgents: 5 parallel Sonnet agents for CLAUDE.md compliance, bug detection, historical context, PR history, and code comments
commit-commands Git workflow automation for committing, pushing, and creating pull requests Commands: /commit, /commit-push-pr, /clean_gone - Streamlined git operations
explanatory-output-style Adds educational insights about implementation choices and codebase patterns (mimics the deprecated Explanatory output style) Hook: SessionStart - Injects educational context at the start of each session
feature-dev Comprehensive feature development workflow with a structured 7-phase approach Command: /feature-dev - Guided feature development workflowAgents: code-explorer, code-architect, code-reviewer - For codebase analysis, architecture design, and quality review
frontend-design Create distinctive, production-grade frontend interfaces that avoid generic AI aesthetics Skill: frontend-design - Auto-invoked for frontend work, providing guidance on bold design choices, typography, animations, and visual details
hookify Easily create custom hooks to prevent unwanted behaviors by analyzing conversation patterns or explicit instructions Commands: /hookify, /hookify:list, /hookify:configure, /hookify:helpAgent: conversation-analyzer - Analyzes conversations for problematic behaviorsSkill: writing-rules - Guidance on hookify rule syntax
learning-output-style Interactive learning mode that requests meaningful code contributions at decision points (mimics the unshipped Learning output style) Hook: SessionStart - Encourages users to write meaningful code (5-10 lines) at decision points while receiving educational insights
plugin-dev Comprehensive toolkit for developing Claude Code plugins with 7 expert skills and AI-assisted creation Command: /plugin-dev:create-plugin - 8-phase guided workflow for building pluginsAgents: agent-creator, plugin-validator, skill-reviewerSkills: Hook development, MCP integration, plugin structure, settings, commands, agents, and skill development
pr-review-toolkit Comprehensive PR review agents specializing in comments, tests, error handling, type design, code quality, and code simplification Command: /pr-review-toolkit:review-pr - Run with optional review aspects (comments, tests, errors, types, code, simplify, all)Agents: comment-analyzer, pr-test-analyzer, silent-failure-hunter, type-design-analyzer, code-reviewer, code-simplifier
ralph-wiggum Interactive self-referential AI loops for iterative development. Claude works on the same task repeatedly until completion Commands: /ralph-loop, /cancel-ralph - Start/stop autonomous iteration loopsHook: Stop - Intercepts exit attempts to continue iteration
security-guidance Security reminder hook that warns about potential security issues when editing files Hook: PreToolUse - Monitors 9 security patterns including command injection, XSS, eval usage, dangerous HTML, pickle deserialization, and os.system calls

Installation

These plugins are included in the Claude Code repository. To use them in your own projects:

  1. Install Claude Code globally:
bash
npm install @anthropic-ai/claude-code
  1. Navigate to your project and run Claude Code:
bash
claude
  1. Use the /plugin command to install plugins from marketplaces, or configure them in your project's .claude/settings.json.

For detailed plugin installation and configuration, see the official documentation.

Plugin Structure

Each plugin follows the standard Claude Code plugin structure:

text
plugin-name/
├── .claude-plugin/
│   └── plugin.json          # Plugin metadata
├── commands/                # Slash commands (optional)
├── agents/                  # Specialized agents (optional)
├── skills/                  # Agent Skills (optional)
├── hooks/                   # Event handlers (optional)
├── .mcp.json                # External tool configuration (optional)
└── README.md                # Plugin documentation

Contributing

When adding new plugins to this directory:

  1. Follow the standard plugin structure
  2. Include a comprehensive README.md
  3. Add plugin metadata in .claude-plugin/plugin.json
  4. Document all commands and agents
  5. Provide usage examples

Learn More


Overview (`examples/mdm/README.md`)

MDM Deployment Examples

Example templates for deploying Claude Code managed settings through Jamf, Iru (Kandji), Intune, or Group Policy. Use these as starting points — adjust them to fit your needs.

All templates encode the same minimal example (permissions.disableBypassPermissionsMode). See the settings reference for the full list of keys, and ../settings for more complete example configurations.

Templates

[!WARNING]
These examples are community-maintained templates which may be unsupported or incorrect. You are responsible for the correctness of your own deployment configuration.

File Use with
managed-settings.json Any platform. Deploy to the system config directory.
macos/com.anthropic.claudecode.plist Jamf or Iru (Kandji) Custom Settings payload. Preference domain: com.anthropic.claudecode.
macos/com.anthropic.claudecode.mobileconfig Full configuration profile for local testing or MDMs that take a complete profile.
windows/Set-ClaudeCodePolicy.ps1 Intune Platform scripts. Writes managed-settings.json to C:\Program Files\ClaudeCode\.
windows/ClaudeCode.admx + en-US/ClaudeCode.adml Group Policy or Intune Import ADMX. Writes HKLM\SOFTWARE\Policies\ClaudeCode\Settings (REG_SZ, single-line JSON).

Tips

  • Replace the placeholder PayloadUUID and PayloadOrganization values in the .mobileconfig with your own (uuidgen)
  • Before deploying to your fleet, test on a single machine and confirm /status lists the source under Setting sources — e.g. Enterprise managed settings (plist) on macOS or Enterprise managed settings (HKLM) on Windows
  • Settings deployed this way sit at the top of the precedence order and cannot be overridden by users

Full Documentation

See https://code.claude.com/docs/en/settings#settings-files for complete documentation on managed settings and settings precedence.


Overview (`examples/settings/README.md`)

Settings Examples

Example Claude Code settings files, primarily intended for organization-wide deployments. Use these as starting points — adjust them to fit your needs.

These may be applied at any level of the settings hierarchy, though certain properties only take effect if specified in enterprise settings (e.g. strictKnownMarketplaces, allowManagedHooksOnly, allowManagedPermissionRulesOnly).

Configuration Examples

[!WARNING]
These examples are community-maintained snippets which may be unsupported or incorrect. You are responsible for the correctness of your own settings configuration.

Setting settings-lax.json settings-strict.json settings-bash-sandbox.json
Disable --dangerously-skip-permissions ✅ ✅
Block plugin marketplaces ✅ ✅
Block user and project-defined permission allow / ask / deny ✅ ✅
Block user and project-defined hooks ✅
Deny web fetch and search tools ✅
Bash tool requires approval ✅
Bash tool must run inside of sandbox ✅

Tips

  • Consider merging snippets of the above examples to reach your desired configuration
  • Settings files must be valid JSON
  • Before deploying configuration files to your organization, test them locally by applying to managed-settings.json, settings.json or settings.local.json
  • The sandbox property only applies to the Bash tool; it does not apply to other tools (like Read, Write, WebSearch, WebFetch, MCPs), hooks, or internal commands

Deploying via MDM

To distribute these settings as enterprise-managed policy through Jamf, Iru (Kandji), Intune, or Group Policy, see the deployment templates in ../mdm.

HIPAA deployments

For an organization that has the HIPAA configuration applied, settings-hipaa.json and managed-mcp-hipaa.json are a fuller managed-settings.json and managed-mcp.json pair with sandboxing, a network allowlist, credential protections, and local data retention. README-hipaa.md explains each choice and what to edit before deploying.

Full Documentation

See https://code.claude.com/docs/en/settings for complete documentation on all available managed settings.


Overview (`mods/agents-md/README.md`)

agents-md

AGENTS.md read the way Claude Code reads CLAUDE.md, as a plugin, under
one option, instructionFiles:

  • claude-md: only CLAUDE.md is loaded, by the engine, as today. The plugin
    adds nothing.
  • claude-md-or-agents-md (the default): a project with no instruction files
    of its own gets its AGENTS.md files instead, loaded exactly where and how
    CLAUDE.md would be. "Of its own" is read off what the engine loaded for
    the context: a CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in any
    directory from the root down to the working directory leaves the whole
    project to the engine, and the plugin stays out (the organization's managed
    file, the person's ~/.claude/CLAUDE.md, a .claude/rules file and an
    added directory's CLAUDE.md do not count, as the nested walk does not see
    them either). With none, every AGENTS.md and .claude/AGENTS.md on that
    path joins the instruction files the engine renders, and a Read under a
    subdirectory attaches that directory's AGENTS.md unless a CLAUDE.md
    there claims it.
  • claude-md-and-agents-md: every AGENTS.md is loaded beside CLAUDE.md,
    up and down the tree; a file CLAUDE.md already @-imports, or is a link
    to, is not loaded a second time (compared by path, then by content).
  • managed-only: the project's checked-in and private instruction files and
    the person's own are dropped from the context; the organization's managed
    CLAUDE.md and the engine's memory stay. The engine's nested CLAUDE.md
    attachments on Read are not an event yet and still arrive. (The engine's
    claudeMdExcludes setting also exists, for user, project and local files,
    and applies to the AGENTS.md files this plugin reads too.)

How the files reach the model is the engine's doing, not the plugin's:
prompt.context hands a hook the instruction files behind claudeMd
({ path, kind, content, parent? }, kinds managed, user, project,
local, memory, in load order) and a hook answers the list changed. The
engine then renders claudeMd from the answered files with its own preamble
and framing, announces them by name, and keeps only the managed ones for an
agent that omits project instructions (Explore, Plan, a custom agent with
omitClaudeMd). So an AGENTS.md this plugin adds as a project file is, to
everything downstream, a project instruction file: same place in the context,
same framing, same omission rules, same announcement. An organization's
prepended plugin on prompt.context sits above this one and has the last
word on the files.

hooks/register.ts is the module; everything under hooks/ is its parts,
importing claude-code and one another alone. tests/ runs under
claude plugin test .

Setting the option

As a built-in its option is the /config row "Project instructions", a
picker over the four values, each described there. By hand it is

json
{
  "pluginConfigs": {
    "agents-md@builtin": {
      "options": { "instructionFiles": "claude-md-and-agents-md" }
    }
  }
}

in user settings (~/.claude/settings.json), --settings, or managed
settings; a project's .claude/settings.json is not read for plugin
options. Changing it reloads the module, and the next context the engine
builds (the next turn after the reload, a new conversation, /clear, a
compaction) carries the new mode's files. A hand-typed value outside the
four is told once in the transcript and reads as the default. /plugin
lists the plugin among the built-ins, where a person can turn it off; with
it off the engine reads CLAUDE.md alone. No hooks setting or CLI mode turns
it off (disableAllHooks, allowManagedHooksOnly and --bare govern
settings hooks and installed plugins, not built-ins); where the engine loads
no instruction files (--bare without --add-dir, --safe-mode,
CLAUDE_CODE_DISABLE_CLAUDE_MDS) its walk finds none and it adds none,
CLAUDE.md and AGENTS.md alike.

The option was first keyed projectInstructions, with the values claude,
agents-fallback, both and none. A value still stored under that key is
honoured for now while instructionFiles reads as its default: none as
managed-only, claude as claude-md, agents-fallback as
claude-md-or-agents-md, both as claude-md-and-agents-md, any other
value as claude-md (which adds nothing, never as the default, which loads
AGENTS.md); the first session.start of a load says in the transcript how
it was read. Once instructionFiles is set to anything but its default, the
old key is not read and the transcript says to remove it.

Run from this folder instead (claude --plugin-dir mods/agents-md), the
same entry is keyed "agents-md".

What it hooks

event what the hook does
session.start in every mode: passes the start straight through and floats the usage row for the configured mode, never awaited; the first start of a load logs how a stored projectInstructions value is read. The session's start never waits on this plugin
prompt.context under claude-md-or-agents-md and claude-md-and-agents-md: walks $.fs.ancestors for the AGENTS.md files above the working directory and answers them as project instruction files, each @ import its own entry after its file, each placed where a project file of its directory stands (root first, before the first deeper project file, else after the last project file, before memory); files the engine already holds by path or by content are left out; under claude-md-or-agents-md it answers nothing when the project has a CLAUDE.md of its own (among the handed files, else found by a $.fs.ancestors walk, so a CLAUDE.md the engine loaded and then withheld still counts), and names the files it loaded in the debug log ($.ui.log with to: "debug": no CLAUDE.md found; AGENTS.md loaded: , nothing in the transcript) once, and again after a move to another project root; handed unknown files (a hook above rewrote the claudeMd text) it adds nothing; the first context of a load sends the load row (counts) and the feature mark; under managed-only (matcher: a project, local or user file present): answers the list without those kinds
agent.spawn on fork: true under claude-md-or-agents-md and claude-md-and-agents-md: a fork the Agent tool starts shares its parent's prompt prefix, so the parent loop's delivered nested files are copied to the fork's loop and not attached to it again (a run that resumes a fork is passed on untouched, the fork keeping the set its own loop was given; a /fork or /subtask fork does not raise agent.spawn yet and starts from an empty set, as every fork did before; a fork started in the same tool batch as a Read inherits that Read's file although its prefix holds a placeholder for it)
tool.call on Read under claude-md-or-agents-md and claude-md-and-agents-md, for a file under the session's project root ($.session.root(), read live, so /cd, a host's directory change and worktree moves are followed and a moved root starts the delivered sets and the fallback decision over; a file elsewhere gets nothing, as the engine attaches no nested CLAUDE.md there; and nothing anywhere in a run where the engine attaches nothing to a turn, --bare with its CLAUDE_CODE_SIMPLE or CLAUDE_CODE_DISABLE_ATTACHMENTS, read on every Read through $.env.get as the engine reads them on every turn): walks only the directories strictly between the root and the read file ($.fs.ancestors with below: root, as the engine walks only those for a nested CLAUDE.md, never up to the filesystem root again) and attaches their AGENTS.md files not yet given to that agent loop, not already among the context's instruction files (by path or, for a project file, by text) and not claimed by a CLAUDE.md of the same directory (or imported by one), as context after the tool result, framed Contents of : byte for byte as the engine frames a nested CLAUDE.md, whatever its size; each file once per loop and conversation (the context's recomputation after a compaction or /clear starts the count over), the context's files never; a Read that attached files sends the nested row. A ~ or ~/ path is read under the home directory as the Read tool reads it

What it calls on `$`

fs.ancestors (with each found file's parts: the file and its imports
apart; with below on a Read; it finds nothing on a thin client, whose
workspace files are remote, as the engine's own walk does), session.root,
session.cwd, env.get (HOME and USERPROFILE, once per load, the
profile first on a Windows spelling of the working directory, so a ~/ path
the model hands a Read resolves where the Read tool reads it; CLAUDE_CODE_SIMPLE
and CLAUDE_CODE_DISABLE_ATTACHMENTS on every Read), ui.log,
telemetry.log and telemetry.mark.

$.telemetry is the telemetry plugin's noun; where that
plugin is not seated the calls find no noun and are dropped without a trace,
and nothing else changes.

What it logs

Counts and closed choices only; no path and no file text. Each row goes
through $.telemetry.log, so it exists only where the telemetry plugin
does:

event when properties
agents_md_mode once per fresh load, at session.start mode (claude-md | claude-md-or-agents-md | claude-md-and-agents-md | managed-only), is_interactive
agents_md_load the first context of a load, under claude-md-or-agents-md and claude-md-and-agents-md mode, file_count (AGENTS.md files handed to the engine), import_count (their @ imports), total_content_length, yielded (claude-md-or-agents-md stood down for a CLAUDE.md of the project's own), walk_failed; with it one $.telemetry.mark for feature agents_md: ok, or sad with reason walk_failed
agents_md_nested a Read that attached nested files mode, file_count

Where it still differs from CLAUDE.md

All of these apply only to the modes that load AGENTS.md,
claude-md-or-agents-md (the default) and claude-md-and-agents-md. Each
names a loader fact a plugin cannot reach through the events it has today.

  1. Nested files attach on a text Read only. The engine also attaches a
    directory's CLAUDE.md for a file @-mentioned in the prompt, for the
    IDE's opened file or selection, and for the Read tool's notebook, image
    and PDF results.
  2. A nested file the plugin attaches is not registered in the loop's
    read-file state, so after a compaction the engine does not restore it
    among the recently read files (the plugin attaches it again at the next
    Read under that directory instead), and a change to it mid-session is
    not re-announced.
  3. /cd carries the new tree's CLAUDE.md in its own notice; the plugin's
    files for the new tree arrive in the same next request through the
    engine's instructions announcement instead.
  4. Paths compare by spelling; the engine resolves a symlinked alias of the
    working directory before deciding a file is inside it.
  5. --add-dir directories contribute no AGENTS.md, where the engine can
    load their CLAUDE.md.
  6. /memory and the # shortcut do not know AGENTS.md files, and the
    engine's own initial-load row does not count them (this plugin's
    agents_md_load row does).
  7. An @ import outside the working directory inside an AGENTS.md is
    honoured only once the approval the engine asks for a CLAUDE.md's
    external imports has been given (without it the import is left out, as a
    CLAUDE.md's is); the approval dialog itself is raised for CLAUDE.md
    imports alone.
  8. A subagent that is not a fork gets a nested AGENTS.md at its own first
    Read under that directory even when its parent's loop was already given
    it; the engine does not hand such a subagent the nested CLAUDE.md again.
    A fork matches the engine on both sides.

Testing

text
claude plugin test mods/agents-md

tests/register.test.ts covers the default mode: a project with AGENTS.md
alone gets it as a project instruction file and one debug-log line naming
it, with nothing in the transcript, a project with a CLAUDE.md of its own is
left to the engine without a walk, a failed walk leaves the context as handed,
and the start hands $.telemetry the mode row alone where a test seats a
provider for that noun, and goes on untouched where none is seated.


Overview (`mods/diff/README.md`)

diff

The diff pane as a plugin: /diff opens the session's uncommitted changes
beside the transcript, one row per changed file and every file's hunks
beneath, and closes it again; each toggle leaves Diff panel shown or
Diff panel hidden in the transcript. The header, the file list and its
toggles stay put while the wheel moves the hunks under them three rows a
tick, or the list a file a tick while the wheel is over a list longer than
its eight rows (the plugin answers the pane's ui.scroll itself); a row's
click puts that file's hunks at the top; the list also scrolls under the
built-in's list keys (ctrl+up/ctrl+down, opt+up/opt+down), and
ctrl+x b moves the comparison base on, as the built-in's chord does: both
through Buttons that declare the engine's own actions. The pane refreshes
as Claude edits and runs shell commands, and while it is open it polls
the repository's HEAD so a commit or checkout made elsewhere shows too.
The main loop's first successful edit of a session opens the pane by
itself, as the built-in panel opens on its first checkpoint: where the
layout docks it beside the transcript (the fullscreen layout, which each
drawing's viewport says), the terminal is wide enough (144 columns when
the person never chose, 110 when they kept it open before; a person who
closed it is left alone) and file checkpointing is on; a subagent's edit
opens nothing, and where the surface does not say, nothing opens by
itself. A docked pane fetches before it opens, as the built-in panel
primes its data, so it never lands on Loading diff…; an open the engine
leaves waiting undrawn is withdrawn, so no later resize seats it, and the
next edit asks again. An open answered no-surface (nothing is attached
that draws it yet, as before a host's page attaches) is kept instead:
/diff says so, nothing polls or refreshes while no one sees the pane, and
its first drawing reads the repository again and counts it shown. A session
resumed or continued whose transcript already holds such an edit opens the
pane on the same terms as soon as the width is known, as the built-in opens
on the history it restores.

Under the fullscreen layout a terminal under 110 columns gets the
built-in's line asking for a wider one and nothing opens. Without that
layout (CLAUDE_CODE_NO_FLICKER=0, which /diff learns from the command's
presentation) the pane opens inline at any width, focused and as tall
as its content (the open's rows), in the built-in dialog's shape: the
title, the count, five file rows at a time round the selected one (❯,
where the focus ring starts; the plugin follows the ring's walk through
ui.focus and re-centres the rows as the built-in does), the key hints;
Enter shows that file's hunks alone,
Escape backs out to the list and then closes, leaving Diff dialog dismissed; toasts show while it is up, as beside the docked pane. A file's
ask button arms that file: its hunks ride the next prompt as context, once.

The pane compares the working tree against HEAD, split at the session's
start (the default; the start the engine gives in $.session.usage(), so a
resumed session keeps its first and /clear begins anew), against HEAD
plainly, or against the merge-base with
the default branch; the base line under the header names a base other than
the session's, and the choice is kept per repository in the plugin's store.
A picker shows one earlier turn's edits instead of the working tree, read
from the session's messages. Files that changed before the session started
(by their timestamp, among the paths already dirty when the pane first
read the repository), and noise (lockfiles, generated and test files), are
listed apart and folded until asked for; a rename lists as git prints it.
Outside a git repository /diff says so and does nothing else.

Git runs when the built-in panel's would: nothing at the session's start;
one git rev-parse, in the directory the session started in, when /diff
or the first edit a pane has room to open on first needs the repository
(an answer of no repository is kept too, until /clear or /resume
forgets it); and the working tree is read only by a fetch for a pane that
is open, after an edit that landed or a shell command that ran. The one
read the built-in has no counterpart for is a git status at a pane's
first fetch, which stands in for the change time the built-in dates a
moved file by.

hooks/register.ts is the module; everything under hooks/ is its parts.

What it hooks

event what the hook does
session.start Binds the engine once and registers /diff (a session where another /diff is listed leaves the plugin idle); asks nothing of the repository, which /diff or the first edit pins when it comes; off its dispatch, reads the transcript, and for a resumed session whose turns edited opens the pane as the first edit would.
ui.render of PromptHint Reads the terminal's width and whether its layout docks a pane, which decide whether the first edit opens the pane.
ui.render of Pane Draws the pane: docked, the header, base line, source picker, file list and toggles over the window of hunks; inline, the dialog.
command.run of diff Pins the repository when none is, opens or closes the pane (focused and closing on Escape without the fullscreen layout), says which, and remembers the choice.
ui.close of the pane Backs out of the dialog's detail view instead of closing; else remembers the person's close as /diff's.
ui.scroll of the pane Docked, moves the hunks under the pinned header and list (three rows a wheel tick, a page a page key), or the list when the wheel is over it, and keeps the engine's window still.
ui.focus in the pane In the dialog's list, selects the file the ring lands on, re-centres the five rows on it, and lands the ring where that row now sits.
command.run of clear, resume Closes the pane and forgets the session's state, the pinned repository with it.
tool.call of Edit, Write, NotebookEdit After an edit that landed (not refused, not failed), refreshes an open pane; the main loop's first such edit opens it, pinning the repository then if the terminal has the room and checkpointing is on.
tool.call of Bash, PowerShell After a command that was not refused, failed and interrupted ones too, refreshes an open pane.
prompt.submit Adds the armed file's hunks to the prompt's context and disarms.

What it calls on `$`

clock.after, clock.every, clock.now, command.register, env.get
(CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING), fs.list, fs.read, fs.stat,
process.run (git, read-only), session.id, session.messages,
settings.read, store.get, store.set, telemetry.log, telemetry.mark,
ui.close, ui.invalidate, ui.log, ui.open, ui.resolve, ui.status.

$.telemetry is the telemetry plugin's noun; where it is absent the rows
are dropped and nothing else changes.

Try it

sh
claude --plugin-dir /path/to/diff

then /diff inside a git repository with a modified file.


Overview (`mods/sec-default/README.md`)

sec-default

The security default for organizations. Function hooks give every plugin a
say on every event, in chain order, and the plugins a person installs sit
in the user tier, beneath the organization's prepend tier and above its
append tier. Some of what an organization sets today (its classic hooks,
its managed CLAUDE.md and rules, its settings, its MCP allowlist, the deny
rules in force on its machines) was never within a person's reach before
function hooks; seated outermost, this plugin keeps exactly those out of the
user tier's reach and adds no policy of its own. Everything else passes
through untouched.

It has three moves and nothing else: continue past the user tier
(next.to(e, "append")), refuse a user-tier caller or module by name
({ deny } when next.origin.tier is user, { refuse } when a module's
pinned e.tier is), or pass (next(e)). A subject's provenance is the
event's pinned e.provider; policy is read through
$.settings.read({ source: "policy" }), one read serving a burst of tool
calls; both fail closed, so an unreadable policy counts as a policy in force.

hooks/register.ts is the module; hooks/policy/ reads the managed
settings it decides by.

The rows

event from the outermost seat
classic.* Continue past the user tier: the organization's settings hooks see the engine's input and their answer stands.
prompt.section, prompt.context, prompt.attachment, skill.prompt, attribution.text Continue past the user tier: managed CLAUDE.md, rules and policy skills, and what the engine injects for the model beside them (a settings hook's note, the instruction files, a mode's reminder), are not a person's plugin's to reword at these events. A person's plugins keep prompt.submit and its additive context. This does not cover the variables that turn off CLAUDE.md loading: a person's plugin or settings can set CLAUDE_CODE_DISABLE_CLAUDE_MDS, CLAUDE_CODE_SIMPLE or CLAUDE_CODE_SAFE_MODE, and no CLAUDE.md loads, the managed one included.
session.append For a row the engine injects for the model (the attachment and hook-context doors: a reminder, a settings hook's context), for a compaction's rows (the compaction door: its summary and boundary), for a skill's body as a call of the Skill tool hands it over (the tool-message door, that tool's rows alone, since the row does not say whose skill it is) and for a note an organization's plugin appends, continue past the user tier: the row is kept as made, so what passed prompt.attachment whole is not blanked or reworded on its way into the conversation. For a skill the hold does that much and no more: it stops rewording of the row in transit. A person's tool.call hook can still answer for a Skill call or swap input.skill, as it can for any tool; allowManagedModsOnly closes that. Every other row (a prompt, a response, a tool result, another tool's message, a delivery, a command's row, a notice, a note of a person's plugin, and a note the engine itself makes, a Stop hook's feedback among them) passes as the chain leaves it. What is held of a hook is its verdict and the context it adds; the words a hook's block feeds back to the model are such an engine-made note.
session.compact Continue past the user tier, whole: a conversation a person's plugin answers in place of a compaction is never installed, so the conversation a compaction leaves is the engine's or the organization's own making, and its summary is stored as made (the session.append row). A person's own compaction hook does not run where this plugin is seated; a plugin of theirs may still ask for a compaction, which the engine then makes.
prompt.compose Continue past the user tier: the system prompt's list of sections is what the organization's tiers, the built-ins and the engine's own composition make it. A person's plugin neither drops, reorders nor rewrites a section, nor changes the facts the list is composed from, nor answers a list of its own in its place. The engine raises this event only when some loaded plugin hooks it, so where this plugin is seated every render of the system prompt runs the chain.
settings.read Continue past the user tier: no user hook rewrites what any caller reads as settings, this plugin's own policy reads included.
tool.describe, command.describe, agent.offer, agent.spawn When the subject's pinned e.provider.tier is prepend or append (a policy-installed plugin, the managed folder, a policy MCP server), continue past the user tier; a subject provided by user, builtin or core passes.
tool.register A caller in prepend or append continues past the user tier. A user-tier caller is refused by name while managed settings hold allowedMcpServers (set at all, empty included). With no allowlist, one is still refused whose tool, called mcp____<tool>, would read as a tool of a server the organization delivers: a managedMcpServers entry, or a server of the enterprise managed-mcp.json, which the policy read names under that key. So is one whose name reads as a plugin the organization seats itself (prependPlugins, appendPlugins, or an id managed enabledPlugins turns on, by true or by a version list, as the engine reads an entry), or as an MCP server such a plugin's own manifest declares, which the engine spells under the plugin's scope (mcp__plugin__<server>__). A user-tier plugin keeps its own name exactly when the id the engine recorded for it (<name>@<marketplace>: the settings key the loader resolved, never the plugin's manifest) is one managed enabledPlugins turn on, compared as the engine compares ids (NFC, then lower case). That is how an organization's own plugin registers its tools where the engine leaves it in the user tier: only a copy read in place from a local folder marketplace that managed settings name is vouched for, so a plugin from a remote marketplace (git, GitHub, npm) can never be vouched for in this release, and neither is one a version list turns on. For an organization that means such a plugin runs among a person's plugins in the chain, not ahead of them, and keeps its tools by this exemption alone. A plugin loaded with --plugin-dir is always <name>@inline and never matches; nor does a same-named plugin from another marketplace, one whose name only folds to the organization's, or an id policy lists only in prependPlugins or appendPlugins. A person who registers a marketplace of their own under the organization's marketplace name gets an equal id, and so the exemption: it gives that plugin what every plugin had before this hold existed, and strictKnownMarketplaces in managed settings closes it today by allowing no other marketplace source. The mod hears a plugin's id at its admission, so after a load that seats the mod afresh while other plugins stay seated (a load that folds again, as a policy change mid-session can cause) the organization's own plugin is refused its name until the session restarts. A plugin's own MCP servers are connected by the engine from its manifest, not registered through tool.register, so they are unaffected. An id's name is everything before its last at-sign, as the engine parts ids, so a scoped @scope/name@npm counts. A managed-mcp.json that is present and cannot be read whole names nobody: the policy read marks it (managedMcpServersUnreadable) and every such registration is refused while it stands, its servers never taken for none; the only other reader of the mark is tool.list (the next row), so a person's plugins still load and still set what is not pinned. A server the file names and the engine dropped with a warning is still named; a warning about a server that loads is no failure. Names are compared folded, as a model reads them (spelled as the engine spells a name inside a tool's name, every character outside letters, digits, - and _ a _ and nothing normalized; then lower case, every run of - and _ one _; a seated plugin counts under its name composed and decomposed, since the engine spells its tools from its manifest's own form): a plugin named as the server in any case or with other separators, one whose name and tool together spell it, and one whose tool's own name folds to nothing, is refused. A server whose name folds to nothing (no letter or digit in it) cannot be told from any name, so while the policy names one every user-tier registration is refused. The engine pins the tool's name at this event (a hook beneath that hands on another name fails, and the chain goes on without it), so the name judged is the name registered. Otherwise it passes.
tool.list The tools of the organization's managed MCP servers, of the plugins it seats itself and of the MCP servers those plugins' own manifests declare (told by the name whole, as the engine spells it inside a tool's name: mcp__<server>__, never by a fold, so another server whose name only begins like the organization's is not taken for it; a seated plugin and its own servers, under its scope mcp__plugin__, fold to fold as the registration check compares, so policy may list its id in another letter case, and another plugin whose name begins with the seated one's and a - or _ reads the same) are listed as the organization's tiers listed them; every other tool as the user tier left it. Where the server file cannot be read, every mcp__ tool counts as the organization's. With no policy to read, or a refusal from either listing, the organization's listing stands whole.
tool.check A deny, an ask a settings rule, a classic hook, a setting's own check or an organization's ceiling on the tool stands behind, an ask a host answers in the person's place and an ask a built-in or an organization's hook put to a person, hold whole over the user tier: when a person's plugin rewrote the verdict it was handed without tightening it (a more permissive decision, or the same decision under another reason or with what it names changed), the dispatch is run again past the user tier, and unless the chain's answer is the stricter, that verdict, if it is a deny or names what stands behind it or who it is put to, is the answer as the engine gave it. See Deny rules hold. Every other verdict passes as the chain left it.
ui.log A line a plugin in prepend or append logs, this one's included, continues past the user tier: no user hook rewrites or drops it, and none runs inside the hook that logged it. Every other line passes.
env.get A read by a plugin in prepend or append continues past the user tier: no user hook answers what the organization's own plugin reads. Every other read passes.
env.set A write by a plugin in prepend or append continues past the user tier, whatever the variable: no user hook rewrites or drops what the organization's own plugin sets. A variable managed settings set in env (its name in any case) is pinned, and so are CLAUDE_CODE_PROCESS_WRAPPER where they name a launcher with processWrapper and, always, the nine variables that move where policy and sign-in are read from or how policy's tiers compose (CLAUDE_CODE_MANAGED_SETTINGS_PATH, CLAUDE_CODE_REMOTE_SETTINGS_PATH, CLAUDE_CODE_MOCK_REMOTE_SETTINGS, CLAUDE_CODE_DISABLE_ADMIN_ENV_UNION, CLAUDE_CONFIG_DIR, CLAUDE_SECURESTORAGE_CONFIG_DIR, USE_LOCAL_OAUTH, USE_STAGING_OAUTH and CLAUDE_LOCAL_OAUTH_API_BASE, which choose the server sign-in goes to; all nine on every build), and, on every build too, ten variables that can load code into a child the engine starts (LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, DYLD_INSERT_LIBRARIES, DYLD_LIBRARY_PATH, DYLD_FRAMEWORK_PATH, BASH_ENV, ENV, ZDOTDIR, NODE_OPTIONS): setting or unsetting it, a user-tier caller is refused by name and a built-in's write continues past the user tier. Any other variable is a person's plugin's to set. With no policy to read, every variable counts as pinned. allowModsToOverrideDenyRules does not unpin. See Pinned variables.
plugin.register A hooks module in the user tier (one a person installed, named with --plugin-dir, or keeps in their mods folder) is refused while managed settings set this plugin's allowManagedModsOnly option; otherwise it passes. Modules in prepend, append and builtin are never asked about.
everything else Passes: prompt.submit, turn.*, tool.call, command.run, command.register, command.list, agent.register, config.*, prompt.fill, prompt.suggest, prompt.edit, prompt.read, session.* but session.append and session.compact, ui.* but ui.log, fs.*, http.fetch, process.run, store.*, clock.*, model.*, mcp.call, audio.*, agent.list, engine.create.

Options an administrator sets

Two, in managed settings, under this plugin's own pluginConfigs entry,
keyed by the id the CLI builds the plugin in under (only this spelling of the
id is read):

json
{
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": { "allowManagedModsOnly": true }
    }
  }
}

allowManagedModsOnly: only the mods the organization deploys through
managed settings, and the ones built into Claude Code, load. A hooks module
a person installed, named with --plugin-dir or keeps in their mods folder
is refused whenever it loads or reloads (one already running when the option
is set keeps running until then), with one line that names it: mods are limited to your organization's by policy (allowManagedModsOnly); was not loaded
(in the debug log, and on screen where the session hot-reloads the mod's
folder). A plain -p run has it in the debug log alone; the mod is still
not loaded. Settings hooks, status lines and /goal are not touched by it.

  • The decision reads the tier the CLI pins on the module and nothing the
    module says of itself: a person's copy carrying an organization mod's name
    is still in the user tier and is refused.
  • Refused means nothing of the module joins: no hook, no tool, no command.
    Its top-level code has run once by then, in the closed context every hooks
    module is evaluated in, with no call on $ served.
  • Only managed settings are read ($.settings.read({ source: "policy" })):
    the same entry in a person's, a project's or a --settings file neither
    turns it on nor off. On unless absent or false, so a mistyped "true" or
    1 still locks. A value the settings schema rejects (null, an object),
    here or in any other pluginConfigs entry, makes the CLI ignore the whole
    pluginConfigs key with a settings warning, and the option reads as unset.
  • It fails closed: when the read of managed settings is refused (a hook beneath
    denies it) or this plugin's hook fails, its .catch refuses the module,
    with the same line, and names the failure in the debug log; so a policy
    that cannot be read keeps every person's mod out at load. Where this plugin
    is not seated there is no such rule, and mods load as they do without it.
  • Where managed settings define prependPlugins, that list must name this
    plugin (next section) for the option to apply.
  • claude plugin test is not covered: it runs a mod's tests in an engine of
    their own and loads nothing into a session.

allowModsToOverrideDenyRules: the plugins a person installs may answer
over a settings deny rule on tool.check, as they could before this plugin
held deny rules, and over every other deny, an ask rule, a classic hook's
ask, a setting's own ask or an ask a host or a person answers with it: the one option
covers all that holds there. Off unless it is the
literal true; an option that reads as unset leaves them holding. See
Deny rules hold.

What it hooks

classic.*, prompt.section, prompt.context, prompt.attachment,
prompt.compose, skill.prompt,
attribution.text, session.append, session.compact, settings.read, tool.describe, command.describe,
agent.offer, agent.spawn, tool.register, tool.list, tool.check,
ui.log, env.get, env.set, plugin.register.

Hooking tool.check has a cost: the engine raises that event only when some
loaded plugin hooks it, so where this plugin is seated every tool call now
runs the tool.check chain, where before only a session with such a plugin
did. So has hooking ui.log, env.get and env.set: each such call of any
plugin's now runs a chain, and an env.set from outside the organization's tiers waits on
the policy read.

What it calls on `$`

settings.read, and ui.log: to the debug log, and for the one line a
person reads when something held over a plugin of theirs. It continues to
the append tier with next.to, which only a plugin in a managed tier may
do.

Deny rules hold

On tool.check any hook may answer any verdict, so a plugin a person
installs to stop the permission prompts (() => ({ decision: "allow" }))
would also lift a deny rule, an ask rule or a PreToolUse hook's ask, a
managed one included, the read block's ask on a shell command, and the ask a
host was to answer. Where this plugin is seated it does not:

  • The hook first runs the chain as it is. If no link that may hold a
    person's plugin rewrote the verdict handed up to it (a more permissive
    decision, or the same decision under another reason, rule or hook; a
    tightening is no rewrite), the answer passes: nothing of the person's
    changed anything, and a plugin that only listens, or only tightens, adds no
    run of its own.
    This is read off next.trace, whose tiers the engine pins: a link that never
    called next is measured against a deny, and since the engine lists
    neighbouring plugins that share a worker as one batch under its first
    member's tier, a prepend entry beneath this plugin counts as well as a
    user one. Whether a person's plugin did the rewriting is never settled
    here, only by the next step.
  • Otherwise it runs the dispatch once more with the user tier left out
    (next.to(e, "append")). That verdict never passed through a person's
    plugin, so neither the decision nor the rule it names can have been
    rewritten or erased, and a plugin that answered without calling next
    changes nothing: the rules are evaluated in this run. The two runs differ
    by the user tier alone, so where they differ and the chain's answer is not
    the stricter, the user tier rewrote it. A deny is returned in place of the
    chain's answer whatever decided it; an ask, when it names what decided it,
    a settings rule (rule), a classic hook (hook), a setting whose own
    check asked (setting) or an organization's ask cap on the tool
    (ceiling), or names who answers it (decider: a host, or a person a
    built-in or an organization's hook put it to). It is returned
    whole, so the reason this event answers, which a person reads in the
    prompt and the engine writes into a refusal, is the engine's, and what it
    names is still named. (The refusal then enters the conversation as a tool
    result, a row a person's plugin may still reword at session.append.) A
    stricter answer of theirs (a deny over an ask) stands.
  • Any rule, any classic hook, any such setting and any such cap counts,
    whoever configured it: a verdict carries the rule as written, the hook's
    event, the setting's key and the cap, never where any was read from. A
    deny holds unnamed because
    it can stand in front of such an ask: lifted, the call would run with nobody
    asked. An ask that names none of them and that the person answers at a
    dialog (the mode's own, a check of the engine's own that no setting turns
    on) is not held.
  • A person: a hook that answers ask with decider: "person" keeps the
    call from the classifier's allow. Made by a built-in or an organization's
    hook, that ask holds, so a person's plugin neither allows it nor turns it
    back into a plain ask. A person's own plugin may ask a person too, over a
    verdict that does not hold, and over a host's ask by changing only its
    decider to "person": that is a tightening and passes. Any other change
    to a host's ask stays held. As for any hook's ask, a rule for the whole tool
    is not kept; a narrower rule the person saves is theirs and settles nothing
    while the hook asks.
  • The setting the engine names today is the read block's
    (permissions.blockReadsOutsideWorkingDirectories), for the two asks the
    block keeps for the person: about a shell command that reads outside the
    working directories, and, while the block is on, about a command the model
    wants run outside the sandbox, which is what holds its reads in. The file
    tools refuse such a read outright, and a deny holds as it is.
  • A host: where the permission callback of the program that runs the session
    answers its asks (an SDK host's can_use_tool, a permission prompt tool;
    a cloud session's host is one), the engine's own ask says so
    (decider: "host"), in every loop of the process, a subagent's included,
    and only where the host would be asked. Such an ask holds, the mode's own
    too: it goes on to whatever the mode puts between an ask and the host
    (auto mode's classifier) and then to the callback, as it would with no
    plugin loaded. An evaluation the engine has not classified is held.
  • Where no host can be asked on an evaluation, it names none, and a
    person's plugin's allow answers as it does with no host. That is a closed
    list, pinned by a test: an in-process teammate's own function (under a
    headless leader its ask is cancelled or never answered); the comment
    auto-edit's own checks (one that is not an allow ends in a notice); the
    observer's gate (an ask there is a deny); a fork, subtask, workflow or
    forked command that has no session function of its own; and a skill's
    inline shell command where no hand-off exists, since an ask then fails
    the render. With a hand-off, in auto mode, that command's ask is left to
    the model's own call, which the host is asked about: it holds.
  • An ask that is certain to be refused with nobody asked names no host, so
    a person's plugin's allow answers it as it does in a session no host
    runs: under dontAsk, in a loop no prompt can show in (a background
    agent's; in auto mode there, with no chain, the plugin's allow comes
    before the classifier, as it does on main), once a permission prompt
    tool's server has left the session. An ask only a dialog on this computer
    can show holds under a prompt tool and on a served call: the engine denies
    it there, and a plugin's allow does not turn that deny into an allow.
    What is not certain holds: every other mode, a
    Chrome tool's ask under dontAsk (a site grant sends it on), and, where
    the host is set to be asked again after every allow auto mode's
    classifier gives, a loop no prompt can show in.
  • A call this computer runs for a cloud session names that session as its
    host: its ask goes there and holds. Serving marks nothing for this
    computer's own session: its calls name a host only if one answers them.
  • The two hosts the engine knows to show the question to the person on a
    card (the IDE pane, the desktop app's Code tab) are that person's dialog
    and are not named. The session's start says which it is, once, for the
    hold and for the card alike; nothing written later changes it. Only the
    host's own request is such a card: a permission prompt tool's question
    holds in a pane too. The
    entrypoint is asserted by the start environment, not proven: whoever sets
    the environment a session is spawned with can claim a pane.
  • An organization's plugin (prepend or append) or a built-in that allows
    over a deny rule takes part in both runs, so its answer stands (a prepended
    one that loosens is what brings the second run about, so its hooks run
    twice on such a call). The mode's own ask
    that a person's plugin turns into an allow, with nothing named behind it
    and the person the one who would have been asked, stands: that is what such
    a plugin is for.
  • tool.check pins the question (tool, input, tool_use_id), so no hook
    can have the rules evaluated on one command and another run; a rewrite
    belongs to tool.call, which runs before any of this.
  • The person is told once for each name and kind in a session, in the
    transcript and the debug log: tried to lift a deny rule in your settings from a <tool> call (<rule>); the deny rule holds over the plugins you install (allowModsToOverrideDenyRules), or tried to reword where
    the decision was kept and its words or its rule were not. The kinds are a deny rule,
    an ask rule, a <event> hook's ask, a <key> setting's ask, a host's ask and a refusal (a deny that names no rule); only the two rule kinds
    carry in your settings and a rule. Plugins the
    engine ran as one
    batch are named together, as it names them (audit+easy). A plain -p
    run has it in the debug log alone; the call is still denied, or asked
    about, with its own message. The line goes past the user tier (the ui.log
    row): a hook of theirs that heard it would run inside this plugin's own
    tool.check hook, and the engine leaves a hook out of whatever is raised
    from inside it.
  • What this does not reach: a held ask is still an ask, so whatever answers
    asks for the person answers it, a classic PermissionRequest hook of
    theirs included (allowManagedHooksOnly is the control for those). Nor an
    ask of the engine's own check that no setting turns on (a dangerous
    removal's): at a dialog the verdict does not tell it from the mode's own,
    so a person's plugin may still answer it there. Nor a session nobody
    answers asks for (a plain -p run, where an ask is refused): the mode's
    own ask is a person's plugin's to allow there. Nor a hosted session where
    this plugin is not seated: a person's plugin answers the mode's ask there
    as it does at a dialog. Nor an ask an organization's own plugin answers
    without passing on the engine's verdict: it names nothing unless that
    plugin names it.
  • It does not reach a person's classic PreToolUse hook that allows
    either: the engine then raises no ask at all, tool.check never runs, and
    the host is not asked. That is the same with no plugin loaded.
  • If the hook itself fails, its .catch answers from the one run it can
    read: a verdict no plugin of the person's rewrote stands, one they
    tightened included; one they rewrote, or a run that rejected, is refused
    in this plugin's own words, since the rules and hooks were never consulted.

An organization that wants the plugins its people install to override deny
rules, and all else that holds with them, says so in managed settings, under
this plugin's own options:

json
{
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": { "allowModsToOverrideDenyRules": true }
    }
  }
}

Only the managed source is read ($.settings.read({ source: "policy" })),
so the same key in a person's, a project's or a local settings file, or in
--settings, is never consulted; only the literal true counts, and a
policy that cannot be read leaves them all holding. So does a policy no
administrator composed: where the only policy is a document the person can
write themselves (the Windows HKCU hive), or a remote policy the server
has not yet confirmed this session, the option is not taken from it.
That policy still holds what it holds; it grants nothing.

Pinned variables

$.env.set writes the session's own environment. A variable managed
settings set in env is the organization's to decide, so this plugin
refuses a person's plugin that sets or unsets one (the env.set row). It
refuses the same of the launcher's variable where policy names a launcher,
and, on every build and whatever managed settings hold, of the nine
variables that move where policy and sign-in are read from: a write of one
would point a later load or launch at another policy. An
organization's own plugin's reads, writes and log lines continue past the
user tier's hooks (the env.get, env.set and ui.log rows).

It refuses the same of ten variables that can load code into a child the
engine starts, a managed hook's command among them: the loader's
(LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, DYLD_INSERT_LIBRARIES,
DYLD_LIBRARY_PATH, DYLD_FRAMEWORK_PATH), a shell's start file
(BASH_ENV, ENV, ZDOTDIR) and the runtime's options (NODE_OPTIONS).
Each reaches some children, not all: BASH_ENV a bash that is not
interactive, ENV an interactive shell in sh mode, NODE_OPTIONS a Node
child, and macOS drops the DYLD_ names for protected binaries.
That pin is a list, not a boundary. A person's plugin can start a process
as the person by other roads, and other variables steer a child too
(PATH, the home variables, a credential file's path). The pin keeps the
organization's hook commands and tools from being re-pointed by accident
or by a careless plugin, not by a hostile one.

  • At a load, from the first admission until the set serves, an op a plugin
    makes (one it left running between the load's steps too) is raised through
    the plugins admitted so far, this one first: a pinned variable is
    refused to a person's plugin.register hook then as at any later time.
  • What this does not reach: a variable that managed env does not set and
    that is not among those names is a person's plugin's to write, and the
    children the engine starts afterwards (Bash, an MCP server, $.process.run,
    a person's own hook) start from the environment as written.
  • A hook the organization defines is the exception: one in managed settings,
    one of a plugin managed settings install, and the managed status line and
    file suggestion commands. A plugin counts as one managed settings install
    only when it is read in place from a folder those settings name; a plugin
    they merely enable by id, loaded from a copy on the person's machine (a
    marketplace download, or the person's own folder under that id), is not
    treated as the organization's, for its hooks or for its writes. The
    organization's hook's command starts from the environment, and is
    wrapped in the CLAUDE_CODE_SHELL_PREFIX, as they stood before any write a
    person's plugin made with $.env.set in this process: a variable such a
    plugin set or deleted reads as it did before, absent if it was absent. A
    managed HTTP hook's header variables are read the same way, and so is the
    time allowed to the hooks that run as a session ends. What an
    organization's plugin, or one built into the CLI, writes still reaches the
    hook, also where it writes a variable a person's plugin wrote first; a
    value a later settings reload puts over the person's plugin's value stands
    too. A write counts as the organization's only when no person's plugin
    stands behind it. A write made while serving a person's plugin, or in a
    call a person's plugin raised, is a person's; so is an organization's
    write whose value a hook of a person's plugin changed before it was made.
  • A person still decides the environment Claude Code starts in (PATH,
    LD_PRELOAD, CLAUDE_CODE_SHELL_PREFIX are theirs to set before launch,
    and in their own settings files), and a managed hook starts from that
    environment like every other child. The same holds for the proxy and
    certificate, credential, provider and home variables (HTTPS_PROXY,
    NODE_EXTRA_CA_CERTS, ANTHROPIC_API_KEY, HOME and their like): they are
    not pinned, because a person sets the same ones in their own settings and
    shell, so a pin on env.set would not close that road. Where that road is
    closed, the engine closes it for a plugin too, with or without this
    plugin seated: in a session that asks its organization for its settings (a
    Cowork cloud session), a plugin that is not built in sets or unsets only a
    variable the filters on every settings env would let a person's own
    settings file set there, and any other write (the proxy and certificate
    variables among them) is held and answered { deny }. A plugin the
    container's managed settings enable is held alike: the session may be able
    to write that file. So is a write, or an unset, of a name any settings tier
    above the person's sets there (the project's, the local, a --settings
    file's or the organization's own settings env), and a built-in's own
    write in three corners: the built-in serves a plugin that is not built in,
    it writes from a dispatch such a plugin raised, or it writes beneath a call
    some hook rewrote, since who rewrote it cannot be told. An organization
    pins the variables its hooks rely on by setting them in managed env. An
    organization's plugin's $.env.get is answered past the user tier's hooks,
    with the environment as written.

Where it is seated

The CLI seats it first in the prepend tier wherever hooks modules load on a
machine with managed settings or a managed-mcp.json, or for a Team or
Enterprise organization,
unless managed settings define prependPlugins: then that list is the
whole prepend tier, and the organization names sec-default@builtin in it
at the position it wants, e.g. "prependPlugins": ["acme-guard@acme-tools", "sec-default@builtin"], or leaves it out. Once seated by the machine's
managed settings or by the plan, it stays seated until the session ends: a
plan that reads differently at a later reload (a token variable a plugin
set, an apiKeyHelper that appeared in a person's settings, another
sign-in) does not unseat it. How a person signs in before a launch is
theirs, so a seat that rests on the plan alone follows the sign-in at the
next launch; managed settings on the machine are what hold it there. The
organization's own prependPlugins list still decides at every reload,
with one exception: a Cowork cloud session that asks its organization for
its managed settings seats it by default, and there a prependPlugins list
that leaves it out does not unseat it. The only such list a session there
can hold is a file's in its container, which the session can write as well
as its environment can, so it may add a hold and never lift one. That
default ends once the organization's 200 has set nothing, the server
has named a Pro or Max plan for the launch's login and the host's plan
variable agrees: it is then known that nothing seats it, as in the
terminal, and a policy served later brings it back. It
is a plugin folder like any
other, but its one move that matters, next.to, is refused outside a
managed tier, so loading it with --plugin-dir seats a plugin that can
only pass.


Overview (`mods/telemetry/README.md`)

telemetry

Plugin analytics as a plugin: its hooks on telemetry.log and
telemetry.mark are what those two events do, built over the nouns its
engine.create step is handed, and a gate above them serves the plugins
built into Claude Code alone: a call from a plugin a person installed or an
administrator listed is refused with a reason (the host stamps every call
with the plugin that raised it, next.origin, and the gate reads its tier).
On an engine that has no $.telemetry of its own the same step adds the
noun, so the calls exist there too. An entry names where it goes with to:
anthropic, the default, is this mod's; one for collector, the telemetry
collector an operator configured, is passed on beneath untouched, and to
is never part of a row.
$.telemetry.log({ event, props }) queues one event as one first-party
row, tengu_plugin_<event>; $.telemetry.mark({ feature, kind, reason?, props? }) marks one use of a feature as the CLI's own feature events do,
tengu_feature_<kind> with a feature_name and the mark's properties
beside it. Both resolve once the row is queued. Rows go out in batches: one
POST to the event-logging ingest with the session's own credential
($.session.authorize(), resolved for each batch) a few seconds after the
first row was queued, at once when a hundred wait, and when the session
ends; a batch the ingest refuses with a server error, a timeout or a rate
limit is tried once more. A session with no first-party credential, or an
ingest that still refuses, drops the batch; each outcome is one line in the
debug log.

Each row carries what the CLI's own rows carry, gathered through $ once
a session: an event id, the install's device id and the signed-in account's
ids from the CLI's global config, the session's id, model, client type,
entrypoint and interactivity, and an env block (platform and
architecture from one uname probe, terminal, shell, package managers and
runtimes, CI and GitHub Actions, the remote container, the deployment, the
Linux distribution and kernel, WSL, the working directory's version
control, and the engine's version, base version and build time from
$.session.version(), left empty on an engine that does not answer it),
with the repository's remote hash beside the row's properties. What the
engine alone knows (its runtime's version, the process's memory, the
request's betas, the subscription tier, the calling agent) is not on $,
and those columns stay empty.

It sends nothing wherever the CLI's own analytics are off: under
DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC or
DO_NOT_TRACK, in a test run, on any third-party provider (Bedrock,
Vertex, Foundry and kin) the host does not manage, on a cloud gateway
(the environment's switch or the managed policy's login pins), and on a
deployment with its own OAuth URL. Each is read through $.env and
$.settings before every batch, so a session that has since moved to a
third-party provider or a gateway sends nothing more; when the switches
cannot be read, nothing is sent either. The row's user_type is ant
when USER_TYPE says so, else external.

Nothing free-form reaches a row. An event name and every property key is a
snake_case token; a value is a finite number, a boolean, or a Choice (a
string named together with the list it is chosen from), under log and
mark alike; mark takes ok, sad or bad, with a reason required on
the last two and refused on the first. An entry that breaks a rule is
refused before anything is queued. Of the environment, a variable whose
value is a secret, or names a person or a host, is read for whether it is
set and nothing more; a shell is its basename from a closed list.

hooks/register.ts is the module; types/index.d.ts is the noun's contract,
the one declaration of $.telemetry that this mod's hooks, a mod calling the
noun and a test answering it all read.

What it hooks

telemetry.*, the gate: a caller in the built-in tier (or the engine) goes
on, any other is refused, and a gate that throws refuses too.
telemetry.log and telemetry.mark, beneath the gate: the entry is checked
and its row queued, the hook answering { value }, or { deny } with the
reason for an entry that breaks a rule, so the caller's promise rejects
naming it. engine.create: the sender is built over await next(e), and
the step hands up { ...{ telemetry }, ...beneath }: what is beneath is
spread last, so its own telemetry stands where it has one and this mod's
is added where it has none; nothing beneath is replaced.
session.start, to learn whether a person is at the prompt; session.end,
to send what still waits.

What it calls on `$`

session.authorize, session.id, session.model, session.surfaces,
session.cwd, session.repo, settings.read, env.get (the switches and
the describing variables, by literal name), fs.read, fs.list,
fs.exists, process.run (one sh -c of uname and command -v),
clock.after, clock.sleep, http.fetch and ui.log (to the debug log),
each on the interface the fold handed it.

Where it runs, whom it serves

This plugin is seated by the CLI itself, on every build whose own analytics
are on, and nowhere else; it serves the plugins bundled with the CLI and
refuses every other caller. It is not meant to be installed or loaded with
--plugin-dir; the folder has a manifest so it reads like every other
plugin, not so it can stand alone. A built-in that calls $.telemetry
where this one is absent finds no such noun, or, on an engine with the noun
of its own, one whose calls queue nothing; either way that is "no analytics
here".


Overview (`plugins/agent-sdk-dev/README.md`)

Agent SDK Development Plugin

A comprehensive plugin for creating and verifying Claude Agent SDK applications in Python and TypeScript.

Overview

The Agent SDK Development Plugin streamlines the entire lifecycle of building Agent SDK applications, from initial scaffolding to verification against best practices. It helps you quickly start new projects with the latest SDK versions and ensures your applications follow official documentation patterns.

Features

Command: `/new-sdk-app`

Interactive command that guides you through creating a new Claude Agent SDK application.

What it does:

  • Asks clarifying questions about your project (language, name, agent type, starting point)
  • Checks for and installs the latest SDK version
  • Creates all necessary project files and configuration
  • Sets up proper environment files (.env.example, .gitignore)
  • Provides a working example tailored to your use case
  • Runs type checking (TypeScript) or syntax validation (Python)
  • Automatically verifies the setup using the appropriate verifier agent

Usage:

bash
/new-sdk-app my-project-name

Or simply:

bash
/new-sdk-app

The command will interactively ask you:

  1. Language choice (TypeScript or Python)
  2. Project name (if not provided)
  3. Agent type (coding, business, custom)
  4. Starting point (minimal, basic, or specific example)
  5. Tooling preferences (npm/yarn/pnpm or pip/poetry)

Example:

bash
/new-sdk-app customer-support-agent
# → Creates a new Agent SDK project for a customer support agent
# → Sets up TypeScript or Python environment
# → Installs latest SDK version
# → Verifies the setup automatically

Agent: `agent-sdk-verifier-py`

Thoroughly verifies Python Agent SDK applications for correct setup and best practices.

Verification checks:

  • SDK installation and version
  • Python environment setup (requirements.txt, pyproject.toml)
  • Correct SDK usage and patterns
  • Agent initialization and configuration
  • Environment and security (.env, API keys)
  • Error handling and functionality
  • Documentation completeness

When to use:

  • After creating a new Python SDK project
  • After modifying an existing Python SDK application
  • Before deploying a Python SDK application

Usage:
The agent runs automatically after /new-sdk-app creates a Python project, or you can trigger it by asking:

text
"Verify my Python Agent SDK application"
"Check if my SDK app follows best practices"

Output:
Provides a comprehensive report with:

  • Overall status (PASS / PASS WITH WARNINGS / FAIL)
  • Critical issues that prevent functionality
  • Warnings about suboptimal patterns
  • List of passed checks
  • Specific recommendations with SDK documentation references

Agent: `agent-sdk-verifier-ts`

Thoroughly verifies TypeScript Agent SDK applications for correct setup and best practices.

Verification checks:

  • SDK installation and version
  • TypeScript configuration (tsconfig.json)
  • Correct SDK usage and patterns
  • Type safety and imports
  • Agent initialization and configuration
  • Environment and security (.env, API keys)
  • Error handling and functionality
  • Documentation completeness

When to use:

  • After creating a new TypeScript SDK project
  • After modifying an existing TypeScript SDK application
  • Before deploying a TypeScript SDK application

Usage:
The agent runs automatically after /new-sdk-app creates a TypeScript project, or you can trigger it by asking:

text
"Verify my TypeScript Agent SDK application"
"Check if my SDK app follows best practices"

Output:
Provides a comprehensive report with:

  • Overall status (PASS / PASS WITH WARNINGS / FAIL)
  • Critical issues that prevent functionality
  • Warnings about suboptimal patterns
  • List of passed checks
  • Specific recommendations with SDK documentation references

Workflow Example

Here's a typical workflow using this plugin:

  1. Create a new project:
bash
/new-sdk-app code-reviewer-agent
  1. Answer the interactive questions:
text
Language: TypeScript
Agent type: Coding agent (code review)
Starting point: Basic agent with common features
  1. Automatic verification:
    The command automatically runs agent-sdk-verifier-ts to ensure everything is correctly set up.

  2. Start developing:

bash
# Set your API key
echo "ANTHROPIC_API_KEY=your_key_here" > .env

# Run your agent
npm start
  1. Verify after changes:
text
"Verify my SDK application"

Installation

This plugin is included in the Claude Code repository. To use it:

  1. Ensure Claude Code is installed
  2. The plugin commands and agents are automatically available

Best Practices

  • Always use the latest SDK version: /new-sdk-app checks for and installs the latest version
  • Verify before deploying: Run the verifier agent before deploying to production
  • Keep API keys secure: Never commit .env files or hardcode API keys
  • Follow SDK documentation: The verifier agents check against official patterns
  • Type check TypeScript projects: Run npx tsc --noEmit regularly
  • Test your agents: Create test cases for your agent's functionality

Resources

Troubleshooting

Type errors in TypeScript project

Issue: TypeScript project has type errors after creation

Solution:

  • The /new-sdk-app command runs type checking automatically
  • If errors persist, check that you're using the latest SDK version
  • Verify your tsconfig.json matches SDK requirements

Python import errors

Issue: Cannot import from claude_agent_sdk

Solution:

  • Ensure you've installed dependencies: pip install -r requirements.txt
  • Activate your virtual environment if using one
  • Check that the SDK is installed: pip show claude-agent-sdk

Verification fails with warnings

Issue: Verifier agent reports warnings

Solution:

  • Review the specific warnings in the report
  • Check the SDK documentation references provided
  • Warnings don't prevent functionality but indicate areas for improvement

Author

Ashwin Bhat ([email protected])

Version

1.0.0


Overview (`plugins/claude-opus-4-5-migration/README.md`)

Claude Opus 4.5 Migration Plugin

Migrate your code and prompts from Sonnet 4.x and Opus 4.1 to Opus 4.5.

Overview

This skill updates your code and prompts to be compatible with Opus 4.5. It automates the migration process, handling model strings, beta headers, and other configuration details. If you run into any issues with Opus 4.5 after migration, you can continue using this skill to adjust your prompts.

Usage

text
"Migrate my codebase to Opus 4.5"

Learn More

Refer to our prompting guide for best practices on prompting Claude models.

Authors

William Hu ([email protected])


Overview (`plugins/code-review/README.md`)

Code Review Plugin

Automated code review for pull requests using multiple specialized agents with confidence-based scoring to filter false positives.

Overview

The Code Review Plugin automates pull request review by launching multiple agents in parallel to independently audit changes from different perspectives. It uses confidence scoring to filter out false positives, ensuring only high-quality, actionable feedback is posted.

Commands

`/code-review`

Performs automated code review on a pull request using multiple specialized agents.

What it does:

  1. Checks if review is needed (skips closed, draft, trivial, or already-reviewed PRs)
  2. Gathers relevant CLAUDE.md guideline files from the repository
  3. Summarizes the pull request changes
  4. Launches 4 parallel agents to independently review:
    • Agents #1 & #2: Audit for CLAUDE.md compliance
    • Agent #3: Scan for obvious bugs in changes
    • Agent #4: Analyze git blame/history for context-based issues
  5. Scores each issue 0-100 for confidence level
  6. Filters out issues below 80 confidence threshold
  7. Outputs review (to terminal by default, or as PR comment with --comment flag)

Usage:

bash
/code-review [--comment]

Options:

  • --comment: Post the review as a comment on the pull request (default: outputs to terminal only)

Example workflow:

bash
# On a PR branch, run locally (outputs to terminal):
/code-review

# Post review as PR comment:
/code-review --comment

# Claude will:
# - Launch 4 review agents in parallel
# - Score each issue for confidence
# - Output issues ≥80 confidence (to terminal or PR depending on flag)
# - Skip if no high-confidence issues found

Features:

  • Multiple independent agents for comprehensive review
  • Confidence-based scoring reduces false positives (threshold: 80)
  • CLAUDE.md compliance checking with explicit guideline verification
  • Bug detection focused on changes (not pre-existing issues)
  • Historical context analysis via git blame
  • Automatic skipping of closed, draft, or already-reviewed PRs
  • Links directly to code with full SHA and line ranges

Review comment format:

markdown
## Code review

Found 3 issues:

1. Missing error handling for OAuth callback (CLAUDE.md says "Always handle OAuth errors")

https://github.com/owner/repo/blob/abc123.../src/auth.ts#L67-L72

2. Memory leak: OAuth state not cleaned up (bug due to missing cleanup in finally block)

https://github.com/owner/repo/blob/abc123.../src/auth.ts#L88-L95

3. Inconsistent naming pattern (src/conventions/CLAUDE.md says "Use camelCase for functions")

https://github.com/owner/repo/blob/abc123.../src/utils.ts#L23-L28

Confidence scoring:

  • 0: Not confident, false positive
  • 25: Somewhat confident, might be real
  • 50: Moderately confident, real but minor
  • 75: Highly confident, real and important
  • 100: Absolutely certain, definitely real

False positives filtered:

  • Pre-existing issues not introduced in PR
  • Code that looks like a bug but isn't
  • Pedantic nitpicks
  • Issues linters will catch
  • General quality issues (unless in CLAUDE.md)
  • Issues with lint ignore comments

Installation

This plugin is included in the Claude Code repository. The command is automatically available when using Claude Code.

Best Practices

Using `/code-review`

  • Maintain clear CLAUDE.md files for better compliance checking
  • Trust the 80+ confidence threshold - false positives are filtered
  • Run on all non-trivial pull requests
  • Review agent findings as a starting point for human review
  • Update CLAUDE.md based on recurring review patterns

When to use

  • All pull requests with meaningful changes
  • PRs touching critical code paths
  • PRs from multiple contributors
  • PRs where guideline compliance matters

When not to use

  • Closed or draft PRs (automatically skipped anyway)
  • Trivial automated PRs (automatically skipped)
  • Urgent hotfixes requiring immediate merge
  • PRs already reviewed (automatically skipped)

Workflow Integration

Standard PR review workflow:

bash
# Create PR with changes
# Run local review (outputs to terminal)
/code-review

# Review the automated feedback
# Make any necessary fixes

# Optionally post as PR comment
/code-review --comment

# Merge when ready

As part of CI/CD:

bash
# Trigger on PR creation or update
# Use --comment flag to post review comments
/code-review --comment
# Skip if review already exists

Requirements

  • Git repository with GitHub integration
  • GitHub CLI (gh) installed and authenticated
  • CLAUDE.md files (optional but recommended for guideline checking)

Troubleshooting

Review takes too long

Issue: Agents are slow on large PRs

Solution:

  • Normal for large changes - agents run in parallel
  • 4 independent agents ensure thoroughness
  • Consider splitting large PRs into smaller ones

Too many false positives

Issue: Review flags issues that aren't real

Solution:

  • Default threshold is 80 (already filters most false positives)
  • Make CLAUDE.md more specific about what matters
  • Consider if the flagged issue is actually valid

No review comment posted

Issue: /code-review runs but no comment appears

Solution:
Check if:

  • PR is closed (reviews skipped)
  • PR is draft (reviews skipped)
  • PR is trivial/automated (reviews skipped)
  • PR already has review (reviews skipped)
  • No issues scored ≥80 (no comment needed)

Issue: Code links don't render correctly in GitHub

Solution:
Links must follow this exact format:

text
https://github.com/owner/repo/blob/[full-sha]/path/file.ext#L[start]-L[end]
  • Must use full SHA (not abbreviated)
  • Must use #L notation
  • Must include line range with at least 1 line of context

GitHub CLI not working

Issue: gh commands fail

Solution:

  • Install GitHub CLI: brew install gh (macOS) or see GitHub CLI installation
  • Authenticate: gh auth login
  • Verify repository has GitHub remote

Tips

  • Write specific CLAUDE.md files: Clear guidelines = better reviews
  • Include context in PRs: Helps agents understand intent
  • Use confidence scores: Issues ≥80 are usually correct
  • Iterate on guidelines: Update CLAUDE.md based on patterns
  • Review automatically: Set up as part of PR workflow
  • Trust the filtering: Threshold prevents noise

Configuration

Adjusting confidence threshold

The default threshold is 80. To adjust, modify the command file at commands/code-review.md:

markdown
Filter out any issues with a score less than 80.

Change 80 to your preferred threshold (0-100).

Customizing review focus

Edit commands/code-review.md to add or modify agent tasks:

  • Add security-focused agents
  • Add performance analysis agents
  • Add accessibility checking agents
  • Add documentation quality checks

Technical Details

Agent architecture

  • 2x CLAUDE.md compliance agents: Redundancy for guideline checks
  • 1x bug detector: Focused on obvious bugs in changes only
  • 1x history analyzer: Context from git blame and history
  • Nx confidence scorers: One per issue for independent scoring

Scoring system

  • Each issue independently scored 0-100
  • Scoring considers evidence strength and verification
  • Threshold (default 80) filters low-confidence issues
  • For CLAUDE.md issues: verifies guideline explicitly mentions it

GitHub integration

Uses gh CLI for:

  • Viewing PR details and diffs
  • Fetching repository data
  • Reading git blame and history
  • Posting review comments

Author

Boris Cherny ([email protected])

Version

1.0.0


Overview (`plugins/commit-commands/README.md`)

Commit Commands Plugin

Streamline your git workflow with simple commands for committing, pushing, and creating pull requests.

Overview

The Commit Commands Plugin automates common git operations, reducing context switching and manual command execution. Instead of running multiple git commands, use a single slash command to handle your entire workflow.

Commands

`/commit`

Creates a git commit with an automatically generated commit message based on staged and unstaged changes.

What it does:

  1. Analyzes current git status
  2. Reviews both staged and unstaged changes
  3. Examines recent commit messages to match your repository's style
  4. Drafts an appropriate commit message
  5. Stages relevant files
  6. Creates the commit

Usage:

bash
/commit

Example workflow:

bash
# Make some changes to your code
# Then simply run:
/commit

# Claude will:
# - Review your changes
# - Stage the files
# - Create a commit with an appropriate message
# - Show you the commit status

Features:

  • Automatically drafts commit messages that match your repo's style
  • Follows conventional commit practices
  • Avoids committing files with secrets (.env, credentials.json)
  • Includes Claude Code attribution in commit message

`/commit-push-pr`

Complete workflow command that commits, pushes, and creates a pull request in one step.

What it does:

  1. Creates a new branch (if currently on main)
  2. Stages and commits changes with an appropriate message
  3. Pushes the branch to origin
  4. Creates a pull request using gh pr create
  5. Provides the PR URL

Usage:

bash
/commit-push-pr

Example workflow:

bash
# Make your changes
# Then run:
/commit-push-pr

# Claude will:
# - Create a feature branch (if needed)
# - Commit your changes
# - Push to remote
# - Open a PR with summary and test plan
# - Give you the PR URL to review

Features:

  • Analyzes all commits in the branch (not just the latest)
  • Creates comprehensive PR descriptions with:
    • Summary of changes (1-3 bullet points)
    • Test plan checklist
    • Claude Code attribution
  • Handles branch creation automatically
  • Uses GitHub CLI (gh) for PR creation

Requirements:

  • GitHub CLI (gh) must be installed and authenticated
  • Repository must have a remote named origin

`/clean_gone`

Cleans up local branches that have been deleted from the remote repository.

What it does:

  1. Lists all local branches to identify [gone] status
  2. Identifies and removes worktrees associated with [gone] branches
  3. Deletes all branches marked as [gone]
  4. Provides feedback on removed branches

Usage:

bash
/clean_gone

Example workflow:

bash
# After PRs are merged and remote branches are deleted
/clean_gone

# Claude will:
# - Find all branches marked as [gone]
# - Remove any associated worktrees
# - Delete the stale local branches
# - Report what was cleaned up

Features:

  • Handles both regular branches and worktree branches
  • Safely removes worktrees before deleting branches
  • Shows clear feedback about what was removed
  • Reports if no cleanup was needed

When to use:

  • After merging and deleting remote branches
  • When your local branch list is cluttered with stale branches
  • During regular repository maintenance

Installation

This plugin is included in the Claude Code repository. The commands are automatically available when using Claude Code.

Best Practices

Using `/commit`

  • Review the staged changes before committing
  • Let Claude analyze your changes and match your repo's commit style
  • Trust the automated message, but verify it's accurate
  • Use for routine commits during development

Using `/commit-push-pr`

  • Use when you're ready to create a PR
  • Ensure all your changes are complete and tested
  • Claude will analyze the full branch history for the PR description
  • Review the PR description and edit if needed
  • Use when you want to minimize context switching

Using `/clean_gone`

  • Run periodically to keep your branch list clean
  • Especially useful after merging multiple PRs
  • Safe to run - only removes branches already deleted remotely
  • Helps maintain a tidy local repository

Workflow Integration

Quick commit workflow:

bash
# Write code
/commit
# Continue development

Feature branch workflow:

bash
# Develop feature across multiple commits
/commit  # First commit
# More changes
/commit  # Second commit
# Ready to create PR
/commit-push-pr

Maintenance workflow:

bash
# After several PRs are merged
/clean_gone
# Clean workspace ready for next feature

Requirements

  • Git must be installed and configured
  • For /commit-push-pr: GitHub CLI (gh) must be installed and authenticated
  • Repository must be a git repository with a remote

Troubleshooting

`/commit` creates empty commit

Issue: No changes to commit

Solution:

  • Ensure you have unstaged or staged changes
  • Run git status to verify changes exist

`/commit-push-pr` fails to create PR

Issue: gh pr create command fails

Solution:

  • Install GitHub CLI: brew install gh (macOS) or see GitHub CLI installation
  • Authenticate: gh auth login
  • Ensure repository has a GitHub remote

`/clean_gone` doesn't find branches

Issue: No branches marked as [gone]

Solution:

  • Run git fetch --prune to update remote tracking
  • Branches must be deleted from the remote to show as [gone]

Tips

  • Combine with other tools: Use /commit during development, then /commit-push-pr when ready
  • Let Claude draft messages: The commit message analysis learns from your repo's style
  • Regular cleanup: Run /clean_gone weekly to maintain a clean branch list
  • Review before pushing: Always review the commit message and changes before pushing

Author

Anthropic ([email protected])

Version

1.0.0


Overview (`plugins/explanatory-output-style/README.md`)

Explanatory Output Style Plugin

This plugin recreates the deprecated Explanatory output style as a SessionStart
hook.

WARNING: Do not install this plugin unless you are fine with incurring the token
cost of this plugin's additional instructions and output.

What it does

When enabled, this plugin automatically adds instructions at the start of each
session that encourage Claude to:

  1. Provide educational insights about implementation choices
  2. Explain codebase patterns and decisions
  3. Balance task completion with learning opportunities

How it works

The plugin uses a SessionStart hook to inject additional context into every
session. This context instructs Claude to provide brief educational explanations
before and after writing code, formatted as:

text
`★ Insight ─────────────────────────────────────`
[2-3 key educational points]
`─────────────────────────────────────────────────`

Usage

Once installed, the plugin activates automatically at the start of every
session. No additional configuration is needed.

The insights focus on:

  • Specific implementation choices for your codebase
  • Patterns and conventions in your code
  • Trade-offs and design decisions
  • Codebase-specific details rather than general programming concepts

Migration from Output Styles

This plugin replaces the deprecated "Explanatory" output style setting. If you
previously used:

json
{
  "outputStyle": "Explanatory"
}

You can now achieve the same behavior by installing this plugin instead.

More generally, this SessionStart hook pattern is roughly equivalent to
CLAUDE.md, but it is more flexible and allows for distribution through plugins.

Note: Output styles that involve tasks besides software development, are better
expressed as
subagents, not as
SessionStart hooks. Subagents change the system prompt while SessionStart hooks
add to the default system prompt.

Managing changes

  • Disable the plugin - keep the code installed on your device
  • Uninstall the plugin - remove the code from your device
  • Update the plugin - create a local copy of this plugin to personalize this
    plugin

Overview (`plugins/feature-dev/README.md`)

Feature Development Plugin

A comprehensive, structured workflow for feature development with specialized agents for codebase exploration, architecture design, and quality review.

Overview

The Feature Development Plugin provides a systematic 7-phase approach to building new features. Instead of jumping straight into code, it guides you through understanding the codebase, asking clarifying questions, designing architecture, and ensuring quality—resulting in better-designed features that integrate seamlessly with your existing code.

Philosophy

Building features requires more than just writing code. You need to:

  • Understand the codebase before making changes
  • Ask questions to clarify ambiguous requirements
  • Design thoughtfully before implementing
  • Review for quality after building

This plugin embeds these practices into a structured workflow that runs automatically when you use the /feature-dev command.

Command: `/feature-dev`

Launches a guided feature development workflow with 7 distinct phases.

Usage:

bash
/feature-dev Add user authentication with OAuth

Or simply:

bash
/feature-dev

The command will guide you through the entire process interactively.

The 7-Phase Workflow

Phase 1: Discovery

Goal: Understand what needs to be built

What happens:

  • Clarifies the feature request if it's unclear
  • Asks what problem you're solving
  • Identifies constraints and requirements
  • Summarizes understanding and confirms with you

Example:

text
You: /feature-dev Add caching
Claude: Let me understand what you need...
        - What should be cached? (API responses, computed values, etc.)
        - What are your performance requirements?
        - Do you have a preferred caching solution?

Phase 2: Codebase Exploration

Goal: Understand relevant existing code and patterns

What happens:

  • Launches 2-3 code-explorer agents in parallel
  • Each agent explores different aspects (similar features, architecture, UI patterns)
  • Agents return comprehensive analyses with key files to read
  • Claude reads all identified files to build deep understanding
  • Presents comprehensive summary of findings

Agents launched:

  • "Find features similar to [feature] and trace implementation"
  • "Map the architecture and abstractions for [area]"
  • "Analyze current implementation of [related feature]"

Example output:

text
Found similar features:
- User authentication (src/auth/): Uses JWT tokens, middleware pattern
- Session management (src/session/): Redis-backed, 24hr expiry
- API security (src/api/middleware/): Rate limiting, CORS

Key files to understand:
- src/auth/AuthService.ts:45 - Core authentication logic
- src/middleware/authMiddleware.ts:12 - Request authentication
- src/config/security.ts:8 - Security configuration

Phase 3: Clarifying Questions

Goal: Fill in gaps and resolve all ambiguities

What happens:

  • Reviews codebase findings and feature request
  • Identifies underspecified aspects:
    • Edge cases
    • Error handling
    • Integration points
    • Backward compatibility
    • Performance needs
  • Presents all questions in an organized list
  • Waits for your answers before proceeding

Example:

text
Before designing the architecture, I need to clarify:

1. OAuth provider: Which OAuth providers? (Google, GitHub, custom?)
2. User data: Store OAuth tokens or just user profile?
3. Existing auth: Replace current auth or add alongside?
4. Sessions: Integrate with existing session management?
5. Error handling: How to handle OAuth failures?

Critical: This phase ensures nothing is ambiguous before design begins.

Phase 4: Architecture Design

Goal: Design multiple implementation approaches

What happens:

  • Launches 2-3 code-architect agents with different focuses:
    • Minimal changes: Smallest change, maximum reuse
    • Clean architecture: Maintainability, elegant abstractions
    • Pragmatic balance: Speed + quality
  • Reviews all approaches
  • Forms opinion on which fits best for this task
  • Presents comparison with trade-offs and recommendation
  • Asks which approach you prefer

Example output:

text
I've designed 3 approaches:

Approach 1: Minimal Changes
- Extend existing AuthService with OAuth methods
- Add new OAuth routes to existing auth router
- Minimal refactoring required
Pros: Fast, low risk
Cons: Couples OAuth to existing auth, harder to test

Approach 2: Clean Architecture
- New OAuthService with dedicated interface
- Separate OAuth router and middleware
- Refactor AuthService to use common interface
Pros: Clean separation, testable, maintainable
Cons: More files, more refactoring

Approach 3: Pragmatic Balance
- New OAuthProvider abstraction
- Integrate into existing AuthService
- Minimal refactoring, good boundaries
Pros: Balanced complexity and cleanliness
Cons: Some coupling remains

Recommendation: Approach 3 - gives you clean boundaries without
excessive refactoring, and fits your existing architecture well.

Which approach would you like to use?

Phase 5: Implementation

Goal: Build the feature

What happens:

  • Waits for explicit approval before starting
  • Reads all relevant files identified in previous phases
  • Implements following chosen architecture
  • Follows codebase conventions strictly
  • Writes clean, well-documented code
  • Updates todos as progress is made

Notes:

  • Implementation only starts after you approve
  • Follows patterns discovered in Phase 2
  • Uses architecture designed in Phase 4
  • Continuously tracks progress

Phase 6: Quality Review

Goal: Ensure code is simple, DRY, elegant, and functionally correct

What happens:

  • Launches 3 code-reviewer agents in parallel with different focuses:
    • Simplicity/DRY/Elegance: Code quality and maintainability
    • Bugs/Correctness: Functional correctness and logic errors
    • Conventions/Abstractions: Project standards and patterns
  • Consolidates findings
  • Identifies highest severity issues
  • Presents findings and asks what you want to do:
    • Fix now
    • Fix later
    • Proceed as-is
  • Addresses issues based on your decision

Example output:

text
Code Review Results:

High Priority Issues:
1. Missing error handling in OAuth callback (src/auth/oauth.ts:67)
2. Memory leak: OAuth state not cleaned up (src/auth/oauth.ts:89)

Medium Priority:
1. Could simplify token refresh logic (src/auth/oauth.ts:120)
2. Consider extracting OAuth config validation

All tests pass. Code follows project conventions.

What would you like to do?

Phase 7: Summary

Goal: Document what was accomplished

What happens:

  • Marks all todos complete
  • Summarizes:
    • What was built
    • Key decisions made
    • Files modified
    • Suggested next steps

Example:

text
Feature Complete: OAuth Authentication

What was built:
- OAuth provider abstraction supporting Google and GitHub
- OAuth routes and middleware integrated with existing auth
- Token refresh and session integration
- Error handling for all OAuth flows

Key decisions:
- Used pragmatic approach with OAuthProvider abstraction
- Integrated with existing session management
- Added OAuth state to prevent CSRF

Files modified:
- src/auth/OAuthProvider.ts (new)
- src/auth/AuthService.ts
- src/routes/auth.ts
- src/middleware/authMiddleware.ts

Suggested next steps:
- Add tests for OAuth flows
- Add more OAuth providers (Microsoft, Apple)
- Update documentation

Agents

`code-explorer`

Purpose: Deeply analyzes existing codebase features by tracing execution paths

Focus areas:

  • Entry points and call chains
  • Data flow and transformations
  • Architecture layers and patterns
  • Dependencies and integrations
  • Implementation details

When triggered:

  • Automatically in Phase 2
  • Can be invoked manually when exploring code

Output:

  • Entry points with file:line references
  • Step-by-step execution flow
  • Key components and responsibilities
  • Architecture insights
  • List of essential files to read

`code-architect`

Purpose: Designs feature architectures and implementation blueprints

Focus areas:

  • Codebase pattern analysis
  • Architecture decisions
  • Component design
  • Implementation roadmap
  • Data flow and build sequence

When triggered:

  • Automatically in Phase 4
  • Can be invoked manually for architecture design

Output:

  • Patterns and conventions found
  • Architecture decision with rationale
  • Complete component design
  • Implementation map with specific files
  • Build sequence with phases

`code-reviewer`

Purpose: Reviews code for bugs, quality issues, and project conventions

Focus areas:

  • Project guideline compliance (CLAUDE.md)
  • Bug detection
  • Code quality issues
  • Confidence-based filtering (only reports high-confidence issues ≥80)

When triggered:

  • Automatically in Phase 6
  • Can be invoked manually after writing code

Output:

  • Critical issues (confidence 75-100)
  • Important issues (confidence 50-74)
  • Specific fixes with file:line references
  • Project guideline references

Usage Patterns

bash
/feature-dev Add rate limiting to API endpoints

Let the workflow guide you through all 7 phases.

Manual agent invocation:

Explore a feature:

text
"Launch code-explorer to trace how authentication works"

Design architecture:

text
"Launch code-architect to design the caching layer"

Review code:

text
"Launch code-reviewer to check my recent changes"

Best Practices

  1. Use the full workflow for complex features: The 7 phases ensure thorough planning
  2. Answer clarifying questions thoughtfully: Phase 3 prevents future confusion
  3. Choose architecture deliberately: Phase 4 gives you options for a reason
  4. Don't skip code review: Phase 6 catches issues before they reach production
  5. Read the suggested files: Phase 2 identifies key files—read them to understand context

When to Use This Plugin

Use for:

  • New features that touch multiple files
  • Features requiring architectural decisions
  • Complex integrations with existing code
  • Features where requirements are somewhat unclear

Don't use for:

  • Single-line bug fixes
  • Trivial changes
  • Well-defined, simple tasks
  • Urgent hotfixes

Requirements

  • Claude Code installed
  • Git repository (for code review)
  • Project with existing codebase (workflow assumes existing code to learn from)

Troubleshooting

Agents take too long

Issue: Code exploration or architecture agents are slow

Solution:

  • This is normal for large codebases
  • Agents run in parallel when possible
  • The thoroughness pays off in better understanding

Too many clarifying questions

Issue: Phase 3 asks too many questions

Solution:

  • Be more specific in your initial feature request
  • Provide context about constraints upfront
  • Say "whatever you think is best" if truly no preference

Architecture options overwhelming

Issue: Too many architecture options in Phase 4

Solution:

  • Trust the recommendation—it's based on codebase analysis
  • If still unsure, ask for more explanation
  • Pick the pragmatic option when in doubt

Tips

  • Be specific in your feature request: More detail = fewer clarifying questions
  • Trust the process: Each phase builds on the previous one
  • Review agent outputs: Agents provide valuable insights about your codebase
  • Don't skip phases: Each phase serves a purpose
  • Use for learning: The exploration phase teaches you about your own codebase

Author

Sid Bidasaria ([email protected])

Version

1.0.0


Overview (`plugins/frontend-design/README.md`)

Frontend Design Plugin

Generates distinctive, production-grade frontend interfaces that avoid generic AI aesthetics.

What It Does

Claude automatically uses this skill for frontend work. Creates production-ready code with:

  • Bold aesthetic choices
  • Distinctive typography and color palettes
  • High-impact animations and visual details
  • Context-aware implementation

Usage

text
"Create a dashboard for a music streaming app"
"Build a landing page for an AI security startup"
"Design a settings panel with dark mode"

Claude will choose a clear aesthetic direction and implement production code with meticulous attention to detail.

Learn More

See the Frontend Aesthetics Cookbook for detailed guidance on prompting for high-quality frontend design.

Authors

Prithvi Rajasekaran ([email protected])
Alexander Bricken ([email protected])


Overview (`plugins/hookify/README.md`)

Hookify Plugin

Easily create custom hooks to prevent unwanted behaviors by analyzing conversation patterns or from explicit instructions.

Overview

The hookify plugin makes it simple to create hooks without editing complex hooks.json files. Instead, you create lightweight markdown configuration files that define patterns to watch for and messages to show when those patterns match.

Key features:

  • 🎯 Analyze conversations to find unwanted behaviors automatically
  • 📝 Simple markdown configuration files with YAML frontmatter
  • 🔍 Regex pattern matching for powerful rules
  • 🚀 No coding required - just describe the behavior
  • 🔄 Easy enable/disable without restarting

Quick Start

1. Create Your First Rule

bash
/hookify Warn me when I use rm -rf commands

This analyzes your request and creates .claude/hookify.warn-rm.local.md.

2. Test It Immediately

No restart needed! Rules take effect on the very next tool use.

Ask Claude to run a command that should trigger the rule:

text
Run rm -rf /tmp/test

You should see the warning message immediately!

Usage

Main Command: /hookify

With arguments:

text
/hookify Don't use console.log in TypeScript files

Creates a rule from your explicit instructions.

Without arguments:

text
/hookify

Analyzes recent conversation to find behaviors you've corrected or been frustrated by.

Helper Commands

List all rules:

text
/hookify:list

Configure rules interactively:

text
/hookify:configure

Enable/disable existing rules through an interactive interface.

Get help:

text
/hookify:help

Rule Configuration Format

Simple Rule (Single Pattern)

.claude/hookify.dangerous-rm.local.md:

markdown
---
name: block-dangerous-rm
enabled: true
event: bash
pattern: rm\s+-rf
action: block
---

⚠️ **Dangerous rm command detected!**

This command could delete important files. Please:
- Verify the path is correct
- Consider using a safer approach
- Make sure you have backups

Action field:

  • warn: Shows warning but allows operation (default)
  • block: Prevents operation from executing (PreToolUse) or stops session (Stop events)

Advanced Rule (Multiple Conditions)

.claude/hookify.sensitive-files.local.md:

markdown
---
name: warn-sensitive-files
enabled: true
event: file
action: warn
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.env$|credentials|secrets
  - field: new_text
    operator: contains
    pattern: KEY
---

🔐 **Sensitive file edit detected!**

Ensure credentials are not hardcoded and file is in .gitignore.

All conditions must match for the rule to trigger.

Event Types

  • bash: Triggers on Bash tool commands
  • file: Triggers on Edit, Write, MultiEdit tools
  • stop: Triggers when Claude wants to stop (for completion checks)
  • prompt: Triggers on user prompt submission
  • all: Triggers on all events

Pattern Syntax

Use Python regex syntax:

Pattern Matches Example
rm\s+-rf rm -rf rm -rf /tmp
console\.log\( console.log( console.log("test")
(eval|exec)\( eval( or exec( eval("code")
\.env$ files ending in .env .env, .env.local
chmod\s+777 chmod 777 chmod 777 file.txt

Tips:

  • Use \s for whitespace
  • Escape special chars: \. for literal dot
  • Use | for OR: (foo|bar)
  • Use .* to match anything
  • Set action: block for dangerous operations
  • Set action: warn (or omit) for informational warnings

Examples

Example 1: Block Dangerous Commands

markdown
---
name: block-destructive-ops
enabled: true
event: bash
pattern: rm\s+-rf|dd\s+if=|mkfs|format
action: block
---

🛑 **Destructive operation detected!**

This command can cause data loss. Operation blocked for safety.
Please verify the exact path and use a safer approach.

This rule blocks the operation - Claude will not be allowed to execute these commands.

Example 2: Warn About Debug Code

markdown
---
name: warn-debug-code
enabled: true
event: file
pattern: console\.log\(|debugger;|print\(
action: warn
---

🐛 **Debug code detected**

Remember to remove debugging statements before committing.

This rule warns but allows - Claude sees the message but can still proceed.

Example 3: Require Tests Before Stopping

markdown
---
name: require-tests-run
enabled: false
event: stop
action: block
conditions:
  - field: transcript
    operator: not_contains
    pattern: npm test|pytest|cargo test
---

**Tests not detected in transcript!**

Before stopping, please run tests to verify your changes work correctly.

This blocks Claude from stopping if no test commands appear in the session transcript. Enable only when you want strict enforcement.

Advanced Usage

Multiple Conditions

Check multiple fields simultaneously:

markdown
---
name: api-key-in-typescript
enabled: true
event: file
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.tsx?$
  - field: new_text
    operator: regex_match
    pattern: (API_KEY|SECRET|TOKEN)\s*=\s*["']
---

🔐 **Hardcoded credential in TypeScript!**

Use environment variables instead of hardcoded values.

Operators Reference

  • regex_match: Pattern must match (most common)
  • contains: String must contain pattern
  • equals: Exact string match
  • not_contains: String must NOT contain pattern
  • starts_with: String starts with pattern
  • ends_with: String ends with pattern

Field Reference

For bash events:

  • command: The bash command string

For file events:

  • file_path: Path to file being edited
  • new_text: New content being added (Edit, Write)
  • old_text: Old content being replaced (Edit only)
  • content: File content (Write only)

For prompt events:

  • user_prompt: The user's submitted prompt text

For stop events:

  • Use general matching on session state

Management

Enable/Disable Rules

Temporarily disable:
Edit the .local.md file and set enabled: false

Re-enable:
Set enabled: true

Or use interactive tool:

text
/hookify:configure

Delete Rules

Simply delete the .local.md file:

bash
rm .claude/hookify.my-rule.local.md

View All Rules

text
/hookify:list

Installation

This plugin is part of the Claude Code Marketplace. It should be auto-discovered when the marketplace is installed.

Manual testing:

bash
cc --plugin-dir /path/to/hookify

Requirements

  • Python 3.7+
  • No external dependencies (uses stdlib only)

Troubleshooting

Rule not triggering:

  1. Check rule file exists in .claude/ directory (in project root, not plugin directory)
  2. Verify enabled: true in frontmatter
  3. Test regex pattern separately
  4. Rules should work immediately - no restart needed
  5. Try /hookify:list to see if rule is loaded

Import errors:

  • Ensure Python 3 is available: python3 --version
  • Check hookify plugin is installed

Pattern not matching:

  • Test regex: python3 -c "import re; print(re.search(r'pattern', 'text'))"
  • Use unquoted patterns in YAML to avoid escaping issues
  • Start simple, then add complexity

Hook seems slow:

  • Keep patterns simple (avoid complex regex)
  • Use specific event types (bash, file) instead of "all"
  • Limit number of active rules

Contributing

Found a useful rule pattern? Consider sharing example files via PR!

Future Enhancements

  • Severity levels (error/warning/info distinctions)
  • Rule templates library
  • Interactive pattern builder
  • Hook testing utilities
  • JSON format support (in addition to markdown)

License

MIT License


Overview (`plugins/learning-output-style/README.md`)

Learning Style Plugin

This plugin combines the unshipped Learning output style with explanatory functionality as a SessionStart hook.

Note: This plugin differs from the original unshipped Learning output style by also incorporating all functionality from the explanatory-output-style plugin, providing both interactive learning and educational insights.

WARNING: Do not install this plugin unless you are fine with incurring the token cost of this plugin's additional instructions and the interactive nature of learning mode.

What it does

When enabled, this plugin automatically adds instructions at the start of each session that encourage Claude to:

  1. Learning Mode: Engage you in active learning by requesting meaningful code contributions at decision points
  2. Explanatory Mode: Provide educational insights about implementation choices and codebase patterns

Instead of implementing everything automatically, Claude will:

  1. Identify opportunities where you can write 5-10 lines of meaningful code
  2. Focus on business logic and design choices where your input truly matters
  3. Prepare the context and location for your contribution
  4. Explain trade-offs and guide your implementation
  5. Provide educational insights before and after writing code

How it works

The plugin uses a SessionStart hook to inject additional context into every session. This context instructs Claude to adopt an interactive teaching approach where you actively participate in writing key parts of the code.

When Claude requests contributions

Claude will ask you to write code for:

  • Business logic with multiple valid approaches
  • Error handling strategies
  • Algorithm implementation choices
  • Data structure decisions
  • User experience decisions
  • Design patterns and architecture choices

When Claude won't request contributions

Claude will implement directly:

  • Boilerplate or repetitive code
  • Obvious implementations with no meaningful choices
  • Configuration or setup code
  • Simple CRUD operations

Example interaction

Claude: I've set up the authentication middleware. The session timeout behavior is a security vs. UX trade-off - should sessions auto-extend on activity, or have a hard timeout?

In auth/middleware.ts, implement the handleSessionTimeout() function to define the timeout behavior.

Consider: auto-extending improves UX but may leave sessions open longer; hard timeouts are more secure but might frustrate active users.

You: [Write 5-10 lines implementing your preferred approach]

Educational insights

In addition to interactive learning, Claude will provide educational insights about implementation choices using this format:

text
`★ Insight ─────────────────────────────────────`
[2-3 key educational points about the codebase or implementation]
`─────────────────────────────────────────────────`

These insights focus on:

  • Specific implementation choices for your codebase
  • Patterns and conventions in your code
  • Trade-offs and design decisions
  • Codebase-specific details rather than general programming concepts

Usage

Once installed, the plugin activates automatically at the start of every session. No additional configuration is needed.

Migration from Output Styles

This plugin combines the unshipped "Learning" output style with the deprecated "Explanatory" output style. It provides an interactive learning experience where you actively contribute code at meaningful decision points, while also receiving educational insights about implementation choices.

If you previously used the explanatory-output-style plugin, this learning plugin includes all of that functionality plus interactive learning features.

This SessionStart hook pattern is roughly equivalent to CLAUDE.md, but it is more flexible and allows for distribution through plugins.

Managing changes

  • Disable the plugin - keep the code installed on your device
  • Uninstall the plugin - remove the code from your device
  • Update the plugin - create a local copy of this plugin to personalize it

Philosophy

Learning by doing is more effective than passive observation. This plugin transforms your interaction with Claude from "watch and learn" to "build and understand," ensuring you develop practical skills through hands-on coding of meaningful logic.


Overview (`plugins/plugin-dev/README.md`)

Plugin Development Toolkit

A comprehensive toolkit for developing Claude Code plugins with expert guidance on hooks, MCP integration, plugin structure, and marketplace publishing.

Overview

The plugin-dev toolkit provides seven specialized skills to help you build high-quality Claude Code plugins:

  1. Hook Development - Advanced hooks API and event-driven automation
  2. MCP Integration - Model Context Protocol server integration
  3. Plugin Structure - Plugin organization and manifest configuration
  4. Plugin Settings - Configuration patterns using .claude/plugin-name.local.md files
  5. Command Development - Creating slash commands with frontmatter and arguments
  6. Agent Development - Creating autonomous agents with AI-assisted generation
  7. Skill Development - Creating skills with progressive disclosure and strong triggers

Each skill follows best practices with progressive disclosure: lean core documentation, detailed references, working examples, and utility scripts.

Guided Workflow Command

/plugin-dev:create-plugin

A comprehensive, end-to-end workflow command for creating plugins from scratch, similar to the feature-dev workflow.

8-Phase Process:

  1. Discovery - Understand plugin purpose and requirements
  2. Component Planning - Determine needed skills, commands, agents, hooks, MCP
  3. Detailed Design - Specify each component and resolve ambiguities
  4. Structure Creation - Set up directories and manifest
  5. Component Implementation - Create each component using AI-assisted agents
  6. Validation - Run plugin-validator and component-specific checks
  7. Testing - Verify plugin works in Claude Code
  8. Documentation - Finalize README and prepare for distribution

Features:

  • Asks clarifying questions at each phase
  • Loads relevant skills automatically
  • Uses agent-creator for AI-assisted agent generation
  • Runs validation utilities (validate-agent.sh, validate-hook-schema.sh, etc.)
  • Follows plugin-dev's own proven patterns
  • Guides through testing and verification

Usage:

bash
/plugin-dev:create-plugin [optional description]

# Examples:
/plugin-dev:create-plugin
/plugin-dev:create-plugin A plugin for managing database migrations

Use this workflow for structured, high-quality plugin development from concept to completion.

Skills

1. Hook Development

Trigger phrases: "create a hook", "add a PreToolUse hook", "validate tool use", "implement prompt-based hooks", "${CLAUDE_PLUGIN_ROOT}", "block dangerous commands"

What it covers:

  • Prompt-based hooks (recommended) with LLM decision-making
  • Command hooks for deterministic validation
  • All hook events: PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification
  • Hook output formats and JSON schemas
  • Security best practices and input validation
  • ${CLAUDE_PLUGIN_ROOT} for portable paths

Resources:

  • Core SKILL.md (1,619 words)
  • 3 example hook scripts (validate-write, validate-bash, load-context)
  • 3 reference docs: patterns, migration, advanced techniques
  • 3 utility scripts: validate-hook-schema.sh, test-hook.sh, hook-linter.sh

Use when: Creating event-driven automation, validating operations, or enforcing policies in your plugin.

2. MCP Integration

Trigger phrases: "add MCP server", "integrate MCP", "configure .mcp.json", "Model Context Protocol", "stdio/SSE/HTTP server", "connect external service"

What it covers:

  • MCP server configuration (.mcp.json vs plugin.json)
  • All server types: stdio (local), SSE (hosted/OAuth), HTTP (REST), WebSocket (real-time)
  • Environment variable expansion (${CLAUDE_PLUGIN_ROOT}, user vars)
  • MCP tool naming and usage in commands/agents
  • Authentication patterns: OAuth, tokens, env vars
  • Integration patterns and performance optimization

Resources:

  • Core SKILL.md (1,666 words)
  • 3 example configurations (stdio, SSE, HTTP)
  • 3 reference docs: server-types (~3,200w), authentication (~2,800w), tool-usage (~2,600w)

Use when: Integrating external services, APIs, databases, or tools into your plugin.

3. Plugin Structure

Trigger phrases: "plugin structure", "plugin.json manifest", "auto-discovery", "component organization", "plugin directory layout"

What it covers:

  • Standard plugin directory structure and auto-discovery
  • plugin.json manifest format and all fields
  • Component organization (commands, agents, skills, hooks)
  • ${CLAUDE_PLUGIN_ROOT} usage throughout
  • File naming conventions and best practices
  • Minimal, standard, and advanced plugin patterns

Resources:

  • Core SKILL.md (1,619 words)
  • 3 example structures (minimal, standard, advanced)
  • 2 reference docs: component-patterns, manifest-reference

Use when: Starting a new plugin, organizing components, or configuring the plugin manifest.

4. Plugin Settings

Trigger phrases: "plugin settings", "store plugin configuration", ".local.md files", "plugin state files", "read YAML frontmatter", "per-project plugin settings"

What it covers:

  • .claude/plugin-name.local.md pattern for configuration
  • YAML frontmatter + markdown body structure
  • Parsing techniques for bash scripts (sed, awk, grep patterns)
  • Temporarily active hooks (flag files and quick-exit)
  • Real-world examples from multi-agent-swarm and ralph-wiggum plugins
  • Atomic file updates and validation
  • Gitignore and lifecycle management

Resources:

  • Core SKILL.md (1,623 words)
  • 3 examples (read-settings hook, create-settings command, templates)
  • 2 reference docs: parsing-techniques, real-world-examples
  • 2 utility scripts: validate-settings.sh, parse-frontmatter.sh

Use when: Making plugins configurable, storing per-project state, or implementing user preferences.

5. Command Development

Trigger phrases: "create a slash command", "add a command", "command frontmatter", "define command arguments", "organize commands"

What it covers:

  • Slash command structure and markdown format
  • YAML frontmatter fields (description, argument-hint, allowed-tools)
  • Dynamic arguments and file references
  • Bash execution for context
  • Command organization and namespacing
  • Best practices for command development

Resources:

  • Core SKILL.md (1,535 words)
  • Examples and reference documentation
  • Command organization patterns

Use when: Creating slash commands, defining command arguments, or organizing plugin commands.

6. Agent Development

Trigger phrases: "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "autonomous agent"

What it covers:

  • Agent file structure (YAML frontmatter + system prompt)
  • All frontmatter fields (name, description, model, color, tools)
  • Description format with blocks for reliable triggering
  • System prompt design patterns (analysis, generation, validation, orchestration)
  • AI-assisted agent generation using Claude Code's proven prompt
  • Validation rules and best practices
  • Complete production-ready agent examples

Resources:

  • Core SKILL.md (1,438 words)
  • 2 examples: agent-creation-prompt (AI-assisted workflow), complete-agent-examples (4 full agents)
  • 3 reference docs: agent-creation-system-prompt (from Claude Code), system-prompt-design (~4,000w), triggering-examples (~2,500w)
  • 1 utility script: validate-agent.sh

Use when: Creating autonomous agents, defining agent behavior, or implementing AI-assisted agent generation.

7. Skill Development

Trigger phrases: "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content"

What it covers:

  • Skill structure (SKILL.md with YAML frontmatter)
  • Progressive disclosure principle (metadata → SKILL.md → resources)
  • Strong trigger descriptions with specific phrases
  • Writing style (imperative/infinitive form, third person)
  • Bundled resources organization (references/, examples/, scripts/)
  • Skill creation workflow
  • Based on skill-creator methodology adapted for Claude Code plugins

Resources:

  • Core SKILL.md (1,232 words)
  • References: skill-creator methodology, plugin-dev patterns
  • Examples: Study plugin-dev's own skills as templates

Use when: Creating new skills for plugins or improving existing skill quality.

Installation

Install from claude-code-marketplace:

bash
/plugin install plugin-dev@claude-code-marketplace

Or for development, use directly:

bash
cc --plugin-dir /path/to/plugin-dev

Quick Start

Creating Your First Plugin

  1. Plan your plugin structure:

    • Ask: "What's the best directory structure for a plugin with commands and MCP integration?"
    • The plugin-structure skill will guide you
  2. Add MCP integration (if needed):

    • Ask: "How do I add an MCP server for database access?"
    • The mcp-integration skill provides examples and patterns
  3. Implement hooks (if needed):

    • Ask: "Create a PreToolUse hook that validates file writes"
    • The hook-development skill gives working examples and utilities

Development Workflow

The plugin-dev toolkit supports your entire plugin development lifecycle:

text
┌─────────────────────┐
│  Design Structure   │  → plugin-structure skill
│  (manifest, layout) │
└──────────┬──────────┘
           │
┌──────────▼──────────┐
│  Add Components     │
│  (commands, agents, │  → All skills provide guidance
│   skills, hooks)    │
└──────────┬──────────┘
           │
┌──────────▼──────────┐
│  Integrate Services │  → mcp-integration skill
│  (MCP servers)      │
└──────────┬──────────┘
           │
┌──────────▼──────────┐
│  Add Automation     │  → hook-development skill
│  (hooks, validation)│     + utility scripts
└──────────┬──────────┘
           │
┌──────────▼──────────┐
│  Test & Validate    │  → hook-development utilities
│                     │     validate-hook-schema.sh
└──────────┬──────────┘     test-hook.sh
           │                 hook-linter.sh

Features

Progressive Disclosure

Each skill uses a three-level disclosure system:

  1. Metadata (always loaded): Concise descriptions with strong triggers
  2. Core SKILL.md (when triggered): Essential API reference (~1,500-2,000 words)
  3. References/Examples (as needed): Detailed guides, patterns, and working code

This keeps Claude Code's context focused while providing deep knowledge when needed.

Utility Scripts

The hook-development skill includes production-ready utilities:

bash
# Validate hooks.json structure
./validate-hook-schema.sh hooks/hooks.json

# Test hooks before deployment
./test-hook.sh my-hook.sh test-input.json

# Lint hook scripts for best practices
./hook-linter.sh my-hook.sh

Working Examples

Every skill provides working examples:

  • Hook Development: 3 complete hook scripts (bash, write validation, context loading)
  • MCP Integration: 3 server configurations (stdio, SSE, HTTP)
  • Plugin Structure: 3 plugin layouts (minimal, standard, advanced)
  • Plugin Settings: 3 examples (read-settings hook, create-settings command, templates)
  • Command Development: 10 complete command examples (review, test, deploy, docs, etc.)

Documentation Standards

All skills follow consistent standards:

  • Third-person descriptions ("This skill should be used when...")
  • Strong trigger phrases for reliable loading
  • Imperative/infinitive form throughout
  • Based on official Claude Code documentation
  • Security-first approach with best practices

Total Content

  • Core Skills: ~11,065 words across 7 SKILL.md files
  • Reference Docs: ~10,000+ words of detailed guides
  • Examples: 12+ working examples (hook scripts, MCP configs, plugin layouts, settings files)
  • Utilities: 6 production-ready validation/testing/parsing scripts

Use Cases

Building a Database Plugin

text
1. "What's the structure for a plugin with MCP integration?"
   → plugin-structure skill provides layout

2. "How do I configure an stdio MCP server for PostgreSQL?"
   → mcp-integration skill shows configuration

3. "Add a Stop hook to ensure connections close properly"
   → hook-development skill provides pattern

Creating a Validation Plugin

text
1. "Create hooks that validate all file writes for security"
   → hook-development skill with examples

2. "Test my hooks before deploying"
   → Use validate-hook-schema.sh and test-hook.sh

3. "Organize my hooks and configuration files"
   → plugin-structure skill shows best practices

Integrating External Services

text
1. "Add Asana MCP server with OAuth"
   → mcp-integration skill covers SSE servers

2. "Use Asana tools in my commands"
   → mcp-integration tool-usage reference

3. "Structure my plugin with commands and MCP"
   → plugin-structure skill provides patterns

Best Practices

All skills emphasize:

✅ Security First

  • Input validation in hooks
  • HTTPS/WSS for MCP servers
  • Environment variables for credentials
  • Principle of least privilege

✅ Portability

  • Use ${CLAUDE_PLUGIN_ROOT} everywhere
  • Relative paths only
  • Environment variable substitution

✅ Testing

  • Validate configurations before deployment
  • Test hooks with sample inputs
  • Use debug mode (claude --debug)

✅ Documentation

  • Clear README files
  • Documented environment variables
  • Usage examples

Contributing

This plugin is part of the claude-code-marketplace. To contribute improvements:

  1. Fork the marketplace repository
  2. Make changes to plugin-dev/
  3. Test locally with cc --plugin-dir
  4. Create PR following marketplace-publishing guidelines

Version

0.1.0 - Initial release with seven comprehensive skills and three validation agents

Author

Daisy Hollman ([email protected])

License

MIT License - See repository for details


Note: This toolkit is designed to help you build high-quality plugins. The skills load automatically when you ask relevant questions, providing expert guidance exactly when you need it.


Overview (`plugins/pr-review-toolkit/README.md`)

PR Review Toolkit

A comprehensive collection of specialized agents for thorough pull request review, covering code comments, test coverage, error handling, type design, code quality, and code simplification.

Overview

This plugin bundles 6 expert review agents that each focus on a specific aspect of code quality. Use them individually for targeted reviews or together for comprehensive PR analysis.

Agents

1. comment-analyzer

Focus: Code comment accuracy and maintainability

Analyzes:

  • Comment accuracy vs actual code
  • Documentation completeness
  • Comment rot and technical debt
  • Misleading or outdated comments

When to use:

  • After adding documentation
  • Before finalizing PRs with comment changes
  • When reviewing existing comments

Triggers:

text
"Check if the comments are accurate"
"Review the documentation I added"
"Analyze comments for technical debt"

2. pr-test-analyzer

Focus: Test coverage quality and completeness

Analyzes:

  • Behavioral vs line coverage
  • Critical gaps in test coverage
  • Test quality and resilience
  • Edge cases and error conditions

When to use:

  • After creating a PR
  • When adding new functionality
  • To verify test thoroughness

Triggers:

text
"Check if the tests are thorough"
"Review test coverage for this PR"
"Are there any critical test gaps?"

3. silent-failure-hunter

Focus: Error handling and silent failures

Analyzes:

  • Silent failures in catch blocks
  • Inadequate error handling
  • Inappropriate fallback behavior
  • Missing error logging

When to use:

  • After implementing error handling
  • When reviewing try/catch blocks
  • Before finalizing PRs with error handling

Triggers:

text
"Review the error handling"
"Check for silent failures"
"Analyze catch blocks in this PR"

4. type-design-analyzer

Focus: Type design quality and invariants

Analyzes:

  • Type encapsulation (rated 1-10)
  • Invariant expression (rated 1-10)
  • Type usefulness (rated 1-10)
  • Invariant enforcement (rated 1-10)

When to use:

  • When introducing new types
  • During PR creation with data models
  • When refactoring type designs

Triggers:

text
"Review the UserAccount type design"
"Analyze type design in this PR"
"Check if this type has strong invariants"

5. code-reviewer

Focus: General code review for project guidelines

Analyzes:

  • CLAUDE.md compliance
  • Style violations
  • Bug detection
  • Code quality issues

When to use:

  • After writing or modifying code
  • Before committing changes
  • Before creating pull requests

Triggers:

text
"Review my recent changes"
"Check if everything looks good"
"Review this code before I commit"

6. code-simplifier

Focus: Code simplification and refactoring

Analyzes:

  • Code clarity and readability
  • Unnecessary complexity and nesting
  • Redundant code and abstractions
  • Consistency with project standards
  • Overly compact or clever code

When to use:

  • After writing or modifying code
  • After passing code review
  • When code works but feels complex

Triggers:

text
"Simplify this code"
"Make this clearer"
"Refine this implementation"

Note: This agent preserves functionality while improving code structure and maintainability.

Usage Patterns

Individual Agent Usage

Simply ask questions that match an agent's focus area, and Claude will automatically trigger the appropriate agent:

text
"Can you check if the tests cover all edge cases?"
→ Triggers pr-test-analyzer

"Review the error handling in the API client"
→ Triggers silent-failure-hunter

"I've added documentation - is it accurate?"
→ Triggers comment-analyzer

Comprehensive PR Review

For thorough PR review, ask for multiple aspects:

text
"I'm ready to create this PR. Please:
1. Review test coverage
2. Check for silent failures
3. Verify code comments are accurate
4. Review any new types
5. General code review"

This will trigger all relevant agents to analyze different aspects of your PR.

Proactive Review

Claude may proactively use these agents based on context:

  • After writing code → code-reviewer
  • After adding docs → comment-analyzer
  • Before creating PR → Multiple agents as appropriate
  • After adding types → type-design-analyzer

Installation

Install from your personal marketplace:

bash
/plugins
# Find "pr-review-toolkit"
# Install

Or add manually to settings if needed.

Agent Details

Confidence Scoring

Agents provide confidence scores for their findings:

comment-analyzer: Identifies issues with high confidence in accuracy checks

pr-test-analyzer: Rates test gaps 1-10 (10 = critical, must add)

silent-failure-hunter: Flags severity of error handling issues

type-design-analyzer: Rates 4 dimensions on 1-10 scale

code-reviewer: Scores issues 0-100 (91-100 = critical)

code-simplifier: Identifies complexity and suggests simplifications

Output Formats

All agents provide structured, actionable output:

  • Clear issue identification
  • Specific file and line references
  • Explanation of why it's a problem
  • Suggestions for improvement
  • Prioritized by severity

Best Practices

When to Use Each Agent

Before Committing:

  • code-reviewer (general quality)
  • silent-failure-hunter (if changed error handling)

Before Creating PR:

  • pr-test-analyzer (test coverage check)
  • comment-analyzer (if added/modified comments)
  • type-design-analyzer (if added/modified types)
  • code-reviewer (final sweep)

After Passing Review:

  • code-simplifier (improve clarity and maintainability)

During PR Review:

  • Any agent for specific concerns raised
  • Targeted re-review after fixes

Running Multiple Agents

You can request multiple agents to run in parallel or sequentially:

Parallel (faster):

text
"Run pr-test-analyzer and comment-analyzer in parallel"

Sequential (when one informs the other):

text
"First review test coverage, then check code quality"

Tips

  • Be specific: Target specific agents for focused review
  • Use proactively: Run before creating PRs, not after
  • Address critical issues first: Agents prioritize findings
  • Iterate: Run again after fixes to verify
  • Don't over-use: Focus on changed code, not entire codebase

Troubleshooting

Agent Not Triggering

Issue: Asked for review but agent didn't run

Solution:

  • Be more specific in your request
  • Mention the agent type explicitly
  • Reference the specific concern (e.g., "test coverage")

Agent Analyzing Wrong Files

Issue: Agent reviewing too much or wrong files

Solution:

  • Specify which files to focus on
  • Reference the PR number or branch
  • Mention "recent changes" or "git diff"

Integration with Workflow

This plugin works great with:

  • build-validator: Run build/tests before review
  • Project-specific agents: Combine with your custom agents

Recommended workflow:

  1. Write code → code-reviewer
  2. Fix issues → silent-failure-hunter (if error handling)
  3. Add tests → pr-test-analyzer
  4. Document → comment-analyzer
  5. Review passes → code-simplifier (polish)
  6. Create PR

Contributing

Found issues or have suggestions? These agents are maintained in:

  • User agents: ~/.claude/agents/
  • Project agents: .claude/agents/ in claude-cli-internal

License

MIT

Author

Daisy ([email protected])


Quick Start: Just ask for review and the right agent will trigger automatically!


Overview (`plugins/ralph-wiggum/README.md`)

Ralph Wiggum Plugin

Implementation of the Ralph Wiggum technique for iterative, self-referential AI development loops in Claude Code.

What is Ralph?

Ralph is a development methodology based on continuous AI agent loops. As Geoffrey Huntley describes it: "Ralph is a Bash loop" - a simple while true that repeatedly feeds an AI agent a prompt file, allowing it to iteratively improve its work until completion.

The technique is named after Ralph Wiggum from The Simpsons, embodying the philosophy of persistent iteration despite setbacks.

Core Concept

This plugin implements Ralph using a Stop hook that intercepts Claude's exit attempts:

bash
# You run ONCE:
/ralph-loop "Your task description" --completion-promise "DONE"

# Then Claude Code automatically:
# 1. Works on the task
# 2. Tries to exit
# 3. Stop hook blocks exit
# 4. Stop hook feeds the SAME prompt back
# 5. Repeat until completion

The loop happens inside your current session - you don't need external bash loops. The Stop hook in hooks/stop-hook.sh creates the self-referential feedback loop by blocking normal session exit.

This creates a self-referential feedback loop where:

  • The prompt never changes between iterations
  • Claude's previous work persists in files
  • Each iteration sees modified files and git history
  • Claude autonomously improves by reading its own past work in files

Quick Start

bash
/ralph-loop "Build a REST API for todos. Requirements: CRUD operations, input validation, tests. Output <promise>COMPLETE</promise> when done." --completion-promise "COMPLETE" --max-iterations 50

Claude will:

  • Implement the API iteratively
  • Run tests and see failures
  • Fix bugs based on test output
  • Iterate until all requirements met
  • Output the completion promise when done

Commands

/ralph-loop

Start a Ralph loop in your current session.

Usage:

bash
/ralph-loop "<prompt>" --max-iterations <n> --completion-promise "<text>"

Options:

  • --max-iterations <n> - Stop after N iterations (default: unlimited)
  • --completion-promise <text> - Phrase that signals completion

/cancel-ralph

Cancel the active Ralph loop.

Usage:

bash
/cancel-ralph

Prompt Writing Best Practices

1. Clear Completion Criteria

❌ Bad: "Build a todo API and make it good."

✅ Good:

markdown
Build a REST API for todos.

When complete:
- All CRUD endpoints working
- Input validation in place
- Tests passing (coverage > 80%)
- README with API docs
- Output: <promise>COMPLETE</promise>

2. Incremental Goals

❌ Bad: "Create a complete e-commerce platform."

✅ Good:

markdown
Phase 1: User authentication (JWT, tests)
Phase 2: Product catalog (list/search, tests)
Phase 3: Shopping cart (add/remove, tests)

Output <promise>COMPLETE</promise> when all phases done.

3. Self-Correction

❌ Bad: "Write code for feature X."

✅ Good:

markdown
Implement feature X following TDD:
1. Write failing tests
2. Implement feature
3. Run tests
4. If any fail, debug and fix
5. Refactor if needed
6. Repeat until all green
7. Output: <promise>COMPLETE</promise>

4. Escape Hatches

Always use --max-iterations as a safety net to prevent infinite loops on impossible tasks:

bash
# Recommended: Always set a reasonable iteration limit
/ralph-loop "Try to implement feature X" --max-iterations 20

# In your prompt, include what to do if stuck:
# "After 15 iterations, if not complete:
#  - Document what's blocking progress
#  - List what was attempted
#  - Suggest alternative approaches"

Note: The --completion-promise uses exact string matching, so you cannot use it for multiple completion conditions (like "SUCCESS" vs "BLOCKED"). Always rely on --max-iterations as your primary safety mechanism.

Philosophy

Ralph embodies several key principles:

1. Iteration > Perfection

Don't aim for perfect on first try. Let the loop refine the work.

2. Failures Are Data

"Deterministically bad" means failures are predictable and informative. Use them to tune prompts.

3. Operator Skill Matters

Success depends on writing good prompts, not just having a good model.

4. Persistence Wins

Keep trying until success. The loop handles retry logic automatically.

When to Use Ralph

Good for:

  • Well-defined tasks with clear success criteria
  • Tasks requiring iteration and refinement (e.g., getting tests to pass)
  • Greenfield projects where you can walk away
  • Tasks with automatic verification (tests, linters)

Not good for:

  • Tasks requiring human judgment or design decisions
  • One-shot operations
  • Tasks with unclear success criteria
  • Production debugging (use targeted debugging instead)

Real-World Results

  • Successfully generated 6 repositories overnight in Y Combinator hackathon testing
  • One $50k contract completed for $297 in API costs
  • Created entire programming language ("cursed") over 3 months using this approach

Learn More

For Help

Run /help in Claude Code for detailed command reference and examples.


Overview (`plugins/security-guidance/README.md`)

security-guidance

Security review for Claude-generated code. Three layers:

  1. Pattern warnings — instant regex-based reminders on Edit/Write for ~25 known-dangerous patterns (yaml.load, torch.load(weights_only=False), pickle.load on untrusted data, raw innerHTML, hardcoded secrets, etc.).
  2. LLM diff review — when Claude finishes a turn, the plugin sends the diff to a fast LLM call (Opus 4.7 by default) and feeds high-severity findings back to Claude so it can fix them before you see the response.
  3. Agentic commit review — on git commit, an SDK-driven reviewer reads related files (Read/Grep/Glob) to trace data flow across the codebase, catching multi-file vulnerabilities pattern matching misses (IDOR, auth bypass, cross-file SSRF).

Findings cover common web-vulnerability classes — injection, XSS, SSRF, hardcoded secrets, IDOR, auth bypass, unsafe deserialization, and path traversal among others.

Install

text
/plugin install security-guidance@claude-plugins-official

Marketplace ships enabled by default in Claude Code — no setup beyond having the CLI itself.

Prerequisites

  • Claude Code CLI ≥ v2.1.144
  • Python 3.8+ on PATH (python3, python, or py -3 — the plugin picks the first that works)
  • A working API path (subscription, API key, or 3P provider config)

Configuration

All configuration is via environment variables. None are required for default behavior.

Selecting a model

bash
# 1P / gateway: a canonical model id
SECURITY_REVIEW_MODEL=claude-opus-4-7   # default

# Bedrock: use the inference-profile id
SECURITY_REVIEW_MODEL=us.anthropic.claude-opus-4-7

# Vertex: use the Vertex date-tag form
SECURITY_REVIEW_MODEL=claude-opus-4-7@20260218

SECURITY_REVIEW_MODEL controls the LLM diff review. SG_AGENTIC_MODEL (same syntax) controls the agentic commit reviewer; defaults to the same model.

Enabling/disabling layers

Variable Default What it does
SECURITY_GUIDANCE_DISABLE=1 unset Kill switch — disables the entire plugin
ENABLE_PATTERN_RULES=0 on Disable layer 1 (regex pattern warnings)
ENABLE_CODE_SECURITY_REVIEW=0 on Disable all LLM reviews (Stop hook + commit/push)
ENABLE_STOP_REVIEW=0 on Disable only the Stop-hook diff review, keeping commit/push reviews. Useful for multi-agent / shared-worktree setups where another agent can move HEAD between a worker's turns
ENABLE_COMMIT_REVIEW=0 on Disable layer 3 (agentic commit review)

Higher-recall mode

bash
SG_DUAL_OR=on   # default off

Runs two parallel review calls and unions the findings. Catches a few percentage points more vulnerabilities in our testing, at roughly 2× the API cost per review. Most users don't need it.

Org-specific policies

Drop a claude-security-guidance.md in any of:

  • ~/.claude/claude-security-guidance.md — user-wide rules
  • /.claude/claude-security-guidance.md — project rules, intended to be committed
  • /.claude/claude-security-guidance.local.md — local overrides, intended to be .gitignore'd

All three are loaded and concatenated into the LLM diff review's prompt in the order user → project → project-local. If the combined size exceeds the 8 KB prompt budget, the tail is truncated, so user-wide rules are kept and project-local rules are dropped first. The agentic commit reviewer (layer 3) does not currently read this file. Example:

markdown
# Acme security rules

- All SELECTs against the `customers` or `orders` tables MUST go through `db.replica`,
  never `db.primary`. Primary is for writes only.
- Background jobs must not use the user-context auth token; they get
  service-account creds from `jobs.get_service_account()`.
- Calls to `requests.get(url)` with a user-controlled `url` need
  the SSRF-allowlist wrapper at `acme.net.safe_request`.

Built-in rules cover common web-vulnerability classes without it — claude-security-guidance.md is for things specific to your codebase that the model can't infer.

Privacy and data handling

The plugin sends data to a model endpoint to perform its reviews. Specifically, each Stop-hook diff review transmits the changed file paths, the diff hunks, and the relevant file contents in the diff; each agentic commit review additionally transmits any files the reviewer pulls in via Read/Grep/Glob while tracing data flow. Your claude-security-guidance.md contents (user, project, and local) are appended to the prompt on every review, so don't put secrets in it.

Where that data goes depends on your Claude Code configuration:

  • Default (Anthropic API / subscription): sent to api.anthropic.com and handled under Anthropic's Commercial Terms and Privacy Policy.
  • LLM gateway (ANTHROPIC_BASE_URL set): sent to your gateway URL instead. The gateway operator's terms apply.
  • 3rd-party providers (Bedrock / Vertex / Foundry / Mantle): sent to your configured provider endpoint. The provider's data-handling terms apply (e.g., AWS / GCP / Azure).

The plugin writes its own debug log to ~/.claude/security/log.txt (override with SECURITY_GUIDANCE_DEBUG_LOG). The log contains diffstate metadata and finding categories — no full file contents or model prompts — and rotates at 1 MB. Nothing is uploaded.

Limitations

This is a best-effort assistive tool, not a guarantee. Treat findings as suggestions, not as a substitute for human code review, SAST/DAST, dependency scanning, or pen-testing. The reviewer can miss vulnerabilities, produce false positives, and may behave differently across codebases, languages, and model versions. No warranty is provided — use is subject to Anthropic's Commercial Terms.

Troubleshooting

Plugin doesn't seem to fire — check that ~/.claude/claude-security-guidance.md (or hook activity) shows in debug logs. Run Claude Code with --debug-file /tmp/claude/debug.txt and grep for security_reminder_hook. The plugin also writes its own log to ~/.claude/security/log.txt.

Review never finds anything — verify your API path works. On 3P providers, check SECURITY_REVIEW_MODEL is set to a provider-specific id (not a bare claude-opus-4-7). On LLM gateways, check the gateway's logs for POST /v1/messages traffic from the plugin.

Too many false positives — drop SECURITY_REVIEW_MODEL to a cheaper model (claude-sonnet-4-6) and re-evaluate; if precision is the priority, stay on Opus 4.7.

Want to silence a specific finding — add a comment to the line explaining why it's safe; the LLM reviewer treats inline justifications as exclusions. For systemic exclusions, document them in your claude-security-guidance.md.

Reporting issues

Open an issue on the security-guidance plugin repo with:

  • The Claude Code CLI version (claude --version)
  • Provider setup (1P / Bedrock / Vertex / LLM gateway / etc.)
  • A minimal repro diff
  • The relevant section of ~/.claude/security/log.txt

Overview (`examples/gateway/aws/README.md`)

Claude apps gateway on AWS

Reference deployment artifacts for running Claude apps gateway on AWS with
Amazon Bedrock as the upstream: ECS on Fargate or EKS, Amazon RDS for
PostgreSQL, AWS Secrets Manager, and IAM-role auth to Bedrock.

These files are provided as a working example rather than a supported production
deployment. Adapt them to your own environment.

File Purpose
setup.sh Scripts the walkthrough end to end via the aws CLI
Dockerfile Runtime image for the claude gateway binary (bakes in gateway.yaml)
gateway.yaml.example Gateway config template, AWS-shaped (Bedrock upstream, Okta IdP)
terraform/ Provisions the full architecture (two-pass apply — see terraform/README.md)

Overview (`examples/gateway/gcp/README.md`)

Claude Gateway on Google Cloud

Reference deployment artifacts for running Claude Gateway on GCP with Agent
Platform (formerly Vertex AI) as the upstream: Cloud Run or GKE, Cloud SQL for
PostgreSQL, Secret Manager, and service-account auth to Agent Platform.

These files are provided as a working example rather than a supported production
deployment. Adapt them to your own environment.

File Purpose
setup.sh Scripts the walkthrough end to end via gcloud
Dockerfile Runtime image for the claude gateway binary
gateway.yaml.example Gateway config template, GCP-shaped (Agent Platform upstream, Google Workspace IdP)
terraform/ Provisions the full architecture (two-pass apply — see terraform/README.md)

Overview (`examples/gateway/aws/terraform/README.md`)

Claude apps gateway — Terraform (ECS Fargate)

Terraform equivalent of ../setup.sh. Lets end-users provision and manage
the gateway with terraform apply. Covers the same scope (walkthrough §1–7,
ECS track): security groups → task + execution IAM roles → ECR repository →
private-subnet RDS for PostgreSQL → Secrets Manager secrets → ECS Fargate
service behind an internal ALB. The VPC and private subnets are walkthrough
prerequisites, passed in as variables — unlike the GCP example, no network is
created here.

Files

File Purpose
versions.tf Provider pins (aws, random)
variables.tf All inputs (defaults match setup.sh's)
main.tf Resources
outputs.tf ALB DNS name + zone ID, image, roles, DB endpoint
terraform.tfvars.example Copy to terraform.tfvars and edit

Prerequisites

  1. ../gateway.yaml created and FULLY filled in — copy the template first:
    cp ../gateway.yaml.example ../gateway.yaml, then replace every REPLACE_ME
    (Terraform reads this file and enforces no REPLACE_ME via a precondition).
    Unlike the GCP example there is no placeholder-first-pass: the config is
    baked into the image, and public_url is your own internal hostname,
    which you choose up front (you already hold its ACM certificate).
    gateway.yaml is gitignored; the committed template is gateway.yaml.example.
  2. The prebuilt linux-x64 claude binary at ../claude — the Claude Code
    release binary, which includes the gateway subcommand (see the
    walkthrough).
    See ../setup.sh's DIST_URL/DIST_SHA256 download path for a
    checksum-verified fetch.
  3. A VPC with two+ private subnets in different AZs and NAT egress, an ACM
    certificate
    for your internal gateway hostname, and Bedrock model access
    enabled in the console (cross-region us.anthropic.* profiles need it in each
    region the profile spans), with the one-time use case form submitted.
  4. A remote backend for shared use (see below). State holds secrets — never commit it.

Deploy

Terraform creates the ECR repository but does not build/push the image, so
the apply is two passes: a targeted apply to create the repo, then build/push,
then the full apply.

text
/* Detailed source-code truncated for AI context efficiency. */

Set in terraform.tfvars:

  • region, vpc_id, private_subnet_ids, corporate_cidr
  • acm_certificate_arn — the certificate for your internal gateway hostname
    (gateway.yaml's public_url host), served by the ALB's HTTPS listener
  • image_tag (after building/pushing — step 2 above). The repo enforces
    immutable tags, so a gateway.yaml edit means a rebuild under a new
    tag and an image_tag bump (../setup.sh automates this by tagging
    <version>-cfg<sha8-of-gateway.yaml>)
  • oidc_client_secret — required (the ECS tasks inject latest of this
    secret at start; with no version they fail with
    ResourceInitializationError). Terraform creates the secret + version from it.

Tear down

Tear down a trial with terraform destroy: set deletion_protection = false,
run terraform apply to record that on RDS and the ALB (and to flip RDS to
skip_final_snapshot — the provider checks the value in state, not config,
so destroy would still refuse otherwise), then terraform destroy.

The same switch drives the Secrets Manager recovery window: the three secrets
have fixed names, and a secret deleted with the default 30-day recovery
window keeps its name reserved — a later terraform apply would fail with a
name conflict until the window elapses. With deletion_protection = false the
destroy deletes them immediately (recovery_window_in_days = 0). If you
destroyed a deployment that still had deletion_protection = true (or tore
down an older copy of this module), clear the scheduled deletions before
re-applying:

bash
for s in gateway-postgres-url gateway-jwt-secret gateway-oidc-client-secret; do
  aws secretsmanager delete-secret --secret-id "$s" --force-delete-without-recovery
done

Guard rails

Tuned so accidental deletion is hard but greenfield teardown stays easy:

  • deletion_protection = true (variable, default true) on RDS and the ALB —
    blocks accidental deletion; set false when you intend to terraform destroy.
    The same switch controls RDS skip_final_snapshot, so a protected instance
    always leaves a final snapshot.
  • ECR tags are immutable and scanned on push — a deployed tag can never
    be silently re-pointed at different bytes. For production, also restrict push
    rights on the repo to your CI / image-promotion pipeline rather than operator
    credentials.
  • The IAM roles carry only the walkthrough's least-privilege documents: Bedrock
    invoke on the Anthropic model ARNs (task role) and secretsmanager:GetSecretValue
    on exactly the three secrets this module creates (by ARN) plus the AWS-managed
    ECS execution policy (execution role). Inline policies are scoped to these
    roles, so nothing else in the account is touched.
  • TLS everywhere it terminates: the ALB listener pins
    ELBSecurityPolicy-TLS13-1-2-2021-06 (no TLS 1.0/1.1), and the store
    connection uses sslmode=verify-full against the RDS CA bundle baked into
    the image, with rds.force_ssl=1 enforcing TLS server-side.

Private access

The ALB is internal with ip_address_type = "ipv4" (a dual-stack internal
ALB publishes public-range AAAA records, which the CLI's /login
private-network check rejects), and its security group admits only
corporate_cidr on 443. Reaching it from on-prem requires your existing
routing into the VPC (Direct Connect / VPN) — operator / network-team-owned
plumbing this module does not create.

After the apply, give developers a privately resolvable hostname: in a Route 53
private hosted zone, alias the host of gateway.yaml's public_url to the ALB
(alb_dns_name / alb_zone_id outputs). The ALB's own *.elb.amazonaws.com
name can't carry your ACM certificate, so use your own name.

The tasks run in the private subnets with no public IP; all egress (Bedrock,
the IdP, Secrets Manager, ECR, CloudWatch Logs) goes through the NAT gateway.
To keep Bedrock traffic off the public path, create a bedrock-runtime
interface VPC endpoint and point the upstream's base_url at it (see
../gateway.yaml.example); the IdP still needs internet egress.

Add a backend so state is shared and locked (and out of git):

hcl
# backend.tf
terraform {
  backend "s3" {
    bucket       = "<your-tf-state-bucket>"
    key          = "claude-gateway/ecs"
    region       = "us-east-1"
    use_lockfile = true # S3-native locking (Terraform >= 1.10); or set dynamodb_table
  }
}

After deploy

  • terraform output alb_dns_name / alb_zone_id — create the Route 53 alias.
  • Register /oauth/callback on the Okta OIDC web app and make sure
    ../gateway.yaml public_url matches the host you aliased.
  • Notes: Terraform does not build the image. To ship a new gateway version or
    a config edit
    , rerun the docker build/push under a new tag and bump
    image_tag — secrets-only rotations roll the service without a rebuild (the
    task definition stamps a hash of the managed secret values), but a
    gateway.yaml edit reaches the container only through the rebuilt image.

Overview (`examples/gateway/gcp/terraform/README.md`)

Claude Gateway — Terraform (Cloud Run)

Terraform equivalent of ../setup.sh. Lets end-users provision and manage
the gateway with terraform apply. Covers the same scope (walkthrough §1–7): APIs →
service account + IAM → Artifact Registry repo → VPC + Private Services Access →
private-IP Cloud SQL (PG16) → secrets → Cloud Run with Direct VPC egress.

Files

File Purpose
versions.tf Provider pins (google, random)
variables.tf All inputs (defaults match setup.sh's)
main.tf Resources
outputs.tf Service URL, OAuth redirect URI, SA, DB info
terraform.tfvars.example Copy to terraform.tfvars and edit

Prerequisites

  1. ../gateway.yaml created and filled in — copy the template first:
    cp ../gateway.yaml.example ../gateway.yaml, then replace every REPLACE_ME
    (Terraform reads this file and enforces no REPLACE_ME via a precondition).
    Leave public_url at its placeholder for the first apply; set it to the
    run.app URL (the service_url output) or your LB hostname and re-apply.
    gateway.yaml is gitignored; the committed template is gateway.yaml.example.
  2. A remote backend for shared use (see below). State holds secrets — never commit it.

Deploy

Terraform creates the Artifact Registry repo but does not build/push the
image, so the apply is two passes: a targeted apply to create the repo, then
build/push, then the full apply.

bash
cp terraform.tfvars.example terraform.tfvars   # edit it
terraform init

# 1. Create just the Artifact Registry repo (the -target warning is expected):
terraform apply -target=google_artifact_registry_repository.repo

# 2. Download the public Claude Code linux-x64 release binary (it includes the
#    `gateway` subcommand; the Dockerfile picks it up at gcp/claude), verify its
#    sha256 against the release manifest, then build and push the image:
BASE="https://downloads.claude.ai/claude-code-releases"
VERSION="$(curl -fsSL --proto '=https' "${BASE}/latest")"
curl -fL --proto '=https' --proto-redir '=https' -o ../claude \
  "${BASE}/${VERSION}/linux-x64/claude"
WANT="$(curl -fsSL --proto '=https' "${BASE}/${VERSION}/manifest.json" \
  | tr -d '[:space:]' | grep -oE '"linux-x64"[^}]*' | grep -oE '[a-f0-9]{64}' | head -1)"
[ "$(openssl dgst -sha256 ../claude | awk '{print $NF}')" = "${WANT}" ] \
  && echo "sha256 OK" || { echo "checksum mismatch" >&2; rm -f ../claude; }
gcloud auth configure-docker us-east5-docker.pkg.dev --quiet
docker build --platform=linux/amd64 --provenance=false \
  -f ../Dockerfile -t "us-east5-docker.pkg.dev/<project>/claude-gateway/gateway:${VERSION}" ..
docker push "us-east5-docker.pkg.dev/<project>/claude-gateway/gateway:${VERSION}"

# 3. Full apply:
terraform apply

(../setup.sh §3 automates the same download-and-verify.)

Set in terraform.tfvars:

  • project_id, region
  • image_tag (after building/pushing — step 2 above)
  • oidc_client_secret — required (the Cloud Run service mounts latest of
    this secret; with no version the deploy fails). Terraform creates the
    secret + version from it.
  • invoker_iam_disabled / allow_unauthenticated — the gateway runs its own
    OIDC, so the Cloud Run invoker IAM check must be opened or disabled.
    Preferred: invoker_iam_disabled = true (no allUsers binding; works
    under Domain Restricted Sharing). Fallback: allow_unauthenticated = true
    grants allUsers run.invoker — fine on a normal org, but DRS orgs reject
    allUsers (set it false there, since an LB does not bypass the IAM
    check). If both paths are blocked by org policy, use the GKE track.
  • ingress — defaults to internal-only (no public URL). Claude Code's /login
    only accepts gateway hosts on private addresses, so public ingress cannot serve
    clients; the two-pass OAuth bootstrap must be completed from inside the VPC (or a
    PSC-connected corp network). See "Private access" below.

Tear down a trial with terraform destroy: set deletion_protection = false,
run terraform apply to record that in state (the provider checks the value in
state, not config, so destroy would still refuse otherwise), then terraform destroy. The destroy will stop at the VPC network
because the Private Services Access peering is intentionally left in place
(deletion_policy = ABANDON — see Guard rails below); finish by deleting the
peering manually once the Cloud SQL instance is gone, then re-run destroy:

bash
gcloud services vpc-peerings delete --service=servicenetworking.googleapis.com \
  --network=cc-gateway-vpc --project=<project>
terraform destroy

Guard rails

Tuned so accidental deletion is hard but greenfield teardown stays easy:

  • deletion_protection = true (variable, default true) on Cloud SQL and Cloud Run —
    blocks accidental deletion; set false when you intend to terraform destroy.
  • disable_on_destroy = false on APIs — tearing down config never disables APIs.
  • deletion_policy = ABANDON on the PSA peering — never tears down the
    service-networking peering automatically (it's shared by every private-IP
    service on the VPC). On the dedicated VPC this module creates, that means
    terraform destroy stops at the network step; delete the peering manually
    per the teardown note above.
  • IAM uses non-authoritative _member resources, so other project/secret bindings
    are never clobbered.

Private access (internal ingress) — the default

By default the service has no public URL (ingress = "INGRESS_TRAFFIC_INTERNAL_ONLY"),
and there is no public-ingress option: Claude Code's /login rejects gateway hosts that
resolve to public addresses, so public exposure cannot serve clients. Reach the service
from inside the VPC, or via the private-access plumbing below.

With internal-only ingress, public_url stays the run.app URL (Google-managed cert) —
no load balancer or your own certificate required. But internal ingress alone does
not let corporate on-prem clients reach run.app; that needs operator /
network-team-owned
plumbing that Cloud Run does not create for you (validate it's in
place before relying on internal ingress):

  1. A Private Service Connect endpoint for Google APIs (an internal VIP in the VPC).
  2. A Cloud DNS private zone for run.app resolving *.run.app to that endpoint IP.
  3. On-prem routing to the endpoint over Cloud VPN / Interconnect.

This is normally managed centrally in the network/hub project, so the module does not
provision it. See Private networking and Cloud Run.
For a greenfield trial without this plumbing, complete the OAuth bootstrap from inside
the VPC — e.g. a browser proxied through an in-VPC VM (SSH SOCKS tunnel over IAP).

For a custom internal hostname or your own TLS cert, use
INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER and front the service with your own internal
Application Load Balancer (also not provisioned by this module).

Add a backend so state is shared and locked (and out of git):

hcl
# backend.tf
terraform {
  backend "gcs" {
    bucket = "<your-tf-state-bucket>"
    prefix = "claude-gateway/cloudrun"
  }
}

After deploy

  • terraform output service_url / oauth_redirect_uri.
  • Register the redirect URI on the Google OAuth client and make sure
    ../gateway.yaml public_url matches the host.
  • Notes: Terraform does not build the image. To ship a new gateway version,
    rerun the docker build/push under a new tag and bump image_tag — a bare
    re-apply under an unchanged tag does not roll a new revision (Cloud Run
    resolves the tag to a digest only at revision creation, and an unchanged
    image attribute means no new revision).

Overview (`plugins/plugin-dev/skills/command-development/README.md`)

Command Development Skill

Comprehensive guidance on creating Claude Code slash commands, including file format, frontmatter options, dynamic arguments, and best practices.

Overview

This skill provides knowledge about:

  • Slash command file format and structure
  • YAML frontmatter configuration fields
  • Dynamic arguments ($ARGUMENTS, $1, $2, etc.)
  • File references with @ syntax
  • Bash execution with !` syntax
  • Command organization and namespacing
  • Best practices for command development
  • Plugin-specific features (${CLAUDE_PLUGIN_ROOT}, plugin patterns)
  • Integration with plugin components (agents, skills, hooks)
  • Validation patterns and error handling

Skill Structure

SKILL.md (~2,470 words)

Core skill content covering:

Fundamentals:

  • Command basics and locations
  • File format (Markdown with optional frontmatter)
  • YAML frontmatter fields overview
  • Dynamic arguments ($ARGUMENTS and positional)
  • File references (@ syntax)
  • Bash execution (!` syntax)
  • Command organization patterns
  • Best practices and common patterns
  • Troubleshooting

Plugin-Specific:

  • ${CLAUDE_PLUGIN_ROOT} environment variable
  • Plugin command discovery and organization
  • Plugin command patterns (configuration, template, multi-script)
  • Integration with plugin components (agents, skills, hooks)
  • Validation patterns (argument, file, resource, error handling)

References

Detailed documentation:

  • frontmatter-reference.md: Complete YAML frontmatter field specifications

    • All field descriptions with types and defaults
    • When to use each field
    • Examples and best practices
    • Validation and common errors
  • plugin-features-reference.md: Plugin-specific command features

    • Plugin command discovery and organization
    • ${CLAUDE_PLUGIN_ROOT} environment variable usage
    • Plugin command patterns (configuration, template, multi-script)
    • Integration with plugin agents, skills, and hooks
    • Validation patterns and error handling

Examples

Practical command examples:

  • simple-commands.md: 10 complete command examples

    • Code review commands
    • Testing commands
    • Deployment commands
    • Documentation generators
    • Git integration commands
    • Analysis and research commands
  • plugin-commands.md: 10 plugin-specific command examples

    • Simple plugin commands with scripts
    • Multi-script workflows
    • Template-based generation
    • Configuration-driven deployment
    • Agent and skill integration
    • Multi-component workflows
    • Validated input commands
    • Environment-aware commands

When This Skill Triggers

Claude Code activates this skill when users:

  • Ask to "create a slash command" or "add a command"
  • Need to "write a custom command"
  • Want to "define command arguments"
  • Ask about "command frontmatter" or YAML configuration
  • Need to "organize commands" or use namespacing
  • Want to create commands with file references
  • Ask about "bash execution in commands"
  • Need command development best practices

Progressive Disclosure

The skill uses progressive disclosure:

  1. SKILL.md (~2,470 words): Core concepts, common patterns, and plugin features overview
  2. References (~13,500 words total): Detailed specifications
    • frontmatter-reference.md (~1,200 words)
    • plugin-features-reference.md (~1,800 words)
    • interactive-commands.md (~2,500 words)
    • advanced-workflows.md (~1,700 words)
    • testing-strategies.md (~2,200 words)
    • documentation-patterns.md (~2,000 words)
    • marketplace-considerations.md (~2,200 words)
  3. Examples (~6,000 words total): Complete working command examples
    • simple-commands.md
    • plugin-commands.md

Claude loads references and examples as needed based on task.

Command Basics Quick Reference

File Format

markdown
---
description: Brief description
argument-hint: [arg1] [arg2]
allowed-tools: Read, Bash(git:*)
---

Command prompt content with:
- Arguments: $1, $2, or $ARGUMENTS
- Files: @path/to/file
- Bash: !`command here`

Locations

  • Project: .claude/commands/ (shared with team)
  • Personal: ~/.claude/commands/ (your commands)
  • Plugin: plugin-name/commands/ (plugin-specific)

Key Features

Dynamic arguments:

  • $ARGUMENTS - All arguments as single string
  • $1, $2, $3 - Positional arguments

File references:

  • @path/to/file - Include file contents

Bash execution:

  • !command`` - Execute and include output

Frontmatter Fields Quick Reference

Field Purpose Example
description Brief description for /help "Review code for issues"
allowed-tools Restrict tool access Read, Bash(git:*)
model Specify model sonnet, opus, haiku
argument-hint Document arguments [pr-number] [priority]
disable-model-invocation Manual-only command true

Common Patterns

Simple Review Command

markdown
---
description: Review code for issues
---

Review this code for quality and potential bugs.

Command with Arguments

markdown
---
description: Deploy to environment
argument-hint: [environment] [version]
---

Deploy to $1 environment using version $2

Command with File Reference

markdown
---
description: Document file
argument-hint: [file-path]
---

Generate documentation for @$1

Command with Bash Execution

markdown
---
description: Show Git status
allowed-tools: Bash(git:*)
---

Current status: !`git status`
Recent commits: !`git log --oneline -5`

Development Workflow

  1. Design command:

    • Define purpose and scope
    • Determine required arguments
    • Identify needed tools
  2. Create file:

    • Choose appropriate location
    • Create .md file with command name
    • Write basic prompt
  3. Add frontmatter:

    • Start minimal (just description)
    • Add fields as needed (allowed-tools, etc.)
    • Document arguments with argument-hint
  4. Test command:

    • Invoke with /command-name
    • Verify arguments work
    • Check bash execution
    • Test file references
  5. Refine:

    • Improve prompt clarity
    • Handle edge cases
    • Add examples in comments
    • Document requirements

Best Practices Summary

  1. Single responsibility: One command, one clear purpose
  2. Clear descriptions: Make discoverable in /help
  3. Document arguments: Always use argument-hint
  4. Minimal tools: Use most restrictive allowed-tools
  5. Test thoroughly: Verify all features work
  6. Add comments: Explain complex logic
  7. Handle errors: Consider missing arguments/files

Status

Completed enhancements:

  • ✓ Plugin command patterns (${CLAUDE_PLUGIN_ROOT}, discovery, organization)
  • ✓ Integration patterns (agents, skills, hooks coordination)
  • ✓ Validation patterns (input, file, resource validation, error handling)

Remaining enhancements (in progress):

  • Advanced workflows (multi-step command sequences)
  • Testing strategies (how to test commands effectively)
  • Documentation patterns (command documentation best practices)
  • Marketplace considerations (publishing and distribution)

Maintenance

To update this skill:

  1. Keep SKILL.md focused on core fundamentals
  2. Move detailed specifications to references/
  3. Add new examples/ for different use cases
  4. Update frontmatter when new fields added
  5. Ensure imperative/infinitive form throughout
  6. Test examples work with current Claude Code

Version History

v0.1.0 (2025-01-15):

  • Initial release with basic command fundamentals
  • Frontmatter field reference
  • 10 simple command examples
  • Ready for plugin-specific pattern additions

Overview (`plugins/plugin-dev/skills/plugin-structure/README.md`)

Plugin Structure Skill

Comprehensive guidance on Claude Code plugin architecture, directory layout, and best practices.

Overview

This skill provides detailed knowledge about:

  • Plugin directory structure and organization
  • plugin.json manifest configuration
  • Component organization (commands, agents, skills, hooks)
  • Auto-discovery mechanisms
  • Portable path references with ${CLAUDE_PLUGIN_ROOT}
  • File naming conventions

Skill Structure

SKILL.md (1,619 words)

Core skill content covering:

  • Directory structure overview
  • Plugin manifest (plugin.json) fields
  • Component organization patterns
  • ${CLAUDE_PLUGIN_ROOT} usage
  • File naming conventions
  • Auto-discovery mechanism
  • Best practices
  • Common patterns
  • Troubleshooting

References

Detailed documentation for deep dives:

  • manifest-reference.md: Complete plugin.json field reference

    • All field descriptions and examples
    • Path resolution rules
    • Validation guidelines
    • Minimal vs. complete manifest examples
  • component-patterns.md: Advanced organization patterns

    • Component lifecycle (discovery, activation)
    • Command organization patterns
    • Agent organization patterns
    • Skill organization patterns
    • Hook organization patterns
    • Script organization patterns
    • Cross-component patterns
    • Best practices for scalability

Examples

Three complete plugin examples:

  • minimal-plugin.md: Simplest possible plugin

    • Single command
    • Minimal manifest
    • When to use this pattern
  • standard-plugin.md: Well-structured production plugin

    • Multiple components (commands, agents, skills, hooks)
    • Complete manifest with metadata
    • Rich skill structure
    • Integration between components
  • advanced-plugin.md: Enterprise-grade plugin

    • Multi-level organization
    • MCP server integration
    • Shared libraries
    • Configuration management
    • Security automation
    • Monitoring integration

When This Skill Triggers

Claude Code activates this skill when users:

  • Ask to "create a plugin" or "scaffold a plugin"
  • Need to "understand plugin structure"
  • Want to "organize plugin components"
  • Need to "set up plugin.json"
  • Ask about "${CLAUDE_PLUGIN_ROOT}" usage
  • Want to "add commands/agents/skills/hooks"
  • Need "configure auto-discovery" help
  • Ask about plugin architecture or best practices

Progressive Disclosure

The skill uses progressive disclosure to manage context:

  1. SKILL.md (~1600 words): Core concepts and workflows
  2. References (~6000 words): Detailed field references and patterns
  3. Examples (~8000 words): Complete working examples

Claude loads references and examples only as needed based on the task.

This skill works well with:

  • hook-development: For creating plugin hooks
  • mcp-integration: For integrating MCP servers (when available)
  • marketplace-publishing: For publishing plugins (when available)

Maintenance

To update this skill:

  1. Keep SKILL.md lean and focused on core concepts
  2. Move detailed information to references/
  3. Add new examples/ for common patterns
  4. Update version in SKILL.md frontmatter
  5. Ensure all documentation uses imperative/infinitive form

Overview (`plugins/plugin-dev/skills/hook-development/scripts/README.md`)

Hook Development Utility Scripts

These scripts help validate, test, and lint hook implementations before deployment.

validate-hook-schema.sh

Validates hooks.json configuration files for correct structure and common issues.

Usage:

bash
./validate-hook-schema.sh path/to/hooks.json

Checks:

  • Valid JSON syntax
  • Required fields present
  • Valid hook event names
  • Proper hook types (command/prompt)
  • Timeout values in valid ranges
  • Hardcoded path detection
  • Prompt hook event compatibility

Example:

bash
cd my-plugin
./validate-hook-schema.sh hooks/hooks.json

test-hook.sh

Tests individual hook scripts with sample input before deploying to Claude Code.

Usage:

bash
./test-hook.sh [options] <hook-script> <test-input.json>

Options:

  • -v, --verbose - Show detailed execution information
  • -t, --timeout N - Set timeout in seconds (default: 60)
  • --create-sample <event-type> - Generate sample test input

Example:

bash
# Create sample test input
./test-hook.sh --create-sample PreToolUse > test-input.json

# Test a hook script
./test-hook.sh my-hook.sh test-input.json

# Test with verbose output and custom timeout
./test-hook.sh -v -t 30 my-hook.sh test-input.json

Features:

  • Sets up proper environment variables (CLAUDE_PROJECT_DIR, CLAUDE_PLUGIN_ROOT)
  • Measures execution time
  • Validates output JSON
  • Shows exit codes and their meanings
  • Captures environment file output

hook-linter.sh

Checks hook scripts for common issues and best practices violations.

Usage:

bash
./hook-linter.sh <hook-script.sh> [hook-script2.sh ...]

Checks:

  • Shebang presence
  • set -euo pipefail usage
  • Stdin input reading
  • Proper error handling
  • Variable quoting (injection prevention)
  • Exit code usage
  • Hardcoded paths
  • Long-running code detection
  • Error output to stderr
  • Input validation

Example:

bash
# Lint single script
./hook-linter.sh ../examples/validate-write.sh

# Lint multiple scripts
./hook-linter.sh ../examples/*.sh

Typical Workflow

  1. Write your hook script

    bash
    vim my-plugin/scripts/my-hook.sh
  2. Lint the script

    bash
    ./hook-linter.sh my-plugin/scripts/my-hook.sh
  3. Create test input

    bash
    ./test-hook.sh --create-sample PreToolUse > test-input.json
    # Edit test-input.json as needed
  4. Test the hook

    bash
    ./test-hook.sh -v my-plugin/scripts/my-hook.sh test-input.json
  5. Add to hooks.json

    bash
    # Edit my-plugin/hooks/hooks.json
  6. Validate configuration

    bash
    ./validate-hook-schema.sh my-plugin/hooks/hooks.json
  7. Test in Claude Code

    bash
    claude --debug

Tips

  • Always test hooks before deploying to avoid breaking user workflows
  • Use verbose mode (-v) to debug hook behavior
  • Check the linter output for security and best practice issues
  • Validate hooks.json after any changes
  • Create different test inputs for various scenarios (safe operations, dangerous operations, edge cases)

Common Issues

Hook doesn't execute

Check:

  • Script has shebang (#!/bin/bash)
  • Script is executable (chmod +x)
  • Path in hooks.json is correct (use ${CLAUDE_PLUGIN_ROOT})

Hook times out

  • Reduce timeout in hooks.json
  • Optimize hook script performance
  • Remove long-running operations

Hook fails silently

  • Check exit codes (should be 0 or 2)
  • Ensure errors go to stderr (>&2)
  • Validate JSON output structure

Injection vulnerabilities

  • Always quote variables: "$variable"
  • Use set -euo pipefail
  • Validate all input fields
  • Run the linter to catch issues

--- METRICS ---