Claude Skill Scripts — Research Notes

# How Scripts Work in Claude Skills

Research notes — compiled from the official Claude Code docs and the Agent Skills open standard

## 1. Overview: What Is a Skill?

A skill is a folder containing a `SKILL.md` file (with YAML frontmatter + Markdown instructions) plus optional supporting files. Claude Code discovers skills in:

Location | Path | Scope
--- | --- | ---
Personal | `~/.claude/skills/<name>/SKILL.md` | All your projects
Project | `.claude/skills/<name>/SKILL.md` | This project only
Plugin | `<plugin>/skills/<name>/SKILL.md` | Where plugin enabled
Enterprise | Managed settings | Entire org

Skills follow the Agent Skills open standard (adopted by Claude Code, Cursor, VS Code, Gemini CLI, Roo Code, and many others). Claude Code extends the standard with invocation control, subagent execution, and dynamic context injection.

## 2. Skill Directory Structure

    my-skill/
    ├── SKILL.md           # Required — metadata + instructions (the entrypoint)
    ├── scripts/           # Optional — executable code Claude can run
    │   ├── validate.sh
    │   └── process.py
    ├── references/        # Optional — extra docs loaded on demand
    │   └── REFERENCE.md
    ├── assets/            # Optional — templates, schemas, data files
    │   └── template.json
    └── examples/          # Optional — example outputs
        └── sample.md

Key points from the spec:

- `SKILL.md` is the only required file. Everything else is optional.
- Supporting files (`scripts/`, `references/`, `assets/`) are loaded on demand, not automatically injected into context.
- `SKILL.md` should be kept under 500 lines. Move detailed material to separate files.

## 3. How Scripts Under `scripts/` Are Used by Claude Code

### Key Insight

Scripts are not automatically executed when a skill loads. They are files that Claude is instructed to run via the Bash tool, according to the instructions in `SKILL.md`. The `scripts/` directory is simply a conventional place to put executable code that the skill's instructions tell Claude to run.

Here's the full lifecycle:

1. Discovery — Claude Code scans skill directories and loads each skill's `name` and `description` into context so Claude knows what's available (~100 tokens per skill).
2. Activation — When a skill is invoked (by the user via `/skill-name`, or by Claude when it decides the skill is relevant), the full SKILL.md body is loaded into Claude's context.
3. Instruction following — Claude reads the SKILL.md instructions, which tell it to run specific scripts. Claude uses its `Bash` tool to execute them.
4. Script execution — Claude runs the script as a shell command. The script's stdout/stderr are returned to Claude, which then uses the output to continue its task.

Scripts are not magic. They are regular files (Python, Bash, JS, etc.) that Claude runs via its Bash tool. The `scripts/` directory is purely a convention — you reference scripts from `SKILL.md` using relative paths, and Claude executes them as shell commands.

### How Claude resolves script paths

There are two approaches:

### A. Relative paths from SKILL.md

You reference scripts relative to the skill directory root. Claude resolves these automatically:

    # In SKILL.md:
    Run the validation script:
    ```bash
    bash scripts/validate.sh "$INPUT_FILE"
    ```

### B. Using `${CLAUDE_SKILL_DIR}`

For scripts that need absolute paths (e.g., when the working directory might be different), use the `${CLAUDE_SKILL_DIR}` substitution variable, which resolves to the directory containing the skill's `SKILL.md`:

    # In SKILL.md:
    ```bash
    python ${CLAUDE_SKILL_DIR}/scripts/visualize.py .
    ```

Or with a hardcoded personal skill path:

    python ~/.claude/skills/codebase-visualizer/scripts/visualize.py .

### The `allowed-tools` connection

If your script needs Claude to run Bash commands, you can pre-approve them in frontmatter so Claude doesn't ask for permission each time:

    ---
    name: my-skill
    allowed-tools: Bash(python *), Bash(bash *)
    ---

## 4. Conventions for Writing Skill Scripts

These conventions come from the Agent Skills "Using Scripts" guide and are critical for making scripts work well with Claude (or any AI agent):

### 🚫 No interactive prompts

This is a hard requirement. Agents run scripts in non-interactive shells — they cannot respond to TTY prompts, password dialogs, or confirmation menus. A script that blocks on input will hang indefinitely.

    # ❌ Bad: hangs waiting for input
    $ python scripts/deploy.py
    Target environment: _

    # ✅ Good: accepts input via flags
    $ python scripts/deploy.py --env staging --tag v1.2.3

    # ✅ Good: clear error when required args missing
    $ python scripts/deploy.py
    Error: --env is required. Options: development, staging, production.
    Usage: python scripts/deploy.py --env staging --tag v1.2.3

### 📖 Implement `--help`

`--help` output is the primary way an agent learns your script's interface. Include a brief description, available flags, and usage examples:

    Usage: scripts/process.py [OPTIONS] INPUT_FILE

    Process input data and produce a summary report.

    Options:
      --format FORMAT   Output format: json, csv, table (default: json)
      --output FILE     Write output to FILE instead of stdout
      --verbose         Print progress to stderr

    Examples:
      scripts/process.py data.csv
      scripts/process.py --format csv --output report.csv data.csv

### 📝 Write helpful error messages

When the agent gets an error, the message directly shapes its next attempt. Say what went wrong, what was expected, and what to try:

    # ❌ Opaque
    Error: invalid input

    # ✅ Actionable
    Error: --format must be one of: json, csv, table. Received: "xml"

