Skip to content

Rewrite Unit 2 around a Claude Code workflow#108

Open
burtenshaw wants to merge 2 commits intocoursefrom
codex/review-unit-2-draft
Open

Rewrite Unit 2 around a Claude Code workflow#108
burtenshaw wants to merge 2 commits intocoursefrom
codex/review-unit-2-draft

Conversation

@burtenshaw
Copy link
Copy Markdown
Collaborator

Summary

  • restructure Unit 2 into a single Claude Code-focused learning path with a new intro, publish step, quiz, and conclusion
  • align the course outline and navigation to match the new Unit 2 scope and certification path
  • replace the old starter scaffold with a canonical app.py flow and add a runnable agent/ mini-project for the load/select/compose exercise
  • add Unit 2 quiz data and new content covering activation debugging, mid-session iteration, skill-creator, and current hf CLI publishing

Testing

  • python3 -m compileall course/units/en/unit2/starter/app.py course/units/en/unit2/starter/agent
  • python3 -m json.tool course/quiz/data/unit_2.json >/dev/null
  • git diff --check

Base: variant A (Claude Code — install, activation debugging, build Space, iterate)
From variant B: 'Inside the Box' (load/select/compose) + 'The Real SDK' (native SDK path)
From variant D: skill-creator install/tour, the loop, description optimization

Minimal prose edits — files moved into place for review.
@burtenshaw burtenshaw changed the base branch from main to course March 31, 2026 09:34
Copy link
Copy Markdown

@mnielan-ant mnielan-ant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[deleted]

Comment on lines +28 to +31
```bash
/plugin marketplace add huggingface/skills
/plugin install gradio@huggingface/skills
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ran this as written and got Plugin "gradio" not found. The @ suffix needs the registered marketplace name (huggingface-skills), and the plugin is huggingface-gradio per marketplace.json. Also adding /reload-plugins — after install the slash menu is cached, so /huggingface-gradio returns "Unknown skill" until you reload (line 76 mentions this but a student hits the error before getting there).

Same name/suffix issue is in unit0/setup.mdx:45 and unit1/hands-on-find-install.mdx:40,89,137,175 (hugging-face-model-trainerhuggingface-llm-trainer, etc.) — flagging here rather than spamming those files since it's the same fix pattern.

Suggested change
```bash
/plugin marketplace add huggingface/skills
/plugin install gradio@huggingface/skills
```
```bash
/plugin marketplace add huggingface/skills
/plugin install huggingface-gradio@huggingface-skills
/reload-plugins
```

/plugin install gradio@huggingface/skills
```

Use this when someone else maintains the skill and ships it as part of a plugin. Plugin skills are namespaced as `/plugin-name:skill-name`. For this repository, the plugin name is `huggingface-skills`, so a plugin-installed skill gets a namespaced command instead of a bare `/skill-name`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small corrections: huggingface-skills is the marketplace name; the plugin here is huggingface-gradio. And the namespaced form is optional — current Claude Code accepts both bare /huggingface-gradio and /huggingface-gradio:huggingface-gradio.

Suggested change
Use this when someone else maintains the skill and ships it as part of a plugin. Plugin skills are namespaced as `/plugin-name:skill-name`. For this repository, the plugin name is `huggingface-skills`, so a plugin-installed skill gets a namespaced command instead of a bare `/skill-name`.
Use this when someone else maintains the skill and ships it as part of a plugin. Plugin skills can be invoked with the bare name (`/huggingface-gradio`) or the namespaced form (`/plugin-name:skill-name`) if you need to disambiguate.

