skill-registry-catalog

Core

Catalog third-party AI agent skills from public registries — a categorized, tracked catalog of skills worth evaluating.

Category: Meta Tier: Broadly empowering, nearly any user benefits Source: Generalized from existing Updated: 2026-07-20

What it does

The agent pulls skill data from public registries (skills.md, skillsmp.com), filters it by the categories you care about, and builds a repository where every third-party skill gets its own folder. Skills are split into three buckets — **approved** (already in your local library), **pending** (awaiting your review), and **other** (out of focus) — and a counter tracks how many skills you add per time window. Optional CI re-scans the registries on a schedule so the catalog stays current. This is the "what's out there worth evaluating" skill. It deliberately keeps third-party skills separate from your own so you can approve or reject them one at a time.

How an agent uses it

  • Survey public skill registries (skills.md, skillsmp.com) for specific domains — Discord,

security/pentest, backend, API, MCP, frontend, etc.

  • Produce a repo the user can browse and approve/reject one skill at a time.
  • Track ingestion volume over time (hour / day / week / month / year / all-time).
  • The user asks to "look at these registries and catalog the skills" or "track external skills

separated from my own."

What you get

Install this skill and your Hermes agent can catalog third-party ai agent skills from public registries — a categorized, tracked catalog of skills worth evaluating. No manual setup, no scripts to run — the agent handles it.

Install command

hermes skills install https://raw.githubusercontent.com/THEROCKSSS/hermes-skills-portfolio/main/skills/skill-registry-catalog/SKILL.md
View SKILL.md on GitHub
---
name: skill-registry-catalog
description: Use when the user wants to survey public agent-skill registries (skills.md, skillsmp.com) for a domain and build a categorized, source-cited catalog repo with approved/pending buckets and live ingestion counters — not for organizing skills already adopted into the user's own library.
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
  hermes:
    tags: [skill-registry, cataloging, ci-automation, github-api, forgejo-api, skills-md]
    related_skills: [skill-publish, portfolio-upkeep, skills-portfolio-scaffold]
---

# skill-registry-catalog

## Overview

Build a categorized, source-cited catalog of third-party agent skills harvested from public
registries. Each skill is separated from your own library so it is easy to triage — approved
skills (matching your local library) and pending skills (awaiting human review) live in their
own folders, with a master `CATALOG.md` and live ingestion counters.

## When to Use

- Survey public skill registries (skills.md, skillsmp.com) for specific domains — Discord,
  security/pentest, backend, API, MCP, frontend, etc.
- Produce a repo the user can browse and approve/reject one skill at a time.
- Track ingestion volume over time (hour / day / week / month / year / all-time).
- The user asks to "look at these registries and catalog the skills" or "track external skills
  separated from my own."

## Sources

Two public registries are the defaults. Fetch structured data from their JSON APIs, not the
HTML pages.

| Registry | List page | JSON API | Notes |
|---|---|---|---|
| skills.md | `https://skills.md/skills` | `https://skills.md/api/skills` | Returns the full array in one call |
| skillsmp.com | `https://skillsmp.com/search` | `https://skillsmp.com/api/skills?page=N&limit=100` | Caps at 100/page — must paginate |

Fetch from `terminal` with `curl`/`urllib`, or from the browser console with `fetch()`. Keep
the HTML pages for visual confirmation only; the catalog data comes from the JSON.

### Response shapes (abridged)

skills.md element:
```json
{"name":"api-test-suite","displayName":"API Test Suite",
 "description":"Generate and run API test suites...","category":"Development Tools",
 "tags":["api","testing","automation","qa"],"pricing":{"tier":"free"},"source":"official"}
```

skillsmp.com element:
```json
{"id":"...","name":"openspec-apply-change","author":"Orient-Software-Development",
 "description":"...","githubUrl":"https://github.com/.../tree/main/.claude/skills/...",
 "stars":0,"updatedAt":"1783911957","path":"SKILL.md",
 "route":{"ownerSlug":"...","repoSlug":"...","routeSlug":"...","sourceSkillPath":"..."}}
```

