One read of Claude Code CLIclaude-code-20261009T193701Z
11 pages moved out of 221 read.
Pages moved
11
significant first
Pages read
221
in this capture
Captured
19:37 UTC
Corpus hash
5d5e647f86d1
corpus-hash
What this read moved
1-11 of 11plugins/host-marketplace Changed · +8 / -2 lines
from line 357
357357
358358### How users accept a headersHelper command
359359
360A user accepts a plugin entry's command each time they install or update that one plugin by itself. They do that from the plugin's own view in `/plugin`, or with `claude plugin install` or `claude plugin update`. Claude Code shows the command and the archive URL, and runs the command only after the user accepts.
360A user accepts a plugin entry's command each time they install or update that one plugin by itself. Claude Code shows the command and the archive URL, and runs the command only after the user accepts.
361361
362Users can install or update the plugin inside a Claude Code session in a terminal, in their shell with no session running, or in the VS Code extension:
363
364* **Terminal session**: from the plugin's own view in `/plugin`.
365* **Shell**: with `claude plugin install` or `claude plugin update`.
366* **VS Code extension**: from the [**Manage plugins** dialog](/docs/en/vs-code#manage-plugins), with version 2.1.290 or later of the extension.
367
362368In a non-interactive shell, pass [`--yes`](/docs/en/plugins/cli-reference#plugin-install) to accept the command. To accept only the command that a previous `--json` run displayed, pass [`--accept-command`](/docs/en/plugins/cli-reference#plugin-install) with the `sha256` the run reported.
363369
364Claude Code runs only the command it showed, for the archive URL it showed. If the entry's command or archive URL changed in between, Claude Code refuses the install or update. A change in the query string alone doesn't count.
370Claude Code runs only the command it showed, for the archive URL it showed. If the entry's command or archive URL changed in between, Claude Code refuses the install or update. A change in the query string alone doesn't count, except in the VS Code extension or with `--accept-command`.
365371
366372<h3 id="installs-and-updates-that-refuse-the-command-instead-of-asking">
367373 Installs and updates that refuse a command instead of asking
plugins/mods/events Changed · +10 / -3 lines
from line 127
127127
128128After Claude edits or writes an `.mdx` file, a dim line in the transcript names the file. Nothing is logged for another kind of file, or for a call that was refused or failed. Claude's view of the call doesn't change, because the hook returns the result it received.
129129
130To change a call, pass changed arguments to `next`. To retry a call, call `next(e)` again: a hook that sees `isError` on the first result can run the tool a second time and return that result. To answer a call yourself, return an object with a `result` field, such as `{ result: 'Skipped by my-mod' }`, without calling `next`. When you do that, no permission prompt appears and the tool doesn't run, so the result you return is all Claude learns about what happened.
130Your hook can also change a call, retry it, answer it itself, or withhold its result:
131131
132* **Change the call**: pass changed arguments to `next`.
133* **Retry the call**: call `next(e)` again. A hook that sees `isError` on the first result can run the tool a second time and return that result.
134* **Answer the call yourself**: return an object with a `result` field, without calling `next`, and for a built-in tool, give `result` the shape that tool's own result has in [the types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build). No permission prompt appears and the tool doesn't run, so the result you return is all Claude learns about what happened.
135* **Withhold the result from Claude**: return `{ deny: reason }` after `await next(e)`. Claude reads your reason in place of what `next` returned. When the tool ran, the deny keeps its result from Claude and undoes nothing the tool did. When the tool ran and succeeded, the reason follows a note such as `Bash ran, and a plugin withheld its result:`.
136
132137Hooks in your organization's [managed settings](/docs/en/server-managed-settings) run before any mod's `tool.call` hook, and a block from one of them is final.
133138
134139#### Hold a tool call until the user decides
from line 206
201206
202207| To do this | Return this |
203208| :- | :- |
204| Rewrite the prompt. The message in the transcript shows the new text. | `next({ ...e, text: newText })` |
209| Rewrite the prompt. The transcript and your [prompt history](/docs/en/interactive-mode#command-history) show the new text. | `next({ ...e, text: newText })` |
205210| Add text only Claude reads, after the prompt | `next({ ...e, context: [...(e.context ?? []), extraText] })` |
206211| Stop the prompt from being sent | `{ drop: 'the reason' }` |
207212
from line 226
221226
222227When you send a prompt such as `open a PR for this change`, your message looks the same in the transcript, and Claude also reads a line such as `Current branch: feature/auth` after it. A prompt that doesn't mention a pull request goes through unchanged, and `git` doesn't run.
223228
224To stop a prompt, return `{ drop: 'the reason' }` without calling `next`. If your hook returns a `drop` after its `next(e)` call let the prompt through, the turn still runs, and the hook [fails](#handle-a-hook-that-fails) with a message that includes `a drop after its next() was answered`.
229To stop a prompt, return `{ drop: 'the reason' }` without calling `next`. The text goes back into the user's prompt input, and they see `Prompt dropped by a hook:` followed by your reason, so address the reason to them. If your hook returns a `drop` after its `next(e)` call let the prompt through, the turn still runs, and the hook [fails](#handle-a-hook-that-fails) with a message that includes `a drop after its next() was answered`.
225230
226231[Other events](/docs/en/plugins/mods/reference#prompts-and-what-claude-reads) cover the rest of what Claude reads: `prompt.section` for each section of the system prompt, `prompt.context` for the context sent with the first message, and `skill.prompt` for a skill's text. Text from these hooks that changes between requests [invalidates the prompt cache](/docs/en/prompt-caching).
227232
from line 341
336341
337342* **`tool.check`**: return `{ decision: 'deny', reason: 'the reason' }`
338343* **`plugin.register`**: return `{ refuse: 'the reason' }`, as [Refuse mods when your check fails](/docs/en/plugins/mods/admin#refuse-mods-when-your-check-fails) shows
344
345At `tool.call`, a `deny` returned after `next` resolved [withholds the result from Claude](#guard-or-change-a-tool-call).
339346
340347## Next steps
341348
plugins/mods/reference Changed · +3 / -2 lines
from line 52
5252| :- | :- | :- |
5353| [`tool.call`](/docs/en/plugins/mods/events#guard-or-change-a-tool-call) | A tool is about to run | `next(e)`, `{ deny: reason }`, or `{ result }` |
5454| [`tool.check`](/docs/en/plugins/mods/events#where-settings-hooks-run-in-the-order) | Claude Code decides whether a tool call may run, after the `tool.call` and `PreToolUse` hooks. `next(e)` resolves to the decision the rules, the permission mode, and those hooks reached. | `{ decision }`, which is `allow`, `ask`, or `deny` |
55| `tool.describe` | Once for each tool, when its description is first sent to Claude | `{ description }`, optionally with `isDeferred` set to `true` to put the tool behind [tool search](/docs/en/mcp#scale-with-mcp-tool-search) or `false` to load it upfront |
55| `tool.describe` | Once for each tool, when its description is first sent to Claude. A second time for an MCP tool when Claude loads it through [tool search](/docs/en/mcp#scale-with-mcp-tool-search), with `e.description` set to the text Claude reads for the loaded tool. | `{ description }`, optionally with `isDeferred` set to `true` to put the tool behind tool search or `false` to load it upfront |
5656
5757#### Agent and organization fields on `tool.check`
5858
from line 113
113113| `session.end` | The session ends, or `/clear`, `/resume`, or `/branch` runs. `e.reason` is `clear`, `resume`, `logout`, `prompt_input_exit`, or `other`. `/branch` reports `resume`. | `next(e)` |
114114| `session.compact` | The conversation is about to be compacted | `{ skip: reason }` |
115115| [`session.receive`](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions), [`session.send`](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions) | A message arrives from, or is about to go to, another agent or session. See [Send and receive messages between sessions](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions). | `{ consumed: reason }` for `receive`, `{ isDelivered: false, reason }` for `send` |
116| `session.append` | Once for each row the conversation keeps, such as a prompt, a response block, a tool result, or a notice, before it's stored | `next({ ...e, message })` to rewrite the row's `content` |
116| `session.append` | Once for each row the conversation keeps, such as a prompt, a response block, a tool result, or a notice, before it's stored | `next({ ...e, message })` with a changed `message.content`, to rewrite the row's text blocks or the `content` of a `tool_result` block in it |
117117| `session.attach`, `session.detach` | Another app connects to or disconnects from the session | `next(e)` |
118118| `session.measure` | After each turn, and when a plan limit's percent used changes | `next(e)` |
119119
from line 286
286286| `$.ui.invalidate('ui.render')` redraws | Throttled to 10 a second, or 30 in the terminal for the visible pane, the expanded band, and the hint line under the prompt. Calls that come sooner are coalesced. |
287287| `$.ui.toast` | Shown for 4 seconds unless you pass `{ timeoutMs }` |
288288| A pane opened without the user asking | Placed from 144 terminal columns, 110 after they've opened it once |
289| Scopes, such as functions, blocks, and loops, nested inside one another in one file of a hooks module | 2,000 |
289290| Command, tool, subagent type, and pane names | Letters, digits, `_`, and `-`, up to 64 characters |
290291| One `claude plugin test` test | 5 seconds unless the test sets `timeoutMs` |
291292
plugins/mods/troubleshoot Changed · +12 / -0 lines
### `code nested too deep to scan: more than 2000 scopes` ### Claude Code stops asking to enable hot reloading
from line 90
9090
9191Set or change the value. The end of the line names its `pluginConfigs` entry in `settings.json`.
9292
93### `code nested too deep to scan: more than 2000 scopes`
94
95The line starts with the mod's name, then `hooks module did not load:`, the file, and `code nested too deep to scan: more than 2000 scopes`. A file in a hooks module can't nest scopes, such as functions, blocks, and loops, more than [2,000 deep](/docs/en/plugins/mods/reference#limits). [`claude plugin validate`](/docs/en/plugins/mods/create#check-what-claude-code-reads-from-your-mod) reports the same reason.
96
97Rewrite the code so its scopes nest less deeply.
98
9399### No mod loads in a directory you opened for the first time
94100
95101You haven't answered the trust prompt for the directory.
from line 107
101107You started Claude Code with `--safe-mode`.
102108
103109Start without the flag.
110
111### Claude Code stops asking to enable hot reloading
112
113Claude writes a mod in an interactive session, nothing loads, and Claude Code doesn't ask again [whether to enable hot reloading](/docs/en/plugins/mods/create#ask-claude-for-a-mod). If the question ends three times without an answer picked, hot reloading stays off. For example, the question ends that way when you set [`askUserQuestionTimeout`](/docs/en/settings-reference#askuserquestiontimeout) and the time passes before you answer. That setting applies here because Claude Code asks in the same [question dialog that `AskUserQuestion` uses](/docs/en/tools-reference#question-auto-continue-timeout). A question you dismiss yourself doesn't count toward the three.
114
115To run the mod, [copy its directory out of the mods folder](/docs/en/plugins/mods/create#use-the-mod-in-other-sessions), then in your shell start a new session with `--plugin-dir`, as in `claude --plugin-dir ~/mods/git-branch`.
104116
105117## A hook is skipped or a mod is unloaded
106118
plugins/troubleshooting Changed · +53 / -1 lines
from line 229
229229* **You own the marketplace**: put the file at that location and re-add the marketplace
230230* **Someone else hosts it**: ask the owner for the exact source they publish
231231
232<h3 id="cannot-install-plugins-from-a-marketplace-with-this-name">
233 `Cannot add marketplace "<name>": Claude Code cannot install plugins from a marketplace with this name`
234</h3>
235
236You added a marketplace, and the [`name`](/docs/en/plugins/marketplace-reference#top-level-fields) in its `marketplace.json` isn't valid as the part after `@` in a [plugin id](/docs/en/plugins/loading#find-where-a-plugin-came-from) such as `my-plugin@my-marketplace`. Claude Code refuses the add and registers nothing.
237
238The rest of the message states the rule for the name. In this example, `_internal` breaks the rule by starting with `_`:
239
240```text theme={null}
241Cannot add marketplace "_internal": Claude Code cannot install plugins from a marketplace with this name. Each part of a plugin id (plugin@marketplace) may use only the letters a-z and A-Z, digits, ".", "_" and "-", and must start with a letter or digit. The name is set by "name" in the marketplace's marketplace.json; ask its maintainer to change it.
242```
243
244Give the marketplace a name that fits that rule, then add it again:
245
246* **You own the marketplace**: change `name` in `marketplace.json`, for example to `internal-tools`
247* **Someone else hosts it**: ask the owner to change the name
248
249Before v2.1.295, Claude Code reported the add in this example as successful.
250
232251<h3 id="ssh-authentication-failed-or-https-authentication-failed">
233252 `SSH authentication failed` or `HTTPS authentication failed`
234253</h3>
from line 793
774793
775794Claude Code copies the unusable records into the `.set-aside` file and drops them from the list. Claude Code never reads the copies back, and the copies age out on the [`cleanupPeriodDays`](/docs/en/settings-reference#cleanupperioddays) schedule.
776795
796<h3 id="does-not-load-so-claude-code-ignores-the-whole-file">
797 `does not load (...), so Claude Code ignores the whole file`
798</h3>
799
800The command worked. The settings file the warning names has an error, so Claude Code ignores the whole file, including anything the command wrote there, until you fix it.
801
802Fix the error the warning names. For a value Claude Code doesn't accept, [Fix a broken settings file](/docs/en/settings#fix-a-broken-settings-file) says how. Then run the command again if its change is no longer in the file.
803
804The warning follows the success line of `claude plugin install`, `enable`, `disable`, or `claude plugin marketplace add` in your shell:
805
806```text theme={null}
807⚠ /home/user/.claude/settings.json does not load (its "permissions" is not valid), so Claude Code ignores the whole file, including anything this command wrote there. Fix the file, then run this command again if its change is missing. If a newer Claude Code wrote the file, update Claude Code instead.
808```
809
810The text in parentheses names the error:
811
812* **`its "<key>" is not valid`**: the quoted setting holds a value Claude Code doesn't accept. Look up the setting in the [settings reference](/docs/en/settings-reference) for the values it takes. When more than one value fails, the text names the first setting and counts the others, as in `its "permissions" and 1 other value are not valid`.
813* **`it is not a JSON object`**: the file's top level isn't a JSON object, such as a file whose top level is an array.
814
777815<h3 id="a-plugin-you-disabled-still-loads">
778816 `Disabled in ~/.claude/settings.json but still loads`
779817</h3>
from line 875
837875
838876If the stderr shows the plugin's path cut off at a space, the hook's shell-form command uses `${CLAUDE_PLUGIN_ROOT}` outside quotes and the install path contains a space. Wrap the variable in double quotes or use [exec form](/docs/en/hooks#exec-form-and-shell-form). To find the unquoted variable, run `claude plugin validate` on the plugin's directory and look for its [quoting warning](/docs/en/plugins/manifest-reference#quoting-and-path-separators).
839877
878If the notice reads `Failed to run: Plugin directory does not exist: <path>`, see [`Plugin directory does not exist`](#plugin-directory-does-not-exist).
879
840880For any other error, run the hook's command yourself from the plugin directory to see the full output, or capture the full stderr with [debug logging](/docs/en/hooks#debug-hooks).
841881
842882#### A plugin hook blocks a tool call or prompt
from line 907
867907 </Step>
868908</Steps>
869909
910<h3 id="plugin-directory-does-not-exist">
911 `Plugin directory does not exist: <path>`
912</h3>
913
914Run `/reload-plugins` at the Claude Code prompt first, even though the message says to reinstall. A plugin's hook fails with `Failed to run: Plugin directory does not exist: <path> (<plugin> — run /plugin to reinstall)`, and the hook doesn't run, when the directory your session loaded the plugin's hooks from is gone from disk. [`Plugin directory not found at path: <path>`](#plugin-directory-not-found-at-path) is a different message, about a marketplace entry.
915
916The reload loads the plugin's hooks from its current directory. The failure is shown once per session for each hook event and command, so the hook going quiet doesn't confirm the fix. Read the reload's output instead:
917
918* **`Reloaded:` with no errors line**: the plugin's hooks no longer point at the missing directory
919* **`N errors during load. Run /plugin for details.`**: open the **Errors** tab in `/plugin` and follow this page's entry for the message it shows
920* **A line that ends `Run /reload-plugins --force to apply.`**: nothing reloaded, and the hooks keep failing. Run `/reload-plugins --force` at the Claude Code prompt
921
870922<h3 id="invalid-mcp-server-config-for-and-mcp-servers-that-dont-start">
871923 `Invalid MCP server config for "<server>"` and MCP servers that don't start
872924</h3>
from line 1097
10451097
10461098You ran `claude plugin validate <path>`, or `/plugin validate <path>` in a session, and it printed `Found N errors` and `Validation failed`, then exited with code 1.
10471099
1048The validator reads the manifest at the path you give it: `.claude-plugin/plugin.json` for a plugin directory, or `.claude-plugin/marketplace.json` for a marketplace directory. For a marketplace, it prefixes problems in an entry's own manifest with the entry index, as `plugins[1] plugin.json → json: ...`.
1100The validator reads the manifest at the path you give it: `.claude-plugin/plugin.json` for a plugin directory, `.claude-plugin/marketplace.json` for a marketplace directory, or both for a directory that holds both. For a marketplace, it prefixes problems in an entry's own manifest with the entry index, as `plugins[1] plugin.json → json: ...`. Before v2.1.289, Claude Code validated a directory that holds both as a marketplace alone.
10491101
10501102The table covers the messages that stop validation and two warnings, `No frontmatter block found` and `Unknown field '<key>'`, which stop it only when you pass `--strict`. Other warnings, such as a missing description, aren't listed.
10511103
claude-tag Changed · +1 / -1 lines
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
Nothing in the body moved in this read. What changed is above.
errors Changed · +3 / -0 lines
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
from line 255
255255| `Marketplace name impersonates an official Anthropic/Claude marketplace` | [Plugin errors](#claude-code-refuses-the-marketplace-name) |
256256| `Marketplace "<name>" is already added from a different source` | [Plugin errors](#marketplace-is-already-added-from-a-different-source) |
257257| `"<name>" is another spelling of "<reserved>", a reserved marketplace name` | [Plugin errors](#marketplace-name-is-another-spelling-of-a-reserved-name) |
258| `Cannot add marketplace "<name>": Claude Code cannot install plugins from a marketplace with this name` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#cannot-install-plugins-from-a-marketplace-with-this-name) |
258259| `Marketplace "<name>" is added but ignored` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#marketplace-is-added-but-ignored) |
259260| `Marketplace "<name>" is registered but was refused (see the debug log)` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#marketplace-is-added-but-ignored) |
260261| `references ${user_config.*} in a shell-form command` | [Plugin errors](#plugin-command-references-user-config) |
from line 264
263264| `Plugin archive integrity check failed` | [Plugin errors](#plugin-archive-integrity-check-failed) |
264265| `An npm plugin source must name a registry package` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#an-npm-plugin-source-must-name-a-registry-package) |
265266| `The packages it lists are not installed` / `The packages it lists were not installed, because` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#the-packages-it-lists-are-not-installed) |
267| `does not load (...), so Claude Code ignores the whole file` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#does-not-load-so-claude-code-ignores-the-whole-file) |
266268| `path escapes plugin directory` | [Plugin errors](#path-escapes-plugin-directory) |
267269| `path could not be checked` | [Plugin errors](#path-could-not-be-checked) |
268270| `its marketplace entry path does not stay inside the marketplace directory` | [Plugin errors](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory) |
from line 275
273275| `"<plugin>" was not uninstalled: it is still switched on in <file>` | [Plugin errors](#plugin-was-not-uninstalled) |
274276| `"<plugin>" was not uninstalled: <file> is there and could not be read` | [Plugin errors](#plugin-was-not-uninstalled) |
275277| `Plugin "<plugin>" was not uninstalled: installed_plugins.json` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#installed-plugins-json-holds-a-record-this-version-cannot-read) |
278| `Plugin directory does not exist: <path>` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#plugin-directory-does-not-exist) |
276279| `Error: No such tool available: <tool name>` | [Tool errors](#no-such-tool-available) |
277280| `would be spawned with zero tools — refusing` | [Tool errors](#agent-would-be-spawned-with-zero-tools) |
278281| `File is covered by a Read deny rule in your permission settings` | [Tool errors](#file-is-covered-by-a-read-deny-rule) |
from line 2782
27792782
27802783## Command-line errors
27812784
2782These errors come from the `claude` command line and its subcommands, from a command name you submit at the prompt, and from commands such as `/security-review` that gather context by running shell commands before their prompt runs. They also come from `/tui`, which relaunches the CLI.
2783
2784<h3 id="conflict-between-bg-and-print">
2785 Conflict between `--bg` and `--print`
2786</h3>
2787
2788This message requires Claude Code v2.1.198 or later. You combined `--bg` with `-p` or `--print` in the same `claude` invocation. `--bg` starts a [background session](/docs/en/agent-view#from-your-shell) that you later attach to with `claude agents`, while `--print` runs [non-interactively](/docs/en/headless) and never starts th
2785These errors come from the `claude` command line and its subcommands, from a command name you submit at the prompt, and from commands such as `/security-review`
plugins/install Changed · +2 / -0 lines
from line 240
240240
241241The shell command adds the marketplace without a confirmation step. A marketplace you've already added from that source is reused. A new one is added under the same [organization policy checks](/docs/en/plugins/org#restrict-what-users-can-install) as `claude plugin marketplace add`, and is declared in your user settings even when you pass `--scope project`.
242242
243If you haven't added that marketplace yet, the command prints `Successfully added marketplace: <name> (declared in user settings)` and then [installs the plugin](#install-from-your-shell).
244
243245### Add a private marketplace
244246
245247A private marketplace is one in a repository you need credentials to clone, on GitHub or any other git host. You add it with the same `/plugin marketplace add` or `claude plugin marketplace add` command as a public one. Claude Code clones it with the git credentials already on your machine and never prompts, so each way of connecting has a requirement:
plugins/marketplace-reference Changed · +1 / -1 lines
from line 54
5454
5555| Field | Type | Description |
5656| :- | :- | :- |
57| `name` | string | Marketplace identifier: letters, digits, `.`, `_`, and `-`, starting with a letter or digit, and no `..`. `claude plugin validate` fails any other name, because Claude Code can't install plugins from a marketplace that uses one. Users type the name after `@` in a [plugin id](/docs/en/plugins/loading#find-where-a-plugin-came-from) such as `my-plugin@my-marketplace` when they install a plugin. See [Reserved names](#reserved-names) |
57| `name` | string | Marketplace identifier: letters, digits, `.`, `_`, and `-`, starting with a letter or digit, and no `..`. `claude plugin validate` fails any other name, because Claude Code [can't install plugins from a marketplace that uses one](/docs/en/plugins/troubleshooting#cannot-install-plugins-from-a-marketplace-with-this-name). Users type the name after `@` in a [plugin id](/docs/en/plugins/loading#find-where-a-plugin-came-from) such as `my-plugin@my-marketplace` when they install a plugin. See [Reserved names](#reserved-names) |
5858| `owner` | object | Maintainer information. `name` is required; `email` and `url` are optional |
5959| `plugins` | array | [Plugin entries](#plugin-entries). Each entry is validated on its own, so one invalid entry doesn't fail the marketplace |
6060| `$schema` | string | JSON Schema URL for editor autocomplete. Ignored at load time |
plugins/mods/create Changed · +1 / -1 lines
from line 265
265265 Get type definitions for your version
266266</h3>
267267
268Each time Claude Code loads or reloads a mod from a directory you pass to `--plugin-dir`, or a mod [Claude wrote for you](#ask-claude-for-a-mod), it writes TypeScript declaration files, ending in `.d.ts`, into `.claude-plugin/types/` inside the mod's directory. They describe the exact events, mods API methods, and elements in the Claude Code version you're running, so your editor can autocomplete and type-check your hooks. To browse the declarations online, read [`mods/types/claude-code.d.ts`](https://github.com/anthropics/claude-code/blob/main/mods/types/claude-code.d.ts) in the Claude Code repository, whose first line names the version that wrote it. The directory holds these files:
268When Claude Code loads a mod from `--plugin-dir` in an interactive session, or a mod [Claude wrote for you](#ask-claude-for-a-mod), it writes TypeScript declaration files into the mod's `.claude-plugin/types/` directory. They describe the exact events, mods API methods, and elements in the Claude Code version you're running, so your editor can autocomplete and type-check your hooks. The directory holds these files:
269269
270270| Path | What it declares |
271271| :- | :- |
plugins/publish Changed · +1 / -1 lines
from line 94
9494}
9595```
9696
97In your shell, run `claude plugin validate .` in the repository to check the file before you push.
97In your shell, run `claude plugin validate .` in the repository before you push. For what the run checks, see [Validate a directory](/docs/en/plugins/cli-reference#validate-a-directory).
9898
9999[Create a marketplace](/docs/en/plugins/create-marketplace) covers the layout with several plugins in one repository.
100100