/plugin install gradio@huggingface/skills
```

Use this when someone else maintains the skill and ships it as part of a plugin. Plugin skills are namespaced as `/plugin-name:skill-name`. For this repository, the plugin name is `huggingface-skills`, so a plugin-installed skill gets a namespaced command instead of a bare `/skill-name`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you run /plugin install, Claude Code prompts for a scope (Personal / Project shared / Project local) and the page doesn't say which to pick. Suggest adding right after this paragraph:

When prompted for a scope, pick Personalhuggingface-gradio is a general-purpose skill you'll want everywhere. The starter's hf-brand/brutalist skills, by contrast, live in the project's .claude/skills/ because they only make sense for that one app.

(One sentence is enough — a full scope breakdown would pull focus from the activation lesson.)

1. Say what the skill does
2. Say when to use it in the language a user would actually type

## Slash Commands vs Auto-Activation
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading-order nit: this section introduces the two ways a skill enters a turn (auto vs explicit /), but the "How Activation Works" section above it has already dived into the mechanics of auto activation. Swapping them — this section first, then "How Activation Works" — gives the reader the "two routes in" model before drilling into one of them.


- `disable-model-invocation: true` stops automatic activation and keeps the skill manual-only
- `user-invocable: false` hides it from the slash-command menu
- `paths:` limits activation to matching files or folders
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth linking the full reference here — there are several more keys (allowed-tools, allowed-directories, etc.) and the docs will stay current as the set grows.

Suggested change
- `paths:` limits activation to matching files or folders
- `paths:` limits activation to matching files or folders
See the [Claude Code skills reference](https://code.claude.com/docs/en/skills) for the full set of frontmatter fields.


## Skills vs MCP

Skills are instructions. MCP servers are tools. A skill teaches Claude how to do something with the tools it already has; an MCP server gives Claude a new capability, like talking to Slack or querying a database. You will often use them together, but they solve different problems.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Skills are instructions. MCP servers are tools. A skill teaches Claude how to do something with the tools it already has; an MCP server gives Claude a new capability, like talking to Slack or querying a database. You will often use them together, but they solve different problems.
Skills are instructions; MCP servers provide tools. A skill tells Claude *how* to use what it already has. An MCP server gives Claude something new to use — a Slack client, a database connection, a browser. You'll often use them together: the `huggingface-gradio` skill tells Claude how to structure a Gradio app, and it needs no MCP server because writing Python files is a tool Claude already has. A skill for "post my model card to Slack" would need both — the skill for the *how*, a Slack MCP server for the *ability*.

Comment on lines +7 to +12
Copy your Unit 1 skill into your personal Claude Code skills directory:

```bash
mkdir -p ~/.claude/skills/dataset-publisher
cp path/to/your/dataset-publisher/SKILL.md ~/.claude/skills/dataset-publisher/
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit 1's hands-on-write-skill.mdx already ends with cp -r dataset-publisher/ ~/.claude/skills/dataset-publisher/, so for most students this is a no-op and the path/to/your/ placeholder is confusing. Suggest:

Suggested change
Copy your Unit 1 skill into your personal Claude Code skills directory:
```bash
mkdir -p ~/.claude/skills/dataset-publisher
cp path/to/your/dataset-publisher/SKILL.md ~/.claude/skills/dataset-publisher/
```
If you completed Unit 1, `dataset-publisher` is already in `~/.claude/skills/dataset-publisher/`. If you skipped Unit 1, grab the skill from [Hands-on: Write Your First Skill](../unit1/hands-on-write-skill) before continuing.

