AGENTS.md · git:20261010.2342078 · 2026-10-10 · sha256 b14eb5a705fc8d49
AGENTS.md git:20261010.2342078A
Immutable. This exact content never changes and is served at /api/v1/blob/b14eb5a705fc8d49.
# Authoring & maintaining the `rpa-skills` catalog
Agent guide for working **inside this aggregator repository**. Read it before editing either marketplace
manifest, the README Skills table, or the installer.
> Naming (Russian): the adjective for "agent / agentic" is **«агентный»**, never «агентский».
## What this repo is
This repo is the **catalog**, not the skills. Each skill lives in its **own repository**
(`EvilFreelancer/rpa-init`, `.../logika`, …) and that repo is the **single source of truth** for the skill's
text, `version`, `description`, and tags. This catalog only *points* at those repos and re-states some of
their metadata so agents can discover and install them.
The same catalog is exposed to different agents through three surfaces:
```
rpa-skills/
├─ .claude-plugin/
│ └─ marketplace.json # Claude Code marketplace (per-plugin `version` + `description`)
├─ .agents/plugins/
│ └─ marketplace.json # Codex marketplace (git-backed sources; version resolved from the skill repo)
├─ install.sh # folder-based installer for Cursor & co. (ALL_SKILLS array of repo names)
├─ README.md # human overview + the Skills table (one row per skill)
├─ AGENTS.md # this file — the collection-wide process
├─ CLAUDE.md # symlink → AGENTS.md (so Claude Code reads the same guide)
└─ LICENSE
```
## ⚠️ Golden rule: the catalog mirrors the skills — keep them in sync
When you change a skill **in its own repo** — bump its version, reword its description, change its
tags/category — this catalog keeps showing the **old** metadata until you update it here. The catalog
**follows, never leads**: release in the skill repo first, then mirror the change here in the same PR/commit.
Nothing is allowed to drift.
### The catalog surface — every place a skill's metadata is duplicated
| Changed in the skill repo | Update here |
|---------------------------|-------------|
| **version** bump | `.claude-plugin/marketplace.json` → the plugin's `version`. Codex manifest only if its entry pins a `ref`/`sha` (see below). **Always** patch-bump the top-level `metadata.version` in both manifests (`2.2.0` → `2.2.1`). |
| **description** | `description` in **both** manifests **and** the README Skills-table row. |
| **tags / category** | `category` in **both** manifests. |
| **new skill added** | add an entry to **both** manifests, a README table row, the `install.sh` `ALL_SKILLS` array, and **minor**-bump `metadata.version`. |
| **skill removed / renamed** | remove or rename it in **all four** places above. |
### Version sync — the two manifests behave differently
- **`.claude-plugin/marketplace.json`** carries an explicit `version` per plugin. It is a **copy** of the
skill's own version → bump it here every time the skill's `plugin.json` / `SKILL.md` version changes.
- **`.agents/plugins/marketplace.json`** (Codex) has **no** per-plugin `version`. Codex reads the version
from the skill's own `.codex-plugin/plugin.json` at the git `ref` the entry points to:
- entry pinned to a moving branch (`"ref": "main"`, the current default) → it auto-follows the skill repo,
**nothing to bump**;
- entry pinned to a **tag or `sha`** for reproducibility → update that `ref`/`sha` on every release.
- The top-level **`metadata.version`** (present in both manifests) is the **catalog** version, and it must
move on **every** catalog change. Keep it identical in both manifests:
- **patch** bump (`2.2.0` → `2.2.1`) when a skill's `version` or `description` is mirrored here. One patch
per sync commit, even when several skills are mirrored at once;
- **minor** bump (`2.2.1` → `2.3.0`) when the catalog changes shape - a skill added, removed, or renamed;
- **major** bump when the manifest format itself changes in a way installers must adapt to.
### Worked example — releasing `rpa-init` 1.1.0
1. **In the `rpa-init` repo:** bump to `1.1.0`, edit the description if it changed, commit, tag, push.
2. **Here in `rpa-skills`:**
- `.claude-plugin/marketplace.json` — set `rpa-init` → `"version": "1.1.0"`; update `description` if changed.
- `.agents/plugins/marketplace.json` — update `description` if changed. If the entry pins a tag/sha, point
it at the new release; if it points at `main`, nothing to do.
- `README.md` — update the `rpa-init` row only if its purpose/description changed.
- `install.sh` — no change (it clones by repo name, not by version).
- `metadata.version` — patch-bump it in **both** manifests (`2.2.0` → `2.2.1`); mirroring a skill is a
catalog release too.
3. Validate and commit (below).
## Coddy reads this catalog
Coddy has `EvilFreelancer/rpa-skills` built in as a system source, so whatever lands on `main` here reaches
every Coddy user on their next `coddy skills sync`: an added skill gets installed, a mirrored version gets
pulled. Push only entries whose skill repository is public and resolves. Separately, coddy-agent vendors
`crossreview` and the `rpa-*` skills into its binary (`make skills-vendor`, sources in
`scripts/bundled-skills.json` there); a release of one of those skills also needs that re-vendoring to
reach users who never sync.
## Adding a new skill to the catalog
1. Publish the skill's **own repo** first (flat layout: `SKILL.md` at the repo root, its own
`.claude-plugin/` + `.codex-plugin/` manifests). The catalog cannot resolve an entry whose repo is not
pushed. The skill's `.claude-plugin/plugin.json` must **not** contain a `category` key: the plugin
manifest schema is strict, `claude plugin validate` rejects unknown keys
(`Unrecognized key: "category"`), and the install fails before the skill is ever downloaded.
`category` belongs **only** in this catalog's `marketplace.json` entries, where both manifests accept it.
2. Add a plugin entry to **both** manifests, and use a **`url` source with an HTTPS clone URL** in both:
`source: {source:"url", url:"https://github.com/EvilFreelancer/<name>.git", ref:"main"}` (plus
`policy` + `category` in the Codex entry). Never use `source: {source:"github", repo:"owner/name"}`
for the Claude entry: the CLI clones `github` sources over **SSH**
(`git@github.com:owner/name.git`), so the install fails on any machine without a GitHub SSH key —
the default for Windows and Claude Desktop users. Public repositories over HTTPS need no
authentication.
3. Add a row to the README **Skills** table and add `<name>` to `install.sh`'s `ALL_SKILLS`.
4. Minor-bump `metadata.version` in both manifests.
## Validate before committing
```bash
python3 -m json.tool .claude-plugin/marketplace.json >/dev/null && echo claude-ok
python3 -m json.tool .agents/plugins/marketplace.json >/dev/null && echo codex-ok
bash -n install.sh && echo installer-ok
# the skill list must be identical across all three catalog surfaces:
python3 - <<'PY'
import json,re
claude=[p['name'] for p in json.load(open('.claude-plugin/marketplace.json'))['plugins']]
codex =[p['name'] for p in json.load(open('.agents/plugins/marketplace.json'))['plugins']]
m=re.search(r'ALL_SKILLS=\((.*?)\)', open('install.sh').read(), re.S)
sh=m.group(1).split() if m else []
print('claude :', claude)
print('codex :', codex)
print('install :', sh)
print('IN SYNC :', claude==codex and set(claude)==set(sh))
PY
```
## Commit checklist
- [ ] The skill's own repo already released the change (the catalog **follows**, never leads).
- [ ] Both manifests updated — `version` where applicable, `description`, `category`.
- [ ] README **Skills** table row updated.
- [ ] `install.sh` `ALL_SKILLS` updated if a skill was added / removed / renamed.
- [ ] `metadata.version` bumped and identical in both manifests — patch for a mirrored skill release, minor
when the catalog shape changed.
- [ ] JSON validates and the skill lists match across both manifests + `install.sh`.
- [ ] Conventional commit, e.g. `chore(catalog): sync rpa-init 1.1.0`.
---
Part of the **[rpa-skills](https://github.com/EvilFreelancer/rpa-skills)** collection. Each skill repo has its
own `AGENTS.md` for authoring **that** skill; this file governs the **catalog**. See also
[cursor-vibe-prompts](https://github.com/EvilFreelancer/cursor-vibe-prompts).