# skill-release: a brief for rebuilding it

This describes a Claude Code skill for sharing your own skills in public without developing them in public. It describes behaviour and decisions, so you can rebuild it for your own setup. The original is one Python script (run with `uv`, needing only PyYAML) and a SKILL.md.

## The problem

Skills you build for yourself fill up with your own details: machine names, home-folder paths, colleagues' names, your employer, your email address, private web addresses. You want to share some of them, but making your working repo public would publish all of that, and its history too. You also don't want a second copy that you have to keep editing by hand.

## The design

Publishing is a one-way copy, made on request:

```
skill source (where you keep working)
   └─▶ check: what would go out, what looks private, where it will run
         └─▶ export: cleaned copy committed to a local clone of the public repo
               └─▶ a person reads the diff and says yes ─▶ git push
```

- **Settings live outside the tool.** A folder in your home directory holds two files. `tools.yaml` says which tools to share, where each comes from, what to leave out and what text to swap in the public copy. `scrub.txt` is your own list of private details (machine names, colleagues, employers, domains), one regular expression per line. Neither file is ever copied anywhere, because a list of what you're hiding is itself private. The skill's `references/setup.md` has an example of each.
- **Git sources export the committed version only,** never work in progress. The check says when there are uncommitted changes.
- **Every export is a fresh copy.** The public folder is replaced, so files deleted at the source disappear from the public copy too.

## What the check looks for

Blocking:

- anything on your list of private details, including in file names;
- email addresses, apart from no-reply and example.com addresses;
- private IP addresses, including 100.64.0.0/10, the range Tailscale uses;
- strings shaped like common API keys and private keys;
- home-folder paths with a real user name;
- `*.ts.net` network names;
- files over 50 MB.

It also skips caches, virtual environments, `node_modules`, `.env` files, logs and backups automatically. The scan can't read images or video, so it lists them for a person to look at.

## Where it will run

The check also reports where the skill will run:

- **Claude Code, as a plugin:** blocked if the name isn't lowercase letters, digits and hyphens matching the folder, or if any file still refers to the skill's installed path (`~/.claude/skills/<name>`). A plugin installs somewhere else.
- **Cowork and Claude chat:** "no" if the instructions need a program their sandbox can't run (`uv`, `ffmpeg`, a signed-in CLI and so on). Otherwise there are caveats for a description over 200 characters, scripts (code execution must be on), calls to outside services, and API keys.

## What the export changes

- `~/.claude/skills/<name>/` becomes `${CLAUDE_SKILL_DIR}/`, which Claude Code substitutes in SKILL.md and in `allowed-tools`.
- Frontmatter keys Claude Code doesn't recognise move under `metadata:`. When this was written (October 2026), Claude chat's skill upload refused any key outside a short list.
- It writes `.claude-plugin/plugin.json` with no version field, so each public commit counts as an update for people who installed it.
- It records the source revision, the date and the where-it-runs results in `snapshot.json`, so the site can show them and `status` can tell which public copies are behind.

## The review step

- Branches and pull requests on a public repo are public as soon as they're pushed, so review happens before the push, on your own machine.
- A pre-push hook reruns the scan over every tracked file as a backstop. It can't replace a person reading the diff, because no pattern list knows every name.

## What the first exports taught

- **Skills tied to one setup need a split, not a scrub.** Text swaps can't clean a skill built around one person's folders and machines. The general method stays in SKILL.md, and everything about the owner's setup moves to a `local.md` that SKILL.md reads when it exists. The owner's sessions behave as before, and the export leaves local.md out.
- **Ask whoever maintains a skill before changing it.** Draft the change in a separate folder and let them apply it. That matters even more when the maintainer is another Claude session that relies on the skill every day.
- **Curated lists get example files.** A list of accounts someone follows is personal, so the public copy gets a short example instead.
- **Stop when a safety check blocks you.** A hook or permission check that fires is the user's to overrule. Don't rephrase the command to get past it.
- **People read the diff.** No pattern list knows every colleague's name or every private ID.

## Rebuilding it

- The scan is the core: your patterns plus the built-in checks above, run over the transformed output rather than the source.
- Keep the settings file format small. Rewrites are literal text swaps, and "allow" patterns excuse false positives such as "MIT License".
- Test it on a fake skill that contains a planted hostname, an email address and an installed path. Confirm the export refuses it and writes nothing.
