Refresh Index logo

Refresh Index

Community
luongnv89
refresh-index

Sync every enabled repo in the curated skill index and open a confirmation-gated PR. Use when refreshing already-indexed sources. Don't use for adding new repos, improving a single skill, or installing skills locally.

Overview

Publisherluongnv89
Repositoryasm
Skill namerefresh-index
Stars
955
Forks
82
Bundled files
6
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 6 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by luongnv89 on GitHub. Read the source before you install it.

Installation

Install the Refresh Index AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/luongnv89/asm/tree/main/skills/refresh-index
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/luongnv89/asm.git /tmp/asm
mkdir -p .claude/skills
cp -r /tmp/asm/skills/refresh-index .claude/skills/refresh-index
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Refresh Index in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Refresh Index on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Refresh Index is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Refresh Index

Re-ingest every enabled repository in data/skill-index-resources.json so data/skill-index/{owner}_{repo}.json matches upstream. Classify each repo as updated / unchanged / failed / skipped, verify the catalog rebuilds, then open one data-only PR after explicit confirmation.

This is the inverse of skill-index-updater (that skill adds repos). Keep SKILL.md as the spine and load step detail from references/ so the agent's context budget stays small.

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, or a release needs current upstream skill metadata

Do not trigger for: adding a new repository (skill-index-updater), authoring or improving a single skill (skill-creator), opening an upstream PR (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:

bash
branch="$(git rev-parse --abbrev-ref HEAD)"
dirty=0
if [ -n "$(git status --porcelain)" ]; then
  git stash push -u -m "pre-refresh-index: ${branch}"
  dirty=1
fi
git fetch origin
git pull --rebase origin "$branch"
if [ "$dirty" -eq 1 ]; then
  git 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.

  • node on PATH (command -v node) — Node >= 22 per package.json engines
  • npm on PATH (command -v npm) — required by npm run preindex; the ingester evaluates skills in-process, so no asm binary is needed
  • gh on PATH and authenticated (gh auth status) — required for PR creation
  • git on 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. Long scripts and templates live in references/; read the linked file when you reach that step.

Many agent hosts start each command in a fresh shell. Start every code block with ROOT="$(git rev-parse --show-toplevel)"; RES="$ROOT/data/skill-index-resources.json" instead of relying on variables from an earlier step.

Step 1: Enumerate the index

Read data/skill-index-resources.json and split entries, keyed on the source string (github:owner/repo) because that is the identifier preindex echoes:

bash
ROOT="$(git rev-parse --show-toplevel)"
RES="$ROOT/data/skill-index-resources.json"
jq -r '.repos[] | select(.enabled == true)  | .source' "$RES"
jq -r '.repos[] | select(.enabled == false) | .source' "$RES"
jq -r '.repos[] | select(.enabled == true) | "\(.source)\t\(.owner)_\(.repo)"' "$RES"
jq empty "$ROOT"/data/skill-index/*.json   # exits non-zero if any file is invalid
git -C "$ROOT" status --porcelain -- website/ data/
  • enabled[] — "enabled": true. These will be refreshed.
  • disabled[] — "enabled": false. These land in skipped with reason "disabled in skill-index-resources.json". The list may be empty; then W = 0.

Verification: enabled[] is non-empty, every per-repo JSON parses, and git status --porcelain -- website/ data/ prints nothing. If any check fails, stop. A clean website/ is what lets Step 5 restore the tracked files build-catalog rewrites.

Step 2: Snapshot pre-run skill counts

Record current skillCount for each enabled repo so Step 7 can report deltas. Run the loop in references/snapshot.md. Missing index file → pre-count 0.

Step 3: Run npm run preindex

Re-ingest every enabled repo. Capture stdout and the exit code — preindex exits 1 if any repo fails, but do not abort. Partial results still classify.

preindex writes each ingest to getIndexDir() before copying it into data/skill-index/. Without an override that is the user's real ~/.config/agent-skill-manager/skill-index/, a change no git diff shows. Always set ASM_CONFIG_DIR to a scratch directory:

bash
ROOT="$(git rev-parse --show-toplevel)"
mkdir -p /tmp/refresh-index/asm-config
LOG="/tmp/refresh-index/preindex.log"
cd "$ROOT"
ASM_CONFIG_DIR=/tmp/refresh-index/asm-config npm run preindex > "$LOG" 2>&1
PREINDEX_EXIT=$?
cat "$LOG"

preindex clones every enabled repo in sequence and can run for many minutes. If the host's command timeout is shorter, run the command in the background and wait until the log ends with the Done: N succeeded, M failed line; then read the exit code.

Verification: the log exists and contains one line per enabled repo: {source} ... {N} skills or {source} ... FAILED: {error}. If the log is empty or no line matches, stop — that is environmental, not a per-repo failure.

Step 4: Classify each repo

Match each {source} log line to data/skill-index/{owner}_{repo}.json in git status --porcelain (which also lists new, untracked index files). Every ingest rewrites timestamps, so "changed" means changed after the timestamps are stripped. Read references/classify.md for the comparison and the four-row signal table. Capture post-run skillCount; failed repos keep the pre-count.

Step 5: Rebuild the website catalog (verification only)

Confirm the refreshed index is structurally valid. website/catalog.json is gitignored — never stage it.

bash
cd "$ROOT"
npx tsx scripts/build-catalog.ts
jq empty website/catalog.json
git restore -- website/ data/repo-stars.json

Verification: the first two commands exit 0. If either fails, stop — the data files are internally inconsistent and the PR must not land. build-catalog also rewrites tracked outputs (website/*-stats.json, website/robots.txt, and data/repo-stars.json on any networked run) with fresh values; git restore -- website/ data/repo-stars.json reverts them. That is safe only because Step 1 confirmed website/ and data/ were clean. It does not touch the gitignored website/catalog.json.

Step 6: Detect unexpected diff scope

Confirm the only files that changed are under data/skill-index/ (and data/skill-index-resources.json only if the user explicitly bumped updatedAt):

bash
UNEXPECTED=$(git status --porcelain | cut -c4- \
  | grep -v -E '^data/skill-index/' \
  | grep -v -E '^data/skill-index-resources\.json$' \
  || true)
if [ -n "$UNEXPECTED" ]; then
  echo "⚠ Unexpected files in diff:"
  printf '%s\n' "$UNEXPECTED"
fi

npm run preindex does not modify data/skill-index-resources.json. If unexpected files appear, stop. Do not commit a mixed change.

Step 7: Print the four-bucket summary

Render the markdown in references/summary-template.md. If X + Y + Z + W does not equal len(enabled) + len(disabled), stop and re-check Step 4.

Step 8: Confirmation gate, commit, and PR

Do not proceed without explicit user confirmation (yes only). Never commit on main: if the current branch is main, create chore/refresh-index-<YYYYMMDD> first. Read references/commit-and-pr.md for the branch step, the diff-stat prompt, conventional-commit message, and gh pr create body. Stage only data/skill-index/ (plus the resources file if intentionally modified). Never stage website/catalog.json.

Verification: gh pr view --json url returns the new PR URL. Print it back to the user.

Final output

End the run with the Step 7 summary, preceded by a short header the user can read without scrolling (template in references/summary-template.md):

  1. Result — first line: PR opened, stopped before commit (declined gate or empty diff), or blocked at Step N with the reason.
  2. Evidence — the checks that ran and their results: preindex exit code, build-catalog exit, diff-scope check, and the PR URL.
  3. Uncertainty — build-catalog proves the index is structurally valid, not that every upstream skill installs. Failed repos keep their old index data. Name any repo whose bucket was inferred from a missing log line.
  4. Decision — what the user must still do: review and merge the PR, or re-run after fixing the named failure. Approval to commit was the Step 8 yes; no other approval is needed.

Step Completion Reports

Emit a compact status block after each step:

◆ Step N — [step name]
··································································
  [check 1]:         √ pass
  [check 2]:         × fail — [reason]
  Result:            PASS | FAIL | PARTIAL

Use √ for pass, × for fail, — for context. Checks per step:

  • Repo sync — branch up to date, stash restored (if dirty)
  • Step 1 — enabled[] non-empty, per-repo JSON parseable, website/ and data/ clean
  • Step 2 — snapshot written
  • Step 3 — log exists, one line per enabled source
  • Step 4 — every repo in exactly one bucket, totals add up
  • Step 5 — build-catalog exit 0, catalog.json valid JSON
  • Step 6 — diff scope contained
  • Step 7 — summary printed, X+Y+Z+W matches list sizes
  • Step 8 — user confirmed yes, PR URL returned (skip this block if the user declined)

Expected Output

On a successful run, verify all of the following:

  1. Repo synced — branch is up to date with origin; any local edits were stashed and restored cleanly.
  2. npm run preindex completed — exit code captured; per-repo lines visible in the log.
  3. Every repo bucketed — every enabled repo lands in exactly one of updated / unchanged / failed, and every disabled repo (if any) lands in skipped. Totals add up.
  4. npx tsx scripts/build-catalog.ts succeeded — website/catalog.json rebuilt and is valid JSON. Not staged.
  5. Diff scope contained — only data/skill-index/*.json (and optionally data/skill-index-resources.json if explicitly refreshed) appear in git diff.
  6. User confirmed — explicit yes recorded before commit + push.
  7. PR opened — conventional-commit title (chore(index): refresh indexed skill sources), body filled from the Step 8 template, URL returned to the user.

If any of items 1–5 fails, stop before the Step 8 confirmation gate: no commit, no push, no PR.

Acceptance Criteria

  • Exactly the files under data/skill-index/ (and optionally data/skill-index-resources.json) are staged
  • website/catalog.json was rebuilt as a check and was not staged
  • preindex ran with ASM_CONFIG_DIR pointing under /tmp/refresh-index/
  • Four-bucket totals equal len(enabled) + len(disabled)
  • Commit message matches the template in references/commit-and-pr.md
  • gh pr view --json url returns a URL

When reviewing a run's output (by eval or by a human), also check that a reader can:

  • Find the main result — the first line states PR opened, stopped before commit, or blocked.
  • Separate facts from assumptions — observed exit codes and diffs are distinct from the stated limits of build-catalog.
  • Trace claims — each bucket entry maps to a preindex.log line or a git diff file; the PR claim maps to the returned URL.
  • See the next decision — review/merge, or the fix to apply before re-running.

An agent's own review cannot confirm human understanding. A reviewer who received no human feedback records understanding as unconfirmed.

Example

Given 2 enabled repos (one gained a skill) and 1 disabled repo, the expected output summary looks like:

## Refresh summary — 3 repos processed

### ✓ Updated (1)
| Repo | Before | After | Δ |
|------|--------|-------|---|
| anthropics/skills | 14 | 15 | +1 |

### · Unchanged (1)
| Repo | Skills |
|------|--------|
| obra/superpowers | 22 |

### ○ Skipped (1)
| Repo | Reason |
|------|--------|
| owner3/repo3 | disabled in skill-index-resources.json |

Edge Cases

Read references/edge-cases.md for the full list (empty enabled set, unreachable upstream, empty ingest, catalog rebuild failure, declined confirmation, unauthenticated gh). Handle those without crashing; never git checkout -- files the user did not stage.

Cleanup

After the PR is opened (or the pipeline aborts), remove temporary artifacts:

bash
rm -rf /tmp/refresh-index

Leave the working tree as the user left it. Do not git checkout anything they did not stage.

References

  • references/snapshot.md — Step 2 skill-count snapshot loop
  • references/classify.md — Step 4 signal table (updated / unchanged / failed / skipped)
  • references/summary-template.md — Step 7 four-bucket markdown
  • references/commit-and-pr.md — Step 8 confirmation, commit, and PR commands
  • references/edge-cases.md — edge cases and error handling

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Refresh Index AI skill do?

Sync every enabled repo in the curated skill index and open a confirmation-gated PR. Use when refreshing already-indexed sources. Don't use for adding new repos, improving a single skill, or installing skills locally.

Why use Refresh Index on TypingMind?

Because you install it once and use it with any model. Refresh Index is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Refresh Index in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/luongnv89/asm/tree/main/skills/refresh-index. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Refresh Index?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Refresh Index?

As many as you like. As long as a model supports skills, you can use Refresh Index with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Refresh Index AI skill free?

Yes. It is published on GitHub by luongnv89 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