About agent-skills-catalog
A skill for building Next.js App Router catalogs of Agent Skills stored in external repositories. It provides a local, commit-pinned sync and parsers, pages, eval displays, and validation so builds read repository content without network access.
Key features
- 01Commit-pinned whole-skill sync
- 02Skill and eval file parsing
- 03Catalog pages and search
- 04Latest recorded eval result display
- 05Content validation and tests
Use cases
- 01Creating a repository-backed skills catalog
- 02Mirroring skill releases into a site repository
- 03Displaying agent eval results
- 04Validating catalog content during tests
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ timerise-ai/ agent-skills-catalog --skill agent-skills-catalogAfter installing, type/agent-skills-catalogin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
.gitignoreCHANGELOG.mdCLAUDE.mdLICENSEREADME.md.github/workflows/agent-eval.ymlassets/content/skills/example-skill/meta.mdassets/content/skills/example-skill/upstream/README.mdCHANGELOG.mdsync.jsonassets/content/skills/example-skill/upstream/evals/prompts.md2026-10-30-claude-code-p1.mdassets/content/skills/example-skill/upstream/references/provenance.mdevals/prompts.mdreferences/data-model.mdadaptation.mdextensions.mdevals.mdloader.mdparsing.mdtesting.mdui.mdsync.mdprovenance.mdroutes.mdDetails
From the project READMEAgent Skills catalog: synced skill files, pages, eval results
A skills catalog is a set of pages about files that live somewhere else, so the page must say exactly
what the skill's repository says, at one commit, and nothing else. Written by the engineer who has shipped
this module, which holds that as verified properties: the sync reads every file of a skill at one commit
and swaps it in whole, the build reads the disk and never the network, every eval file either renders or
fails the tests with its reason, and the eval cards show the recorded result of the newest run per agent
and prompt. The record is in references/provenance.md.
When to use
Building or extending pages on a Next.js App Router site that list Agent Skills published as repositories
(each with SKILL.md, README.md, CHANGELOG.md and an evals/ folder), with their rules, releases,
install commands and agent eval results.
When NOT to use
- Writing or hardening a skill itself: that is the skill's own repository; to fix one from its eval
runs, the sibling
skill-eval-loopskill. - Running agent evals: the runs are made elsewhere and committed to each skill's
evals/; this module only reads them. - A blog or a help center from markdown in the repository: the sibling
blog-markdownandhelp-center-markdownskills. Here the markdown is someone else's and is never edited. - A package registry or marketplace with accounts, uploads or downloads: different trust model.
Architecture
skill repositories (GitHub, or local checkouts)
| npm run skills:sync head sha first, every file at that sha, staged, swapped in whole
v
content/skills/<slug>/meta.md host-written: category, tagline, related
content/skills/<slug>/upstream/ sync-written only: SKILL.md README.md CHANGELOG.md
references/provenance.md evals/*.md sync.json
content/skills/_index/README.md optional index table: Builds and Backend cells
| build time, no network
v
lib/skills/catalog.ts getSkill(slug), getAllSkills(), categories, related React cache()
markdown.ts + upstream.ts sections, rules, tables, releases, provenance (SKILL_LAYOUT)
evals.ts prompts, parseEval (ok or reason), sortRuns, latestRuns
validate.ts every problem the loader forgives, as errors and warnings
|
+-- /skills catalog: SkillSummary[] to a client search and filter
+-- /skills/[slug] a skill page, or a category page when the slug is a category
+-- sitemap, JSON-LD dates from the changelog, never from the build
+-- catalog.test.ts validateCatalog() errors fail npm test
Critical facts
- Each skill has two halves.
meta.mdholds what the repository does not (category, tagline, related) and only the host writes it;upstream/holds the repository's files and only the sync writes it. - The layout is the parser's contract.
SKILL_LAYOUTnames the headings the loader reads; a skill that strays loses that section and the validator says which. Nothing is guessed from prose. - Upstream links are relative to their repository.
references/x.mddoes not exist on the site, soSkillMarkdownresolves every relative link against the file's folder on GitHub. - One
[slug]segment serves skills and categories.dynamicParams = falsekeeps every page static, and the validator fails on a skill slug that equals a category id. - A run file is free text anyone can propose. Only an Actions run URL in the organization's own
repositories becomes an "Agent log" link; JSON-LD escapes
<. - Run files do not sort as text.
-p1.mdsorts after-p1-2.md, so the order is date, thenrunNumber, then name. - The build never needs GitHub. An unattended run with no network commits the example skill from
assets/content/so the pages, validator and tests have content, and hands overnpm run skills:sync.gray-matter,react-markdown,remark-gfmandvitestcome from npm, which is not an external service. The templates are copied, not rewritten: only the seam values in adaptation.md change, and the five test files run unmodified: 24 tests.
Hard rules
The same eight, in order, as the README and adaptation.md.
Never fetch a skill at build or request time. The sync writes files into the repository and the build reads the disk, so a deploy never depends on GitHub's rate limit or its cache.
Read every file of a skill at one commit. Resolve the head sha first and fetch each file at that sha; a raw URL on the branch name is cached for minutes and mixes two commits.
Swap a skill's mirror in whole or not at all. Stage the folder, then rename it into place, so a failed sync leaves the previous copy and a file deleted upstream disappears here.
Never drop an eval file silently.
parseEvalreturns the reason it cannot show a file, andvalidateCatalog()turns each one into an error that failsnpm test.
Show the recorded result of the newest run per agent and prompt. Failing runs render like passing ones, nothing is recomputed or picked for looking better, and an agent with no run is named.
Normalize YAML dates before reading frontmatter as text. An unquoted
date: 2026-09-26is a Date, and a Date read as text is an empty string that rejects the run.
Never retype a skill's text on the site. Rules, releases, prompts and results come from
upstream/;meta.mdcarries only what the repository does not, and the sync never touches it.
Only summaries cross to the client. The catalog's search gets
SkillSummary[]; a wholeSkillin a client component ships every README to every visitor.
Quick start
- Fill in the seam contract, the organization and the categories: adaptation.md.
- Write the config, categories and types, and lay out
content/skills/: data-model.md. - Copy the sync and wire
npm run skills:sync; run it, or with no network copyassets/content/into the app: sync.md. - Copy the frontmatter, layout, markdown and upstream readers: parsing.md.
- Copy the eval parser: evals.md.
- Copy the loader and the validator: loader.md.
- Add the catalog and
[slug]pages, JSON-LD and the sitemap: routes.md. - Add the components, then style them through the
data-skill-*hooks: ui.md. - Copy
vitest.config.tsand the five test files, wirenpm test, and run it withnpm run typecheckandnpm run build: testing.md. - The final message, not only a README, hands over: the organization and branch in
config.tsand the sync, thatnpm run skills:syncruns after every skill release and its result is committed,GITHUB_TOKENfor more than about thirty skills, thatsiteUrlmust be set before deploying (a literal, never an environment variable), and that the example skill is deleted after the first real sync. Next: extensions.md; before simplifying anything, provenance.md.
Reference directory
| Scenario | Trigger keywords | Reference |
|---|---|---|
| Fitting this into an existing app | adapt, seam, organization, rename, host probe, categories, dependencies | adaptation.md |
| Config, categories, types, folders | config, SKILLS_CATALOG, category, meta.md, Skill, SkillSummary, content/skills | data-model.md |
| Pulling skills into the repository | sync, skills:sync, GitHub, raw.githubusercontent.com, sha, GITHUB_TOKEN, rate limit, sync.json, local | sync.md |
| Reading SKILL.md, README, changelog | gray-matter, frontmatter, Date, heading, SKILL_LAYOUT, list, table, release, provenance, index table | parsing.md |
| Prompts and eval runs | evals, prompts.md, parseEval, result, partial, runNumber, latestRuns, runUrl, interventions | evals.md |
| Loading the catalog and validating it | getSkill, getAllSkills, cache, related, validateCatalog, warning, error | loader.md |
| Pages, metadata, JSON-LD, sitemap | route, page.tsx, generateStaticParams, dynamicParams, category page, TechArticle, BreadcrumbList, sitemap | routes.md |
| Cards, search, eval cards, markdown | SkillCatalog, search, filter, EvalRuns, SkillMarkdown, relative links, urlTransform, data-skill | ui.md |
| Tests and the content validator | vitest, npm test, catalog.test, fixture, example skill, alias | testing.md |
| Beyond the shipped module | Markdown copy, llms.txt, price, call to action, assistant, eval collection, badges | extensions.md |
| Why the templates differ from the earlier implementation | provenance, audit, ledger, kept deliberately, added | provenance.md |
Part of the Timerise Skills index, which lists the sibling skills.