npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

skill-profiles

v0.10.0

Published

Maintain many AI agent skills across profiles without bloat.

Readme


Version : 0.9.0

skill-profiles

Maintain many AI agent skills across profiles without bloating every session, since every skill's description eats context in the agent's prompt.

You keep every skill in one vault. At session start you load one or more profiles (plus an always-on set) into the agent that asked. Each session sees only the skills that matter for the work at hand.

Works with Claude Code, Cursor, Codex, Pi, Charm Crush, VS Code, OpenCode, Zed, and harnesses that use the shared ~/.agents/skills folder. Other agents: register their skills path with sp agent-folder add.

Think of a wardrobe. A skill is a garment; a profile is a whole outfit on one hanger — the dinner suit is jacket, trousers, shirt and shoes. The vault is the wardrobe, and the agent's skills folder is what you're wearing. Usually you dress for one occasion; sometimes you mix and match hangers. What comes off goes back on the rail, not in the bin.

Install

npm install -g skill-profiles
sp setup     # deploy the trigger skill + /sp-install (Claude Code)
sp init      # stand up the vault; import existing skills

The CLI is available as skill-profiles and the short alias sp.

Mental model

  • Vault — real skill files live in ~/.skill-profiles/vault/<profile>/<skill>/. Profiles are physical folders you can inspect and hand-edit.
  • __must-use__ — a special profile whose skills are always linked on every load (includes the trigger skill).
  • __solo__ — skills loaded on their own (-u / --solo-skill), or the fallback when no profile is chosen. Former name: __unsorted__ (migrated automatically).
  • Load is replace, not merge — sp load clears managed links in the agent's skills folder, then symlinks the chosen profile(s) + __must-use__ (plus any solo addons for this load only). Use sp append to add profile(s) on top of what is already loaded.
  • Multi-copy — the same skill name may exist in several profiles as independent copies. Names must be unique within a profile (they flatten into one agent folder on load).
  • Load / scan scope — only folders listed in the archive's agent-folders.json (native global defaults, plus any you add). Not the current project's directory; project-cwd .agents/skills is not scanned.

Commands

Archive
  init [--dry-run]        Stand up the vault; import existing skills
  setup                   Deploy trigger skill + /sp-install command
  seed                    Create starter profiles (idempotent)

Skills
  install [--native="<cmd>"] [source] [--profile p] [--agent id] [--name n]
                   [--force] [--all] [--agents [names]] [--hooks [names]]
                   [--no-timeout] [--capture] [--target-folder id ...]
                          Clone a skill from git into a profile, or capture a
                          native installer (--native / --capture) into the vault
                          First git install may copy companion agents for Claude/Cursor
                          --agents/--hooks: all; =name1,name2: selected components
                          source: owner/repo · owner/repo@skill · URL · local path
                          --no-timeout: don't give up on a slow clone (big repo)
                          --native="<cmd>": run cmd, diff agent homes, store in vault
                          --capture: same, but cmd is the <source> positional
                          --target-folder: limit which harness homes to snapshot
  update <skill|--all>    Re-fetch skill copies from recorded source
  adopt [--agent id]      Import stray skills from agent folders
  skill require <profile/skill> <profile/required-skill> ...
  skill unrequire <profile/skill> [profile/required-skill ...]
  skill requirements <profile/skill>

Load
  load [profile ...] [--agent id] [-u name ...] [--category c ...]
                          Clear managed links; link profile(s) + __must-use__
                          "_" loads no profile; -u/--solo-skill adds solo skills
                          --category loads profiles matching any given category
                          First named profile wins name collisions
  append [profile ...] [--agent id] [-u name ...] [--category c ...]
                          Like load, but keep what is already loaded
                          Already-loaded skills win name collisions
  agents:  claude-code/claude · agents/zed · codex · cursor · pi · crush/charm
           vscode · opencode

Agent folders
  agent-folder ls                     List registered skills folders
  agent-folder add <path> [--name id] [--label "..."]
                          Register another skills folder to scan/load
  agent-folder rm <id>                Unregister a skills folder
  agent-folder sync                   Add missing stock defaults; keep customs
  agent-folder reset [--force]        Replace list with stock defaults

Profiles
  profile ls [--category c ...]       Match any; "" includes uncategorized
  profile categories
  profile show <name>
  profile new <name> [--desc "..."] [--category c ...]
  profile set <name> [--desc "..."] [--category c ...]
  profile rename <from> <to>          Preserve skills, metadata, and usage stats
  profile rm <name>
  profile add <name> <skill>          Copy skill into profile
  profile mv <skill> <from> <to>      Move skill between profiles
  profile merge <into> <from> [--soft]
                          Move all skills from <from> into <into>, then delete
                          <from> (--soft keeps <from> in place)

  help · --version