### Parsing quirks (real, not theoretical)

- **skillsmp.com caps at 100 per response** even if you pass `limit=1000`. Paginate `page=1..N`
  until a page returns `[]` or fewer than 100 items:
  ```python
  all_sk = []
  for p in range(1, 30):
      d = json.load(urlopen(f"https://skillsmp.com/api/skills?page={p}&limit=100"))
      s = d.get("skills", [])
      if not s:
          break
      all_sk += s
  ```
- **skills.md `/api/skills`** can return the JSON array concatenated with `===` plus an HTML
  error page if multiple candidate URLs were fetched together in one console call. Slice before
  parsing:
  ```python
  raw = wrapper["result"]
  end = raw.find("}]") + 2
  skills = json.loads(raw[:end])
  ```
- **skillsmp.com `/api/search?q=` returns 404.** There is no text-search API — pull the full
  paginated `/api/skills` and filter client-side.

## Workflow

### 1. Confirm sources and categories
Agree the registries and focus categories with the user (e.g. Discord, Security/Pentest, Backend,
API, MCP). Categories are defined as regex keyword maps over each skill's
`name + description + tags + category/author` (lower-cased).

```python
CATS = {
  "Discord":         [r"discord"],
  "Security/Pentest":[r"security", r"pentest", r"penetration", r"vuln", r"\baudit\b",
                      r"exploit", r"\bcve\b", r"secure", r"threat", r"secret", r"\bauth\b",
                      r"hardening"],
  "Backend":         [r"backend", r"server", r"\bdb\b", r"database", r"orm", r"microservice",
                      r"fastapi", r"django", r"express", r"\bsql\b"],
  "API":             [r"\bapi\b", r"\brest\b", r"graphql", r"openapi", r"endpoint",
                      r"webhook", r"\bsdk\b"],
  "MCP":             [r"\bmcp\b", r"model context protocol", r"mcp server", r"mcp client"],
}
```

### 2. Extract + filter
- Pull both datasets as JSON (see quirks above).
- Run each skill through the category maps; a skill hits a category if any pattern matches.
- Cross-reference each skill name against the user's **local skill library** to decide
  approved vs pending (see Filtering).
- Dedupe by `(source, name)`.

### 3. Build the catalog repo
```
<repo>/
├── README.md            # overview + live COUNTERS block
├── CATALOG.md           # 3-bucket master list (approved / pending / other)
├── .github/workflows/   # validate.yml, counters.yml, rescan.yml
├── scripts/             # build_catalog.py, counters.py
└── skills/
    ├── approved/<name>__<source>/{README.md, SKILL.md}
    └── pending/<name>__<source>/{README.md, SKILL.md}
```
- Per-skill `SKILL.md` frontmatter: `name`, `source` (direct registry URL), `status`
  (`approved` | `pending`), `incorporated_as` (for approved).
- Per-skill `README.md`: description, metadata table, Original URL, an action checkbox for review.
- Folder names join skill and source so the same skill from two registries does not collide:
  `<name>__<source>` (e.g. `api-test-suite__skills.md`).

### 4. Cross-reference against local library
Decide `approved` vs `pending`:
- **Approved** — the skill's name or function overlaps an existing local skill, or it is a
  known upgrade of one you already use. Keep the match loose-but-verified.
- **Other** — does not fit any focus category and is not approved; still recorded so re-scans
  stay stable.
Require either exact local-skill-name containment **or** an explicit `known_upgrades` map
(e.g. `api-test-suite`, `backend-patterns`, `generate-dockerfile`, `repo-security-audit`,
`discord-suite`). Reject bare substring hits (`image`, `write`, `backend`) — they over-match.

## Catalog Structure

`CATALOG.md` is the master index with three buckets:

