Harvard Data Science Initiative Harvard Faculty of Arts and Sciences

Generative AI for Scholarship

Harvard Data Science Initiative (HDSI) & Faculty of Arts and Sciences (FAS)

Building Custom Skills in Claude Code

Skills are reusable instructions that teach Claude Code how to perform specific tasks. Each skill becomes a slash command (like /reviewpaper or /analyze-data) that you can invoke any time. Skills are just markdown files with a bit of YAML configuration at the top — no programming required.

1 Skills Are Not Stored Prompts

You might think of a skill as a saved prompt — a convenient way to avoid retyping the same question. That undersells what's happening. A stored prompt is a message you send to an AI and wait for a text response. A skill is a set of instructions for an autonomous agent.

When you invoke a skill, Claude Code doesn't just generate text. It acts: it reads files, writes files, runs shell commands, installs packages, searches the web, creates directories, executes Python scripts, and iterates on its own work. A skill sets an agent loose to do your bidding, following the instructions you wrote.

Stored Prompt Claude Code Skill
What it produces Text response Files, code, plots, reports — actual work products
Can it take action? No — you copy/paste the output Yes — reads, writes, and executes on your machine
Multi-step? One response Plans, iterates, recovers from errors, asks follow-up questions
Reusable? Copy/paste into new chats Always available as a slash command, auto-discovered
Think of it this way: A stored prompt is like giving someone verbal instructions. A skill is like hiring a research assistant, giving them a written procedures manual, and letting them do the work.

2 What Is a Skill, Technically?

A skill is a directory containing a SKILL.md file. Your skills directory looks like this:

~/.claude/
    skills/
        newskill/
            SKILL.md
        reviewpaper/
            SKILL.md
        analyze-data/
            SKILL.md
            templates/
                report-template.md

Each SKILL.md file has two parts: YAML frontmatter (configuration) and markdown body (instructions for Claude).

Example: a simple skill

---
name: summarize-csv
description: Load a CSV file and produce a summary of its contents.
argument-hint: [filename]
allowed-tools: Read, Bash
---

# Summarize CSV Data

Load the file: **$ARGUMENTS**

1. Show the first 10 rows
2. List all columns with their data types
3. Report the number of rows and any missing values
4. Generate descriptive statistics for numeric columns
5. Suggest what kind of analysis this data might support

After saving this file, you can type /summarize-csv mydata.csv in any Claude Code session and it will follow those exact instructions.

3 Skill Configuration Options

The YAML frontmatter at the top of SKILL.md controls how the skill behaves. All fields are optional except description (recommended).

Field What It Does Example
name The slash command name (defaults to directory name) review-paper
description What the skill does — Claude uses this to decide when to auto-invoke Critique an academic paper
argument-hint Shows in autocomplete to guide the user [filename]
allowed-tools Tools the skill can use without asking permission Read, Write, Bash
model Override which model to use opus, sonnet, haiku
disable-model-invocation Set to true so only you can trigger it (not Claude automatically) true
user-invocable Set to false to hide from / menu (Claude-only background knowledge) false
context Set to fork to run in an isolated subagent fork
agent Subagent type when forked Explore, Plan, general-purpose

Variables you can use in the skill body

Variable What It Contains
$ARGUMENTS Everything the user typed after the slash command
$0, $1, $2 Individual arguments by position (0-indexed)
Best practice: add a -h flag. Any skill that accepts arguments should support -h to print a help message (like a Unix man page). Include a "Step 0: Parse Arguments" section in your skill that checks for -h, prints usage info, and stops. This makes your skills self-documenting — anyone can type /my-skill -h to see what it does and what options it supports.

4 Where Skills Live

Location Scope Use When
~/.claude/skills/ Personal — all your projects General-purpose skills you always want available
.claude/skills/ Project — this repo only Project-specific skills, shareable with collaborators via git

5 Inline vs. Forked: Two Ways to Run a Skill

By default, a skill runs inline — in your main conversation. You see everything the agent does in real time and can interact with it. Alternatively, setting context: fork runs the skill in an isolated subagent that works independently and returns a summary when it's done.

Inline (default) Forked (context: fork)
You see Every step as it happens A summary when the agent finishes
You can interact Yes — ask questions, redirect mid-task No — agent works autonomously
Good for Interactive, iterative tasks where you want control Well-defined tasks you want to hand off completely
Context Shares your conversation history Isolated — only sees the skill instructions

Examples: when to use each

