# Add More Skill

> Use when the user wants to install, update, sync, list, or remove agent skills sourced from external repositories (e.g. a GitHub repo containing SKILL.md files), or to discover new skills. Runs the full add/update/discovery workflow: clones the source repo into a cache, scans it for skills, suggests which ones are relevant to the user's setup, resolves conflicts with already-installed skills, tracks every install in prefs.local.json so reruns can detect updates and new skills, and wires the chosen skills into all harnesses. Triggers on phrases like "add skills from <repo>", "install more skills", "fetch skills from", "sync/update my skills", "check my skills for updates", "show installed skills", "discover new skills".

- Skill: `xpressabhi/add-more-skill` (Agent Skill)
- Install (CLI): `npx skillmds@latest add xpressabhi/add-more-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xpressabhi/add-more-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: xpressabhi (https://skillmd.com/u/xpressabhi)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/xpressabhi/add-more-skill

---


# Add More Skill

A single workflow for installing, updating, and managing skills from external skill repositories. Because this repo is the canonical copy that `install.py` symlinks into every harness, "installing a skill" always means: **copy it into the repo and re-run the installer**. Two destinations exist:

- `<repo>/skills/<name>/` — skills you intend to **own and commit** (your own or curated skills)
- `<repo>/skills-external/<name>/` — skills **borrowed from other repos** (gitignored, never committed; stays on this machine)

By default, skills from external repos install into `skills-external/`. Use `skills/` only when the user explicitly wants a skill committed (e.g. "add it to the repo so others get it too"). Never copy skill dirs directly into harness directories (except in the degraded fallback, section 7).

All state — what was installed, from where, at which commit — is tracked in the gitignored `prefs.local.json` under `skill_sources`, so rerunning this skill detects upstream updates, newly added skills, and skills deleted upstream. Records drift from reality (hand-deleted dirs, copies made without a record, edits), so section 1 reconciles `prefs.local.json` against the disk before any add/update/sync/remove and prompts the user to fix anything out of place.

## 0. Resolve your setup first

**Locate the canonical repo** (try in order):
1. `$AGENT_SKILLS_REPO` environment variable
2. `repo_dir` in `prefs.local.json` (also check `~/Documents/GitHub/agent-skills`, `~/code/agent-skills`, `~/.agents/agent-skills`)
3. the current directory, if it contains `install.py` and a `skills/` dir
4. ask the user

If no repo is found anywhere, fall back to section 7 (direct install). If `repo_dir` is missing from prefs, write it in now.

**Load state**: read `<repo>/prefs.local.json`. Pay attention to `repo_dir` and `skill_sources` (ignore keys starting with `_` — they are comments/examples).

**Cache**: clone external repos to `~/.agents/cache/add-more-skill/<owner>__<repo>/`. The cache is persistent so update checks are cheap. Create the directory as needed.

**Local skill inventory** (for conflict checks): collect skill names present in
- `<repo>/skills/` (canonical copy, committed)
- `<repo>/skills-external/` (borrowed, gitignored)
- `~/.agents/skills/`, `~/.config/opencode/skills/`, `~/.claude/skills/`, `~/.codex/skills/`

When listing harness dirs, resolve symlinks with `readlink` — most entries point back into the canonical repo and must not be counted as duplicates.

**Then run the state sanity check (section 1) before any add, update, sync, or remove** — records in `prefs.local.json` are only trustworthy if they match the disk.

## 1. Sanity-check state before add / update / sync / remove

`prefs.local.json` records what was installed, but the bookkeeping can drift
from reality — a skill dir deleted by hand, a copy made without a record, an
edit that changed the hash. Operating on stale records makes adds and updates
miss the actual setup: they silently no-op, duplicate, or overwrite the wrong
thing. So before every add (section 2), sync (section 3), or remove (section 5),
reconcile every record against the disk and **prompt the user to fix anything
out of place — either by adding (installing) the skill or by updating
`prefs.local.json` to match reality**. Never proceed with known mismatches
unresolved.

### 1.1 Recorded skill missing on disk
For each `skills[name]` record in every source, check the install dir
(`<repo>/skills-external/<name>` when `external: true`, else
`<repo>/skills/<name>`):
```bash
test -d "<repo>/<dir>/<name>"   # missing → the record is a ghost
```
Ask the user to fix it — either **add the skill** (copy it from the source
cache at the recorded `commit` if the clone exists and `rel_path` is still
valid, else re-clone the source first; then run the installer) or **update
prefs** (delete the entry from `skill_sources` so syncs stop chasing a ghost).

### 1.2 Skill on disk with no record
Scan every dir containing `SKILL.md` under `<repo>/skills-external/` (and any
`<repo>/skills/` dirs that are not this repo's own skills) and check that no
`skill_sources[].skills` entry claims it:
- **In `skills-external/`** → an untracked borrow. Ask the user to fix it —
  **update prefs** to record it (match the dir's `local_hash` against skills in
  `~/.agents/cache/add-more-skill/*/` to find the source, ask the user if
  unknown; write the entry with the right `rel_path`, `commit`, `local_hash`,
  `external: true`) or **remove it** (back up to `<repo>/.backups/<ts>/`
  first). Otherwise later syncs will treat it as removable or duplicate it.
- **In `skills/`** → usually your own curated skill; being untracked is fine
  and `list` (section 4) marks it `untracked`. Only if it looks borrowed
  (content matches a cached source) offer to record it as `external: false`.

### 1.3 Recorded hash ≠ on-disk hash
Compare each record's `local_hash` with the live fingerprint of its install
dir (same command as 2.8):
```bash
find "<repo>/<dir>/<name>" -type f | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}'
```
Mismatch → the skill changed since install (hand edit, partial copy, another
tool overwrote it). Ask the user which reality is correct: **keep the local
edits** (update `local_hash` in prefs so syncs treat it as locally modified and
never overwrite it silently) or **restore the recorded state** (reinstall from
the source cache at the recorded `commit`, then run the installer).

### 1.4 Source cache or commit mismatch
For each source, confirm the cache clone exists and sits at the recorded
`last_commit`:
```bash
test -d ~/.agents/cache/add-more-skill/<owner>__<repo>
git -C "$CACHE" rev-parse HEAD   # should equal the recorded last_commit
```
Missing or different → updates and diff checks will be wrong. Fix by
re-cloning (2.2) or `git fetch` + checkout of the recorded commit. If the
recorded commit is unreachable upstream, ask: **update prefs** to the current
HEAD (the next sync treats everything as updated) or drop the source record.

### 1.5 Recorded rel_path invalid at the recorded commit
```bash
git -C "$CACHE" cat-file -e <last_commit>:<rel_path>/SKILL.md   # fails → moved upstream
```
Ask the user to fix it: locate the new path
(`git -C "$CACHE" ls-tree -r --name-only <last_commit> | grep '/SKILL.md$'`),
**update prefs** with the new `rel_path` and re-apply the skill, or drop the
record.

### 1.6 Apply fixes, then proceed
For every mismatch, present the finding with its fix options, get the user's
pick (their harness's interactive prompt, like 2.6), apply it, and validate
`prefs.local.json` with `python3 -m json.tool`. Re-run this check once after
the fixes; only when it comes back clean, continue to add (section 2), sync
(section 3), or remove (section 5). If the user declines to fix a mismatch,
exclude the affected skill from the operation and say so explicitly.

## 2. add — install skills from a repo

### 2.1 Get the repo
The user may give a full URL, `owner/repo`, or nothing. If nothing, offer the curated discovery list (section 8) or ask them to share a repo. Normalize to a canonical source key `owner/repo` (strip scheme and trailing `.git`), and keep the display URL.

### 2.2 Clone into the cache
```bash
git clone --quiet <url> ~/.agents/cache/add-more-skill/<owner>__<repo>
BRANCH=$(git -C "$CACHE" rev-parse --abbrev-ref HEAD)
HEAD=$(git -C "$CACHE" rev-parse HEAD)
```
Clone fully (no `--depth`) so diffs work on later syncs. If a full clone is pathologically slow, use `git clone --filter=blob:none` and run `git fetch --unshallow` at the first sync.

### 2.3 Scan for skills
```bash
find "$CACHE" -name SKILL.md \
  -not -path '*/.git/*' -not -path '*/node_modules/*' \
  -not -path '*/.github/*' -not -path '*/.vscode/*' -not -path '*/docs/*'
```
Cap depth at ~4 levels. For each match:
- skill **name** = parent directory name (fall back to the repo name when `SKILL.md` sits at the repo root)
- parse frontmatter `name` and `description`; if frontmatter `name` differs from the dir name, use the frontmatter name and note the mismatch
- record the skill's **relative path** inside the cache — needed for diffing on later syncs

### 2.4 Suggest relevance
Build local context: which harnesses are installed (`opencode` / `claude` / `codex` binaries), keys in `prefs.env`, MCP server names, and names + descriptions of already-installed skills. For each candidate score:
- **+2** — description keywords match the user's context (e.g. `browser`/`chrome`/`playwright` when the user has those MCP servers or prefs keys; `git`/`commit` skills for this repo; `notion` when prefs mention it)
- **+1** — the skill fills a domain no installed skill covers (testing, docs, security, devops, web, data, design, marketing, …)

Present three groups:
- **Recommended** (score ≥ 2) with the reason, e.g. "matches your chrome MCP setup"
- **Available** — everything else, one line each
- **Conflicts** — see 2.5

Show each as `name — description` truncated to ~100 chars. Never install anything without an explicit user selection.

### 2.5 Conflict check (duplication handling)
For each candidate name, check the local inventory (both `skills/` and `skills-external/`):
1. **Not installed anywhere** → clean install.
2. **In `skills-external/`, tracked to the same source** → already installed; move to the sync path instead (section 3), don't re-add.
3. **In `skills/`, tracked to the same source** → the user explicitly committed it; treat as already installed (sync path), don't re-add.
4. **Tracked to a different source** (name clash) → ask: skip / overwrite / install as `name-from-owner`. Overwriting drops the other source's record — say so before doing it.
5. **Present locally but not tracked** (hand-written, or harness-only skills like codex's `playwright`) → likely locally authored; default **skip**, offering: overwrite (back up to `<repo>/.backups/<ts>/` first) or rename.

### 2.6 Present & confirm
Number the final actionable list. Use your harness's interactive prompt (the Question tool in opencode; otherwise ask in chat and wait). Accept comma-separated ranges and `all`/`none`. Re-confirm when the selection overwrites anything.

### 2.7 Copy into the repo
By default (borrowed skills), install into the gitignored external dir:
```bash
cp -R "$CACHE/<rel_path>" "<repo>/skills-external/<name>"
```
If the user explicitly wants the skill committed so other users get it too, install into `skills/` instead and mark the record `"external": false`. Copy the whole skill dir (scripts, references, templates included). Remove any stray dotfiles from the copy, keep the skill's own resources.

### 2.8 Record state
Update `prefs.local.json` (preserve every other key; validate with `python3 -m json.tool`):
```json
"skill_sources": {
  "<owner/repo>": {
    "url": "<display url>",
    "branch": "<branch>",
    "added_at": "<now>",
    "last_sync_at": "<now>",
    "last_commit": "<HEAD>",
    "skills": {
      "<name>": {
        "rel_path": "<path of skill dir inside the source clone>",
        "external": true,
        "installed_at": "<now>",
        "updated_at": null,
        "commit": "<HEAD>",
        "local_hash": "<sha256>"
      }
    }
  }
}
```
`external` records where the skill lives: `true` → `<repo>/skills-external/<name>` (gitignored, not committed), `false`/missing → `<repo>/skills/<name>`. `local_hash` is the fingerprint of the installed dir used to detect local edits on later syncs:
```bash
find "<repo>/skills-external/<name>" -type f | sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}'
```

### 2.9 Wire it in & verify
Run the installer in the repo: `./install.sh` (Unix) or `.\install.ps1` (Windows), or `python3 install.py`. Use `--dry-run` first if unsure. Then verify at least one harness picked it up, e.g. `ls -la ~/.config/opencode/skills/<name>`. Remind the user that running harnesses must be restarted to see the new skill.

## 3. sync — update everything

Run the sanity check (section 1) first and resolve every mismatch — syncing against stale records misses the actual setup. Then, for each source recorded in `skill_sources`:
1. Ensure the cache clone exists (clone it if missing, like 2.2).
2. `git -C "$CACHE" fetch --quiet origin`; `NEW=$(git -C "$CACHE" rev-parse origin/$BRANCH)`.
3. Compare `NEW` with the recorded `last_commit`:
   - **Same commit** → no upstream change. Still compare the recorded `local_hash` against the installed dir; if they differ, the user edited the skill locally — flag it as "locally modified (your edits are preserved)".
   - **New commit** → classify each recorded skill:
     - **updated** — `git -C "$CACHE" diff --quiet $last_commit..$NEW -- <rel_path>` exits non-zero. If the local copy's hash no longer matches the recorded `local_hash` (user edits), ask before overwriting.
     - **new** — `SKILL.md` dirs present at `$NEW` that are not in this source's recorded `skills`
     - **removed** — recorded skills whose `rel_path` no longer exists at `$NEW` (`git -C "$CACHE" cat-file -e $NEW:<rel_path>` fails)
4. Present a plan: "update X (n skills), add Y, remove Z" with one-line descriptions and counts. Let the user select; locally-modified items get a per-item choice (update / keep local).
5. Apply: for updates and removals, back up the current dir to `<repo>/.backups/<ts>/` first, then `cp -R` the new version or `rm -rf` the agreed removal. Use each skill's recorded `external` flag to target `skills-external/` vs `skills/`. New skills install exactly like 2.7.
6. Record: bump `last_sync_at` and `last_commit` to `NEW`; per skill update `updated_at`, `commit`, `local_hash`; drop removed ones.
7. Re-run the installer (2.9), verify, remind about restarts.

If the user asks to update only a **specific skill**, treat just that one as the scope.

## 4. list — inventory & discovery

Print a table: skill name | source (repo key or `local`) | status. Status is one of: `current` / `update available` / `locally modified` / `source deleted` (upstream removed it, still installed) / `untracked` (in the canonical repo but not from any source). Mark skills in `skills-external/` with a `(external)` tag so it's clear they aren't committed. Then, if the user wants more skills, offer the curated discovery list (section 8).

## 5. remove — uninstall a skill

Run the sanity check (section 1) first so records and disk agree on what is actually installed. Only remove skills that are tracked from a source, or that the user confirms are theirs to remove. Steps: confirm the exact name, back up `<repo>/<skills-external or skills>/<name>` (per the recorded `external` flag) to `<repo>/.backups/<ts>/`, delete it, drop the entry from `skill_sources`, re-run the installer. Never remove skills that ship with this repo (e.g. `enhance-repo`, `add-more-skill`) unless explicitly asked.

## 6. State schema

Top level of `prefs.local.json` (gitignored — never commit it):
- `repo_dir` — path to the canonical repo (seeded by this skill if missing)
- `skill_sources` — map of `<owner/repo>` → source record:
  - `url`, `branch`, `added_at`, `last_sync_at`, `last_commit`
  - `skills` — map of skill name → `{ rel_path, external, installed_at, updated_at, commit, local_hash }`; `external: true` = lives in gitignored `skills-external/` (not committed)
- `_*` keys are comments/examples; ignore them.

Section 1 reconciles every record against the disk before any add/update/sync/remove: a record without a matching install dir, an install dir without a record, a `local_hash` that no longer matches, a cache clone that isn't at `last_commit`, or a `rel_path` that no longer exists at the recorded commit are all flagged and fixed (reinstall / record / remove) **before** the operation proceeds.

## 7. Direct-install fallback (no canonical repo found)

If the canonical repo cannot be located, install by copying each chosen skill dir into `~/.agents/skills/<name>/` and, for each installed harness, into its own skills dir (`~/.config/opencode/skills`, `~/.claude/skills`, `~/.codex/skills`). Track state in `~/.agents/add-more-skill.json` with the same schema. Warn the user this is a degraded mode — no repo-based wiring or central management. If the repo exists, always prefer `skills-external/` over this fallback.

## 8. Discovery seeds (well-known public collections)

| Repo | What's in it |
| ---- | ------------ |
| anthropics/skills | official, tested skills (documents, design, presentations…) |
| obra/superpowers | TDD-driven development methodology skills (very popular) |
| ComposioHQ/awesome-claude-skills | 78+ general-purpose skills (SaaS, docs, business automation) |
| alirezarezvani/claude-skills | 200+ skills across 9 domains |
| coreyhaines31/marketingskills | marketing, SEO, copywriting, ads |
| vadimcomanescu/agents-skills | engineering workflow skills (debugging, TDD, verification) |
| wshobson/agents | agents + skill packs |

These are public repos — verify the repo actually exists before cloning (repos get renamed or moved). Always run the relevance + conflict steps on their contents; never install a whole collection blindly.

## 9. Guardrails

- **Safety review before install**: skim each selected `SKILL.md` (and any scripts it references) and flag anything that exfiltrates data, steals credentials, hides commands, or is destructive. Present findings and let the user decide. Never install a skill the user hasn't explicitly picked.
- **Sanity-check state first**: run section 1 before every add/update/sync/remove; never trust `prefs.local.json` records that contradict the disk. Resolve mismatches with the user (add the skill or update the records) before proceeding.
- Never write secrets; `prefs.local.json` is gitignored — never commit it.
- Back up anything you replace (`.backups/<ts>/`, matching the installer's convention).
- Prefer the smallest change: install only the selected skills, update only what changed, remove only what the user agreed to.
- Preserve the repo's conventions and formatting; validate edited JSON with `python3 -m json.tool`.
- After every change, the installer must run successfully — verify the result and report it.

