Skill v1.0.1
currentAutomated scan96/100+2 new
version: "1.0.1" name: refresh-index description: "Re-ingest every already-enabled repo in data/skill-index-resources.json: sync the working tree, run preindex, rebuild the catalog for verification, summarize updated/unchanged/failed/skipped, then gate commit + PR behind explicit confirmation. Use when asked to refresh the index, re-ingest indexed repos, or batch-maintain already-indexed skill sources. Don't use for adding new repos (use skill-index-updater), improving a single skill (use skill-auto-improver), or installing/updating skills on the local machine (use asm install or asm update)." license: MIT compatibility: Claude Code allowed-tools: Bash Read Write Edit Grep Glob effort: high metadata: version: 1.0.0 author: luongnv89
Refresh Index
You are refreshing every enabled repository in the ASM curated skill index. The goal is to re-ingest each source so data/skill-index/{owner}_{repo}.json reflects the latest upstream state, classify each repo as updated / unchanged / failed / skipped, verify the catalog still rebuilds cleanly, and open a single PR that ships only the data changes — with explicit user confirmation before any commit or push.
This is the inverse of skill-index-updater. That skill adds new repos from URLs the user supplies. This skill refreshes the repos that are already enabled in data/skill-index-resources.json.
When to Use
- User asks to "refresh the index", "update the indexed skills", "sync the catalog", "re-ingest all repos", or "batch-maintain the skill index"
- A scheduled refresh is due and the user wants to bring
data/skill-index/*.jsonup to date with upstream changes - A new ASM release is approaching and the catalog should reflect the latest upstream skill metadata
Do not trigger for: adding a new repository to the index (use skill-index-updater), authoring or improving a single skill (skill-creator, skill-auto-improver), opening an upstream PR to a third-party skill (skill-upstream-pr), or installing/updating skills on the local machine (asm install, asm update).
Repo Sync Before Edits (mandatory)
Before re-ingesting anything, pull the latest remote branch:
branch="$(git rev-parse --abbrev-ref HEAD)"dirty=0if [ -n "$(git status --porcelain)" ]; thengit stash push -u -m "pre-refresh-index: ${branch}"dirty=1figit fetch origingit pull --rebase origin "$branch"if [ "$dirty" -eq 1 ]; thengit stash pop || {echo "✗ Stash pop failed — recover with: git stash list && git stash show -p stash@{0}"exit 1}fi
If origin is missing or rebase conflicts occur, stop and ask the user before continuing. Never silently overwrite local edits to data/skill-index/ or data/skill-index-resources.json.
Prerequisites
Verify each before any ingest. Stop and tell the user if any fails.
nodeandnpmon PATH (command -v node,command -v npm) — required bynpm run preindexasmon PATH (command -v asm) — invoked transitively by the ingester forasm evalghon PATH and authenticated (gh auth status) — required for PR creationgiton PATH and inside the ASM repo working tree (git rev-parse --show-toplevel)- Network access to
github.com(each ingest clones the upstream repo)
Pipeline
Follow these steps in order. Each step has a verification check — do not proceed if the check fails.
Step 1: Enumerate the index
Read data/skill-index-resources.json and split entries into two lists:
ROOT="$(git rev-parse --show-toplevel)"RES="$ROOT/data/skill-index-resources.json"
Use jq (or your equivalent JSON reader) to build two lists, keyed on the source string (github:owner/repo) because that is the identifier preindex echoes in its log lines:
enabled[]— every repo with"enabled": true. These will be refreshed.disabled[]— every repo with"enabled": false. These land in the skipped bucket up front with reason"disabled in skill-index-resources.json".
jq -r '.repos[] | select(.enabled == true) | .source' "$RES" # e.g. github:anthropics/skillsjq -r '.repos[] | select(.enabled == false) | .source' "$RES"
Also derive the on-disk file key ({owner}_{repo}) for each enabled repo — this is what data/skill-index/{owner}_{repo}.json is named:
jq -r '.repos[] | select(.enabled == true) | "\(.source)\t\(.owner)_\(.repo)"' "$RES"
Verification: both lists are non-empty (the index always contains at least one enabled repo and one disabled self-reference). Also validate the existing per-repo JSON is parseable before re-ingesting — a pre-existing corruption otherwise gets masked by the refresh:
jq empty data/skill-index/*.json # exits non-zero if any file is invalid
If enabled[] is empty or pre-validation fails, stop — there is nothing safe to refresh.
Step 2: Snapshot pre-run skill counts
Before re-ingesting, record the current skillCount for each enabled repo. This lets Step 7 report skill-count deltas.
mkdir -p /tmp/refresh-indexSNAPSHOT="/tmp/refresh-index/pre-snapshot.json"echo "{}" > "$SNAPSHOT"for entry in $(jq -r '.repos[] | select(.enabled == true) | "\(.owner)_\(.repo)"' "$RES"); dofile="$ROOT/data/skill-index/${entry}.json"if [ -f "$file" ]; thencount=$(jq -r '.skillCount // 0' "$file")jq --arg k "$entry" --argjson v "$count" '. + {($k): $v}' "$SNAPSHOT" > "$SNAPSHOT.tmp" && mv "$SNAPSHOT.tmp" "$SNAPSHOT"fidone
If a repo is enabled but has no existing index file, treat the pre-count as 0. The repo will then show up in updated with a positive delta in Step 7.
Step 3: Run npm run preindex
Re-ingest every enabled repo via the project's preindex script. Capture both stdout and the exit code — preindex exits 1 if any repo fails, but do not abort the run. We still want partial results so the summary can show what succeeded.
LOG="/tmp/refresh-index/preindex.log"cd "$ROOT"set +enpm run preindex 2>&1 | tee "$LOG"PREINDEX_EXIT=$?set -e
Verification: the log file exists and contains one line per enabled repo formatted as either {source} ... {N} skills (success) or {source} ... FAILED: {error} (failure), where {source} matches the github:owner/repo strings from Step 1. If the log is empty or no line matches, stop and surface the error.
Step 4: Classify each repo
Build per-repo status from three signals — the preindex log, git diff on data/skill-index/, and the disabled[] list from Step 1.
DIFF_FILES=$(git diff --name-only -- data/skill-index/ | sort -u)
For each enabled repo, match the preindex log line by its {source} string (github:owner/repo) and look up the on-disk file by {owner}_{repo}:
Signal in preindex.log (per {source} line) | data/skill-index/{owner}_{repo}.json in git diff | Bucket | |
|---|---|---|---|
{source} ... N skills | yes | updated | |
{source} ... N skills | no | unchanged | |
{source} ... FAILED: ... | (either) | failed (capture error message) | |
(no line for this {source}) | (either) | failed (capture as "no output from preindex") |
For each disabled[] repo: skipped with the disabled reason.
Capture each repo's post-run skillCount by reading the (possibly updated) data/skill-index/{owner}_{repo}.json. For failed repos, post-count = pre-count (no change on disk).
Step 5: Rebuild the website catalog (verification only)
Run the catalog build to confirm the refreshed index is structurally valid. `website/catalog.json` is gitignored — never stage it. A failure here means the data files are internally inconsistent and the PR must not land.
cd "$ROOT"npx tsx scripts/build-catalog.ts
Verification: the script exits 0 and website/catalog.json is valid JSON (jq empty website/catalog.json). If it fails, stop the pipeline — investigate the data issue before committing anything.
Step 6: Detect unexpected diff scope
Confirm the only files that changed are the ones we expect — per-repo data under data/skill-index/ and, only if the user explicitly bumped the top-level updatedAt, data/skill-index-resources.json:
UNEXPECTED=$(git diff --name-only \| grep -v -E '^data/skill-index/' \| grep -v -E '^data/skill-index-resources\.json$' \|| true)if [ -n "$UNEXPECTED" ]; thenecho "⚠ Unexpected files in diff:"printf '%s\n' "$UNEXPECTED"# stop and surface to userfi
Note: npm run preindex does not modify data/skill-index-resources.json — it only writes per-repo files under data/skill-index/. The resources file should only appear in the diff if the user is also refreshing the top-level updatedAt timestamp (optional — leave it alone unless asked).
If unexpected files appear (e.g. someone left edits in src/ or skills/), stop and tell the user. Do not commit a mixed change.
Step 7: Print the four-bucket summary
Render a markdown table grouped by bucket, with skill-count deltas. This is what the user reads to decide whether to confirm the PR.
## Refresh summary — N repos processed### ✓ Updated (X)| Repo | Before | After | Δ ||------|--------|-------|---|| anthropics/skills | 14 | 15 | +1 || obra/superpowers | 22 | 22 | 0 |### · Unchanged (Y)| Repo | Skills ||------|--------|| owner1/repo1 | 7 |### ✗ Failed (Z)| Repo | Error ||------|-------|| owner2/repo2 | clone failed: 404 Not Found |### ○ Skipped (W)| Repo | Reason ||------|--------|| luongnv89/asm | disabled in skill-index-resources.json |
If X + Y + Z + W does not equal len(enabled) + len(disabled), the classification is inconsistent — stop and re-check Step 4 before moving on.
Step 8: Confirmation gate, commit, and PR
Do not proceed without explicit user confirmation. Print the diff stat and ask:
git diff --stat -- data/skill-index/ data/skill-index-resources.jsonechoecho "Ready to commit the files above and open a PR."echo "Type 'yes' to continue, anything else to abort."
On yes (and only yes), stage only the index data files — never website/catalog.json, never anything outside data/skill-index/ — commit with the conventional-commit message below, push, and open the PR:
git add data/skill-index/# Only add the resources file if it was intentionally modified (e.g., updatedAt bump):if git diff --name-only | grep -q '^data/skill-index-resources\.json$'; thengit add data/skill-index-resources.jsonfigit commit -m "$(cat <<'EOF'chore(index): refresh indexed skill sourcesRe-ingested all enabled repos in data/skill-index-resources.json.Updated: <X> repo(s)Unchanged: <Y> repo(s)Failed: <Z> repo(s)Skipped: <W> repo(s)EOF)"branch="$(git rev-parse --abbrev-ref HEAD)"git push -u origin "$branch"gh pr create --title "chore(index): refresh indexed skill sources" --body "$(cat <<'EOF'## SummaryRe-ingested all enabled repos in `data/skill-index-resources.json` to bring the catalog up to date with upstream.## Results- **Updated:** <X> repo(s)- **Unchanged:** <Y> repo(s)- **Failed:** <Z> repo(s) (see body for details)- **Skipped:** <W> repo(s) (disabled in resources file)### Updated repos| Repo | Before | After | Δ ||------|--------|-------|---|| ... | ... | ... | ... |### Failed repos| Repo | Error ||------|-------|| ... | ... |## Test Plan- [ ] `data/skill-index/*.json` files are valid JSON- [ ] `npx tsx scripts/build-catalog.ts` rebuilds `website/catalog.json` without errors- [ ] No files outside `data/skill-index/` and `data/skill-index-resources.json` are staged- [ ] CI passesEOF)"
Fill the <X> / <Y> / <Z> / <W> placeholders and the per-bucket tables with the actual numbers from Step 7 before running gh pr create.
Verification: gh pr view --json url returns the new PR URL. Print it back to the user.
Expected Output
On a successful run, the user should see (and the agent should verify) all of the following:
- Repo synced — branch is up to date with
origin, any local edits were stashed and restored cleanly. - `npm run preindex` completed — exit code captured; per-repo lines visible in the log.
- All four buckets populated — every enabled repo lands in exactly one of updated / unchanged / failed, and every disabled repo lands in skipped. Totals add up.
- `npx tsx scripts/build-catalog.ts` succeeded —
website/catalog.jsonrebuilt and is valid JSON. Not staged. - Diff scope contained — only
data/skill-index/*.json(and optionallydata/skill-index-resources.jsonif explicitly refreshed) appear ingit diff. - User confirmed — explicit
yesrecorded before commit + push. - PR opened — conventional-commit title (
chore(index): refresh indexed skill sources), body filled from Step 8 template, URL returned to user.
If any of items 1–5 fails, do not proceed to Steps 6–7.
Edge Cases
Inputs the skill must handle without crashing, in order of likelihood:
- No enabled repos (
enabled[]is empty): stop with an explanation — there is nothing to refresh. - Existing local edits to `data/skill-index/`: the mandatory pre-edit stash (Repo Sync Before Edits) captures them; if the post-run pop conflicts, the recovery hint in the stash block tells the user how to restore.
- A single upstream repo is unreachable (404, network blip):
preindexmarks itFAILEDand continues; the failed repo lands in the failed bucket. The PR still ships for the other repos. - All upstream repos fail (no network, GitHub outage): every enabled repo lands in failed; the diff is empty; stop before Step 8 because there is nothing to commit.
- A repo's ingest produces zero `skillCount` (upstream removed every SKILL.md): treat it as updated with a negative delta — the change is real and worth shipping.
- `npm run preindex` is missing or errors before producing any log lines: stop in Step 3 — this is environmental, not a per-repo failure. Prompt the user to run
npm installand retry. - `npx tsx scripts/build-catalog.ts` fails after a successful preindex: stop in Step 5 — the index is internally inconsistent. Investigate manually before committing anything.
- `website/catalog.json` accidentally appears in `git status`: it is gitignored; if
.gitignorewas broken, fix it before staging. Never `git add website/catalog.json`. - Unexpected files in the diff (someone left WIP edits in
src/orskills/): stop in Step 6 and tell the user — do not commit a mixed change. - User declines the confirmation in Step 8: stop cleanly. Leave the refreshed
data/skill-index/*.jsonfiles in the working tree so the user can inspect or re-confirm later. Do notgit checkout --anything. - `gh` CLI not authenticated: prompt the user to run
gh auth loginbefore retrying Step 8.
Error Handling
- Stash pop conflict after sync: surface the recovery hint, stop the pipeline. The user resolves manually.
- `preindex` exits 1 but produced a partial log: continue to Step 4 — partial results are still useful.
- `build-catalog` exits non-zero: stop. A broken catalog is a structural data issue, not a transient error.
- `git diff` shows unexpected files: stop. Ask the user to either revert unrelated edits or run this skill on a clean branch.
- `gh pr create` fails (auth, network, missing remote): print the staged commit SHA so the user can push and open the PR manually.
Cleanup
After the PR is opened (or the pipeline aborts), remove temporary artifacts:
rm -rf /tmp/refresh-index
Leave the working tree as the user left it. Do not git checkout anything they did not stage.