Skill Inline or Forked? Why
/newskill Inline Needs back-and-forth conversation to refine the skill
/reviewpaper Forked Long-running analysis — let it work while you do other things
/validate-code Forked Runs tests, checks types, reports back — no interaction needed
/ship-it Inline Updates docs, commits, and pushes — you want to review each step
/tree Inline Quick directory listing, immediate output

6 Example Skills

Here are three concrete skills to illustrate different patterns. You don't need to build these now — they're here to show what's possible.

/tree — visualize directory structure

A quick inline skill. Shows a tree view of the current project, like the classic Unix tree command. Note the -h flag for built-in help — a good practice for any skill that accepts arguments:

---
name: tree
description: Display the hierarchical directory structure from the current working directory, like the Unix tree command. Shows three levels deep with counts for deeper content. Supports -L depth, -d dirs-only, and -h for help.
argument-hint: [-L depth] [-d] [-h] [directory]
allowed-tools: Bash, Glob
---

# Display Directory Tree

Arguments: **$ARGUMENTS**

## Step 0: Parse Arguments

Check for flags in $ARGUMENTS:

- **-h**: Print the help text below and stop. Do nothing else.
- **-L N**: Set maximum display depth to N (default: 3)
- **-d**: Show directories only, suppress files
- Any remaining non-flag argument is the target directory (default: cwd)

### Help text (for -h)

When -h is present, print exactly this and stop:

    Usage: /tree [-L depth] [-d] [-h] [directory]

    Display directory structure as an indented tree.

    Options:
      -L N    Show N levels deep (default: 3)
      -d      Directories only (suppress files)
      -h      Show this help message

## Step 1: Display the Tree

1. Use tree-style branch characters (├──, └──, │)
2. Show levels specified by -L (default 3) with full names
3. Directories at the depth limit show a summary:
   ├── subdir/ (12 files, 3 dirs)
4. If -d flag: directories only, suppress files
5. Exclude: .git, __pycache__, .venv, node_modules, .eggs, .tox, .mypy_cache
6. Directories first, then files, alphabetically
7. Summary line at bottom: X directories, Y files

/validate-code — check Python code quality (forked)

A forked skill that runs autonomously and reports back. Good example of context: fork for a task that doesn't need interaction:

---
name: validate-code
description: Run validation and verification checks on Python code. Checks for syntax errors, runs tests, and reviews code quality.
argument-hint: [file-or-directory]
context: fork
agent: general-purpose
allowed-tools: Read, Bash, Grep, Glob
---

# Validate Python Code

Target: **$ARGUMENTS**

Run these checks and report results:

1. **Syntax check**: Run `python3 -m py_compile` on all .py files
2. **Run tests**: Look for test files (test_*.py, *_test.py) and run them with `python3 -m pytest` if available, otherwise `python3 -m unittest`
3. **Import check**: Try importing each module to catch missing dependencies
4. **Code review**: Read each file and flag:
   - Unused imports
   - Functions with no docstring
   - Bare except clauses
   - Hardcoded file paths or credentials
   - Potential division by zero or index errors

Report a summary with PASS/FAIL for each check and specific line numbers for any issues found.

/ship-it — update docs, commit, and push (inline)

An inline skill for the end of a work session. Runs step by step so you can review before committing:

---
name: ship-it
description: Update all documentation to match current code, commit changes, and push to GitHub. Run at the end of a work session.
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
---

# Ship It: Wrap Up and Push

Walk through these steps, pausing to show me what you're doing at each stage:

1. **Review changes**: Run `git status` and `git diff` to show what has changed
2. **Update documentation**: Check if any README, docstrings, or comments need updating to reflect the code changes. Make the updates.
3. **Stage files**: Add the changed files to staging. Show me the list before committing.
4. **Commit**: Write a clear commit message summarizing all changes. Show me the message for approval before committing.
5. **Push**: Push to the remote. Confirm success.

Do NOT proceed past step 3 without my explicit approval of the commit message.

7 Exercise: Build a Skill That Builds Skills

The best way to learn skills is to make one. We're going to create a meta-skill called /newskill that walks you through building any new skill interactively. This is a tool that makes tools.

7a. Install the skill file

Create the skills directory and download the SKILL.md file directly:

mkdir -p ~/.claude/skills/newskill
curl -o ~/.claude/skills/newskill/SKILL.md \
  https://raw.githubusercontent.com/astrostubbs/GenAI-for-Scholarship/main/skills/newskill/SKILL.md

Alternatively, you can copy the full contents shown below in step 7c and save it manually to ~/.claude/skills/newskill/SKILL.md.