```markdown
# Catalog

## Approved (already in your library)
| Name | Source | Category | Local match |
|---|---|---|---|
| api-test-suite | skills.md | Backend/API | api-test-suite |

## Pending (awaiting review)
| Name | Source | Category | Original URL |
|---|---|---|---|
| some-new-skill | skillsmp.com | MCP | https://... |

## Other (out of focus, not approved)
| Name | Source | Category |
|---|---|---|
| ... | ... | ... |
```

Each per-skill folder has a self-contained `README.md` with an `[ ] reviewed` checkbox so a
human can tick skills off one at a time.

## Counters

The user wants time-window tracking. `README.md` carries a fenced block that the counter script
rewrites from git history:

```
<!-- COUNTERS_START -->
| Window | Skills Added |
|---|---|
| Past hour | 0 |
| Past 24h | 0 |
| Past 7d | 0 |
| Past 30d | 0 |
| Past 6mo | 0 |
| Past 1y | 0 |
| All time | 0 |
<!-- COUNTERS_END -->
```

`scripts/counters.py --patch` computes the counts from the commit timestamps of added files under
`skills/` and rewrites the block in place:

```bash
git log --diff-filter=A --name-only --pretty=%ct -- skills/ \
  | python scripts/counters.py --patch
```

## CI/Automation

Put three workflows in your git host's CI directory (GitHub: `.github/workflows/`; Forgejo:
`.forgejo/workflows/`; GitLab: `.gitlab-ci.yml`). Use `[skip ci]` in counter-commit messages to
avoid loops.

- **validate.yml** — on push/PR, lint every `SKILL.md` frontmatter (required: `name`, `source`,
  `status`; `status ∈ {approved, pending}`).
- **counters.yml** — scheduled hourly + on push; runs `counters.py --patch` and commits if the
  block changed.
- **rescan.yml** — scheduled weekly; re-fetches both APIs, diffs new names against existing
  `skills/` entries, and opens one review issue per new focus skill (labels: `pending-approval`,
  `source:*`, `cat:*`).

Issue posting uses your git host's REST API with a token. Labels usually require **numeric IDs**
(GitHub: `labels: [id,...]`), so fetch the label list first and map `name → id`. Never embed the
token in source; read it from a CI secret.

## Common Pitfalls

1. **Trusting a single `limit=1000` call on skillsmp.com.** The API caps at 100/page regardless
   of the requested limit. Loop `page=1..N` until a page returns `[]` or fewer than 100 items, or
   the catalog silently truncates.
2. **Parsing the skills.md response with a bare `json.loads`.** When multiple candidate URLs are
   fetched together in one console call, the response can be the JSON array concatenated with
   `===` plus a trailing HTML error page. Slice at the first `}]` before parsing.
3. **Calling `/api/search?q=` on skillsmp.com.** There is no text-search endpoint — it 404s. Pull
   the full paginated `/api/skills` and filter client-side instead.
4. **Approving on a bare substring match.** Matching `image`, `write`, or `backend` as a
   substring over-matches unrelated skills. Require exact local-skill-name containment or an
   explicit `known_upgrades` map before marking a skill `approved`.
5. **Declaring the catalog "done."** It's a living artifact — re-scans keep adding entries. Hand
   the live repo URL to the user for visual verification instead of self-certifying completion.
6. **Letting the counters workflow commit without `[skip ci]`.** A counter-update commit that
   doesn't skip CI retriggers the same workflow, creating a commit loop.
7. **Using a read-only token for issue/label creation.** The `rescan.yml` workflow needs write
   scope on the target repo; a read-only token fails with 403. Labels also usually require
   numeric IDs — fetch the label list first and map `name → id`.

## Verification Checklist

- [ ] Both registries pulled from their JSON APIs (not scraped HTML), with skillsmp.com paginated
      to a page returning `[]` or `< 100` items.
- [ ] Every entry deduped by `(source, name)` before it lands in `CATALOG.md`.
- [ ] Every `approved` entry has a verified local-skill-name match or an explicit upgrade-map hit
      — no bare substring approvals.
- [ ] `CATALOG.md`'s three buckets (Approved / Pending / Other) match the per-skill folders under
      `skills/approved/` and `skills/pending/`.