Quick start

sp setup
sp init

sp profile new a11y-web --desc "WCAG checks for web apps" --category compliance
sp install vercel-labs/skills@pdf --profile a11y-web --agent claude-code

sp profile ls --category compliance
sp load a11y-web --agent claude-code
sp load a11y-web frontend --agent claude-code

Categories

Each profile may set a categories list in profile.json (also via repeatable --category on profile new / profile set). Categories are lowercase labels used to filter or load profiles when the vault grows large. Existing singular category strings, including comma-separated values, are read compatibly and migrated to a real list on the next write.

sp profile set web --category engineering --category productivity
sp profile ls --category productivity --category design
sp load --category engineering --category productivity
sp profile categories

Multiple category filters use any-match semantics. --category "" includes uncategorized profiles; setting a profile to --category "" clears its list.

Rename a profile

sp profile rename engineering pocock

Rename moves the existing profile directory and updates its internal name, so skills, timestamps, categories, and usage counters are preserved. If it was the configured default profile, that setting follows the new name.

Skill requirements

sp skill require apps/frontend helpers/browser helpers/screenshots
sp skill requirements apps/frontend
sp skill unrequire apps/frontend helpers/screenshots

Requirements are stored under the owning skill in its profile's profile.json. Loading that skill also loads the exact referenced skills, recursively. Cycles are safe. References use profile/skill so independent same-named copies remain unambiguous. Running skill unrequire <profile/skill> without further arguments clears all of that skill's requirements.

Profile rename and skill move operations update references automatically.

Capture a native installer

Some skill packs ship their own installer (Impeccable, marketplace plugins, multi-folder repos). Instead of re-implementing that layout, run the installer under capture and store what it wrote into the vault:

sp install --native="npx impeccable install" --profile design --name impeccable
# equivalent:
sp install "npx impeccable install" --capture --profile design --name impeccable

sp load design --agent claude-code

Flow:

  1. Snapshot (and back up) each registered agent harness home (dirname of the skills folder — e.g. ~/.claude, ~/.cursor), or only the ids passed with repeatable --target-folder.
  2. Run the native command in your terminal (stdio: inherit) so trust prompts, menus, and other installer UI work as usual.
  3. Diff before/after; copy added/changed paths into the vault under vault/<profile>/<name>/ and write .capture-manifest.json.
  4. Restore the harness homes to their pre-install state.
  5. sp load <profile> symlinks captured skills/, agents/, commands/, hooks, and other files from the vault back into each harness home. The capture package itself is not linked as a single skill directory.

Use --name to choose the vault skill name (default: first installer arg). Prefer --target-folder claude-code (etc.) when you only want one harness.

Companion subagent definitions (git install)

On a git skill's first install, sp looks at the repository/plugin root for Markdown subagent definitions under agents/. With --agent claude-code or --agent cursor, those files are copied once into the harness's real agents directory:

  • Claude Code: ~/.claude/agents/
  • Cursor: ~/.cursor/agents/

That path is install-time only: companions are not stored in the vault or re-linked by sp load / sp update. Existing destination files are left untouched. Without --agent, companion definitions are reported and skipped. For profile-scoped agents/hooks from a native installer, use --native instead (above).

Explicit component flags are available when a plugin-style install is wanted:

sp install cursor/plugins/pstack --agent cursor --agents --hooks
sp install owner/repo --agent cursor --agents reviewer,planner --hooks lint

Bare --agents / --hooks installs every discovered component of that type. A comma-separated value selects by agent frontmatter name, filename stem, hook event, hook name, or hook command filename. Explicit flags run even when the skill already exists; automatic root-agent copying remains first-install-only.

When .cursor-plugin/plugin.json exists, declared agents and hooks paths are used, with Cursor's agents/ and hooks/hooks.json defaults for omitted keys. Without a manifest, the same defaults are resolved at the repository root. Individual skill directories are not searched. Only .md files are agent definitions; YAML files under agents/ are ignored as harness metadata.

Hooks are merged additively:

  • Cursor in a Git project: <project>/.cursor/hooks/hooks.json
  • Cursor outside a Git project: ~/.cursor/hooks.json
  • Claude Code: the hooks key in ~/.claude/settings.json

Existing settings are preserved. A source hook with the same event and command as an existing hook is warned about and skipped; every added event and command is printed.

Codex companion agents are skipped because its TOML format cannot preserve the Claude/Cursor fields reliably. Other harnesses are also skipped until they have a compatible native agent-definition format.

