# Run Agent Skills

> Build, validate, and exercise the agent-skills registry. Use when asked to run agent-skills, install its deps, lint or test it, run its bats suites, exercise a Claude Code hook, regenerate the index files, or symlink the skills out to ~/.claude / ~/.agents / ~/.cursor / ~/.opencode.

- Skill: `usrrname/run-agent-skills` (Agent Skill)
- Install (CLI): `npx skillmds@latest add usrrname/run-agent-skills`
- Raw SKILL.md: https://api.skillmd.com/api/skills/usrrname/run-agent-skills/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: usrrname (https://skillmd.com/u/usrrname)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/usrrname/run-agent-skills

---


This repo is a Bun workspace of Markdown-defined skills/agents/rules plus a handful of Bash hooks and one TypeScript helper. There is no app to "launch" — driving it means running the validation pipeline (`bun run validate`) and exercising the Claude Code hooks by piping JSON to their stdin. All paths below are relative to the repo root.

## Prerequisites

```bash
brew install bats-core shellcheck jq
curl -fsSL https://bun.sh/install | bash    # or: brew install oven-sh/bun/bun
```

Versions confirmed working: `bun 1.3.13`, `bats 1.13.0`, `shellcheck 0.11.0`, `jq 1.7.1`.

## Setup

```bash
bun install
```

Installs `markdownlint-cli` and `yaml` into root `node_modules/`. The workspace members (`skills/`, `agents/`, `rules/`) have empty deps — `bun install` finishes in ~50ms when already populated.

## Run (agent path)

The full validation pipeline — lint markdown, lint shell, run bats, check indexes, check README links:

```bash
bun run validate
```

Each step is also addressable individually (and is what you want when iterating):

| command | what it does | exit code |
|---|---|---|
| `bun run lint` | markdownlint on all `**/*.md` | 1 on findings |
| `bun run lint:fix` | markdownlint --fix on all `**/*.md` | 1 on un-fixable findings |
| `bun run lint:sh` | shellcheck on `.claude/hooks/*.sh hooks/*.sh scripts/*.sh skills/symlink-skills/link.sh` | 1 on findings |
| `bun run test` | bats over `.claude/hooks/tests/ hooks/tests/ scripts/tests/ skills/symlink-skills/tests/` | non-zero on test failure |
| `bun run index:gen` | regenerate `index.md` in each category folder from frontmatter | 0 |
| `bun run index:check` | verify `index.md` presence for `skills/ agents/ rules/ commands/ hooks/` anywhere in the tree | non-zero on missing index |
| `bun run readme:check` | verify root `README.md` links every `SKILL.md` and lists every agent | non-zero on drift |

Current test count: **72 bats tests** across the four directories.

## Direct invocation — exercising a hook

The hooks read Claude Code's PostToolUse payload from stdin. Drive them with `jq`-compatible JSON:

```bash
# validate-skill-frontmatter: succeeds (exit 0, no output) on a valid SKILL.md
echo '{"tool_input":{"file_path":"'$PWD'/skills/gcm/SKILL.md"}}' \
  | .claude/hooks/validate-skill-frontmatter.sh

# validate-skill-frontmatter: fails (exit 2, blocking) when name/description missing
TMP=$(mktemp -d); printf '%s\n' '---' 'description: x' '---' > "$TMP/SKILL.md"
echo "{\"tool_input\":{\"file_path\":\"$TMP/SKILL.md\"}}" \
  | .claude/hooks/validate-skill-frontmatter.sh; rm -rf "$TMP"

# session-log-reminder: prints reminder on git-commit, silent on anything else
echo '{"tool_input":{"command":"git commit -m test"}}' | hooks/session-log-reminder.sh
echo '{"tool_input":{"command":"ls -la"}}'             | hooks/session-log-reminder.sh
```

`check-index-md.sh` and `check-readme-sync.sh` are also stdin hooks, but the bun scripts wrap them with the right env: prefer `bun run index:check` and `bun run readme:check` over invoking them directly.

## Install — symlink skills out to loaders

```bash
./skills/symlink-skills/link.sh --help            # see all options
./skills/symlink-skills/link.sh --dry-run         # preview into all default targets
./skills/symlink-skills/link.sh --target /tmp/x --dry-run   # preview into one explicit target
./skills/symlink-skills/link.sh                   # write into the 4 defaults
./skills/symlink-skills/link.sh --unlink          # remove only the symlinks this script made
```

Per-project install of a single skill or agent:

```bash
scripts/add.sh --help
scripts/add.sh --link tmux-processes              # from a local clone
scripts/add.sh --link --type agent adr-author
```

## Gotchas

- **`~/.claude/skills/` may be read-only on a nix-darwin host.** If `$HOME/.claude/skills` is a symlink into `/nix/store/…home-manager-files/.claude/skills` (owned `root:nixbld`, mode `dr-xr-xr-x`), `link.sh` cannot write into it. It will print `! <name> (ln failed — target dir not writable?)` per skill and exit non-zero (`errored=N`). Workaround: either remove `~/.claude/skills` from your home-manager config, or pass `--target` to a writable directory and skip the read-only default.
- **`bun run lint` currently fails (MD040)** on `skills/web-perf/SKILL.md` (7 unfenced code blocks). `bun run validate` therefore stops at the lint step on a fresh clone. `bun run lint:fix` does **not** fix MD040 — you need to add a language to each `` ``` `` fence by hand.
- **`bun run index:gen` is not idempotent across all files.** `.opencode/agents/index.md` rewrites on every run (the other five indexes are stable). Re-run after edits.
- **Indexes are required.** `bun run index:check` enforces `index.md` in every folder named `skills/ agents/ rules/ commands/ hooks/` anywhere in the tree (the repo root is exempt — `README.md` covers it). Drop a new folder there → must include an `index.md`.

## Troubleshooting

- **`error: script "lint" exited with code 1` listing MD040 in web-perf**: pre-existing repo state, not your change. Either fix `skills/web-perf/SKILL.md` (add languages to its code fences) or skip past with `bun run lint:sh && bun run test && bun run index:check && bun run readme:check`.
- **`link.sh` says `linked: …` but `~/.claude/skills/<name>` doesn't exist**: read the script's stderr — `ln: …: Permission denied` means the target is read-only (see nix-darwin gotcha above). The exit code is unreliable here.
- **`bun install` warns about a missing `hooks` workspace**: `hooks/` is a publishable directory but not a workspace. If you see this, the root `package.json` `workspaces` array was edited — it should be exactly `["skills", "agents", "rules"]`.
- **`bats: command not found`**: `brew install bats-core` (not `bats`, which is a different package).

---

Conforms to the Agent Skills specification: <https://agentskills.io/specification>