in a structured way. What's a good approach?
```

This exact prompt comes from the Unit 2 draft logs.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"This exact prompt comes from the Unit 2 draft logs" reads like a leftover authoring note.

Suggested change
This exact prompt comes from the Unit 2 draft logs.

Comment on lines +69 to +85
Rewrite it so it includes natural trigger language:

```yaml
description: Create and publish datasets to the Hugging Face Hub. Use when
the user wants to share structured data, publish a dataset, upload examples
for training, create a dataset card, or share Q&A pairs with a team.
```

Save the file. Then start a fresh Claude Code session and ask the same prompt again.

If you installed the skill through a plugin instead of a plain directory copy, use:

```text
/reload-plugins
```

to make Claude Code pick up the plugin change without restarting.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rewrite it so it includes natural trigger language:
```yaml
description: Create and publish datasets to the Hugging Face Hub. Use when
the user wants to share structured data, publish a dataset, upload examples
for training, create a dataset card, or share Q&A pairs with a team.
```
Save the file. Then start a fresh Claude Code session and ask the same prompt again.
If you installed the skill through a plugin instead of a plain directory copy, use:
```text
/reload-plugins
```
to make Claude Code pick up the plugin change without restarting.
Open `~/.claude/skills/dataset-publisher/SKILL.md` and rewrite the `description` so it includes natural trigger language:
```yaml
description: Create and publish datasets to the Hugging Face Hub. Use when
the user wants to share structured data, publish a dataset, upload examples
for training, create a dataset card, or share Q&A pairs with a team.
```
Save, then ask the same prompt again — Claude Code re-reads skill descriptions each turn, so no restart needed.

Comment on lines +81 to +88
The starter also includes `skills/brutalist/`. Swap it in:

```bash
rm -rf .claude/skills/hf-brand
cp -r skills/brutalist .claude/skills/
```

Then ask Claude to restyle `app.py` again. Same app, different personality:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest dropping the rm -rf and keeping both style skills mounted — then the prompt names the one you want. Shows that multiple skills can coexist and that explicit prompting (or /brutalist) picks between them.

Suggested change
The starter also includes `skills/brutalist/`. Swap it in:
```bash
rm -rf .claude/skills/hf-brand
cp -r skills/brutalist .claude/skills/
```
Then ask Claude to restyle `app.py` again. Same app, different personality:
The starter also includes `skills/brutalist/`. Add it alongside `hf-brand`:
```bash
cp -r skills/brutalist .claude/skills/
```
Then ask Claude to restyle `app.py` using the brutalist skill specifically. Same app, different personality:

Comment on lines +7 to +13
For this course, the least fragile path is to copy the skill directly:

```bash
git clone https://github.com/anthropics/skills ~/anthropic-skills
mkdir -p ~/.claude/skills
cp -R ~/anthropic-skills/skills/skill-creator ~/.claude/skills/
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clone-and-copy works, but it's the one place in the unit that doesn't use the /plugin flow we just taught. skill-creator ships in the example-skills plugin from anthropics/skills, so we can dogfood the lesson:

Suggested change
For this course, the least fragile path is to copy the skill directly:
```bash
git clone https://github.com/anthropics/skills ~/anthropic-skills
mkdir -p ~/.claude/skills
cp -R ~/anthropic-skills/skills/skill-creator ~/.claude/skills/
```
Install it via the Anthropic skills marketplace:
```bash
/plugin marketplace add anthropics/skills
/plugin install example-skills@anthropic-agent-skills
/reload-plugins
```
> **Note:** `example-skills` bundles ~12 example skills, not just `skill-creator`. You'll see them in your `/` menu — that's expected.

@@ -0,0 +1,83 @@
# Quiz: Using Skills with Claude Code
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest shifting the weight from exercise-recall toward concepts that transfer. Q1/2/10 are great as-is; a few others test specific function/file names from one starter (Q4/5/7) or CLI flags (Q9), and Q8's "correct" answer will change if the skill-creator page is retargeted. Draft below keeps the strongest originals (incl. select_skills for the inside-the-box exercise), generalizes Q3, and adds skill-vs-MCP, explicit-vs-auto, and where-should-a-project-skill-live. Answer key is heavy on B's — worth shuffling letters before publish.

Proposed quiz.mdx
# Quiz: Using Skills with Claude Code

Test your understanding of the ideas and workflows from Unit 2. Passing this quiz is part of the **Claude Code Specialization** track described in Unit 0.

The same questions are stored in `course/quiz/data/unit_2.json`.

## Questions

1. Where should a project-local skill live if you want it versioned with the repository?
   A. `~/.claude/skills/<name>/SKILL.md`
   B. `.claude/skills/<name>/SKILL.md`
   C. `skills/<name>/README.md`
   D. `.mcp/<name>/SKILL.md`