- [ ] The `COUNTERS_START`/`COUNTERS_END` block reflects real git history, not placeholder zeros.
- [ ] `validate.yml`, `counters.yml`, and `rescan.yml` are present and counter/rescan commits
      include `[skip ci]`.
# skill-registry-catalog



Survey public AI-agent skill registries and turn them into a categorized, source-cited catalog

you can actually triage — not a bookmark dump.



## What it does



The agent pulls skill data from public registries (skills.md, skillsmp.com), filters it by the

categories you care about, and builds a repository where every third-party skill gets its own

folder. Skills are split into three buckets — **approved** (already in your local library),

**pending** (awaiting your review), and **other** (out of focus) — and a counter tracks how many

skills you add per time window. Optional CI re-scans the registries on a schedule so the catalog

stays current.



This is the "what's out there worth evaluating" skill. It deliberately keeps third-party skills

separate from your own so you can approve or reject them one at a time.



## Install



```bash

hermes skills install https://raw.githubusercontent.com/THEROCKSSS/hermes-skills-portfolio/main/skills/skill-registry-catalog/SKILL.md

```



## How to use



```

"Catalog the Discord, security, and MCP skills from skills.md and skillsmp.com,

 separated from my own library, and track how many I add per week."

```



The agent will:



1. Confirm which registries and focus categories you want.

2. Fetch the structured data from each registry's JSON API.

3. Filter by your categories and cross-reference against your local skill library.

4. Build a repo with per-skill folders, a master `CATALOG.md`, and a `README.md` counter block.

5. (Optional) Wire up CI to re-scan and update counters on a schedule.



## Sources and APIs



Two registries are supported out of the box. Always pull from the JSON API, not the HTML page.



| Registry | JSON API | Behavior |

|---|---|---|

| skills.md | `https://skills.md/api/skills` | Returns the full skill array in one response |

| skillsmp.com | `https://skillsmp.com/api/skills?page=N&limit=100` | Caps at 100 items/page — paginate until empty |



Both return one JSON object per skill with at least `name`, `description`, and a source URL

(skills.md adds `tags`/`category`; skillsmp.com adds `githubUrl`/`author`/`updatedAt`).



### Fetching skillsmp.com (paginated)



```python

import json, urllib.request



def fetch_skillsmp():

    out, page = [], 1

    while True:

        url = f"https://skillsmp.com/api/skills?page={page}&limit=100"

        with urllib.request.urlopen(url) as r:

            data = json.load(r)

        batch = data.get("skills", [])

        if not batch:

            break

        out.extend(batch)

        if len(batch) < 100:

            break

        page += 1

    return out

```



### Fetching skills.md



```python

import json, urllib.request



def fetch_skillsmd():

    with urllib.request.urlopen("https://skills.md/api/skills") as r:

        raw = r.read().decode()

    end = raw.find("}]") + 2          # guard against concatenated error HTML

    return json.loads(raw[:end])

```



### Known parsing quirks



- **skillsmp.com** ignores `limit` above 100 — loop until a short or empty page.

- **skills.md** `/api/skills` can append `===` and an HTML error page if several candidate URLs

  were fetched in one console call. Slice at the first `}]` before parsing.

- **skillsmp.com** has no search API (`/api/search?q=` is 404). Pull all pages and filter locally.



## Catalog structure



```

<repo>/

├── README.md            # overview + live COUNTERS block

├── CATALOG.md           # approved / pending / other

├── .github/workflows/   # validate.yml, counters.yml, rescan.yml

├── scripts/

│   ├── build_catalog.py # scrape + filter + write folders

│   └── counters.py      # time-window counter + README patcher

└── skills/

    ├── approved/<name>__<source>/{README.md, SKILL.md}

    └── pending/<name>__<source>/{README.md, SKILL.md}

```



Folder names join skill and source (`api-test-suite__skills.md`) so the same skill from two

registries never collides. Each per-skill `README.md` carries an `[ ] reviewed` checkbox so a

