diff --git a/content/en/api/kotlin/beta.md b/content/en/api/kotlin/beta.md deleted file mode 100644 index 761bf450c..000000000 --- a/content/en/api/kotlin/beta.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
    \ No newline at end of file diff --git a/content/en/api/kotlin/beta/files.md b/content/en/api/kotlin/beta/files.md deleted file mode 100644 index 0ae699ddc..000000000 --- a/content/en/api/kotlin/beta/files.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
      \ No newline at end of file diff --git a/content/en/api/kotlin/beta/files/delete.md b/content/en/api/kotlin/beta/files/delete.md deleted file mode 100644 index ecbf48406..000000000 --- a/content/en/api/kotlin/beta/files/delete.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
        \ No newline at end of file diff --git a/content/en/api/kotlin/beta/files/download.md b/content/en/api/kotlin/beta/files/download.md deleted file mode 100644 index 563b90c79..000000000 --- a/content/en/api/kotlin/beta/files/download.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
          \ No newline at end of file diff --git a/content/en/api/kotlin/beta/files/list.md b/content/en/api/kotlin/beta/files/list.md deleted file mode 100644 index c83cbdf8c..000000000 --- a/content/en/api/kotlin/beta/files/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
            \ No newline at end of file diff --git a/content/en/api/kotlin/beta/files/retrieve_metadata.md b/content/en/api/kotlin/beta/files/retrieve_metadata.md deleted file mode 100644 index 35797badc..000000000 --- a/content/en/api/kotlin/beta/files/retrieve_metadata.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
              \ No newline at end of file diff --git a/content/en/api/kotlin/beta/files/upload.md b/content/en/api/kotlin/beta/files/upload.md deleted file mode 100644 index 732212a3f..000000000 --- a/content/en/api/kotlin/beta/files/upload.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages.md b/content/en/api/kotlin/beta/messages.md deleted file mode 100644 index 1064ca20b..000000000 --- a/content/en/api/kotlin/beta/messages.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                  \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches.md b/content/en/api/kotlin/beta/messages/batches.md deleted file mode 100644 index e9e622b91..000000000 --- a/content/en/api/kotlin/beta/messages/batches.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                    \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches/cancel.md b/content/en/api/kotlin/beta/messages/batches/cancel.md deleted file mode 100644 index 2e75fd602..000000000 --- a/content/en/api/kotlin/beta/messages/batches/cancel.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                      \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches/create.md b/content/en/api/kotlin/beta/messages/batches/create.md deleted file mode 100644 index c456f1635..000000000 --- a/content/en/api/kotlin/beta/messages/batches/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                        \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches/delete.md b/content/en/api/kotlin/beta/messages/batches/delete.md deleted file mode 100644 index 798c3db85..000000000 --- a/content/en/api/kotlin/beta/messages/batches/delete.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                          \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches/list.md b/content/en/api/kotlin/beta/messages/batches/list.md deleted file mode 100644 index 400f7f88d..000000000 --- a/content/en/api/kotlin/beta/messages/batches/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                            \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches/results.md b/content/en/api/kotlin/beta/messages/batches/results.md deleted file mode 100644 index 93d452262..000000000 --- a/content/en/api/kotlin/beta/messages/batches/results.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                              \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/batches/retrieve.md b/content/en/api/kotlin/beta/messages/batches/retrieve.md deleted file mode 100644 index 6c7369943..000000000 --- a/content/en/api/kotlin/beta/messages/batches/retrieve.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/count_tokens.md b/content/en/api/kotlin/beta/messages/count_tokens.md deleted file mode 100644 index f10b76ac2..000000000 --- a/content/en/api/kotlin/beta/messages/count_tokens.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                  \ No newline at end of file diff --git a/content/en/api/kotlin/beta/messages/create.md b/content/en/api/kotlin/beta/messages/create.md deleted file mode 100644 index 1d72010e2..000000000 --- a/content/en/api/kotlin/beta/messages/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                    \ No newline at end of file diff --git a/content/en/api/kotlin/beta/models.md b/content/en/api/kotlin/beta/models.md deleted file mode 100644 index 0220d407a..000000000 --- a/content/en/api/kotlin/beta/models.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                      \ No newline at end of file diff --git a/content/en/api/kotlin/beta/models/list.md b/content/en/api/kotlin/beta/models/list.md deleted file mode 100644 index 1a67d7329..000000000 --- a/content/en/api/kotlin/beta/models/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                        \ No newline at end of file diff --git a/content/en/api/kotlin/beta/models/retrieve.md b/content/en/api/kotlin/beta/models/retrieve.md deleted file mode 100644 index c6e9fa7ae..000000000 --- a/content/en/api/kotlin/beta/models/retrieve.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                          \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills.md b/content/en/api/kotlin/beta/skills.md deleted file mode 100644 index 1dfa11e0d..000000000 --- a/content/en/api/kotlin/beta/skills.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                            \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/create.md b/content/en/api/kotlin/beta/skills/create.md deleted file mode 100644 index c17982ab2..000000000 --- a/content/en/api/kotlin/beta/skills/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                              \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/delete.md b/content/en/api/kotlin/beta/skills/delete.md deleted file mode 100644 index e56c5fe36..000000000 --- a/content/en/api/kotlin/beta/skills/delete.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/list.md b/content/en/api/kotlin/beta/skills/list.md deleted file mode 100644 index ff0f154c6..000000000 --- a/content/en/api/kotlin/beta/skills/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                  \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/retrieve.md b/content/en/api/kotlin/beta/skills/retrieve.md deleted file mode 100644 index 70031eade..000000000 --- a/content/en/api/kotlin/beta/skills/retrieve.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                    \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/versions.md b/content/en/api/kotlin/beta/skills/versions.md deleted file mode 100644 index 43b55e2f2..000000000 --- a/content/en/api/kotlin/beta/skills/versions.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                      \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/versions/create.md b/content/en/api/kotlin/beta/skills/versions/create.md deleted file mode 100644 index b88fd9e78..000000000 --- a/content/en/api/kotlin/beta/skills/versions/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                        \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/versions/delete.md b/content/en/api/kotlin/beta/skills/versions/delete.md deleted file mode 100644 index e185c7dbe..000000000 --- a/content/en/api/kotlin/beta/skills/versions/delete.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                          \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/versions/list.md b/content/en/api/kotlin/beta/skills/versions/list.md deleted file mode 100644 index bd59984e1..000000000 --- a/content/en/api/kotlin/beta/skills/versions/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                            \ No newline at end of file diff --git a/content/en/api/kotlin/beta/skills/versions/retrieve.md b/content/en/api/kotlin/beta/skills/versions/retrieve.md deleted file mode 100644 index 8cd72bf14..000000000 --- a/content/en/api/kotlin/beta/skills/versions/retrieve.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                              \ No newline at end of file diff --git a/content/en/api/kotlin/completions.md b/content/en/api/kotlin/completions.md deleted file mode 100644 index 572d2629f..000000000 --- a/content/en/api/kotlin/completions.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                \ No newline at end of file diff --git a/content/en/api/kotlin/completions/create.md b/content/en/api/kotlin/completions/create.md deleted file mode 100644 index b69e4bbb9..000000000 --- a/content/en/api/kotlin/completions/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                  \ No newline at end of file diff --git a/content/en/api/kotlin/messages.md b/content/en/api/kotlin/messages.md deleted file mode 100644 index 364f7b19b..000000000 --- a/content/en/api/kotlin/messages.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                    \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches.md b/content/en/api/kotlin/messages/batches.md deleted file mode 100644 index 3b8bce08a..000000000 --- a/content/en/api/kotlin/messages/batches.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                      \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches/cancel.md b/content/en/api/kotlin/messages/batches/cancel.md deleted file mode 100644 index d1e770135..000000000 --- a/content/en/api/kotlin/messages/batches/cancel.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                        \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches/create.md b/content/en/api/kotlin/messages/batches/create.md deleted file mode 100644 index ca7051415..000000000 --- a/content/en/api/kotlin/messages/batches/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                          \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches/delete.md b/content/en/api/kotlin/messages/batches/delete.md deleted file mode 100644 index 58a32fdb4..000000000 --- a/content/en/api/kotlin/messages/batches/delete.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                            \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches/list.md b/content/en/api/kotlin/messages/batches/list.md deleted file mode 100644 index 00c96123b..000000000 --- a/content/en/api/kotlin/messages/batches/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                              \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches/results.md b/content/en/api/kotlin/messages/batches/results.md deleted file mode 100644 index 1929493fc..000000000 --- a/content/en/api/kotlin/messages/batches/results.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                \ No newline at end of file diff --git a/content/en/api/kotlin/messages/batches/retrieve.md b/content/en/api/kotlin/messages/batches/retrieve.md deleted file mode 100644 index 40ade9bba..000000000 --- a/content/en/api/kotlin/messages/batches/retrieve.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                  \ No newline at end of file diff --git a/content/en/api/kotlin/messages/count_tokens.md b/content/en/api/kotlin/messages/count_tokens.md deleted file mode 100644 index 58e0b6144..000000000 --- a/content/en/api/kotlin/messages/count_tokens.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                    \ No newline at end of file diff --git a/content/en/api/kotlin/messages/create.md b/content/en/api/kotlin/messages/create.md deleted file mode 100644 index a379a3808..000000000 --- a/content/en/api/kotlin/messages/create.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                      \ No newline at end of file diff --git a/content/en/api/kotlin/models.md b/content/en/api/kotlin/models.md deleted file mode 100644 index a221cd841..000000000 --- a/content/en/api/kotlin/models.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                        \ No newline at end of file diff --git a/content/en/api/kotlin/models/list.md b/content/en/api/kotlin/models/list.md deleted file mode 100644 index 65cedb575..000000000 --- a/content/en/api/kotlin/models/list.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                          \ No newline at end of file diff --git a/content/en/api/kotlin/models/retrieve.md b/content/en/api/kotlin/models/retrieve.md deleted file mode 100644 index f948cf307..000000000 --- a/content/en/api/kotlin/models/retrieve.md +++ /dev/null @@ -1 +0,0 @@ -Not Found - Claude API Docs
                                                                                            \ No newline at end of file diff --git a/content/en/docs/claude-code/skills.md b/content/en/docs/claude-code/skills.md deleted file mode 100644 index 0e4c50379..000000000 --- a/content/en/docs/claude-code/skills.md +++ /dev/null @@ -1,938 +0,0 @@ -> ## Documentation Index -> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt -> Use this file to discover all available pages before exploring further. - -# Extend Claude with skills - -> Create, manage, and share skills to extend Claude's capabilities in Claude Code. Includes custom commands and bundled skills. - -Skills extend what Claude can do. Create a `SKILL.md` file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you can invoke one directly with `/skill-name`. - -Create a skill when you keep pasting the same instructions, checklist, or multi-step procedure into chat, or when a section of CLAUDE.md has grown into a procedure rather than a fact. Unlike CLAUDE.md content, a skill's body loads only when it's used, so long reference material costs almost nothing until you need it. - - - For built-in commands like `/help` and `/compact`, and bundled skills like `/debug` and `/code-review`, see the [commands reference](/docs/en/commands). - - **Custom commands have been merged into skills.** A file at `.claude/commands/deploy.md` and a skill at `.claude/skills/deploy/SKILL.md` both create `/deploy` and work the same way. Your existing `.claude/commands/` files keep working. Skills add optional features: a directory for supporting files, frontmatter to [control whether you or Claude invokes them](#control-who-invokes-a-skill), and the ability for Claude to load them automatically when relevant. - - -Claude Code skills follow the [Agent Skills](https://agentskills.io) open standard, which works across multiple AI tools. Claude Code extends the standard with additional features like [invocation control](#control-who-invokes-a-skill), [subagent execution](#run-skills-in-a-subagent), and [dynamic context injection](#inject-dynamic-context). - -## Bundled skills - -Claude Code includes a set of bundled skills, such as `/doctor`, `/code-review`, `/batch`, `/debug`, `/loop`, and `/claude-api`. Bundled skills are prompt-based: they give Claude detailed instructions and let it orchestrate the work using its tools. Most built-in commands instead execute fixed logic directly. - -You invoke a bundled skill the same way as any other skill, by typing `/` followed by the skill name. Claude invokes some bundled skills automatically when relevant; others, including `/verify` and `/code-review`, run only when you invoke them, which keeps you in control of when these longer-running checks spend time and tokens. Before v2.1.215, Claude could also run `/verify` and `/code-review` on its own. - -Bundled skills are available in every session. To turn them off, use the [`disableBundledSkills`](/docs/en/settings#available-settings) setting, which disables every bundled skill except `/doctor`. - - - The [`/doctor`](/docs/en/commands#all-commands) setup checkup stays typable when `disableBundledSkills` is on, in Claude Code v2.1.205 and later. To hide it, set the `DISABLE_DOCTOR_COMMAND` environment variable or a [`skillOverrides`](#override-skill-visibility-from-settings) entry of `"doctor": "off"`. Before v2.1.205, `/doctor` was a built-in command rather than a bundled skill. - - -Bundled skills are listed alongside built-in commands in the [commands reference](/docs/en/commands), marked **Skill** in the Purpose column. - -### Run and verify your app - -Three bundled skills work together to launch your app and confirm changes against the running app instead of just tests: - -| Skill | Purpose | -| :--------------------- | :---------------------------------------------------------------------------------------------------------------- | -| `/run` | Launch and drive your app to see a change working | -| `/verify` | Build and run your app to confirm a code change does what it should, without falling back to tests or type checks | -| `/run-skill-generator` | Teach `/run` and `/verify` how to build and launch your project | - -All three skills require Claude Code v2.1.145 or later. Check your version with `claude --version` or the `/status` command. - -`/run` and `/verify` work without setup. They infer the launch from your project type (CLI, server, TUI, browser-driven) and from what's in your README, `package.json`, or `Makefile`. That inference gets unreliable for projects that need anything beyond a standard launch: a database, an env file, a graphical session, a multi-step build. - -`/run-skill-generator` records the recipe instead. It gets your app running from a clean environment, captures what worked (the install commands, the env vars, the launch script), and commits it as a per-project skill at `.claude/skills/run-/`. After that, `/run`, `/verify`, and any other agent in the repo follow the recorded recipe instead of rediscovering it. Run `/run-skill-generator` once per project, and again if the build or launch process changes. - -`/verify` can also record its own recipe. When it has to build and drive your app without a recorded recipe, it writes what worked to `.claude/skills/verify/SKILL.md` at the repo root, or in the touched package directory in a monorepo, so later runs and other agents follow the same steps. At the repo root, the recorded skill replaces the bundled `/verify`. This requires Claude Code v2.1.200 or later. - -Claude edits the recorded file only when it steered a run wrong, such as a command that failed or a missing step, so you can commit the file without per-session diffs. Before v2.1.205, the bundled skill told Claude to fold in anything a run learned, which caused frequent merge conflicts. - -## Getting started - -### Create your first skill - -This example creates a skill that summarizes the uncommitted changes in your git repository and flags anything risky. It pulls the live diff into the prompt before Claude reads it, so the response is grounded in your actual working tree rather than what Claude can guess from open files. Claude loads the skill automatically when you ask about your changes, or you can invoke it directly with `/summarize-changes`. - - - - Create a directory for the skill in your personal skills folder. Personal skills are available across all your projects. - - ```bash theme={null} - mkdir -p ~/.claude/skills/summarize-changes - ``` - - - - Every skill needs a `SKILL.md` file with two parts: YAML frontmatter between `---` markers that tells Claude when to use the skill, and markdown content with the instructions Claude follows when the skill runs. The directory name becomes the command you type, and the `description` helps Claude decide when to load the skill automatically. - - Save this to `~/.claude/skills/summarize-changes/SKILL.md`: - - ```yaml theme={null} - --- - description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff. - --- - - ## Current changes - - !`git diff HEAD` - - ## Instructions - - Summarize the changes above in two or three bullet points, then list any risks you notice such as missing error handling, hardcoded values, or tests that need updating. If the diff is empty, say there are no uncommitted changes. - ``` - - The `` !`git diff HEAD` `` line uses [dynamic context injection](#inject-dynamic-context): Claude Code runs the command and replaces the line with its output before Claude sees the skill content, so the instructions arrive with the current diff already inlined. - - - - Open a git project, make a small edit to any file, and start Claude Code by running `claude`. You can test the skill two ways. - - **Let Claude invoke it automatically** by asking something that matches the description: - - ```text theme={null} - What did I change? - ``` - - **Or invoke it directly** with the skill name: - - ```text theme={null} - /summarize-changes - ``` - - Either way, Claude should respond with a short summary of your edit and a list of risks. - - - -### Where skills live - -Where you store a skill determines who can use it: - -| Location | Path | Applies to | -| :--------- | :-------------------------------------------------- | :----------------------------- | -| Enterprise | See [managed settings](/docs/en/settings#settings-files) | All users in your organization | -| Personal | `~/.claude/skills//SKILL.md` | All your projects | -| Project | `.claude/skills//SKILL.md` | This project only | -| Plugin | `/skills//SKILL.md` | Where plugin is enabled | - -When skills share the same name across levels, enterprise overrides personal, and personal overrides project. A skill at any of these levels also overrides a bundled skill with the same name. For example, a `code-review` skill in your project's `.claude/skills/` replaces the bundled `/code-review`. Plugin skills use a `plugin-name:skill-name` namespace, so they cannot conflict with other levels. If you have files in `.claude/commands/`, those work the same way, but if a skill and a command share the same name, the skill takes precedence. - -Skills also load from nested `.claude/skills/` directories below your working directory. When Claude reads or edits a file in a subdirectory, skills from that subdirectory's `.claude/skills/` become available. This lets a monorepo package provide its own skills that apply when working on that package, even if the session started at the repo root. - -If a nested skill shares a name with another skill, both stay available. For example, with a `deploy` skill at the project root and another in `apps/web/.claude/skills/`: - -* The nested one appears under a directory-qualified name, `apps/web:deploy`. -* Its description says which directory it applies to. -* Claude picks the variant that matches the files it is working on. - -Typing `/deploy` runs the project-root skill. Type the qualified name `/apps/web:deploy` to run the nested variant explicitly. - -When you or Claude invoke the unqualified name, the project-root skill loads, and Claude Code appends a list of the directory-qualified variants to its content with an instruction to also invoke any variant whose directory holds the files Claude is working on. A nested skill therefore still applies to work in its directory when only the unqualified name is invoked. Requires Claude Code v2.1.203 or later. - -A `` entry in the enterprise, personal, or project locations can be a symlink to a directory elsewhere on disk. Claude Code follows the symlink and reads `SKILL.md` from the target directory, and if the same target is reachable from more than one location, Claude Code loads the skill once. Plugin skills handle symlinks differently; see [Share files within a marketplace with symlinks](/docs/en/plugins-reference#share-files-within-a-marketplace-with-symlinks). - - - Add a `.claude-plugin/plugin.json` to a skill folder and it loads as a [plugin](/docs/en/plugins-reference#skills-directory-plugins) named `@skills-dir`, so it can bundle agents, hooks, and MCP servers. In a project's `.claude/skills/`, this requires accepting the workspace trust dialog first. - - -#### Live change detection - -Claude Code watches skill directories for file changes. When you add, edit, or remove a skill under `~/.claude/skills/`, the project `.claude/skills/`, or a `.claude/skills/` inside an `--add-dir` directory, Claude Code picks up the change within the current session, without a restart. If you create a top-level skills directory that didn't exist when the session started, restart Claude Code so it can watch the new directory. - - - Live change detection covers `SKILL.md` text only. For a skill folder that is also a [plugin](/docs/en/plugins-reference#skills-directory-plugins), changes to `hooks/`, `.mcp.json`, `agents/`, and `output-styles/` need `/reload-plugins` to take effect. - - -#### Discovery from parent and nested directories - -Project skills load from `.claude/skills/` in the directory where you start Claude Code and in every parent directory up to the repository root. Starting Claude in a subdirectory still picks up skills defined at the root. To load skills from a directory outside that path at startup, pass it with [`--add-dir`](/docs/en/cli-reference). Claude Code reads `.claude/skills/` inside each added directory alongside the project skills. - -Skills in nested `.claude/skills/` directories below your starting directory aren't loaded at startup. They load the first time Claude reads or edits a file inside that subdirectory, and stay available for the rest of the session. For example, after Claude edits a file under `packages/frontend/`, skills in `packages/frontend/.claude/skills/` become available. Until then, those skills don't appear in autocomplete and can't be invoked by name. - -Each skill is a directory with `SKILL.md` as the entrypoint: - -```text theme={null} -my-skill/ -├── SKILL.md # Main instructions (required) -├── template.md # Template for Claude to fill in -├── examples/ -│ └── sample.md # Example output showing expected format -└── scripts/ - └── validate.sh # Script Claude can execute -``` - -The `SKILL.md` contains the main instructions and is required. Other files are optional and let you build more powerful skills: templates for Claude to fill in, example outputs showing the expected format, scripts Claude can execute, or detailed reference documentation. Reference these files from your `SKILL.md` so Claude knows what they contain and when to load them. See [Add supporting files](#add-supporting-files) for more details. - - - Files in `.claude/commands/` still work and support the same [frontmatter](#frontmatter-reference). Skills are recommended since they support additional features like supporting files. - - -#### Skills from additional directories - -The `--add-dir` flag and `/add-dir` command [grant file access](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) rather than configuration discovery, but skills are an exception: `.claude/skills/` within an added directory is loaded automatically. This exception applies only to `--add-dir` and `/add-dir`. The `permissions.additionalDirectories` setting in `settings.json` grants file access only and does not load skills. See [Live change detection](#live-change-detection) for how edits are picked up during a session. - -Other `.claude/` configuration such as commands and output styles is not loaded from additional directories. See the [exceptions table](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) for the complete list of what is and isn't loaded, and the recommended ways to share configuration across projects. - - - CLAUDE.md files from `--add-dir` directories are not loaded by default. To load them, set `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1`. See [Load from additional directories](/docs/en/memory#load-from-additional-directories). - - -#### Skills in Cowork and cloud sessions - -[Cowork](https://claude.com/product/cowork) sessions and [cloud sessions](/docs/en/cloud-environments#what-carries-over-from-your-setup), including [routines](/docs/en/routines), don't read `~/.claude/skills/` on your machine. Both interactive and scheduled Cowork sessions load the skills enabled for your claude.ai account, synced at session start; manage them from **Customize** in the Desktop app sidebar or from the skills settings on claude.ai. Cloud sessions additionally load project skills committed to the cloned repository's `.claude/skills/`. - -If a skill exists only in `~/.claude/skills/` on your machine, Claude Code reports that the skill was not found when a [routine](/docs/en/routines) invokes it, because each routine run starts as a fresh remote session. To make a personal skill available in these sessions: - -* For Cowork and cloud sessions, enable the skill for your claude.ai account. -* For cloud sessions, you can instead commit the skill to the repository's `.claude/skills/`, or ship it in a plugin declared in the repository's `.claude/settings.json`. Repo-declared plugins [install at session start](/docs/en/cloud-environments#what-carries-over-from-your-setup); plugins enabled only in your user settings don't transfer. - -[Desktop scheduled tasks](/docs/en/desktop-scheduled-tasks) are different: they run locally on your machine and load skills from the same locations as any other local session. - -## Configure skills - -Skills are configured through YAML frontmatter at the top of `SKILL.md` and the markdown content that follows. - -### Types of skill content - -Skill files can contain any instructions, but thinking about how you want to invoke them helps guide what to include: - -**Reference content** adds knowledge Claude applies to your current work. Conventions, patterns, style guides, domain knowledge. This content runs inline so Claude can use it alongside your conversation context. - -```yaml theme={null} ---- -name: api-conventions -description: API design patterns for this codebase ---- - -When writing API endpoints: -- Use RESTful naming conventions -- Return consistent error formats -- Include request validation -``` - -**Task content** gives Claude step-by-step instructions for a specific action, like deployments, commits, or code generation. These are often actions you want to invoke directly with `/skill-name` rather than letting Claude decide when to run them. Add `disable-model-invocation: true` to prevent Claude from triggering it automatically. The example below adds `context: fork`, which runs the skill in its own subagent context; see [Run skills in a subagent](#run-skills-in-a-subagent). - -```yaml theme={null} ---- -name: deploy -description: Deploy the application to production -context: fork -disable-model-invocation: true ---- - -Deploy the application: -1. Run the test suite -2. Build the application -3. Push to the deployment target -``` - -Your `SKILL.md` can contain anything, but thinking through how you want the skill invoked (by you, by Claude, or both) and where you want it to run (inline or in a subagent) helps guide what to include. For complex skills, you can also [add supporting files](#add-supporting-files) to keep the main skill focused. - -Keep the body itself concise. Once a skill loads, its content [stays in context across turns](#skill-content-lifecycle), so every line is a recurring token cost. State what to do rather than narrating how or why, and apply the same conciseness test you would for [CLAUDE.md content](/docs/en/best-practices#write-an-effective-claude-md). - -### Frontmatter reference - -Beyond the markdown content, you can configure skill behavior using YAML frontmatter fields between `---` markers at the top of your `SKILL.md` file: - -```yaml theme={null} ---- -name: my-skill -description: What this skill does -disable-model-invocation: true -allowed-tools: Read Grep ---- - -Your skill instructions here... -``` - -All fields are optional. Only `description` is recommended so Claude knows when to use the skill. - -Boolean fields accept `yes`, `no`, `on`, `off`, `1`, and `0` in any letter case, in addition to `true` and `false`. Before v2.1.218, Claude Code recognized only `true` and `false`. - -| Field | Required | Description | -| :------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `name` | No | Display name shown in skill listings. Defaults to the directory name. See [How a skill gets its command name](#how-a-skill-gets-its-command-name) for how the field interacts with the name you type to invoke the skill. | -| `description` | Recommended | What the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first paragraph of markdown content. Put the key use case first: the combined `description` and `when_to_use` text is truncated at 1,536 characters in the skill listing to reduce context usage. | -| `when_to_use` | No | Additional context for when Claude should invoke the skill, such as trigger phrases or example requests. Appended to `description` in the skill listing and counts toward the 1,536-character cap. | -| `argument-hint` | No | Hint shown during autocomplete to indicate expected arguments. Example: `[issue-number]` or `[filename] [format]`. | -| `arguments` | No | Named positional arguments for [`$name` substitution](#available-string-substitutions) in the skill content. Accepts a space-separated string or a YAML list. Names map to argument positions in order. | -| `disable-model-invocation` | No | Set to `true` to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with `/name`. Also prevents the skill from being [preloaded into subagents](/docs/en/sub-agents#preload-skills-into-subagents). As of v2.1.196, also prevents the skill from running when a [scheduled task](/docs/en/scheduled-tasks) fires with the skill as its prompt. Default: `false`. | -| `user-invocable` | No | Set to `false` to hide from the `/` menu. Use for background knowledge users shouldn't invoke directly. Default: `true`. | -| `allowed-tools` | No | Tools Claude can use without asking permission during the turn that invokes this skill. The grant clears when you send your next message. Accepts a space- or comma-separated string, or a YAML list. See [Pre-approve tools for a skill](#pre-approve-tools-for-a-skill). | -| `disallowed-tools` | No | Tools removed from Claude's available pool while this skill is active. Use for autonomous skills that should never call certain tools, such as `AskUserQuestion` for a background loop. Accepts a space- or comma-separated string, or a YAML list. The restriction clears when you send your next message. Like deny rules, the field can't remove [`EndConversation`](/docs/en/tools-reference#endconversation-tool-behavior) while any other tool remains. | -| `model` | No | Model to use when this skill is active. The override applies for the rest of the current turn and is not saved to settings; the session model resumes on your next prompt. Accepts the same values as [`/model`](/docs/en/model-config), or `inherit` to keep the active model. A value excluded by your organization's [`availableModels`](/docs/en/model-config#restrict-model-selection) allowlist is not used and the session keeps its current model. | -| `effort` | No | [Effort level](/docs/en/model-config#adjust-effort-level) when this skill is active. Overrides the session effort level. Default: inherits from session. Options: `low`, `medium`, `high`, `xhigh`, `max`; available levels depend on the model. | -| `context` | No | Set to `fork` to run in a forked subagent context. See [Run skills in a subagent](#run-skills-in-a-subagent). | -| `agent` | No | Which subagent type to use when `context: fork` is set. | -| `background` | No | Only applies with `context: fork`. Set to `false` to wait for the forked subagent's result in the turn that invoked the skill, instead of [running it in the background](#run-skills-in-a-subagent). Default: `true`. Requires Claude Code v2.1.218 or later. | -| `hooks` | No | Hooks scoped to this skill's lifecycle. See [Hooks in skills and agents](/docs/en/hooks#hooks-in-skills-and-agents) for configuration format. | -| `paths` | No | Glob patterns that limit when this skill is activated. Accepts a comma-separated string or a YAML list. When set, Claude loads the skill automatically only when working with files matching the patterns. Uses the same format as [path-specific rules](/docs/en/memory#path-specific-rules). | -| `shell` | No | Shell to use for `` !`command` `` and ` ```! ` blocks in this skill. Accepts `bash` (default) or `powershell`. Setting `powershell` runs inline shell commands via PowerShell when the [PowerShell tool](/en/tools-reference#powershell-tool) is enabled: it's on by default on Windows without Git Bash, and `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` enables it elsewhere. | - -#### How a skill gets its command name - -The command you type to invoke a skill comes from where the skill file lives and, for plugin skills, also from the frontmatter `name` field. In a personal or project skill, `name` sets only the display label shown in skill listings, and the command still comes from the directory or file name. In a plugin skill, `name` sets the last segment of the command and the plugin prefix stays in place. - -The table below shows where the command name comes from for each layout: - -| Skill location | Command name source | Example | -| :------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | -| Skill directory under `~/.claude/skills/` or `.claude/skills/` | Directory name | `.claude/skills/deploy-staging/SKILL.md` → `/deploy-staging` | -| [Nested](#where-skills-live) `.claude/skills/` directory, when the name clashes with another skill | Subdirectory path relative to the working directory, then the skill directory name | `apps/web/.claude/skills/deploy/SKILL.md` → `/apps/web:deploy` | -| File under `.claude/commands/` | File name without extension | `.claude/commands/deploy.md` → `/deploy` | -| Plugin `skills/` subdirectory | Frontmatter `name` or the directory name, namespaced by plugin | `my-plugin/skills/review/SKILL.md` → `/my-plugin:review`, or `/my-plugin:fancy` with `name: fancy` | -| Plugin root `SKILL.md` | Frontmatter `name`, with the plugin directory name as a fallback | `my-plugin/SKILL.md` with `name: review` → `/my-plugin:review`. See [Path behavior rules](/docs/en/plugins-reference#path-behavior-rules) | - -In a plugin skill, the frontmatter `name` replaces the directory name in the last segment of the command, so `my-plugin/skills/review/SKILL.md` with `name: fancy` becomes `/my-plugin:fancy`. The bare `/fancy` also invokes the skill unless another command already uses that name. Before v2.1.216, the frontmatter name replaced the whole command name, so the menu showed `/fancy` without the plugin prefix and `/my-plugin:fancy` didn't autocomplete. - -In [non-interactive sessions](/docs/en/headless), Claude Code doesn't reserve the names `help` and `feedback` for their terminal-only built-in commands, so a plugin skill with one of those names keeps its bare command there. Claude Code still reserves the name of every other terminal-only built-in, such as `/login`, even though the command can't run in those sessions. From v2.1.216 through v2.1.220, `help` and `feedback` were reserved too, so a plugin skill with one of those names was invocable only by its namespaced command in non-interactive sessions. - -For a plugin-root `SKILL.md`, there is no skill directory to take the name from, so `name` supplies the whole final segment. Without a `name` field, Claude Code falls back to the plugin's directory name. - -#### Available string substitutions - -Skills support string substitution for dynamic values in the skill content: - -| Variable | Description | -| :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `$ARGUMENTS` | All arguments passed when invoking the skill. If `$ARGUMENTS` is not present in the content, arguments are appended as `ARGUMENTS: `. | -| `$ARGUMENTS[N]` | Access a specific argument by 0-based index, such as `$ARGUMENTS[0]` for the first argument. | -| `$N` | Shorthand for `$ARGUMENTS[N]`, such as `$0` for the first argument or `$1` for the second. | -| `$name` | Named argument declared in the [`arguments`](#frontmatter-reference) frontmatter list. Names map to positions in order, so with `arguments: [issue, branch]` the placeholder `$issue` expands to the first argument and `$branch` to the second. | -| `${CLAUDE_SESSION_ID}` | The current session ID. Useful for logging, creating session-specific files, or correlating skill output with sessions. | -| `${CLAUDE_EFFORT}` | The current effort level: `low`, `medium`, `high`, `xhigh`, or `max`. Ultracode is not a distinct level and reports as `xhigh`. Use this to adapt skill instructions to the active effort setting. | -| `${CLAUDE_SKILL_DIR}` | The directory containing the skill's `SKILL.md` file. For plugin skills, this is the skill's subdirectory within the plugin, not the plugin root. Use this in bash injection commands to reference scripts or files bundled with the skill, regardless of the current working directory. | -| `${CLAUDE_PROJECT_DIR}` | The project root directory. This is the same path [hooks](/docs/en/hooks#reference-scripts-by-path) and MCP servers receive as `CLAUDE_PROJECT_DIR`. Use this to reference project-local scripts or files, such as `${CLAUDE_PROJECT_DIR}/.claude/hooks/helper.sh`, independent of where the skill is installed. | - -Claude Code substitutes `${CLAUDE_SKILL_DIR}` and `${CLAUDE_PROJECT_DIR}` in two places: the skill's markdown content, and Bash rules in the [`allowed-tools`](#frontmatter-reference) frontmatter. Using the same variable in both places lets a skill run a bundled script without a permission prompt. The following skill shows the pattern: - -```yaml theme={null} ---- -name: render-chart -description: Render a chart from a CSV file -allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *) ---- - -Run `${CLAUDE_SKILL_DIR}/scripts/render.sh ` to render the chart. -``` - -If this skill is installed at `~/.claude/skills/render-chart/`, both occurrences of `${CLAUDE_SKILL_DIR}` expand to that directory. The `allowed-tools` rule then matches the exact command the skill body tells Claude to run, so the script runs without prompting. - -The `allowed-tools` substitution for `${CLAUDE_SKILL_DIR}` requires Claude Code v2.1.129 or later. On earlier versions the rule stays a literal `${CLAUDE_SKILL_DIR}` string and never matches, so the command still prompts for permission. - -The `${CLAUDE_PROJECT_DIR}` substitution requires Claude Code v2.1.196 or later. - -Indexed arguments use shell-style quoting, so wrap multi-word values in quotes to pass them as a single argument. For example, `/my-skill "hello world" second` makes `$0` expand to `hello world` and `$1` to `second`. The `$ARGUMENTS` placeholder always expands to the full argument string as typed. - -An indexed placeholder with no corresponding argument, such as `$2` when only one argument was passed, stays in the content unchanged. A named placeholder from the [`arguments`](#frontmatter-reference) frontmatter with no matching argument expands to an empty string. - -To include a literal `$` before a digit, `ARGUMENTS`, or a declared argument name, such as `$1.00` in prose, escape it with a backslash: `\$1.00`. A backslash before any other `$` is left unchanged. Only a single backslash directly before the token escapes it. A doubled backslash such as `\\$1` leaves both backslashes in place, and `$1` still expands to the argument value. - -**Example using substitutions:** - -```yaml theme={null} ---- -name: session-logger -description: Log activity for this session ---- - -Log the following to logs/${CLAUDE_SESSION_ID}.log: - -$ARGUMENTS -``` - -### Add supporting files - -Skills can include multiple files in their directory. This keeps `SKILL.md` focused on the essentials while letting Claude access detailed reference material only when needed. Large reference docs, API specifications, or example collections don't need to load into context every time the skill runs. - -```text theme={null} -my-skill/ -├── SKILL.md (required - overview and navigation) -├── reference.md (detailed API docs - loaded when needed) -├── examples.md (usage examples - loaded when needed) -└── scripts/ - └── helper.py (utility script - executed, not loaded) -``` - -Reference supporting files from `SKILL.md` so Claude knows what each file contains and when to load it: - -```markdown theme={null} -## Additional resources - -- For complete API details, see [reference.md](reference.md) -- For usage examples, see [examples.md](examples.md) -``` - -Keep `SKILL.md` under 500 lines. Move detailed reference material to separate files. - -### Control who invokes a skill - -By default, both you and Claude can invoke any skill. You can type `/skill-name` to invoke it directly, and Claude can load it automatically when relevant to your conversation. Two frontmatter fields let you restrict this: - -* **`disable-model-invocation: true`**: Only you can invoke the skill. Use this for workflows with side effects or that you want to control timing, like `/commit`, `/deploy`, or `/send-slack-message`. You don't want Claude deciding to deploy because your code looks ready. - -* **`user-invocable: false`**: Only Claude can invoke the skill. Use this for background knowledge that isn't actionable as a command. A `legacy-system-context` skill explains how an old system works. Claude should know this when relevant, but `/legacy-system-context` isn't a meaningful action for users to take. - -This example creates a deploy skill that only you can trigger. If you set `disable-model-invocation: true`, Claude can't run the skill automatically: - -```yaml theme={null} ---- -name: deploy -description: Deploy the application to production -disable-model-invocation: true ---- - -Deploy $ARGUMENTS to production: - -1. Run the test suite -2. Build the application -3. Push to the deployment target -4. Verify the deployment succeeded -``` - -Here's how the two fields affect invocation and context loading: - -| Frontmatter | You can invoke | Claude can invoke | When loaded into context | -| :------------------------------- | :------------- | :---------------- | :----------------------------------------------------------- | -| (default) | Yes | Yes | Description always in context, full skill loads when invoked | -| `disable-model-invocation: true` | Yes | No | Description not in context, full skill loads when you invoke | -| `user-invocable: false` | No | Yes | Description always in context, full skill loads when invoked | - - - In a regular session, skill descriptions are loaded into context so Claude knows what's available, but full skill content only loads when invoked. [Subagents with preloaded skills](/docs/en/sub-agents#preload-skills-into-subagents) work differently: the full skill content is injected at startup. - - -### Skill content lifecycle - -When you or Claude invoke a skill, the rendered `SKILL.md` content enters the conversation as a single message and stays there for the rest of the session. This persistence applies to the skill's instructions, not its permissions: an [`allowed-tools`](#pre-approve-tools-for-a-skill) grant clears when you send your next message. Claude Code does not re-read the skill file on later turns, so write guidance that should apply throughout a task as standing instructions rather than one-time steps. - -When Claude re-invokes a skill whose rendered content is identical to the copy already in context, Claude Code adds a short note that the skill is already loaded rather than a second copy of the content. When the rendered content differs, because the arguments changed or a [dynamic context](#inject-dynamic-context) command produced new output, Claude Code appends the full content again. Before v2.1.202, every re-invocation appended another full copy of the skill's instructions. - -[Auto-compaction](/docs/en/how-claude-code-works#when-context-fills-up) carries invoked skills forward within a token budget. When the conversation is summarized to free context, Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each. Re-attached skills share a combined budget of 25,000 tokens. Claude Code fills this budget starting from the most recently invoked skill, so older skills can be dropped entirely after compaction if you have invoked many in one session. - -If a skill seems to stop influencing behavior after the first response, the content is usually still present and the model is choosing other tools or approaches. Strengthen the skill's `description` and instructions so the model keeps preferring it, or use [hooks](/docs/en/hooks) to enforce behavior deterministically. If the skill is large or you invoked several others after it, re-invoke it after compaction to restore the full content. - -### Pre-approve tools for a skill - -The `allowed-tools` field grants permission for the listed tools during the turn that invokes the skill, so Claude can use them without prompting you for approval. The grant clears when you send your next message, even though the skill content [stays in context](#skill-content-lifecycle); invoking the skill again re-applies it for that turn. It does not restrict which tools are available: every tool remains callable, and your [permission settings](/docs/en/permissions) still govern tools that are not listed. To pre-approve tools for the whole session rather than a single turn, add allow rules to those permission settings instead. - -For skills checked into a project's `.claude/skills/` directory, `allowed-tools` takes effect after you accept the workspace trust dialog for that folder, the same as permission rules in `.claude/settings.json`. Review project skills before trusting a repository, since a skill can grant itself broad tool access. - -This skill lets Claude run git commands without per-use approval whenever you invoke it: - -```yaml theme={null} ---- -name: commit -description: Stage and commit the current changes -disable-model-invocation: true -allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *) ---- -``` - -To remove tools from Claude's available pool while a skill is active, list them in `disallowed-tools` in the skill's frontmatter. The restriction clears when you send your next message. Like deny rules, the field can't remove [`EndConversation`](/docs/en/tools-reference#endconversation-tool-behavior) while any other tool remains. To block tools across all skills and prompts, add deny rules in your [permission settings](/docs/en/permissions). - -### Pass arguments to skills - -Both you and Claude can pass arguments when invoking a skill. Arguments are available via the `$ARGUMENTS` placeholder. - -This skill fixes a GitHub issue by number. The `$ARGUMENTS` placeholder gets replaced with whatever follows the skill name: - -```yaml theme={null} ---- -name: fix-issue -description: Fix a GitHub issue -disable-model-invocation: true ---- - -Fix GitHub issue $ARGUMENTS following our coding standards. - -1. Read the issue description -2. Understand the requirements -3. Implement the fix -4. Write tests -5. Create a commit -``` - -When you run `/fix-issue 123`, Claude receives "Fix GitHub issue 123 following our coding standards..." - -If you invoke a skill with arguments but the skill doesn't include `$ARGUMENTS`, Claude Code appends `ARGUMENTS: ` to the end of the skill content so Claude still sees what you typed. - -You can also stack several skills at the start of one message. Typing `/write-tests /fix-issue 123` loads both skills and passes the trailing text `123` as `$ARGUMENTS` to each of them. Before v2.1.199, only the first skill loaded and received `/fix-issue 123` as literal argument text. - -Claude Code expands the first skill plus up to five more stacked after it. Expansion stops at the first token that isn't an inline user-invocable skill, so a skill that runs as a [forked subagent](#run-skills-in-a-subagent), such as [`/code-review`](/docs/en/code-review#review-a-diff-locally), or one whose arguments may themselves start with a slash command, such as `/loop`, also ends the run there. That token and everything after it become the argument text for every expanded skill. `/code-review` runs as a forked subagent from v2.1.218; on earlier versions it ran inline and stacked. - -To access individual arguments by position, use `$ARGUMENTS[N]` or the shorter `$N`: - -```yaml theme={null} ---- -name: migrate-component -description: Migrate a component from one framework to another ---- - -Migrate the $ARGUMENTS[0] component from $ARGUMENTS[1] to $ARGUMENTS[2]. -Preserve all existing behavior and tests. -``` - -Running `/migrate-component SearchBar React Vue` replaces `$ARGUMENTS[0]` with `SearchBar`, `$ARGUMENTS[1]` with `React`, and `$ARGUMENTS[2]` with `Vue`. The same skill using the `$N` shorthand: - -```yaml theme={null} ---- -name: migrate-component -description: Migrate a component from one framework to another ---- - -Migrate the $0 component from $1 to $2. -Preserve all existing behavior and tests. -``` - -## Advanced patterns - -### Inject dynamic context - -The `` !`` `` syntax runs shell commands before the skill content is sent to Claude. The command output replaces the placeholder, so Claude receives actual data, not the command itself. - -This skill summarizes a pull request by fetching live PR data with the GitHub CLI. The `` !`gh pr diff` `` and other commands run first, and their output gets inserted into the prompt: - -```yaml theme={null} ---- -name: pr-summary -description: Summarize changes in a pull request -context: fork -agent: Explore -allowed-tools: Bash(gh *) ---- - -## Pull request context -- PR diff: !`gh pr diff` -- PR comments: !`gh pr view --comments` -- Changed files: !`gh pr diff --name-only` - -## Your task -Summarize this pull request... -``` - -When this skill runs: - -1. Each `` !`` `` executes immediately (before Claude sees anything) -2. The output replaces the placeholder in the skill content -3. Claude receives the fully-rendered prompt with actual PR data - -This is preprocessing, not something Claude executes. Claude only sees the final result. - -Substitution runs once over the original file. Command output is inserted as plain text and is not re-scanned for further `` !`` `` placeholders, so a command cannot emit a placeholder for a later pass to expand. - -The inline form is only recognized when `!` appears at the start of a line or immediately after whitespace. If `!` follows another character, as in `` KEY=!`cmd` ``, the placeholder is left as literal text and the command does not run. - -For multi-line commands, use a fenced code block opened with ` ```! ` instead of the inline form: - -````markdown theme={null} -## Environment -```! -node --version -npm --version -git status --short -``` -```` - -To disable this behavior for skills and custom commands from user, project, plugin, or [additional-directory](#skills-from-additional-directories) sources, set `"disableSkillShellExecution": true` in [settings](/docs/en/settings). Each command is replaced with `[shell command execution disabled by policy]` instead of being run. Bundled and managed skills are not affected. This setting is most useful in [managed settings](/docs/en/permissions#managed-settings), where users cannot override it. - - - To request deeper reasoning when a skill runs, include `ultrathink` anywhere in the skill content. See [Use ultrathink for one-off deep reasoning](/docs/en/model-config#use-ultrathink-for-one-off-deep-reasoning). - - -### Run skills in a subagent - -Add `context: fork` to your frontmatter when you want a skill to run in isolation. The skill content becomes the prompt that drives the subagent. It won't have access to your conversation history. - -The forked subagent runs in the [background](/docs/en/sub-agents#run-subagents-in-foreground-or-background): you keep working while it runs, and its result arrives in your conversation when it completes. Set `background: false` in the frontmatter to instead wait for the result in the turn that invoked the skill. Before v2.1.218, forked skills always blocked the turn until they finished. - -Claude Code also waits for the result, even when the skill doesn't set `background: false`, in cases like these: - -* In non-interactive mode, with the `-p` flag or the Agent SDK -* When you set [`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS`](/docs/en/env-vars) to `1`, which also turns off all other background task features -* When you invoke a forked skill while an earlier invocation of the same skill is still running -* When a [scheduled task](/docs/en/scheduled-tasks) fires with the skill as its prompt - -A backgrounded fork also runs with the [narrower tool set that applies to background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background): the skill's subagent is a regular agent type, so the exemption for subagents that fork the conversation doesn't cover it. If your skill's steps depend on a tool outside that set, set `background: false` to keep the full tool set. - -A forked skill that runs in the background applies its edits outside your session's [checkpoints](/docs/en/checkpointing), so `/rewind` doesn't undo them; use git to revert them. - - - `context: fork` only makes sense for skills with explicit instructions. If your skill contains guidelines like "use these API conventions" without a task, the subagent receives the guidelines but no actionable prompt, and returns without meaningful output. - - -Skills and [subagents](/docs/en/sub-agents) work together in two directions: - -| Approach | System prompt | Task | Also loads | -| :--------------------------- | :----------------------- | :-------------------------- | :-------------------------------------------------- | -| Skill with `context: fork` | From agent type | SKILL.md content | CLAUDE.md, except when the agent is Explore or Plan | -| Subagent with `skills` field | Subagent's markdown body | Claude's delegation message | Preloaded skills + CLAUDE.md | - -With `context: fork`, you write the task in your skill and pick an agent type to execute it. The built-in Explore and Plan agents [skip CLAUDE.md and git status](/docs/en/sub-agents#what-loads-at-startup) to keep their context small, so a forked skill using `agent: Explore` sees only the SKILL.md content and the agent's own system prompt. For the inverse, where you define a custom subagent that uses skills as reference material, see [Subagents](/docs/en/sub-agents#preload-skills-into-subagents). - -#### Example: Research skill using Explore agent - -This skill runs research in a forked Explore agent. The skill content becomes the task, and the agent provides read-only tools optimized for codebase exploration: - -```yaml theme={null} ---- -name: deep-research -description: Research a topic thoroughly -context: fork -agent: Explore ---- - -Research $ARGUMENTS thoroughly: - -1. Find relevant files using Glob and Grep -2. Read and analyze the code -3. Summarize findings with specific file references -``` - -When this skill runs: - -1. A new isolated context is created -2. The subagent receives the skill content as its prompt ("Research \$ARGUMENTS thoroughly...") -3. The `agent` field determines the execution environment (model, tools, and permissions) -4. The subagent summarizes its results and returns them to your main conversation when it finishes - -The `agent` field specifies which subagent configuration to use. Options include built-in agents (`Explore`, `Plan`, `general-purpose`) or any custom subagent from `.claude/agents/`. If omitted, uses `general-purpose`. - -### Restrict Claude's skill access - -By default, Claude can invoke any skill that doesn't have `disable-model-invocation: true` set. Skills that define `allowed-tools` grant Claude access to those tools without per-use approval during the turn that invokes the skill; the grant clears when you send your next message. Your [permission settings](/docs/en/permissions) still govern baseline approval behavior for all other tools. A few built-in commands are also available through the Skill tool, including `/init`, `/review`, and `/security-review`. Other built-in commands such as `/compact` are not. - -Three ways to control which skills Claude can invoke: - -**Disable all skills** by denying the Skill tool in `/permissions`: - -```text theme={null} -# Add to deny rules: -Skill -``` - -**Allow or deny specific skills** using [permission rules](/docs/en/permissions): - -```text theme={null} -# Allow only specific skills -Skill(commit) -Skill(review-pr *) - -# Deny specific skills -Skill(deploy *) -``` - -Permission syntax: `Skill(name)` for exact match, `Skill(name *)` for prefix match with any arguments. - -**Hide individual skills** by adding `disable-model-invocation: true` to their frontmatter. This removes the skill from Claude's context entirely. - - - The `user-invocable` field only controls menu visibility, not Skill tool access. Use `disable-model-invocation: true` to block programmatic invocation. - - -### Override skill visibility from settings - -The `skillOverrides` setting controls skill visibility from your [settings](/docs/en/settings) instead of the skill's own frontmatter. Use it for skills whose SKILL.md you don't want to edit, such as ones checked into a shared project repo. The `/skills` menu writes it for you: highlight a skill and press `Space` to cycle states, then `Enter` to save to `.claude/settings.local.json`. - -Each key is a skill name and each value is one of four states: - -| Value | Listed to Claude | In `/` menu | -| :---------------------- | :------------------- | :---------- | -| `"on"` | Name and description | Yes | -| `"name-only"` | Name only | Yes | -| `"user-invocable-only"` | Hidden | Yes | -| `"off"` | Hidden | Hidden | - -The `/skills` menu labels the `"user-invocable-only"` state `user-only`. - -As of v2.1.199, `"off"` also hides the skill from the command lists advertised to [Remote Control](/docs/en/remote-control) clients and to [Agent SDK](/docs/en/agent-sdk/slash-commands) callers, not only the terminal `/` menu. Invoking a hidden skill by its full name still returns the `skillOverrides` error instead of running it. - -A skill that is absent from `skillOverrides` is treated as `"on"`. The example below collapses one skill to its name and turns another off entirely: - -```json theme={null} -{ - "skillOverrides": { - "legacy-context": "name-only", - "deploy": "off" - } -} -``` - -Plugin skills are not affected by `skillOverrides`. Manage those through `/plugin` instead. - -## Evaluate and iterate on a skill - -Seeing a skill trigger tells you Claude found it, not that it did what you intended. To know a skill is working, measure two things separately: whether Claude invokes it on the prompts it should, and whether the output matches what you expect when it does. - -The check for both is a baseline comparison. Collect a few realistic prompts, run each one in a fresh session with the skill available and again with it [disabled](#override-skill-visibility-from-settings), and compare the results. A fresh session matters because leftover context from authoring the skill will mask gaps in the written instructions. - -### Run evals with skill-creator - -The [`skill-creator` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/skill-creator) automates the comparison loop inside Claude Code. Install it from the official marketplace: - -```text theme={null} -/plugin install skill-creator@claude-plugins-official -``` - -If the install fails, match the message Claude Code reports: - -* `Marketplace "claude-plugins-official" not found`: add the marketplace with `/plugin marketplace add anthropics/claude-plugins-official`, then retry the install. -* The plugin is not found in the marketplace: check the plugin name. Claude Code [refreshes a stale marketplace catalog and retries](/docs/en/discover-plugins#install-plugins) before reporting this, so if you turned off [marketplace auto-update](/docs/en/discover-plugins#configure-auto-updates), refresh manually with `/plugin marketplace update claude-plugins-official` and retry the install. - -If the install summary reports `Run /reload-plugins to activate.`, run that command to make the plugin's skills available in the current session. Then ask Claude to evaluate an existing skill, for example `evaluate my summarize-changes skill with skill-creator`. The plugin walks you through writing test cases and runs the loop: - -* **Test cases**: stores prompts, input files, and expected behavior in `evals/evals.json` inside the skill directory -* **Isolated runs**: spawns a [subagent](/docs/en/sub-agents) per test case so each run starts with a clean context, and records token count and duration -* **Grading**: checks each assertion against the output and writes pass or fail with evidence to `grading.json` -* **Benchmark**: aggregates pass rate, time, and tokens for with-skill versus without-skill into `benchmark.json` so you can compare the pass-rate improvement against the token and time overhead -* **Version comparison**: runs a blind A/B between two versions of the skill so you can confirm an edit is an improvement before committing it -* **Description tuning**: generates should-trigger and should-not-trigger prompts, measures the hit rate, and proposes description edits when the skill activates on the wrong requests -* **Review viewer**: opens an HTML report where you inspect each output and record qualitative feedback that the next iteration reads - -For the eval file format and the full iteration workflow, see [Evaluating skill output quality](https://agentskills.io/skill-creation/evaluating-skills) on agentskills.io. For background on the benchmark and comparison modes, see the [skill-creator announcement](https://claude.com/blog/improving-skill-creator-test-measure-and-refine-agent-skills). - -## Share skills - -Skills can be distributed at different scopes depending on your audience: - -* **Project skills**: Commit `.claude/skills/` to version control -* **Plugins**: Create a `skills/` directory in your [plugin](/docs/en/plugins) -* **Managed**: Deploy organization-wide through [managed settings](/docs/en/settings#settings-files) - -### Generate visual output - -Skills can bundle and run scripts in any language, giving Claude capabilities beyond what's possible in a single prompt. One powerful pattern is generating visual output: interactive HTML files that open in your browser for exploring data, debugging, or creating reports. - -This example creates a codebase explorer: an interactive tree view where you can expand and collapse directories, see file sizes at a glance, and identify file types by color. - -Create the Skill directory: - -```bash theme={null} -mkdir -p ~/.claude/skills/codebase-visualizer/scripts -``` - -Save this to `~/.claude/skills/codebase-visualizer/SKILL.md`. The description tells Claude when to activate this Skill, and the instructions tell Claude to run the bundled script. The script path uses [`${CLAUDE_SKILL_DIR}`](#available-string-substitutions) so it resolves correctly whether the skill is installed at the personal, project, or plugin level: - -````yaml theme={null} ---- -name: codebase-visualizer -description: Generate an interactive collapsible tree visualization of your codebase. Use when exploring a new repo, understanding project structure, or identifying large files. -allowed-tools: Bash(python3 *) ---- - -# Codebase Visualizer - -Generate an interactive HTML tree view that shows your project's file structure with collapsible directories. - -## Usage - -Run the visualization script from your project root: - -```bash -python3 ${CLAUDE_SKILL_DIR}/scripts/visualize.py . -``` - -This creates `codebase-map.html` in the current directory and opens it in your default browser. - -## What the visualization shows - -- **Collapsible directories**: Click folders to expand/collapse -- **File sizes**: Displayed next to each file -- **Colors**: Different colors for different file types -- **Directory totals**: Shows aggregate size of each folder -```` - -Save this to `~/.claude/skills/codebase-visualizer/scripts/visualize.py`. This script scans a directory tree and generates a self-contained HTML file with: - -* A **summary sidebar** showing file count, directory count, total size, and number of file types -* A **bar chart** breaking down the codebase by file type (top 8 by size) -* A **collapsible tree** where you can expand and collapse directories, with color-coded file type indicators - -The script requires Python 3 but uses only built-in libraries, so there are no packages to install: - -```python expandable theme={null} -#!/usr/bin/env python3 -"""Generate an interactive collapsible tree visualization of a codebase.""" - -import json -import sys -import webbrowser -from html import escape -from pathlib import Path -from collections import Counter - -IGNORE = {'.git', 'node_modules', '__pycache__', '.venv', 'venv', 'dist', 'build'} - -def scan(path: Path, stats: dict) -> dict: - result = {"name": path.name, "children": [], "size": 0} - try: - for item in sorted(path.iterdir()): - if item.name in IGNORE or item.name.startswith('.'): - continue - if item.is_file(): - size = item.stat().st_size - ext = item.suffix.lower() or '(no ext)' - result["children"].append({"name": item.name, "size": size, "ext": ext}) - result["size"] += size - stats["files"] += 1 - stats["extensions"][ext] += 1 - stats["ext_sizes"][ext] += size - elif item.is_dir(): - stats["dirs"] += 1 - child = scan(item, stats) - if child["children"]: - result["children"].append(child) - result["size"] += child["size"] - except PermissionError: - pass - return result - -def generate_html(data: dict, stats: dict, output: Path) -> None: - ext_sizes = stats["ext_sizes"] - total_size = sum(ext_sizes.values()) or 1 - sorted_exts = sorted(ext_sizes.items(), key=lambda x: -x[1])[:8] - colors = { - '.js': '#f7df1e', '.ts': '#3178c6', '.py': '#3776ab', '.go': '#00add8', - '.rs': '#dea584', '.rb': '#cc342d', '.css': '#264de4', '.html': '#e34c26', - '.json': '#6b7280', '.md': '#083fa1', '.yaml': '#cb171e', '.yml': '#cb171e', - '.mdx': '#083fa1', '.tsx': '#3178c6', '.jsx': '#61dafb', '.sh': '#4eaa25', - } - lang_bars = "".join( - f'
                                                                                            {ext}' - f'
                                                                                            ' - f'{(size/total_size)*100:.1f}%
                                                                                            ' - for ext, size in sorted_exts - ) - def fmt(b): - if b < 1024: return f"{b} B" - if b < 1048576: return f"{b/1024:.1f} KB" - return f"{b/1048576:.1f} MB" - - html = f''' - - Codebase Explorer - - -
                                                                                            - -
                                                                                            -

                                                                                            📁 {escape(data["name"])}

                                                                                            -
                                                                                              -
                                                                                              -
                                                                                              - -''' - output.write_text(html) - -if __name__ == '__main__': - target = Path(sys.argv[1] if len(sys.argv) > 1 else '.').resolve() - stats = {"files": 0, "dirs": 0, "extensions": Counter(), "ext_sizes": Counter()} - data = scan(target, stats) - out = Path('codebase-map.html') - generate_html(data, stats, out) - print(f'Generated {out.absolute()}') - webbrowser.open(f'file://{out.absolute()}') -``` - -To test, open Claude Code in any project and ask "Visualize this codebase." Claude runs the script, which prints the generated file's path, such as `Generated /path/to/codebase-map.html`, and opens it in your browser. If you work in a headless environment where no browser opens, the printed path confirms the script succeeded. - -This pattern works for any visual output: dependency graphs, test coverage reports, API documentation, or database schema visualizations. The bundled script does the work while Claude handles orchestration. - -## Troubleshooting - -### Skill not triggering - -If Claude doesn't use your skill when expected: - -1. Check the description includes keywords users would naturally say -2. Verify the skill appears in `What skills are available?` -3. Try rephrasing your request to match the description more closely -4. Invoke it directly with `/skill-name` if the skill is user-invocable - -If the frontmatter YAML is malformed, Claude Code loads the skill body with empty metadata, so `/skill-name` still works but Claude has no `description` to match against. Run with `--debug` to see the parse error. - -### Skill triggers too often - -If Claude uses your skill when you don't want it: - -1. Make the description more specific -2. Add `disable-model-invocation: true` if you only want manual invocation - -### Skill descriptions are cut short - -Claude Code loads a listing of skill names and descriptions into context so Claude knows what's available. The listing always contains every skill name, but if you have many skills, Claude Code shortens descriptions to fit the listing's character budget, which can strip the keywords Claude needs to match your request. The budget scales at 1% of the model's context window. When the listing overflows, Claude Code drops descriptions starting with the skills you invoke least, so the skills you use most keep their full text. - -Run `/doctor` for an estimate of the listing's context cost and its biggest contributors. When the listing exceeds its budget, Claude Code also writes a warning to the debug log, visible with [`--debug`](/docs/en/cli-reference#cli-flags). - -The Skills row in `/context` reports the size of the listing after the budget is applied, so it matches what the model receives. Before v2.1.196, the row counted the full text of every description and could show a value several times larger than the configured budget. - -To raise the budget, set the [`skillListingBudgetFraction`](/docs/en/settings#available-settings) setting (e.g. `0.02` = 2%) or the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable to a fixed character count. To free budget for other skills, set low-priority entries to `"name-only"` in [`skillOverrides`](#override-skill-visibility-from-settings) so they list without a description. You can also trim the `description` and `when_to_use` text at the source: put the key use case first, since each entry's combined text is capped at 1,536 characters regardless of budget. The cap is configurable with [`skillListingMaxDescChars`](/docs/en/settings#available-settings). - -## Related resources - -* **[Debug your configuration](/docs/en/debug-your-config)**: diagnose why a skill isn't appearing or triggering -* **[Evaluating skill output quality](https://agentskills.io/skill-creation/evaluating-skills)**: the eval file format and iteration workflow on agentskills.io -* **[Skill authoring best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices)**: writing guidance that applies across Claude products -* **[Subagents](/docs/en/sub-agents)**: delegate tasks to specialized agents -* **[Plugins](/docs/en/plugins)**: package and distribute skills with other extensions -* **[Hooks](/docs/en/hooks)**: automate workflows around tool events -* **[Memory](/docs/en/memory)**: manage CLAUDE.md files for persistent context -* **[Commands](/docs/en/commands)**: reference for built-in commands and bundled skills -* **[Permissions](/docs/en/permissions)**: control tool and skill access -* **[Claude Tag skills](https://claude.com/docs/claude-tag/admins/skills-repo)**: project skills committed to a repo also load when that repo is used in a Claude Tag channel diff --git a/content/en/docs/claude-code/troubleshoot-install.md b/content/en/docs/claude-code/troubleshoot-install.md deleted file mode 100644 index 1fa57540c..000000000 --- a/content/en/docs/claude-code/troubleshoot-install.md +++ /dev/null @@ -1,946 +0,0 @@ -> ## Documentation Index -> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt -> Use this file to discover all available pages before exploring further. - -# Troubleshoot installation and login - -> Fix command not found, PATH, permission, network, and authentication errors when installing or signing in to Claude Code. - -If installation fails or you can't sign in, find your error below. For runtime issues after Claude Code is working, see [Troubleshooting](/docs/en/troubleshooting). For configuration problems such as settings not applying or hooks not firing, see [Debug your configuration](/docs/en/debug-your-config). - -## Find your error - -Match the error message or symptom you're seeing to a fix: - -| What you see | Solution | -| :--------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | -| `command not found: claude` or `'claude' is not recognized` | [Fix your PATH](#command-not-found-claude-after-installation) | -| `syntax error near unexpected token '<'` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) | -| `curl: (22) The requested URL returned error: 403` | [Install script returned 403](#install-script-returns-html-instead-of-a-shell-script) | -| `curl: (23)` or `curl: (56) Failure writing output to destination` | [Check connectivity or use an alternative installer](#curl-56-failure-writing-output-to-destination) | -| `Killed` during install on Linux, or `Installation was killed before it could finish (exit code 137)` | [Free memory or add swap space](#install-killed-on-low-memory-linux-servers) | -| `TLS connect error` or `SSL/TLS secure channel` | [Update CA certificates](#tls-or-ssl-connection-errors) | -| `Failed to fetch version` or can't reach download server | [Check network and proxy settings](#check-network-connectivity) | -| `irm is not recognized` or `&& is not valid` | [Use the right command for your shell](#wrong-install-command-on-windows) | -| `Cask 'claude-code' is unavailable: No Cask with this name exists` | [Update Homebrew](#homebrew-cask-unavailable-or-outdated) | -| `'bash' is not recognized as the name of a cmdlet` | [Use the Windows installer command](#wrong-install-command-on-windows) | -| `A parameter cannot be found that matches parameter name 'fsSL'` | [Use the Windows installer command](#wrong-install-command-on-windows) | -| `Claude Code on Windows requires either Git for Windows (for bash) or PowerShell` | [Install a shell](#claude-code-on-windows-requires-either-git-for-windows-for-bash-or-powershell) | -| `Claude Code does not support 32-bit Windows` | [Open Windows PowerShell, not the x86 entry](#claude-code-does-not-support-32-bit-windows) | -| `The process cannot access the file ... because it is being used by another process` | [Clear the downloads folder and retry](#the-process-cannot-access-the-file-during-windows-install) | -| `Error loading shared library` | [Wrong binary variant for your system](#linux-musl-or-glibc-binary-mismatch) | -| `Illegal instruction` | [Architecture or CPU instruction set mismatch](#illegal-instruction) | -| `cannot execute binary file: Exec format error` in WSL | [WSL1 native-binary regression](#exec-format-error-on-wsl1) | -| PowerShell installer completes but `claude` is not found or shows an old version | [Add the install directory to your PATH](#verify-your-path), then open a new terminal | -| `dyld: cannot load`, `dyld: Symbol not found`, or `Abort trap` on macOS | [Binary incompatibility](#dyld-cannot-load-on-macos) | -| `claude update` hangs after `Checking for updates`, or `claude doctor` hangs with no output | [Move the directory at a shell config path](#claude-update-or-claude-doctor-hangs) | -| `Invoke-Expression` or `iex` parse errors quoting HTML tags or CSS, or `ParserError` with `ParseException` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) | -| `running scripts is disabled on this system` or `PSSecurityException` | [Allow the npm shims to run](#running-scripts-is-disabled-on-this-system) | -| `Error: claude native binary not installed` | [Complete the npm install](#native-binary-not-found-after-npm-install) | -| `App unavailable in region` | Claude Code is not available in your country. See [supported countries](https://www.anthropic.com/supported-countries). | -| `unable to get local issuer certificate` | [Configure corporate CA certificates](#tls-or-ssl-connection-errors) | -| `OAuth error` or `403 Forbidden` | [Fix authentication](#login-and-authentication) | -| `Could not load the default credentials` or `Could not load credentials from any providers` | [Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry credentials](#bedrock-agent-platform-or-foundry-credentials-not-loading) | -| `ChainedTokenCredential authentication failed` or `CredentialUnavailableError` | [Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry credentials](#bedrock-agent-platform-or-foundry-credentials-not-loading) | -| `API Error: 500`, `529 Overloaded`, `429`, or other 4xx and 5xx errors not listed above | See the [Error reference](/docs/en/errors) | - -If your issue isn't listed, work through the diagnostic checks below to narrow down the cause. - - - If you'd rather skip the terminal entirely, the [Claude Code Desktop app](/docs/en/desktop-quickstart) lets you install and use Claude Code through a graphical interface. Download it for [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code\&utm_medium=docs) or [Windows](https://claude.com/download?utm_source=claude_code\&utm_medium=docs) and start coding without any command-line setup. On Linux, install the app with apt by following the [Linux install instructions](/docs/en/desktop-linux). - - -## Run diagnostic checks - -### Check network connectivity - -The installer downloads from `downloads.claude.ai`. Verify you can reach it: - - - - ```bash theme={null} - curl -sI https://downloads.claude.ai/claude-code-releases/latest - ``` - - - - ```powershell theme={null} - curl.exe -sI https://downloads.claude.ai/claude-code-releases/latest - ``` - - PowerShell aliases `curl` to `Invoke-WebRequest`, which rejects the `-sI` flags, so call `curl.exe` explicitly. - - - -You reached the server if the first line shows a `200` status. You see `HTTP/2 200` on macOS and Linux, and `HTTP/1.1 200 OK` from the `curl.exe` included with Windows. Other results point to the cause: - -* `403`: usually a proxy or network filter blocking the host, or Claude Code is [not available in your region](https://www.anthropic.com/supported-countries) -* `5xx`: usually a temporary service issue; wait a few minutes and retry - -If you see no output, `Could not resolve host`, or a connection timeout, your network is blocking the connection. Common causes: - -* Corporate firewalls or proxies blocking `downloads.claude.ai` -* Regional network restrictions: try a VPN or alternative network -* TLS/SSL issues: update your system's CA certificates, or check if `HTTPS_PROXY` is configured - -If you're behind a corporate proxy, set `HTTPS_PROXY` and `HTTP_PROXY` to your proxy's address before installing. Ask your IT team for the proxy URL if you don't know it, or check your browser's proxy settings. - -This example sets both proxy variables, then runs the installer through your proxy: - - - - ```bash theme={null} - export HTTP_PROXY=http://proxy.example.com:8080 - export HTTPS_PROXY=http://proxy.example.com:8080 - curl -fsSL https://claude.ai/install.sh | bash - ``` - - - - ```powershell theme={null} - $env:HTTP_PROXY = 'http://proxy.example.com:8080' - $env:HTTPS_PROXY = 'http://proxy.example.com:8080' - irm https://claude.ai/install.ps1 | iex - ``` - - - -### Verify your PATH - -If installation succeeded but you get a `command not found` or `not recognized` error when running `claude`, the install directory isn't in your PATH. Your shell searches for programs in directories listed in PATH, and the installer places `claude` at `~/.local/bin/claude` on macOS/Linux or `%USERPROFILE%\.local\bin\claude.exe` on Windows. - - - The [VS Code extension](/docs/en/vs-code) does not place `claude` at this location. It bundles a private copy of the CLI inside the extension directory for its own chat panel and does not add it to PATH. If you have only installed the extension, `~/.local/bin/claude` will not exist. Run the [standalone install](/docs/en/setup) to use `claude` from a terminal, then continue below. - - -Check if the install directory is in your PATH by listing your PATH entries and filtering for `local/bin`: - - - - ```bash theme={null} - echo $PATH | tr ':' '\n' | grep -Fx "$HOME/.local/bin" - ``` - - If this prints `/Users/you/.local/bin` or `/home/you/.local/bin`, the directory is in your PATH and you can skip to [Check for conflicting installations](#check-for-conflicting-installations). If there's no output, add it to your shell configuration. - - For Zsh, the default on macOS: - - ```bash theme={null} - echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc - source ~/.zshrc - ``` - - For Bash, the default on most Linux distributions: - - ```bash theme={null} - echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc - source ~/.bashrc - ``` - - Alternatively, close and reopen your terminal. - - For other shells such as fish or Nushell, add `~/.local/bin` to your PATH using your shell's own configuration syntax, then restart your terminal. - - Verify the fix worked: - - ```bash theme={null} - claude --version - ``` - - - - ```powershell theme={null} - $env:PATH -split ';' | Select-String '\.local\\bin' - ``` - - If there's no output, add the install directory to your User PATH: - - ```powershell theme={null} - $currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User') - [Environment]::SetEnvironmentVariable('PATH', "$currentPath;$env:USERPROFILE\.local\bin", 'User') - ``` - - Restart your terminal for the change to take effect. - - Verify the fix worked: - - ```powershell theme={null} - claude --version - ``` - - - - ```batch theme={null} - echo %PATH% | findstr /i "local\bin" - ``` - - If there's no output, open System Settings, go to Environment Variables, and add `%USERPROFILE%\.local\bin` to your User PATH variable. Restart your terminal. - - Verify the fix worked: - - ```batch theme={null} - claude --version - ``` - - - -### Check for conflicting installations - -Multiple Claude Code installations can cause version mismatches or unexpected behavior. Check what's installed: - - - - List all `claude` binaries found in your PATH: - - ```bash theme={null} - which -a claude - ``` - - If this prints nothing, no `claude` is on your PATH yet. Go back to [Verify your PATH](#verify-your-path). - - Check the three locations a `claude` binary can come from. `~/.local/bin/claude` is the native installer, `~/.claude/local/` is a legacy local npm install created by older versions of Claude Code, and the npm global list shows a `-g` install: - - ```bash theme={null} - ls -la ~/.local/bin/claude - ``` - - A native install shows a symlink into `~/.local/share/claude/versions/`. A script or a symlink you created yourself at this path is a custom launcher, which [auto-update leaves in place](/docs/en/setup#auto-updates). - - If either `ls` command prints `No such file or directory`, that's not an error. It means nothing is installed at that location, so move on to the next check. - - ```bash theme={null} - ls -la ~/.claude/local/ - ``` - - ```bash theme={null} - npm -g ls @anthropic-ai/claude-code 2>/dev/null - ``` - - - - List all `claude` binaries found in your PATH: - - ```powershell theme={null} - where.exe claude - ``` - - Check whether the native installer placed a binary: - - ```powershell theme={null} - Test-Path "$env:USERPROFILE\.local\bin\claude.exe" - ``` - - - -If you find multiple installations, keep only one. The native install at `~/.local/bin/claude` on macOS/Linux or `%USERPROFILE%\.local\bin\claude.exe` on Windows is recommended. Remove the extras: - -Uninstall an npm global install: - -```bash theme={null} -npm uninstall -g @anthropic-ai/claude-code -``` - -Remove the legacy local npm install: - -```bash theme={null} -rm -rf ~/.claude/local -``` - -On Windows, use PowerShell: - -```powershell theme={null} -Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\local" -``` - -Remove a Homebrew install on macOS. If you installed the `claude-code@latest` cask, substitute that name: - -```bash theme={null} -brew uninstall --cask claude-code -``` - -Remove a WinGet install on Windows: - -```powershell theme={null} -winget uninstall Anthropic.ClaudeCode -``` - -### Check directory permissions - -The installer needs write access to `~/.local/bin/` and `~/.claude/` on macOS and Linux. On Windows the install location is under `%USERPROFILE%`, which is writable by your user by default, so this section rarely applies there. - -Check whether the directories are writable: - -```bash theme={null} -test -w ~/.local/bin && echo "writable" || echo "not writable" -test -w ~/.claude && echo "writable" || echo "not writable" -``` - -If either directory isn't writable, create the install directory and set your user as the owner: - -```bash theme={null} -sudo mkdir -p ~/.local/bin -sudo chown -R $(whoami) ~/.local -``` - -### Verify the binary works - -If `claude --version` prints a version but `claude` crashes or hangs on startup, run these checks to narrow down the cause. If `claude --version` says command not found, go to [Verify your PATH](#verify-your-path) first; the commands below assume `claude` is on your PATH. - -Confirm the binary exists and is executable: - -```bash theme={null} -ls -la "$(command -v claude)" -``` - -On Windows, use PowerShell: - -```powershell theme={null} -Get-Command claude | Select-Object Source -``` - -On Linux, check for missing shared libraries. If `ldd` shows missing libraries, you may need to install system packages. On Alpine Linux and other musl-based distributions, see [Alpine Linux setup](/docs/en/setup#alpine-linux-and-musl-based-distributions). - -```bash theme={null} -ldd "$(command -v claude)" | grep "not found" -``` - -Confirm the binary can execute: - -```bash theme={null} -claude --version -``` - -## Common installation issues - -These are the most frequently encountered installation problems and their solutions. - -### Install script returns HTML instead of a shell script - -When running the install command, you may see one of these errors: - -```text theme={null} -bash: line 1: syntax error near unexpected token `<' -bash: line 1: `' -``` - -On PowerShell, the same problem appears as parse errors pointing into the returned page, with `iex` trying to run HTML and CSS as PowerShell: - -```text theme={null} -iex : At line:1 char:2310 -+ ... igin="anonymous"/> - Side-Scrolling Typing Game - - -
                                                                                              - Score: 0 -
                                                                                              -
                                                                                              -
                                                                                              -
                                                                                              - - - - -``` - -## API Request - - - -```python Python -import anthropic - -client = anthropic.Anthropic( - # defaults to os.environ.get("ANTHROPIC_API_KEY") - api_key="my_api_key", -) -message = client.messages.create( - model="claude-opus-4-6", - max_tokens=2000, - temperature=0, - messages=[ - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Write me a fully complete web app as a single HTML file. The app should contain a simple side-scrolling game where I use WASD to move around. When moving around the world, occasionally the character/sprite will encounter words. When a word is encountered, the player must correctly type the word as fast as possible.The faster the word is successfully typed, the more point the player gets. We should have a counter in the top-right to keep track of points. Words should be random and highly variable to keep the game interesting. \n \nYou should make the website very aesthetic and use Tailwind.", - } - ], - } - ], -) -print(message.content) -``` - -```typescript TypeScript -import Anthropic from "@anthropic-ai/sdk"; - -const anthropic = new Anthropic({ - apiKey: "my_api_key" // defaults to process.env["ANTHROPIC_API_KEY"] -}); - -const msg = await anthropic.messages.create({ - model: "claude-opus-4-6", - max_tokens: 2000, - temperature: 0, - messages: [ - { - role: "user", - content: [ - { - type: "text", - text: "Write me a fully complete web app as a single HTML file. The app should contain a simple side-scrolling game where I use WASD to move around. When moving around the world, occasionally the character/sprite will encounter words. When a word is encountered, the player must correctly type the word as fast as possible.The faster the word is successfully typed, the more point the player gets. We should have a counter in the top-right to keep track of points. Words should be random and highly variable to keep the game interesting. \n \nYou should make the website very aesthetic and use Tailwind." - } - ] - } - ] -}); -console.log(msg); -``` - -```python AWS Bedrock Python -from anthropic import AnthropicBedrock - -# See https://docs.claude.com/claude/reference/claude-on-amazon-bedrock -# for authentication options -client = AnthropicBedrock() - -message = client.messages.create( - model="anthropic.claude-opus-4-6-v1", - max_tokens=2000, - temperature=0, - messages=[ - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Write me a fully complete web app as a single HTML file. The app should contain a simple side-scrolling game where I use WASD to move around. When moving around the world, occasionally the character/sprite will encounter words. When a word is encountered, the player must correctly type the word as fast as possible.The faster the word is successfully typed, the more point the player gets. We should have a counter in the top-right to keep track of points. Words should be random and highly variable to keep the game interesting. \n \nYou should make the website very aesthetic and use Tailwind.", - } - ], - } - ], -) -print(message.content) -``` - -```typescript AWS Bedrock TypeScript -import AnthropicBedrock from "@anthropic-ai/bedrock-sdk"; - -// See https://docs.claude.com/claude/reference/claude-on-amazon-bedrock -// for authentication options -const client = new AnthropicBedrock(); - -const msg = await client.messages.create({ - model: "anthropic.claude-opus-4-6-v1", - max_tokens: 2000, - temperature: 0, - messages: [ - { - role: "user", - content: [ - { - type: "text", - text: "Write me a fully complete web app as a single HTML file. The app should contain a simple side-scrolling game where I use WASD to move around. When moving around the world, occasionally the character/sprite will encounter words. When a word is encountered, the player must correctly type the word as fast as possible.The faster the word is successfully typed, the more point the player gets. We should have a counter in the top-right to keep track of points. Words should be random and highly variable to keep the game interesting. \n \nYou should make the website very aesthetic and use Tailwind." - } - ] - } - ] -}); -console.log(msg); -``` - - \ No newline at end of file diff --git a/content/en/resources/prompt-library/website-wizard.md b/content/en/resources/prompt-library/website-wizard.md deleted file mode 100644 index 446fafb32..000000000 --- a/content/en/resources/prompt-library/website-wizard.md +++ /dev/null @@ -1,415 +0,0 @@ -# Website wizard - -Create one-page websites based on user specifications. - ---- - -> Copy this prompt into the developer [Console](/dashboard) to try it for yourself! - -| | Content | -| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| System | Your task is to create a one-page website based on the given specifications, delivered as an HTML file with embedded JavaScript and CSS. The website should incorporate a variety of engaging and interactive design features, such as drop-down menus, dynamic text and content, clickable buttons, and more. Ensure that the design is visually appealing, responsive, and user-friendly. The HTML, CSS, and JavaScript code should be well-structured, efficiently organized, and properly commented for readability and maintainability. | -| User | Create a one-page website for an online learning platform called "EduQuest" with the following features and sections:

                                                                                              1. A fixed navigation bar with links to course categories (Math, Science, Languages, Arts) and a search bar.
                                                                                              2. A hero section with a video background showcasing students learning online, a dynamic tagline that rotates between "Learn at your own pace," "Discover new passions," and "Expand your horizons" every 3 seconds, and a "Get Started" button leading to a course catalog.
                                                                                              3. A featured courses section displaying course cards with placeholders for course images, titles, instructors, and descriptions.
                                                                                              4. An interactive "Learning Paths" section with a short quiz to determine learning styles and interests, and a button to start the quiz.
                                                                                              5. A "Success Stories" section featuring testimonials from satisfied students, with placeholders for the testimonial text and student names.
                                                                                              6. A footer with links to the platform's blog, FAQ, privacy policy, and a "Contact Us" button that opens a modal window with a contact form and customer support information.

                                                                                              Include filler placeholder content for the video background, course cards, and testimonials. Embed the CSS styles within the ` - - -
                                                                                              - -
                                                                                              - -
                                                                                              - -

                                                                                              Welcome to EduQuest

                                                                                              -

                                                                                              Learn at your own pace

                                                                                              - -
                                                                                              - - - -
                                                                                              -

                                                                                              Success Stories

                                                                                              -
                                                                                              -

                                                                                              "EduQuest helped me learn a new skill and advance my career. Highly recommended!"

                                                                                              -

                                                                                              - John Doe

                                                                                              -
                                                                                              -
                                                                                              -

                                                                                              "I never thought I could learn a new language online, but EduQuest made it possible. Thank you!"

                                                                                              -

                                                                                              - Jane Smith

                                                                                              -
                                                                                              -
                                                                                              - - - - - - -``` - -> This code creates a one-page website for "EduQuest" with the following features and sections: -> -> A fixed navigation bar with links to course categories (Math, Science, Languages, Arts) and a search bar. -> -> A hero section with a placeholder video background, a dynamic tagline that rotates between "Learn at your own pace," "Discover new passions," and "Expand your horizons" every 3 seconds, and a "Get Started" button. -> -> A featured courses section displaying course cards with placeholders for course images, titles, instructors, and descriptions. -> -> A "Success Stories" section featuring testimonials from satisfied students, with placeholders for the testimonial text and student names. -> -> A footer with links to the platform's blog, FAQ, privacy policy, and a "Contact Us" button. -> -> The CSS styles are embedded within the ` -
                                                                                                - -``` - -See `references/widget-templates.md` for more widget shapes. - ---- - -## Design notes that save you a rewrite - -**One widget per tool.** Resist the urge to build one mega-widget that does everything. One tool → one focused widget → one clear result shape. Claude reasons about these far better. - -**Tool description must mention the widget.** Claude only sees the tool description when deciding what to call. "Opens an interactive picker" in the description is what makes Claude reach for it instead of guessing an ID. - -**Widgets are optional at runtime.** Hosts that don't support the apps surface simply ignore `_meta.ui` and render the tool's text content normally. Since your tool handler already returns meaningful text/JSON (the widget's data), degradation is automatic — Claude sees the data directly instead of via the widget. - -**Don't block on widget results for read-only tools.** A widget that just *displays* data (chart, preview) shouldn't require a user action to complete. Return the display widget *and* a text summary in the same result so Claude can continue reasoning without waiting. - -**Layout-fork by item count, not by tool count.** If one use case is "show one result in detail" and another is "show many results side-by-side", don't make two tools — make one tool that accepts `items[]`, and let the widget pick a layout: `items.length === 1` → detail view, `> 1` → carousel. Keeps the server schema simple and lets Claude decide count naturally. - -**Put Claude's reasoning in the payload.** A short `note` field on each item (why Claude picked it) rendered as a callout on the card gives users the reasoning inline with the choice. Mention this field in the tool description so Claude populates it. - -**Normalize image shapes server-side.** If your data source returns images with wildly varying aspect ratios, rewrite to a predictable variant (e.g. square-bounded) *before* fetching for the data-URL inline. Then give the widget's image container a fixed `aspect-ratio` + `object-fit: contain` so everything sits centered. - -**Follow host theme.** `app.getHostContext()?.theme` (after `connect()`) plus `app.onhostcontextchanged` for live updates. Toggle a `.dark` class on ``, keep colors in CSS custom props with a `:root.dark {}` override block, set `color-scheme`. Disable `mix-blend-mode: multiply` in dark — it makes images vanish. - ---- - -## Testing - -**Claude Desktop** — current builds still require the `command`/`args` config shape (no native `"type": "http"`). Wrap with `mcp-remote` and force `http-only` transport so the SSE probe doesn't swallow widget-capability negotiation: - -```json -{ - "mcpServers": { - "my-server": { - "command": "npx", - "args": ["-y", "mcp-remote", "http://localhost:3000/mcp", - "--allow-http", "--transport", "http-only"] - } - } -} -``` - -Desktop caches UI resources aggressively. After editing widget HTML, **fully quit** (⌘Q / Alt+F4, not window-close) and relaunch to force a cold resource re-fetch. - -**Headless JSON-RPC loop** — fast iteration without clicking through Desktop: - -```bash -# test.jsonl — one JSON-RPC message per line -{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"0"}}} -{"jsonrpc":"2.0","method":"notifications/initialized"} -{"jsonrpc":"2.0","id":2,"method":"tools/list"} -{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"your_tool","arguments":{...}}} - -(cat test.jsonl; sleep 10) | npx mcp-remote http://localhost:3000/mcp --allow-http -``` - -The `sleep` keeps stdin open long enough to collect all responses. Parse the jsonl output with `jq` or a Python one-liner. - -**Widget dev loop** — avoid the ⌘Q-relaunch cycle entirely by serving the inlined widget HTML at a plain GET route with a fake `ExtApps` shim that fires `ontoolresult` from a query param: - -```ts -app.get("/widget-preview", (_req, res) => { - const shim = `globalThis.ExtApps={applyHostStyleVariables:()=>{},App:class{ - constructor(){this.h={}} ontoolresult;onhostcontextchanged; - async connect(){const p=new URLSearchParams(location.search).get("payload"); - if(p)this.ontoolresult?.({content:[{type:"text",text:p}]});} - getHostContext(){return{theme:"light"}} - sendMessage(m){console.log("sendMessage",m)} updateModelContext(){} - callServerTool(){return Promise.resolve({content:[]})} openLink(){} downloadFile(){} - }};`; - res.type("html").send(widgetHtml.replace("/*__EXT_APPS_BUNDLE__*/", shim)); -}); -``` - -Open `http://localhost:3000/widget-preview?payload={"rows":[...]}` in a normal browser tab and iterate with ordinary devtools. - -**Host fallback** — use a host without the apps surface (or MCP Inspector) and confirm the tool's text content degrades gracefully. - -**CSP debugging** — open the iframe's own devtools console. CSP violations are the #1 reason widgets silently fail (blank rectangle, no error in the main console). See `references/iframe-sandbox.md`. - ---- - -## Reference files - -- `references/iframe-sandbox.md` — CSP/sandbox constraints, the bundle-inlining pattern, image handling, host theming -- `references/widget-templates.md` — reusable HTML scaffolds for picker / confirm / progress / display -- `references/apps-sdk-messages.md` — the `App` class API: widget ↔ host ↔ server messaging, lifecycle & supersession -- `references/payload-budgeting.md` — host tool-result size caps, prune-then-truncate, heavy assets via `callServerTool` -- `references/abuse-protection.md` — Anthropic egress CIDRs, tiered rate limiting, `trust proxy`, response caching -- `references/directory-checklist.md` — pre-flight for connector-directory submission diff --git a/content/github/skills/skills/algorithmic-art/SKILL.md b/content/github/skills/skills/algorithmic-art/SKILL.md deleted file mode 100644 index 634f6fa42..000000000 --- a/content/github/skills/skills/algorithmic-art/SKILL.md +++ /dev/null @@ -1,405 +0,0 @@ ---- -name: algorithmic-art -description: Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations. -license: Complete terms in LICENSE.txt ---- - -Algorithmic philosophies are computational aesthetic movements that are then expressed through code. Output .md files (philosophy), .html files (interactive viewer), and .js files (generative algorithms). - -This happens in two steps: -1. Algorithmic Philosophy Creation (.md file) -2. Express by creating p5.js generative art (.html + .js files) - -First, undertake this task: - -## ALGORITHMIC PHILOSOPHY CREATION - -To begin, create an ALGORITHMIC PHILOSOPHY (not static images or templates) that will be interpreted through: -- Computational processes, emergent behavior, mathematical beauty -- Seeded randomness, noise fields, organic systems -- Particles, flows, fields, forces -- Parametric variation and controlled chaos - -### THE CRITICAL UNDERSTANDING -- What is received: Some subtle input or instructions by the user to take into account, but use as a foundation; it should not constrain creative freedom. -- What is created: An algorithmic philosophy/generative aesthetic movement. -- What happens next: The same version receives the philosophy and EXPRESSES IT IN CODE - creating p5.js sketches that are 90% algorithmic generation, 10% essential parameters. - -Consider this approach: -- Write a manifesto for a generative art movement -- The next phase involves writing the algorithm that brings it to life - -The philosophy must emphasize: Algorithmic expression. Emergent behavior. Computational beauty. Seeded variation. - -### HOW TO GENERATE AN ALGORITHMIC PHILOSOPHY - -**Name the movement** (1-2 words): "Organic Turbulence" / "Quantum Harmonics" / "Emergent Stillness" - -**Articulate the philosophy** (4-6 paragraphs - concise but complete): - -To capture the ALGORITHMIC essence, express how this philosophy manifests through: -- Computational processes and mathematical relationships? -- Noise functions and randomness patterns? -- Particle behaviors and field dynamics? -- Temporal evolution and system states? -- Parametric variation and emergent complexity? - -**CRITICAL GUIDELINES:** -- **Avoid redundancy**: Each algorithmic aspect should be mentioned once. Avoid repeating concepts about noise theory, particle dynamics, or mathematical principles unless adding new depth. -- **Emphasize craftsmanship REPEATEDLY**: The philosophy MUST stress multiple times that the final algorithm should appear as though it took countless hours to develop, was refined with care, and comes from someone at the absolute top of their field. This framing is essential - repeat phrases like "meticulously crafted algorithm," "the product of deep computational expertise," "painstaking optimization," "master-level implementation." -- **Leave creative space**: Be specific about the algorithmic direction, but concise enough that the next Claude has room to make interpretive implementation choices at an extremely high level of craftsmanship. - -The philosophy must guide the next version to express ideas ALGORITHMICALLY, not through static images. Beauty lives in the process, not the final frame. - -### PHILOSOPHY EXAMPLES - -**"Organic Turbulence"** -Philosophy: Chaos constrained by natural law, order emerging from disorder. -Algorithmic expression: Flow fields driven by layered Perlin noise. Thousands of particles following vector forces, their trails accumulating into organic density maps. Multiple noise octaves create turbulent regions and calm zones. Color emerges from velocity and density - fast particles burn bright, slow ones fade to shadow. The algorithm runs until equilibrium - a meticulously tuned balance where every parameter was refined through countless iterations by a master of computational aesthetics. - -**"Quantum Harmonics"** -Philosophy: Discrete entities exhibiting wave-like interference patterns. -Algorithmic expression: Particles initialized on a grid, each carrying a phase value that evolves through sine waves. When particles are near, their phases interfere - constructive interference creates bright nodes, destructive creates voids. Simple harmonic motion generates complex emergent mandalas. The result of painstaking frequency calibration where every ratio was carefully chosen to produce resonant beauty. - -**"Recursive Whispers"** -Philosophy: Self-similarity across scales, infinite depth in finite space. -Algorithmic expression: Branching structures that subdivide recursively. Each branch slightly randomized but constrained by golden ratios. L-systems or recursive subdivision generate tree-like forms that feel both mathematical and organic. Subtle noise perturbations break perfect symmetry. Line weights diminish with each recursion level. Every branching angle the product of deep mathematical exploration. - -**"Field Dynamics"** -Philosophy: Invisible forces made visible through their effects on matter. -Algorithmic expression: Vector fields constructed from mathematical functions or noise. Particles born at edges, flowing along field lines, dying when they reach equilibrium or boundaries. Multiple fields can attract, repel, or rotate particles. The visualization shows only the traces - ghost-like evidence of invisible forces. A computational dance meticulously choreographed through force balance. - -**"Stochastic Crystallization"** -Philosophy: Random processes crystallizing into ordered structures. -Algorithmic expression: Randomized circle packing or Voronoi tessellation. Start with random points, let them evolve through relaxation algorithms. Cells push apart until equilibrium. Color based on cell size, neighbor count, or distance from center. The organic tiling that emerges feels both random and inevitable. Every seed produces unique crystalline beauty - the mark of a master-level generative algorithm. - -*These are condensed examples. The actual algorithmic philosophy should be 4-6 substantial paragraphs.* - -### ESSENTIAL PRINCIPLES -- **ALGORITHMIC PHILOSOPHY**: Creating a computational worldview to be expressed through code -- **PROCESS OVER PRODUCT**: Always emphasize that beauty emerges from the algorithm's execution - each run is unique -- **PARAMETRIC EXPRESSION**: Ideas communicate through mathematical relationships, forces, behaviors - not static composition -- **ARTISTIC FREEDOM**: The next Claude interprets the philosophy algorithmically - provide creative implementation room -- **PURE GENERATIVE ART**: This is about making LIVING ALGORITHMS, not static images with randomness -- **EXPERT CRAFTSMANSHIP**: Repeatedly emphasize the final algorithm must feel meticulously crafted, refined through countless iterations, the product of deep expertise by someone at the absolute top of their field in computational aesthetics - -**The algorithmic philosophy should be 4-6 paragraphs long.** Fill it with poetic computational philosophy that brings together the intended vision. Avoid repeating the same points. Output this algorithmic philosophy as a .md file. - ---- - -## DEDUCING THE CONCEPTUAL SEED - -**CRITICAL STEP**: Before implementing the algorithm, identify the subtle conceptual thread from the original request. - -**THE ESSENTIAL PRINCIPLE**: -The concept is a **subtle, niche reference embedded within the algorithm itself** - not always literal, always sophisticated. Someone familiar with the subject should feel it intuitively, while others simply experience a masterful generative composition. The algorithmic philosophy provides the computational language. The deduced concept provides the soul - the quiet conceptual DNA woven invisibly into parameters, behaviors, and emergence patterns. - -This is **VERY IMPORTANT**: The reference must be so refined that it enhances the work's depth without announcing itself. Think like a jazz musician quoting another song through algorithmic harmony - only those who know will catch it, but everyone appreciates the generative beauty. - ---- - -## P5.JS IMPLEMENTATION - -With the philosophy AND conceptual framework established, express it through code. Pause to gather thoughts before proceeding. Use only the algorithmic philosophy created and the instructions below. - -### ⚠️ STEP 0: READ THE TEMPLATE FIRST ⚠️ - -**CRITICAL: BEFORE writing any HTML:** - -1. **Read** `templates/viewer.html` using the Read tool -2. **Study** the exact structure, styling, and Anthropic branding -3. **Use that file as the LITERAL STARTING POINT** - not just inspiration -4. **Keep all FIXED sections exactly as shown** (header, sidebar structure, Anthropic colors/fonts, seed controls, action buttons) -5. **Replace only the VARIABLE sections** marked in the file's comments (algorithm, parameters, UI controls for parameters) - -**Avoid:** -- ❌ Creating HTML from scratch -- ❌ Inventing custom styling or color schemes -- ❌ Using system fonts or dark themes -- ❌ Changing the sidebar structure - -**Follow these practices:** -- ✅ Copy the template's exact HTML structure -- ✅ Keep Anthropic branding (Poppins/Lora fonts, light colors, gradient backdrop) -- ✅ Maintain the sidebar layout (Seed → Parameters → Colors? → Actions) -- ✅ Replace only the p5.js algorithm and parameter controls - -The template is the foundation. Build on it, don't rebuild it. - ---- - -To create gallery-quality computational art that lives and breathes, use the algorithmic philosophy as the foundation. - -### TECHNICAL REQUIREMENTS - -**Seeded Randomness (Art Blocks Pattern)**: -```javascript -// ALWAYS use a seed for reproducibility -let seed = 12345; // or hash from user input -randomSeed(seed); -noiseSeed(seed); -``` - -**Parameter Structure - FOLLOW THE PHILOSOPHY**: - -To establish parameters that emerge naturally from the algorithmic philosophy, consider: "What qualities of this system can be adjusted?" - -```javascript -let params = { - seed: 12345, // Always include seed for reproducibility - // colors - // Add parameters that control YOUR algorithm: - // - Quantities (how many?) - // - Scales (how big? how fast?) - // - Probabilities (how likely?) - // - Ratios (what proportions?) - // - Angles (what direction?) - // - Thresholds (when does behavior change?) -}; -``` - -**To design effective parameters, focus on the properties the system needs to be tunable rather than thinking in terms of "pattern types".** - -**Core Algorithm - EXPRESS THE PHILOSOPHY**: - -**CRITICAL**: The algorithmic philosophy should dictate what to build. - -To express the philosophy through code, avoid thinking "which pattern should I use?" and instead think "how to express this philosophy through code?" - -If the philosophy is about **organic emergence**, consider using: -- Elements that accumulate or grow over time -- Random processes constrained by natural rules -- Feedback loops and interactions - -If the philosophy is about **mathematical beauty**, consider using: -- Geometric relationships and ratios -- Trigonometric functions and harmonics -- Precise calculations creating unexpected patterns - -If the philosophy is about **controlled chaos**, consider using: -- Random variation within strict boundaries -- Bifurcation and phase transitions -- Order emerging from disorder - -**The algorithm flows from the philosophy, not from a menu of options.** - -To guide the implementation, let the conceptual essence inform creative and original choices. Build something that expresses the vision for this particular request. - -**Canvas Setup**: Standard p5.js structure: -```javascript -function setup() { - createCanvas(1200, 1200); - // Initialize your system -} - -function draw() { - // Your generative algorithm - // Can be static (noLoop) or animated -} -``` - -### CRAFTSMANSHIP REQUIREMENTS - -**CRITICAL**: To achieve mastery, create algorithms that feel like they emerged through countless iterations by a master generative artist. Tune every parameter carefully. Ensure every pattern emerges with purpose. This is NOT random noise - this is CONTROLLED CHAOS refined through deep expertise. - -- **Balance**: Complexity without visual noise, order without rigidity -- **Color Harmony**: Thoughtful palettes, not random RGB values -- **Composition**: Even in randomness, maintain visual hierarchy and flow -- **Performance**: Smooth execution, optimized for real-time if animated -- **Reproducibility**: Same seed ALWAYS produces identical output - -### OUTPUT FORMAT - -Output: -1. **Algorithmic Philosophy** - As markdown or text explaining the generative aesthetic -2. **Single HTML Artifact** - Self-contained interactive generative art built from `templates/viewer.html` (see STEP 0 and next section) - -The HTML artifact contains everything: p5.js (from CDN), the algorithm, parameter controls, and UI - all in one file that works immediately in claude.ai artifacts or any browser. Start from the template file, not from scratch. - ---- - -## INTERACTIVE ARTIFACT CREATION - -**REMINDER: `templates/viewer.html` should have already been read (see STEP 0). Use that file as the starting point.** - -To allow exploration of the generative art, create a single, self-contained HTML artifact. Ensure this artifact works immediately in claude.ai or any browser - no setup required. Embed everything inline. - -### CRITICAL: WHAT'S FIXED VS VARIABLE - -The `templates/viewer.html` file is the foundation. It contains the exact structure and styling needed. - -**FIXED (always include exactly as shown):** -- Layout structure (header, sidebar, main canvas area) -- Anthropic branding (UI colors, fonts, gradients) -- Seed section in sidebar: - - Seed display - - Previous/Next buttons - - Random button - - Jump to seed input + Go button -- Actions section in sidebar: - - Regenerate button - - Reset button - -**VARIABLE (customize for each artwork):** -- The entire p5.js algorithm (setup/draw/classes) -- The parameters object (define what the art needs) -- The Parameters section in sidebar: - - Number of parameter controls - - Parameter names - - Min/max/step values for sliders - - Control types (sliders, inputs, etc.) -- Colors section (optional): - - Some art needs color pickers - - Some art might use fixed colors - - Some art might be monochrome (no color controls needed) - - Decide based on the art's needs - -**Every artwork should have unique parameters and algorithm!** The fixed parts provide consistent UX - everything else expresses the unique vision. - -### REQUIRED FEATURES - -**1. Parameter Controls** -- Sliders for numeric parameters (particle count, noise scale, speed, etc.) -- Color pickers for palette colors -- Real-time updates when parameters change -- Reset button to restore defaults - -**2. Seed Navigation** -- Display current seed number -- "Previous" and "Next" buttons to cycle through seeds -- "Random" button for random seed -- Input field to jump to specific seed -- Generate 100 variations when requested (seeds 1-100) - -**3. Single Artifact Structure** -```html - - - - - - - - -
                                                                                                -
                                                                                                - -
                                                                                                - - - -``` - -**CRITICAL**: This is a single artifact. No external files, no imports (except p5.js CDN). Everything inline. - -**4. Implementation Details - BUILD THE SIDEBAR** - -The sidebar structure: - -**1. Seed (FIXED)** - Always include exactly as shown: -- Seed display -- Prev/Next/Random/Jump buttons - -**2. Parameters (VARIABLE)** - Create controls for the art: -```html -
                                                                                                - - - ... -
                                                                                                -``` -Add as many control-group divs as there are parameters. - -**3. Colors (OPTIONAL/VARIABLE)** - Include if the art needs adjustable colors: -- Add color pickers if users should control palette -- Skip this section if the art uses fixed colors -- Skip if the art is monochrome - -**4. Actions (FIXED)** - Always include exactly as shown: -- Regenerate button -- Reset button -- Download PNG button - -**Requirements**: -- Seed controls must work (prev/next/random/jump/display) -- All parameters must have UI controls -- Regenerate, Reset, Download buttons must work -- Keep Anthropic branding (UI styling, not art colors) - -### USING THE ARTIFACT - -The HTML artifact works immediately: -1. **In claude.ai**: Displayed as an interactive artifact - runs instantly -2. **As a file**: Save and open in any browser - no server needed -3. **Sharing**: Send the HTML file - it's completely self-contained - ---- - -## VARIATIONS & EXPLORATION - -The artifact includes seed navigation by default (prev/next/random buttons), allowing users to explore variations without creating multiple files. If the user wants specific variations highlighted: - -- Include seed presets (buttons for "Variation 1: Seed 42", "Variation 2: Seed 127", etc.) -- Add a "Gallery Mode" that shows thumbnails of multiple seeds side-by-side -- All within the same single artifact - -This is like creating a series of prints from the same plate - the algorithm is consistent, but each seed reveals different facets of its potential. The interactive nature means users discover their own favorites by exploring the seed space. - ---- - -## THE CREATIVE PROCESS - -**User request** → **Algorithmic philosophy** → **Implementation** - -Each request is unique. The process involves: - -1. **Interpret the user's intent** - What aesthetic is being sought? -2. **Create an algorithmic philosophy** (4-6 paragraphs) describing the computational approach -3. **Implement it in code** - Build the algorithm that expresses this philosophy -4. **Design appropriate parameters** - What should be tunable? -5. **Build matching UI controls** - Sliders/inputs for those parameters - -**The constants**: -- Anthropic branding (colors, fonts, layout) -- Seed navigation (always present) -- Self-contained HTML artifact - -**Everything else is variable**: -- The algorithm itself -- The parameters -- The UI controls -- The visual outcome - -To achieve the best results, trust creativity and let the philosophy guide the implementation. - ---- - -## RESOURCES - -This skill includes helpful templates and documentation: - -- **templates/viewer.html**: REQUIRED STARTING POINT for all HTML artifacts. - - This is the foundation - contains the exact structure and Anthropic branding - - **Keep unchanged**: Layout structure, sidebar organization, Anthropic colors/fonts, seed controls, action buttons - - **Replace**: The p5.js algorithm, parameter definitions, and UI controls in Parameters section - - The extensive comments in the file mark exactly what to keep vs replace - -- **templates/generator_template.js**: Reference for p5.js best practices and code structure principles. - - Shows how to organize parameters, use seeded randomness, structure classes - - NOT a pattern menu - use these principles to build unique algorithms - - Embed algorithms inline in the HTML artifact (don't create separate .js files) - -**Critical reminder**: -- The **template is the STARTING POINT**, not inspiration -- The **algorithm is where to create** something unique -- Don't copy the flow field example - build what the philosophy demands -- But DO keep the exact UI structure and Anthropic branding from the template \ No newline at end of file diff --git a/content/mcp/extensions/apps/build.md b/content/mcp/extensions/apps/build.md deleted file mode 100644 index a1f545740..000000000 --- a/content/mcp/extensions/apps/build.md +++ /dev/null @@ -1,519 +0,0 @@ -> ## Documentation Index -> Fetch the complete documentation index at: https://modelcontextprotocol.io/llms.txt -> Use this file to discover all available pages before exploring further. - -# Build an MCP App - -> Getting started guide for building interactive UI applications with MCP Apps - -## Prerequisites - -You'll need [Node.js](https://nodejs.org/en/download) 18 or higher. Familiarity -with [MCP tools](/specification/latest/server/tools) and -[resources](/specification/latest/server/resources) is recommended since MCP -Apps combine both primitives. Experience with the -[MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) -will help you better understand the server-side patterns. - -## Getting started - -The fastest way to create an MCP App is using an AI coding agent with the MCP -Apps skill. If you prefer to set up a project manually, skip to -[Manual setup](#manual-setup). - -### Using an AI coding agent - -AI coding agents with Skills support can scaffold a complete MCP App project for -you. Skills are folders of instructions and resources that your agent loads when -relevant. They teach the AI how to perform specialized tasks like creating MCP -Apps. - -The `create-mcp-app` skill includes architecture guidance, best practices, and -working examples that the agent uses to generate your project. - - - - If you are using Claude Code, you can install the skill directly with: - - ``` - /plugin marketplace add modelcontextprotocol/ext-apps - /plugin install mcp-apps@modelcontextprotocol-ext-apps - ``` - - You can also use the [Vercel Skills CLI](https://skills.sh/) to install skills across different AI coding agents: - - ```bash theme={null} - npx skills add modelcontextprotocol/ext-apps - ``` - - Alternatively, you can install the skill manually by cloning the ext-apps repository: - - ```bash theme={null} - git clone https://github.com/modelcontextprotocol/ext-apps.git - ``` - - And then copying the skill to the appropriate location for your agent: - - | Agent | Skills directory (macOS/Linux) | Skills directory (Windows) | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------- | - | [Claude Code](https://docs.anthropic.com/en/docs/claude-code/skills) | `~/.claude/skills/` | `%USERPROFILE%\.claude\skills\` | - | [VS Code](https://code.visualstudio.com/docs/copilot/customization/agent-skills) and [GitHub Copilot](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills) | `~/.copilot/skills/` | `%USERPROFILE%\.copilot\skills\` | - | [Gemini CLI](https://geminicli.com/docs/cli/skills/) | `~/.gemini/skills/` | `%USERPROFILE%\.gemini\skills\` | - | [Cline](https://cline.bot/blog/cline-3-48-0-skills-and-websearch-make-cline-smarter) | `~/.cline/skills/` | `%USERPROFILE%\.cline\skills\` | - | [Goose](https://goose-docs.ai/docs/guides/context-engineering/using-skills/) | `~/.config/goose/skills/` | `%USERPROFILE%\.config\goose\skills\` | - | [Codex](https://developers.openai.com/codex/skills/) | `~/.codex/skills/` | `%USERPROFILE%\.codex\skills\` | - | [Cursor](https://cursor.com/docs/context/skills) | `~/.cursor/skills/` | `%USERPROFILE%\.cursor\skills\` | - - - This list is not comprehensive. Other agents may support skills in different locations; check your agent's documentation. - - - For example, with Claude Code you can install the skill globally (available in all projects): - - - ```bash macOS/Linux theme={null} - cp -r ext-apps/plugins/mcp-apps/skills/create-mcp-app ~/.claude/skills/create-mcp-app - ``` - - ```powershell Windows theme={null} - Copy-Item -Recurse ext-apps\plugins\mcp-apps\skills\create-mcp-app $env:USERPROFILE\.claude\skills\create-mcp-app - ``` - - - Or install it for a single project only by copying to `.claude/skills/` in your project directory: - - - ```bash macOS/Linux theme={null} - mkdir -p .claude/skills && cp -r ext-apps/plugins/mcp-apps/skills/create-mcp-app .claude/skills/create-mcp-app - ``` - - ```powershell Windows theme={null} - New-Item -ItemType Directory -Force -Path .claude\skills | Out-Null; Copy-Item -Recurse ext-apps\plugins\mcp-apps\skills\create-mcp-app .claude\skills\create-mcp-app - ``` - - - To verify the skill is installed, ask your agent "What skills do you have access to?" — you should see `create-mcp-app` as one of the available skills. - - - - Ask your AI coding agent to build it: - - ``` - Create an MCP App that displays a color picker - ``` - - The agent will recognize the `create-mcp-app` skill is relevant, load its instructions, then scaffold a complete project with server, UI, and configuration files. - - - Creating a new MCP App with Claude Code - - - - - - ```bash macOS/Linux theme={null} - npm install && npm run build && npm run serve - ``` - - ```powershell Windows theme={null} - npm install; npm run build; npm run serve - ``` - - - - You might need to make sure that you are first in the **app folder** before running the commands above. - - - - - Follow the instructions in [Testing your app](#testing-your-app) below. For the color picker example, start a new chat and ask Claude to provide you a color picker. - - - Testing the color picker in Claude - - - - -### Manual setup - -If you're not using an AI coding agent, or prefer to understand the setup -process, follow these steps. - - - - A typical MCP App project separates the server code from the UI code: - - - - - - - - - - - - - - - - - - - - The server registers the tool and serves the UI resource. The UI resource will eventually be rendered in a secure iframe with deny-by-default CSP configuration. If your app has CSS and JS assets, you will need to [configure CSP](https://apps.extensions.modelcontextprotocol.io/api/documents/Patterns.html#configuring-csp-and-cors), or you can bundle your assets into the HTML with a tool like `vite-plugin-singlefile`, which is what we will do in this tutorial. - - - - ```bash theme={null} - npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk - npm install -D typescript vite vite-plugin-singlefile express cors @types/express @types/cors tsx - ``` - - The `ext-apps` package provides helpers for both the server side (registering tools and resources) and the client side (the `App` class for UI-to-host communication). Vite with the `vite-plugin-singlefile` plugin is used here to bundle your UI and assets into a single HTML file for convenience, but this is optional — you can use any bundler or serve unbundled files if you [configure CSP](https://apps.extensions.modelcontextprotocol.io/api/documents/Patterns.html#configuring-csp-and-cors). - - - - - - The `"type": "module"` setting enables ES module syntax. The `build` script uses the `INPUT` environment variable to tell Vite which HTML file to bundle. The `serve` script runs your server using `tsx` for TypeScript execution. - - ```json theme={null} - { - "type": "module", - "scripts": { - "build": "INPUT=mcp-app.html vite build", - "serve": "npx tsx server.ts" - } - } - ``` - - - - The TypeScript configuration targets modern JavaScript (`ES2022`) and uses ESNext modules with bundler resolution, which works well with Vite. The `include` array covers both the server code in the root and UI code in `src/`. - - ```json theme={null} - { - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "outDir": "dist" - }, - "include": ["*.ts", "src/**/*.ts"] - } - ``` - - - - ```typescript theme={null} - import { defineConfig } from "vite"; - import { viteSingleFile } from "vite-plugin-singlefile"; - - export default defineConfig({ - plugins: [viteSingleFile()], - build: { - outDir: "dist", - rollupOptions: { - input: process.env.INPUT, - }, - }, - }); - ``` - - - - - - With the project structure and configuration in place, continue to [Building an MCP App](#building-an-mcp-app) below to implement the server and UI. - - - -## Building an MCP App - -Let's build a simple app that displays the current server time. This example -demonstrates the full pattern: registering a tool with UI metadata, serving the -bundled HTML as a resource, and building a UI that communicates with the server. - -### Server implementation - -The server needs to do two things: register a tool that includes the -`_meta.ui.resourceUri` field, and register a resource handler that serves the -bundled HTML. Here's the complete server file: - -```typescript theme={null} -// server.ts -console.log("Starting MCP App server..."); - -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; -import { - registerAppTool, - registerAppResource, - RESOURCE_MIME_TYPE, -} from "@modelcontextprotocol/ext-apps/server"; -import cors from "cors"; -import express from "express"; -import fs from "node:fs/promises"; -import path from "node:path"; - -const server = new McpServer({ - name: "My MCP App Server", - version: "1.0.0", -}); - -// The ui:// scheme tells hosts this is an MCP App resource. -// The path structure is arbitrary; organize it however makes sense for your app. -const resourceUri = "ui://get-time/mcp-app.html"; - -// Register the tool that returns the current time -registerAppTool( - server, - "get-time", - { - title: "Get Time", - description: "Returns the current server time.", - inputSchema: {}, - _meta: { ui: { resourceUri } }, - }, - async () => { - const time = new Date().toISOString(); - return { - content: [{ type: "text", text: time }], - }; - }, -); - -// Register the resource that serves the bundled HTML -registerAppResource( - server, - resourceUri, - resourceUri, - { mimeType: RESOURCE_MIME_TYPE }, - async () => { - const html = await fs.readFile( - path.join(import.meta.dirname, "dist", "mcp-app.html"), - "utf-8", - ); - return { - contents: [ - { uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html }, - ], - }; - }, -); - -// Expose the MCP server over HTTP -const expressApp = express(); -expressApp.use(cors()); -expressApp.use(express.json()); - -expressApp.post("/mcp", async (req, res) => { - const transport = new StreamableHTTPServerTransport({ - sessionIdGenerator: undefined, - enableJsonResponse: true, - }); - res.on("close", () => transport.close()); - await server.connect(transport); - await transport.handleRequest(req, res, req.body); -}); - -expressApp.listen(3001, (err) => { - if (err) { - console.error("Error starting server:", err); - process.exit(1); - } - console.log("Server listening on http://localhost:3001/mcp"); -}); -``` - -Let's break down the key parts: - -* **`resourceUri`**: The `ui://` scheme tells hosts this is an MCP App resource. - The path structure is arbitrary. -* **`registerAppTool`**: Registers a tool with the `_meta.ui.resourceUri` field. - When the host calls this tool, the UI is fetched and rendered, and the tool result is passed to it upon arrival. -* **`registerAppResource`**: Serves the bundled HTML when the host requests the UI resource. -* **Express server**: Exposes the MCP server over HTTP on port 3001. - -### UI implementation - -The UI consists of an HTML page and a TypeScript module that uses the `App` -class to communicate with the host. Here's the HTML: - -```html theme={null} - - - - - - Get Time App - - -

                                                                                                - Server Time: - Loading... -

                                                                                                - - - - -``` - -And the TypeScript module: - -```typescript theme={null} -// src/mcp-app.ts -import { App } from "@modelcontextprotocol/ext-apps"; - -const serverTimeEl = document.getElementById("server-time")!; -const getTimeBtn = document.getElementById("get-time-btn")!; - -const app = new App({ name: "Get Time App", version: "1.0.0" }); - -// Establish communication with the host -app.connect(); - -// Handle the initial tool result pushed by the host -app.ontoolresult = (result) => { - const time = result.content?.find((c) => c.type === "text")?.text; - serverTimeEl.textContent = time ?? "[ERROR]"; -}; - -// Proactively call tools when users interact with the UI -getTimeBtn.addEventListener("click", async () => { - const result = await app.callServerTool({ - name: "get-time", - arguments: {}, - }); - const time = result.content?.find((c) => c.type === "text")?.text; - serverTimeEl.textContent = time ?? "[ERROR]"; -}); -``` - -The key parts: - -* **`app.connect()`**: Establishes communication with the host. Call this once - when your app initializes. -* **`app.ontoolresult`**: A callback that fires when the host pushes a tool - result to your app (e.g., when the tool is first called and the UI renders). -* **`app.callServerTool()`**: Lets your app proactively call tools on the server. - Keep in mind that each call involves a round-trip to the server, so design your - UI to handle latency gracefully. - -The `App` class provides additional methods for logging, opening URLs, and -updating the model's context with structured data from your app. See the full -[API documentation](https://apps.extensions.modelcontextprotocol.io/api/). - -## Testing your app - -To test your MCP App, build the UI and start your local server: - - - ```bash macOS/Linux theme={null} - npm run build && npm run serve - ``` - - ```powershell Windows theme={null} - npm run build; npm run serve - ``` - - -In the default configuration, your server will be available at -`http://localhost:3001/mcp`. However, to see your app render, you need an MCP -host that supports MCP Apps. You have several options. - -### Testing with Claude - -[Claude](https://claude.ai) (web) and [Claude Desktop](https://claude.ai/download) -support MCP Apps. For local development, you'll need to expose your server to -the internet. You can run an MCP server locally and use tools like `cloudflared` -to tunnel traffic through. - -In a separate terminal, run: - -```bash theme={null} -npx cloudflared tunnel --url http://localhost:3001 -``` - -Copy the generated URL (e.g., `https://random-name.trycloudflare.com`) and add it -as a [custom connector](https://support.anthropic.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) -in Claude - click on your profile, go to **Settings**, **Connectors**, and -finally **Add custom connector**. - - - Custom connectors are available on paid Claude plans (Pro, Max, or Team). - - - - Adding a custom connector in Claude - - -### Testing with the basic-host - -The `ext-apps` repository includes a test host for development. Clone the repo and -install dependencies: - - - ```bash macOS/Linux theme={null} - git clone https://github.com/modelcontextprotocol/ext-apps.git - cd ext-apps/examples/basic-host - npm install - ``` - - ```powershell Windows theme={null} - git clone https://github.com/modelcontextprotocol/ext-apps.git - cd ext-apps\examples\basic-host - npm install - ``` - - -Running `npm start` from `ext-apps/examples/basic-host/` will start the basic-host -test interface. To connect it to a specific server (e.g., one you're developing), -pass the `SERVERS` environment variable inline: - - - ```bash macOS/Linux theme={null} - SERVERS='["http://localhost:3001/mcp"]' npm start - ``` - - ```powershell Windows theme={null} - $env:SERVERS='["http://localhost:3001/mcp"]'; npm start - ``` - - -Navigate to `http://localhost:8080`. You'll see a simple interface where you can -select a tool and call it. When you call your tool, the host fetches the UI -resource and renders it in a sandboxed iframe. You can then interact with your -app and verify that tool calls work correctly. - - - Example of the QR code MCP App running with the basic host - - -## Learn more - - - - Full SDK reference and API details - - - - Source code, examples, and issue tracker - - - - Technical specification for implementers - - - -## Feedback - -MCP Apps is under active development. If you encounter issues or have ideas for -improvements, open an issue on the -[GitHub repository](https://github.com/modelcontextprotocol/ext-apps/issues). -For broader discussions about the extension's direction, join the conversation -in [GitHub Discussions](https://github.com/modelcontextprotocol/ext-apps/discussions). diff --git a/scripts/fetcher.py b/scripts/fetcher.py old mode 100755 new mode 100644 index a45e772f0..e45ead95f --- a/scripts/fetcher.py +++ b/scripts/fetcher.py @@ -69,6 +69,21 @@ ] +def looks_like_html(content: bytes) -> bool: + """True if the body is an HTML page rather than the markdown we asked for. + + platform.claude.com answers unknown doc paths with its Next.js app shell at + HTTP 200 — a soft 404. raise_for_status() sees nothing wrong, so without + this check the shell gets written straight into a .md file. That is how 53 + files, 44 of them under content/en/api/kotlin/, ended up holding + " Dict: return {"url": url, "status": "skipped"} try: content = await self.fetch_bytes(session, f"{url}.md") + if looks_like_html(content): + # Soft 404: HTTP 200 with the site's HTML shell. Writing it + # would replace docs with markup, and because incremental + # mode skips paths that already exist, a bad file is never + # re-fetched — it just stays wrong. + self.stats["failed"] += 1 + return { + "url": url, "status": "failed", + "error": "upstream returned HTML, not markdown (soft 404)", + } output_path.parent.mkdir(parents=True, exist_ok=True) async with aiofiles.open(output_path, "wb") as f: await f.write(content) @@ -188,6 +213,12 @@ async def download_github_file(self, session, repo, branch, filepath, semaphore) return {"url": url, "status": "skipped"} try: content = await self.fetch_bytes(session, url) + if filepath.endswith(".md") and looks_like_html(content): + self.stats["failed"] += 1 + return { + "url": url, "status": "failed", + "error": "upstream returned HTML, not markdown", + } output_path.parent.mkdir(parents=True, exist_ok=True) async with aiofiles.open(output_path, "wb") as f: await f.write(content)