# Technical Documentation: anthropics/claude-code

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/anthropics/claude-code)

### Overview (`README.md`)

# Claude Code

 [

[npm]: https://img.shields.io/npm/v/@anthropic-ai/claude-code.svg?style=flat-square

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](https://code.claude.com/docs/en/overview)**.

<img src="./demo.gif" />

## 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](https://code.claude.com/docs/en/setup).

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](./plugins/README.md) 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](https://github.com/anthropics/claude-code/issues).

## Connect on Discord

Join the [Claude Developers Discord](https://anthropic.com/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](https://code.claude.com/docs/en/data-usage).

### 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](https://www.anthropic.com/legal/commercial-terms) and [Privacy Policy](https://www.anthropic.com/legal/privacy).

---

### 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`](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) | `/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`](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) | `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:

    claude --plugin-dir mods/diff

## Testing

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

    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](https://docs.claude.com/en/docs/claude-code/plugins).

## Plugins in This Directory

| Name | Description | Contents |
|------|-------------|----------|
| [agent-sdk-dev](./agent-sdk-dev/) | Development kit for working with the Claude Agent SDK | **Command:** `/new-sdk-app` - Interactive setup for new Agent SDK projects<br>**Agents:** `agent-sdk-verifier-py`, `agent-sdk-verifier-ts` - Validate SDK applications against best practices |
| [claude-opus-4-5-migration](./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](./code-review/) | Automated PR code review using multiple specialized agents with confidence-based scoring to filter false positives | **Command:** `/code-review` - Automated PR review workflow<br>**Agents:** 5 parallel Sonnet agents for CLAUDE.md compliance, bug detection, historical context, PR history, and code comments |
| [commit-commands](./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](./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](./feature-dev/) | Comprehensive feature development workflow with a structured 7-phase approach | **Command:** `/feature-dev` - Guided feature development workflow<br>**Agents:** `code-explorer`, `code-architect`, `code-reviewer` - For codebase analysis, architecture design, and quality review |
| [frontend-design](./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](./hookify/) | Easily create custom hooks to prevent unwanted behaviors by analyzing conversation patterns or explicit instructions | **Commands:** `/hookify`, `/hookify:list`, `/hookify:configure`, `/hookify:help`<br>**Agent:** `conversation-analyzer` - Analyzes conversations for problematic behaviors<br>**Skill:** `writing-rules` - Guidance on hookify rule syntax |
| [learning-output-style](./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](./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 plugins<br>**Agents:** `agent-creator`, `plugin-validator`, `skill-reviewer`<br>**Skills:** Hook development, MCP integration, plugin structure, settings, commands, agents, and skill development |
| [pr-review-toolkit](./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)<br>**Agents:** `comment-analyzer`, `pr-test-analyzer`, `silent-failure-hunter`, `type-design-analyzer`, `code-reviewer`, `code-simplifier` |
| [ralph-wiggum](./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 loops<br>**Hook:** Stop - Intercepts exit attempts to continue iteration |
| [security-guidance](./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
```

2. Navigate to your project and run Claude Code:
```bash
claude
```

3. 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](https://docs.claude.com/en/docs/claude-code/plugins).

## Plugin Structure

Each plugin follows the standard Claude Code plugin structure:

```
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

- [Claude Code Documentation](https://docs.claude.com/en/docs/claude-code/overview)
- [Plugin System Documentation](https://docs.claude.com/en/docs/claude-code/plugins)
- [Agent SDK Documentation](https://docs.claude.com/en/api/agent-sdk/overview)

---

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

# MDM Deployment Examples

Example templates for deploying Claude Code [managed settings](https://code.claude.com/docs/en/settings#settings-files) 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](https://code.claude.com/docs/en/settings#available-settings) for the full list of keys, and [`../settings`](../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`](./managed-settings.json) | Any platform. Deploy to the [system config directory](https://code.claude.com/docs/en/settings#settings-files). |
| [`macos/com.anthropic.claudecode.plist`](./macos/com.anthropic.claudecode.plist) | Jamf or Iru (Kandji) **Custom Settings** payload. Preference domain: `com.anthropic.claudecode`. |
| [`macos/com.anthropic.claudecode.mobileconfig`](./macos/com.anthropic.claudecode.mobileconfig) | Full configuration profile for local testing or MDMs that take a complete profile. |
| [`windows/Set-ClaudeCodePolicy.ps1`](./windows/Set-ClaudeCodePolicy.ps1) | Intune **Platform scripts**. Writes `managed-settings.json` to `C:\Program Files\ClaudeCode\`. |
| [`windows/ClaudeCode.admx`](./windows/ClaudeCode.admx) + [`en-US/ClaudeCode.adml`](./windows/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](https://code.claude.com/docs/en/settings#settings-files), 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-lax.json) | [`settings-strict.json`](./settings-strict.json) | [`settings-bash-sandbox.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`](../mdm).

## HIPAA deployments

For an organization that has the HIPAA configuration applied, [`settings-hipaa.json`](./settings-hipaa.json) and [`managed-mcp-hipaa.json`](./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`](./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 <this folder>`.

## 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: <paths>`, 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 <path>:` 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](../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

    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__<plugin>__<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_<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_<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](#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](#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); <plugin>
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](#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: `<plugin> 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:
```
"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:
```
"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
```

2. **Answer the interactive questions:**
```
Language: TypeScript
Agent type: Coding agent (code review)
Starting point: Basic agent with common features
```

3. **Automatic verification:**
The command automatically runs `agent-sdk-verifier-ts` to ensure everything is correctly set up.

4. **Start developing:**
```bash
# Set your API key
echo "ANTHROPIC_API_KEY=your_key_here" > .env

# Run your agent
npm start
```

5. **Verify after changes:**
```
"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

- [Agent SDK Overview](https://docs.claude.com/en/api/agent-sdk/overview)
- [TypeScript SDK Reference](https://docs.claude.com/en/api/agent-sdk/typescript)
- [Python SDK Reference](https://docs.claude.com/en/api/agent-sdk/python)
- [Agent SDK Examples](https://docs.claude.com/en/api/agent-sdk/examples)

## 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 (ashwin@anthropic.com)

## 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

```
"Migrate my codebase to Opus 4.5"
```

## Learn More

Refer to our [prompting guide](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-4-best-practices) for best practices on prompting Claude models.

## Authors

William Hu (whu@anthropic.com)

---

### 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)

### Link formatting broken

**Issue**: Code links don't render correctly in GitHub

**Solution**:
Links must follow this exact format:
```
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](https://cli.github.com/)
- 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 (boris@anthropic.com)

## 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](https://cli.github.com/)
- 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 (support@anthropic.com)

## 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:

```
`★ 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](https://docs.claude.com/en/docs/claude-code/sub-agents), 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
  - Hint: Ask Claude to read
    https://docs.claude.com/en/docs/claude-code/plugins.md and set it up for
    you!

---

### 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:**
```
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:**
```
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:**
```
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:**
```
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:**
```
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:**
```
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

### Full workflow (recommended for new features):
```bash
/feature-dev Add rate limiting to API endpoints
```

Let the workflow guide you through all 7 phases.

### Manual agent invocation:

**Explore a feature:**
```
"Launch code-explorer to trace how authentication works"
```

**Design architecture:**
```
"Launch code-architect to design the caching layer"
```

**Review code:**
```
"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 (sbidasaria@anthropic.com)

## 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

```
"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](https://github.com/anthropics/claude-cookbooks/blob/main/coding/prompting_for_frontend_aesthetics.ipynb) for detailed guidance on prompting for high-quality frontend design.

## Authors

Prithvi Rajasekaran (prithvi@anthropic.com)
Alexander Bricken (alexander@anthropic.com)

---

### 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:
```
Run rm -rf /tmp/test
```

You should see the warning message immediately!

## Usage

### Main Command: /hookify

**With arguments:**
```
/hookify Don't use console.log in TypeScript files
```
Creates a rule from your explicit instructions.

**Without arguments:**
```
/hookify
```
Analyzes recent conversation to find behaviors you've corrected or been frustrated by.

### Helper Commands

**List all rules:**
```
/hookify:list
```

**Configure rules interactively:**
```
/hookify:configure
```
Enable/disable existing rules through an interactive interface.

**Get help:**
```
/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:**
```
/hookify:configure
```

### Delete Rules

Simply delete the `.local.md` file:
```bash
rm .claude/hookify.my-rule.local.md
```

### View All Rules

```
/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](https://github.com/anthropics/claude-code/tree/main/plugins/explanatory-output-style), 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:

```
`★ 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
  - Hint: Ask Claude to read https://docs.claude.com/en/docs/claude-code/plugins.md and set it up for you!

## 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 <example> 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:

```
┌─────────────────────┐
│  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

```
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

```
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

```
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 (daisy@anthropic.com)

## 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:**
```
"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:**
```
"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:**
```
"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:**
```
"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:**
```
"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:**
```
"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:

```
"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:

```
"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):
```
"Run pr-test-analyzer and comment-analyzer in parallel"
```

**Sequential** (when one informs the other):
```
"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 (daisy@anthropic.com)

---

**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

- Original technique: https://ghuntley.com/ralph/
- Ralph Orchestrator: https://github.com/mikeyobrien/ralph-orchestrator

## 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

```
/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
- `<project>/.claude/claude-security-guidance.md` — project rules, intended to be committed
- `<project>/.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](https://www.anthropic.com/legal/commercial-terms) and [Privacy Policy](https://www.anthropic.com/legal/privacy).
- **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](https://www.anthropic.com/legal/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](https://github.com/anthropics/claude-code/issues) 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.

- **Walkthrough**: https://code.claude.com/docs/en/claude-apps-gateway-on-aws
- **Related**: AWS-maintained samples for various customer environments at
  https://github.com/aws-samples/anthropic-on-aws/tree/main/claude-apps-gateway

| 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.

- **Walkthrough**: https://code.claude.com/docs/en/claude-apps-gateway-on-gcp

| 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](https://code.claude.com/docs/en/claude-apps-gateway-on-aws) §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](https://code.claude.com/docs/en/claude-apps-gateway-on-aws)).
   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.

```
/* 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.

## Remote state (recommended for teams)

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 `<public_url>/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](https://code.claude.com/docs/en/claude-apps-gateway-on-gcp) §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](https://cloud.google.com/run/docs/securing/private-networking).
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).

## Remote state (recommended for teams)

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.

## Related Skills

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 ---
- Files Extracted: 29
- Estimated Token Budget: ~48968 tokens
- Canonical Reference: https://codewiki.google/github.com/anthropics/claude-code