When a git source contains many skills, the interactive picker includes Select all and switches to searchable multiselect for long lists.

Agent folders

A fresh archive knows these global skills folders:

| id | path | notes | | --- | --- | --- | | claude-code | ~/.claude/skills | | | agents | ~/.agents/skills | shared; zed is an alias | | codex | ~/.codex/skills | | | cursor | ~/.cursor/skills | | | pi | ~/.pi/agent/skills | | | crush | ~/.config/crush/skills | charm is an alias | | vscode | ~/.copilot/skills | | | opencode | ~/.config/opencode/skills | |

These are persisted in ~/.skill-profiles/agent-folders.json. Use sp agent-folder ls|add|rm|sync|reset to inspect or extend the list. --agent on load / adopt must be one of those ids (or an id you chose when adding a path).

init, adopt, and load only touch folders in that record — never process.cwd() project trees.

Existing version-1 archives receive the newer native targets (pi, crush, vscode, opencode) in memory; run sp agent-folder sync (or reset) to persist them. Version-2 archives pick up opencode the same way. Zed intentionally uses the shared agents target.

Aider is not listed because it does not currently implement Agent Skills discovery. Its --read convention files are not compatible with skill folders.

init — first-run migration

sp init creates the archive layout, scans every registered agent folder that exists on disk, prints a plan, and (after confirmation, with a backup first) triages each entry:

  • dangling symlink → removed
  • symlink into the vault → leave (already managed)
  • external symlink / git clone → skip for now, or import a copy into the vault
  • real skill (SKILL.md) → moved into the vault (pick a profile, or __solo__)

Non-interactive runs send real skills to __solo__ and leave external links/clones alone.

Load

sp load a11y-web --agent claude-code
sp load a11y-web frontend --agent claude-code
sp load a11y-web --agent claude-code -u pdf -u notes
sp load _ --agent claude-code -u pdf
sp load --category compliance --category design --agent claude-code
sp load --list-solo

sp load replaces managed links in the agent folder with the named profile(s) plus __must-use__. Name collisions: __must-use__ wins, then earlier named profiles, then solo addons. Skills installed via --native / --capture also get their captured harness files (agents, commands, hooks, nested skills) symlinked from the vault on load.

You can attach zero-or-more skills from __solo__ beside a profile with repeatable -u <name> / --solo-skill <name>, or load only those skills by using _ as the profile. The old --unsorted-skill, --list-unsorted, and --skill / -s spellings remain as deprecated aliases and print a warning. Addons are managed links, so the next plain sp load drops them.

sp load --list-solo prints skill names in __solo__ without loading.

How agents trigger it

setup writes an always-on skill-profiles skill into __must-use__ and links it into each registered agent's skills folder. Its guidance tells the agent: at session start, ask which profile(s) to load and run sp load, always passing --agent <its-own-id> (e.g. claude-code, cursor).

Claude Code also gets a /sp-install slash command for installs.

Layout

~/.skill-profiles/              # override with SKILL_PROFILES_HOME
├── config.json                 # settings + derived profile index
├── agent-folders.json          # registered skills folders (scan/load targets)
├── backups/<timestamp>.json    # snapshot written before each destructive op
└── vault/
    ├── __must-use__/           # always loaded, alongside the chosen profile(s)
    │   ├── profile.json
    │   └── skill-profiles/     # the trigger skill, written by `sp setup`
    │       └── SKILL.md
    ├── __solo__/               # skills loaded on their own / import fallback
    │   └── profile.json
    ├── <profile>/
        ├── profile.json        # description, categories, usage stats
        └── <skill>/
            ├── SKILL.md
            ├── .skill-source.json       # git origin, if installed via `sp install`
            └── .capture-manifest.json   # native-install capture metadata (if any)

Every profile directory carries a profile.json, the two seeded ones included; sp recreates them on any run if they go missing.

config.json settings:

  • adoptExternal — ask | auto | ignore (stray skills in agent folders)
  • onDirtyLoad — ask | auto-import | abort (real files at load time)
  • defaultProfile — used when sp load is run with no name and no TTY; interactive load is a multi-select
  • preserveUnmanaged — true | false (default false). When true, load leaves unmanaged entries alone (no adopt / dirty import) and skips linking a profile skill whose name is already occupied by one; when false, vault-authoritative adopt/onDirtyLoad behavior applies.

Develop

npm install
npm run build      # tsc → dist/
npm run dev        # watch
SKILL_PROFILES_HOME=/tmp/sp-test node dist/cli.js profile ls

See DESIGN.md for the full design and open questions.