human can tick skills off one at a time.



### Per-skill SKILL.md frontmatter



```yaml

---

name: api-test-suite

source: https://skills.md/skills/api-test-suite

status: approved          # approved | pending

incorporated_as: api-test-suite   # only for approved

---

```



## Filtering



Categories are regex keyword maps over each skill's `name + description + tags + category/author`

(lower-cased). A skill lands in a category if any pattern matches.



```python

CATS = {

    "Discord":          [r"discord"],

    "Security/Pentest": [r"security", r"pentest", r"penetration", r"vuln", r"\baudit\b",

                         r"exploit", r"\bcve\b", r"secure", r"threat", r"secret",

                         r"\bauth\b", r"hardening"],

    "Backend":          [r"backend", r"server", r"\bdb\b", r"database", r"orm",

                         r"microservice", r"fastapi", r"django", r"express", r"\bsql\b"],

    "API":              [r"\bapi\b", r"\brest\b", r"graphql", r"openapi", r"endpoint",

                         r"webhook", r"\bsdk\b"],

    "MCP":              [r"\bmcp\b", r"model context protocol", r"mcp server", r"mcp client"],

}

```



### Approved vs pending



- **Approved** — the skill name or function overlaps a skill already in your local library, or it

  is a known upgrade of one you use.

- **Pending** — everything that fits a focus category but is not yet approved.

- **Other** — does not fit any focus category and is not approved; still recorded so re-scans are

  stable.



Match loosely but verify: require exact local-skill-name containment **or** an explicit

`known_upgrades` allowlist. Reject bare substring hits (`image`, `write`, `backend`) — they

over-match unrelated skills.



## Counters



The `README.md` holds a fenced block the counter script rewrites from git history:



```

<!-- COUNTERS_START -->

| Window | Skills Added |

|---|---|

| Past hour | 0 |

| Past 24h | 0 |

| Past 7d | 0 |

| Past 30d | 0 |

| Past 6mo | 0 |

| Past 1y | 0 |

| All time | 0 |

<!-- COUNTERS_END -->

```



`scripts/counters.py --patch` derives the numbers from the timestamps of added files under

`skills/`:



```bash

git log --diff-filter=A --name-only --pretty=%ct -- skills/ \

  | python scripts/counters.py --patch

```



## CI / automation



Use your git host's CI directory (GitHub `.github/workflows/`, Forgejo `.forgejo/workflows/`,

GitLab `.gitlab-ci.yml`). Put the token in a CI secret — never inline it.



- **validate.yml** — on push/PR, lint every `SKILL.md` for required frontmatter

  (`name`, `source`, `status`; `status ∈ {approved, pending}`).

- **counters.yml** — hourly + on push; runs `counters.py --patch` and commits if the block

  changed. Use `[skip ci]` in the commit message to avoid a self-trigger loop.

- **rescan.yml** — weekly; re-fetches both APIs, diffs new names against existing `skills/`, and

  opens one review issue per new focus skill. Labels generally need **numeric IDs** — fetch the

  label list first and map `name → id`.



## Requirements



- A local skill library to cross-reference against (so "approved" is meaningful).

- Network access to the registries' JSON APIs.

- A git host account and a token with repo/issue write scope for the optional automation.



## Pitfalls



- **Page caps** — skillsmp.com returns at most 100 items per call. Loop until short or empty.

- **Concatenated responses** — slice skills.md output at the first `}]` before `json.loads`.

- **No search API** — skillsmp.com `/api/search` is 404; filter the full pull locally.

- **False-positive approvals** — bare substring matches over-approve. Use exact-name or an

  allowlist.

- **CI loops** — counter commits must carry a skip directive or they re-trigger themselves.

- **Token scope** — repo/issue creation needs write scope; a read-only token fails with 403.



## Example end state



A repo where `CATALOG.md` lists 40 approved, 120 pending, 300 other skills; `README.md` shows

23 skills added in the past 7 days; and a Monday CI job opens five new review issues for skills

that appeared in the registries since last scan.