7b. Verify it's in place

cat ~/.claude/skills/newskill/SKILL.md

7c. What's inside

You should see the contents shown below. This is written for Claude to follow, not for you to read as documentation. A few things that may look unfamiliar:

---
name: newskill
description: Interactively create a new Claude Code skill through conversation. Gathers requirements, then iteratively drafts and refines the skill with user feedback until it's right.
argument-hint: [skill-name]
disable-model-invocation: true
allowed-tools: Read, Write, Bash, Glob, AskUserQuestion
---

# Create a New Skill

You are helping the user build a new Claude Code skill. The skill name provided is: **$ARGUMENTS**

If no skill name was provided, ask the user for one first.

## Step 1: Quick Configuration

Use AskUserQuestion to gather these structural choices (combine into 1-2 questions):

1. **Scope**: Personal (all projects, ~/.claude/skills/) or Project (this repo only, .claude/skills/)?
2. **Invocation**: User only, Claude only, or both?
3. **Execution**: Inline or forked subagent? If forked, which agent type?
4. **Model**: Inherit, opus, sonnet, or haiku?
5. **Arguments**: What arguments does it take? (e.g., [filename], [issue-number])

## Step 1b: Help Flag and Command-Line Options

Ask the user (via AskUserQuestion): "Should this skill support a -h flag
that prints usage help? This makes the skill self-documenting, like a Unix
command. If yes, we'll also ask about any other command-line flags it should
support (e.g., -v for verbose, -o for output file)."

If the user wants a -h flag:
- Ask what other flags/options would be useful for this skill
- The generated skill will include a "Step 0: Parse Arguments" section
  that checks for -h and prints a man-page-style help text, then stops
- All flags will be documented in the help text and in the argument-hint
  frontmatter

## Step 2: Describe What the Skill Should Do

Now ask the user to describe in their own words — in as much detail as they want — what this skill should do when invoked. Tell them:

"Describe what this skill should do. Be as detailed as you like — what steps should it take, what output should it produce, what format should it follow, any specific instructions or constraints. I'll draft the skill from your description and we'll refine it together."

Wait for the user's full description. Do NOT use AskUserQuestion for this — let them type freely in the conversation.

## Step 3: Draft the SKILL.md

Based on everything gathered, produce a complete first draft of the SKILL.md
file. Show it to the user in full — both the YAML frontmatter and the
markdown body.

If the user opted for a -h flag, the generated skill MUST include:
- A "Step 0: Parse Arguments" section that checks for flags
- A help text block printed when -h is detected (then stop)
- The help text should follow man-page conventions: Usage line,
  description, options list, examples
- All flags listed in the argument-hint frontmatter field

After showing the draft, ask: "What would you change? I can adjust the structure, add or remove sections, change the tone, make instructions more or less specific — anything. Or say 'looks good' to save it."

## Step 4: Iterative Refinement

This is the critical step. Repeat this loop:

1. The user gives feedback (add this section, remove that, rephrase this, make it more specific, etc.)
2. You revise the SKILL.md accordingly
3. Show the updated version in full
4. Ask again: "Any more changes, or ready to save?"

Continue until the user says it's ready. Do NOT rush to save — the user should feel they can keep refining as long as they want.

During refinement, actively help:
- If instructions are vague, suggest ways to make them more specific
- If the scope is too broad, suggest breaking it into multiple skills
- If something would work better as a different frontmatter option, say so
- Point out potential issues (e.g., "this needs WebFetch in allowed-tools if you want it to search the web")

## Step 5: Save

Once the user approves:

1. Create the directory at the correct location (personal or project scope)
2. Write the SKILL.md file
3. Create any supporting files discussed during refinement
4. Confirm: "Saved to [path]. You can invoke it with /[name] in your next session (or restart this one)."

7d. Test it

Start a new Claude Code session (or restart your current one):

claude

Then type:

/newskill reviewpaper

Claude will walk you through configuring a new skill called reviewpaper. It will ask you quick configuration questions, then let you describe in detail what the skill should do. It drafts the SKILL.md, shows it to you, and you iterate back and forth until you're satisfied. Then it saves the file.

What just happened: You built a reusable tool that builds reusable tools. The /newskill command is itself a skill — a markdown file with instructions that Claude follows. And it produces more markdown files with instructions that Claude follows. Skills all the way down.

8 Ideas for Skills to Build

Try using /newskill to create skills for tasks you do regularly. Here are some ideas:

9 Key Takeaways

← Back to Session 3