2. What is the main signal Claude uses to decide whether to auto-activate a skill?
   A. The skill directory name
   B. The longest heading inside `SKILL.md`
   C. The `description` field in frontmatter
   D. The file modification time

3. A skill's body is correct, but it never auto-activates on natural prompts. What's the most likely fix?
   A. Move it from `.claude/skills/` to `~/.claude/skills/`
   B. Rewrite the `description` to include the language a user would actually type
   C. Add more headings to `SKILL.md`
   D. Convert it to an MCP server

4. Why does an agent read skill *descriptions* before loading full skill *bodies*?
   A. Descriptions are cached and bodies are not
   B. Selecting on short descriptions is cheap; injecting full bodies costs context, so you only want the relevant ones
   C. Claude Code requires two passes for every skill
   D. Skill bodies cannot be read at runtime

5. What's the difference between a skill and an MCP server?
   A. Skills run in the browser; MCP servers run locally
   B. A skill tells Claude *how* to use tools it has; an MCP server gives Claude a *new* tool
   C. Skills are YAML; MCP servers are JSON
   D. There is no difference — they're interchangeable

6. When would you type `/skill-name` instead of relying on auto-activation?
   A. Auto-activation only works for plugin skills
   B. When you want that specific skill's workflow now, regardless of whether your prompt wording matches its description
   C. Slash invocation is required the first time you use any skill
   D. Auto-activation is deprecated

7. In the `agent/` starter, what is `select_skills(...)` responsible for?
   A. Building the Gradio UI
   B. Choosing which skill names are relevant to the current user message
   C. Writing new skill files
   D. Packaging plugin metadata

8. You're writing a style skill for one specific app. Where should it live?
   A. In the project's `.claude/skills/` — it's specific to this codebase and you'll edit it as the app changes
   B. Installed via `/plugin install` from a marketplace
   C. In `~/.claude/skills/` so every project gets it
   D. Inside `SKILL.md` in the repo root

9. What is `skill-creator` primarily for?
   A. Converting MCP servers into skills
   B. Scaffolding a new skill from scratch — directory, `SKILL.md`, and an eval loop to tune activation
   C. Publishing Spaces to the Hub
   D. Translating skills between agent runtimes

10. Why are small focused skills often better than one giant catch-all skill?
    A. Claude Code ignores large skills entirely
    B. Small skills are easier to trigger, debug, and keep behavior-specific
    C. The Agent Skills specification forbids multi-section skills
    D. Only small skills can contain scripts

<details>
<summary>Answer key</summary>

1. B
2. C
3. B
4. B
5. B
6. B
7. B
8. A
9. B
10. B