### 📊 Use structured output

Prefer JSON, CSV, or TSV over free-form text. Send structured data to stdout and diagnostics to stderr:

    # ❌ Hard to parse
    NAME        STATUS    CREATED
    my-service  running   2025-01-15

    # ✅ Unambiguous
    {"name": "my-service", "status": "running", "created": "2025-01-15"}

### 🔄 Further design considerations

Principle | Why
--- | ---
Idempotency | Agents may retry commands. "Create if not exists" is safer than "create and fail on duplicate."
Input constraints | Reject ambiguous input with a clear error. Use enums and closed sets where possible.
Dry-run support | For destructive operations, a `--dry-run` flag lets the agent preview what will happen.
Meaningful exit codes | Use distinct exit codes for different failure types and document them in `--help`.
Safe defaults | Destructive operations should require explicit `--confirm` or `--force` flags.
Predictable output size | Agent harnesses truncate output beyond ~10-30K chars. Default to summaries; support `--offset` or `--output FILE` for large data.

## 5. Referencing Scripts from SKILL.md

List available scripts and tell the agent how to run them:

    ## Available scripts
    - **`scripts/validate.sh`** — Validates configuration files
    - **`scripts/process.py`** — Processes input data

    ## Workflow
    1. Run the validation script:
       ```bash
       bash scripts/validate.sh "$INPUT_FILE"
       ```
    2. Process the results:
       ```bash
       python3 scripts/process.py --input results.json
       ```

Script execution paths (in code blocks) are relative to the skill directory root, because the agent runs commands from there. The same relative-path convention works in support files like `references/*.md`.

## 6. Self-Contained Scripts (Inline Dependencies)

When you need third-party packages, use inline dependency declarations so the script is self-contained — no separate `requirements.txt` or install step needed:

### Python (PEP 723 + uv)

    #!/usr/bin/env python3
    # /// script
    # dependencies = [
    #     "beautifulsoup4>=4.12,<5",
    #     "requests>=2.31",
    # ]
    # requires-python = ">=3.10"
    # ///

    from bs4 import BeautifulSoup
    import requests
    # ... your code ...

Run with: `uv run scripts/extract.py` — uv creates an isolated environment, installs deps, and runs it.

### Deno (TypeScript/JavaScript)

    import { parse } from "jsr:@std/csv@1.0.4";
    // ... Deno auto-resolves jsr: and npm: imports

Run with: `deno run scripts/process.ts`

### Bun

    import { $ } from "bun";
    // bun auto-installs missing packages

Tip: Pin versions in your inline dependencies (e.g. `"beautifulsoup4>=4.12,<5"`) so the script behaves the same over time.

## 7. Dynamic Context Injection with `!` Commands

Claude Code extends the Agent Skills standard with a preprocessing feature: the `!`command`` syntax runs shell commands before the skill content is sent to Claude. Output replaces the placeholder:

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

This is preprocessing, not something Claude executes. Claude only sees the final rendered output. This is different from scripts in `scripts/` which Claude actively runs during its task.

## 8. Full Example: Codebase Visualizer Skill

This example from the official docs shows the complete pattern — a skill that bundles a Python script to generate an interactive HTML visualization:

### Directory layout

    ~/.claude/skills/codebase-visualizer/
    ├── SKILL.md
    └── scripts/
        └── visualize.py

### SKILL.md

    ---
    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(python *)
    ---

    # Codebase Visualizer

    Generate an interactive HTML tree view of your project's file structure.

    ## Usage

    Run the visualization script from your project root:

    ```bash
    python ~/.claude/skills/codebase-visualizer/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

### scripts/visualize.py

A regular Python script using only stdlib (`json`, `sys`, `webbrowser`, `pathlib`, `collections`). It scans a directory tree and generates a self-contained HTML file. Key properties:

- Takes a directory path as CLI argument (no interactive prompts)
- Uses only built-in libraries (no install step)
- Prints status to stdout (`"Generated /path/to/codebase-map.html"`)
- Opens result in browser automatically

## 9. Quick Checklist for Writing Skill Scripts

# | Convention | Details
--- | --- | ---
1 | Place scripts in `scripts/` | Standard directory name per the Agent Skills spec
2 | Document scripts in SKILL.md | List each script with a description and exact run command
3 | No interactive prompts | Accept all input via CLI flags, env vars, or stdin
4 | Implement `--help` | Agent's primary way to learn the interface
5 | Helpful error messages | Say what went wrong, what was expected, and what to try
6 | Structured output (JSON/CSV) | stdout for data, stderr for diagnostics
7 | Be idempotent | Agents may retry; "create if not exists" is safer
8 | Pin dependency versions | Use PEP 723 inline deps with version ranges
9 | Self-contained if possible | Use `uv run`/`deno run`/`npx` for auto-dependency resolution
10 | Meaningful exit codes | Different codes for different failure types
11 | Safe defaults | Destructive ops need `--confirm` or `--force`
12 | Predictable output size | Default to summaries; support `--offset` for pagination
13 | Set `allowed-tools` | Pre-approve `Bash(python *)` etc. so Claude doesn't ask each time
14 | Use `${CLAUDE_SKILL_DIR}` | For absolute paths that work regardless of cwd

### Sources

- Claude Code Skills Documentation — official docs
- Agent Skills Specification — the open standard
- Agent Skills: Using Scripts — script design guide
- github.com/anthropics/skills — example skills repository