</details>
Proposed unit_2.json
[
  {
    "question": "Where should a project-local skill live if you want it versioned with the repository?",
    "answer_a": "~/.claude/skills/<name>/SKILL.md",
    "answer_b": ".claude/skills/<name>/SKILL.md",
    "answer_c": "skills/<name>/README.md",
    "answer_d": ".mcp/<name>/SKILL.md",
    "correct_answer": "B"
  },
  {
    "question": "What is the main signal Claude uses to decide whether to auto-activate a skill?",
    "answer_a": "The skill directory name",
    "answer_b": "The longest heading inside SKILL.md",
    "answer_c": "The description field in frontmatter",
    "answer_d": "The file modification time",
    "correct_answer": "C"
  },
  {
    "question": "A skill's body is correct, but it never auto-activates on natural prompts. What's the most likely fix?",
    "answer_a": "Move it from .claude/skills/ to ~/.claude/skills/",
    "answer_b": "Rewrite the description to include the language a user would actually type",
    "answer_c": "Add more headings to SKILL.md",
    "answer_d": "Convert it to an MCP server",
    "correct_answer": "B"
  },
  {
    "question": "Why does an agent read skill descriptions before loading full skill bodies?",
    "answer_a": "Descriptions are cached and bodies are not",
    "answer_b": "Selecting on short descriptions is cheap; injecting full bodies costs context, so you only want the relevant ones",
    "answer_c": "Claude Code requires two passes for every skill",
    "answer_d": "Skill bodies cannot be read at runtime",
    "correct_answer": "B"
  },
  {
    "question": "What's the difference between a skill and an MCP server?",
    "answer_a": "Skills run in the browser; MCP servers run locally",
    "answer_b": "A skill tells Claude how to use tools it has; an MCP server gives Claude a new tool",
    "answer_c": "Skills are YAML; MCP servers are JSON",
    "answer_d": "There is no difference",
    "correct_answer": "B"
  },
  {
    "question": "When would you type /skill-name instead of relying on auto-activation?",
    "answer_a": "Auto-activation only works for plugin skills",
    "answer_b": "When you want that specific skill's workflow now, regardless of whether your prompt wording matches its description",
    "answer_c": "Slash invocation is required the first time you use any skill",
    "answer_d": "Auto-activation is deprecated",
    "correct_answer": "B"
  },
  {
    "question": "In the agent/ starter, what is select_skills(...) responsible for?",
    "answer_a": "Building the Gradio UI",
    "answer_b": "Choosing which skill names are relevant to the current user message",
    "answer_c": "Writing new skill files",
    "answer_d": "Packaging plugin metadata",
    "correct_answer": "B"
  },
  {
    "question": "You're writing a style skill for one specific app. Where should it live?",
    "answer_a": "In the project's .claude/skills/ — it's specific to this codebase and you'll edit it as the app changes",
    "answer_b": "Installed via /plugin install from a marketplace",
    "answer_c": "In ~/.claude/skills/ so every project gets it",
    "answer_d": "Inside SKILL.md in the repo root",
    "correct_answer": "A"
  },
  {
    "question": "What is skill-creator primarily for?",
    "answer_a": "Converting MCP servers into skills",
    "answer_b": "Scaffolding a new skill from scratch, including directory, SKILL.md, and an eval loop to tune activation",
    "answer_c": "Publishing Spaces to the Hub",
    "answer_d": "Translating skills between agent runtimes",
    "correct_answer": "B"
  },
  {
    "question": "Why are small focused skills often better than one giant catch-all skill?",
    "answer_a": "Claude Code ignores large skills entirely",
    "answer_b": "Small skills are easier to trigger, debug, and keep behavior-specific",
    "answer_c": "The Agent Skills specification forbids multi-section skills",
    "answer_d": "Only small skills can contain scripts",
    "correct_answer": "B"
  }
]

@@ -0,0 +1,85 @@
# The `skill-creator` Skill
Copy link
Copy Markdown

@mnielan-ant mnielan-ant Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bigger thought on this page: it currently re-tunes the dataset-publisher description that the student already fixed by hand on the previous page, so the before/after they see won't match what's on screen — and it shows skill-creator doing description-tuning rather than its primary job (scaffolding from scratch).

Proposal: have skill-creator build a personal-brand Gradio style skill (my-brand) instead. Student picks 3 adjectives + 2 colors, skill-creator scaffolds it into .claude/skills/, then they re-run the "restyle app.py" prompt with their own skill. It threads build-space → skill-creator → publish into one arc, and the published Space becomes a personal artifact for the certification.

Draft below

Proposed skill-creator.mdx
# The `skill-creator` Skill

You've used two style skills someone else wrote. Now build your own — not by hand, but with `skill-creator`, Anthropic's skill for authoring skills.

## Install It

`skill-creator` ships in the `example-skills` plugin from the Anthropic skills marketplace:

```bash
/plugin marketplace add anthropics/skills
/plugin install example-skills@anthropic-agent-skills
/reload-plugins
```

Run `/skill-creator` to confirm it's available.

<Tip>
`example-skills` bundles about a dozen example skills, not just `skill-creator`. You'll see them in your `/` menu — that's expected.
</Tip>

## What It Gives You

`skill-creator` is not just one markdown file. It is a small toolkit:

```text
skill-creator/
├── SKILL.md
├── scripts/
├── eval-viewer/
├── agents/
└── references/
```

That is progressive disclosure again: `SKILL.md` defines the workflow, `scripts/` runs evaluation and packaging steps, `eval-viewer/` renders results, and `agents/`/`references/` hold material Claude only needs at specific moments.

## Build a Personal Brand Skill

You've seen `hf-brand` and `brutalist`. Now make one that's yours.

Pick three adjectives and two colors. For example: *playful, minimal, confident* with primary `#0ea5e9` and accent `#f97316`. Then, in Claude Code inside `~/unit2-starter`:

```text
Use skill-creator to scaffold a Gradio style skill called `my-brand`.
Aesthetic: playful, minimal, confident. Primary #0ea5e9, accent #f97316.
Include guidance on typography, spacing, and copy tone.
Put it in .claude/skills/my-brand/.
```

`skill-creator` will draft `SKILL.md`, propose a description, and ask whether to run an activation-eval pass. Say yes once — you're after a clean first draft, not a perfect one.

## Try It

`my-brand` is already in `.claude/skills/``skill-creator` put it there alongside `hf-brand` and `brutalist`. Now ask for it by name:

```text
Restyle app.py using the my-brand skill.
```

Same scaffold. Your skill. Your outcome.

![Your branded demo](./assets/mybrand-placeholder.png)

## Why This Matters

`skill-creator` is built for this: scaffolding a skill from scratch — directory, frontmatter, body, eval loop. You used it on a tiny aesthetic skill, but the same workflow scales to skills with helper scripts, templates, and references.

By this point you have seen all three layers:

1. **Use** a skill someone else wrote (`hf-brand`, `brutalist`)
2. **Debug** why a skill doesn't activate (`dataset-publisher`)
3. **Author** a skill from scratch with tooling (`my-brand`)

Now publish the Space — styled with the skill you built.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you take this direction, two cross-refs elsewhere would need a matching tweak:

hands-on-iterate.mdx:79 (closing line):

Suggested change
# The `skill-creator` Skill
Next, use `skill-creator` to scaffold a style skill of your own.

introduction.mdx:13 (learning objective):

Suggested change
# The `skill-creator` Skill
- Use `skill-creator` to scaffold a new skill from scratch and run one activation-eval pass

(Both are fine as-is if you keep the current dataset-publisher flow.)

Comment on lines +54 to +57
# Pass theme to Blocks(), not launch():
with gr.Blocks(theme=theme) as demo:
...
demo.launch()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gradio 6.0 moved theme/css from gr.Blocks() to .launch() — so this guidance now produces a deprecation warning (UserWarning: parameters have been moved from the Blocks constructor to launch() in Gradio 6.0). App still runs, but since the heading says "Gradio 6.x" it's worth flipping. Same change at brutalist/SKILL.md:43-45.

Suggested change
# Pass theme to Blocks(), not launch():
with gr.Blocks(theme=theme) as demo:
...
demo.launch()
# Pass theme to launch() (Gradio 6.x moved it from Blocks):
with gr.Blocks() as demo:
...
demo.launch(theme=theme)

@mnielan-ant
Copy link
Copy Markdown

Ran the whole unit end-to-end as a student (fresh Claude Code, fresh starter dir) — line comments cover everything I hit. Most are small mechanical fixes (/plugin names/suffix, a missing /reload-plugins, a couple of clarity tweaks).

Two bigger proposals are in the threads on skill-creator.mdx and quiz.mdx — both have full draft replacements inline, take or leave.

One thing I couldn't verify from my side: the hf repos create … --space-sdk gradio / hf upload . . syntax in hands-on-publish-space.mdx — your CLI, just flagging for a double-check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants