Write an agent once. Install it everywhere.
A local-first CLI package manager for AI agent and skill files.
apm syncs your library of agent definitions and manages installation into the agent runtimes it currently verifies end-to-end.
It handles: install, diff, update, import, and optional GitHub sync — all with atomic writes, locking, and backups.
| Status | Targets |
|---|---|
| Managed now | Claude Code agents and skills, Gemini CLI agents, Codex skills, Windsurf skills, agents-dir generic store |
| Coming soon / not yet verified end-to-end | Cursor, Continue, Codex agents, Windsurf rules, Gemini skills, generic export UX |
This tool is under active development. It may contain bugs. Always back up your data.
| Define an agent once in your library. Install it to the runtimes `apm` currently verifies — with the right format for each. |
Always know what's installed, what's outdated, and what's drifted. apm list gives you a full picture at a glance.
|
Already have agents scattered across tool directories? apm import brings them into your library with a single command.
|
| Back up and share your library via GitHub. Monorepo or per-agent mode. Push, pull, and diff from the CLI. | Atomic writes, file locking, and automatic backups before every destructive operation. No silent overwrites. | Tag agents with a category and install entire groups at once. Keep your library organized as it grows. |
| Without apm | With apm |
|---|---|
| ❌ You copy-paste the same agent prompt into multiple coding tools — and they drift apart over time. | ✅ One source of truth in your library. Install to supported runtimes with one command. |
❌ You edit an agent directly in ~/.claude/agents/ and forget which version is canonical. |
✅ Library always wins. Runtime is treated as a deploy target, never the source. |
| ❌ You have no idea which installed agents are outdated or missing after switching machines. | ✅ apm list shows sync state for every agent — in-sync, outdated, ready, or unmanaged. |
❌ You accumulate random .md files in your agents directories with no record of where they came from. |
✅ Every installed file is stamped with apm.id, platform, and install timestamp. |
| ❌ Updating an agent means manually finding and overwriting files across multiple tools. | ✅ apm update reinstalls every outdated agent in one shot, with backups. |
git clone https://github.com/alexsmedile/apm.git
cd apm
bash install.sh # links apm into ~/.local/bin
apm setup # configure library path, platform, optional GitHubRequirements:
- bash 4+
- python3 + PyYAML (
pip3 install pyyaml) - git (optional, for GitHub sync)
apm list # show all agents and sync state
apm install agent-mentor # install agent to runtime (~/.claude/agents/)
apm link agent-mentor # symlink runtime file directly to split instructions
apm diff agent-mentor # compare library vs runtime
apm update # reinstall all outdated agents
apm import # import unmanaged runtime agents into libraryapm supports different canonical layouts for agents and skills.
Agents:
agents_db/
agent-mentor/
agent-mentor.md # required root file
instructions/ # optional
agent-mentor@latest.md # optional generic active body
agent-mentor.cc@latest.md # optional platform-specific body
versions/ # optional snapshots/backups/history
Agent rules:
- The canonical ID is the folder name.
- The required root file is
<id>/<id>.md. instructions/is optional and keeps the current body split out of the root file.- Body resolution order is
<id>.<platform-alias>@latest.md→<id>@latest.md→<id>_latest.md(legacy) → root file body.
Skills:
Preferred monorepo-style layout:
skills_db/
repo-name/
skills/
browser-use/
SKILL.md
shadcn/
SKILL.md
Fallback direct layout:
skills_db/
browser-use/
SKILL.md
shadcn/
SKILL.md
Skill rules:
apmprefersskills_db/<repo>/skills/<skill>/SKILL.md.- If a top-level entry has no
skills/folder,apmfalls back toskills_db/<skill>/SKILL.md. - The canonical skill ID is the skill folder name that directly contains
SKILL.md.
Platform aliases: claude-code→cc, cursor→crs, gemini→gmn, codex→cdx, generic→gen
About the "agents". In most AI tools, "agent" means the tool's primary AI persona, but the
agents/directories (~/.claude/agents/,~/.cursor/agents/, etc.) actually hold subagents — specialized, named agents invoked for specific tasks.apmmanages subagents only.
Add category: <name> (or group: <name>) to any agent's frontmatter to group it:
category: devtoolsThen install the whole group at once:
apm install --cat devtoolsapm list shows the category column when any agents have one set.
The tables below list the targets apm currently manages and that were re-checked against current platform docs.
Verified agent install targets:
| Platform | Global target | Project target |
|---|---|---|
claude-code |
~/.claude/agents/ |
.claude/agents/ |
gemini |
~/.gemini/agents/ |
.gemini/agents/ |
agents-dir |
~/.agents/ |
.agents/ |
Verified skill install targets:
| Platform | Global target | Project target | Behavior |
|---|---|---|---|
claude-code |
~/.claude/skills/ |
.claude/skills/ |
symlink skill dir |
codex |
~/.codex/skills/ |
.codex/skills/ |
symlink skill dir |
windsurf |
~/.codeium/windsurf/skills/ |
.windsurf/skills/ |
symlink skill dir |
agents-dir |
~/.agents/skills/ |
.agents/skills/ |
symlink skill dir |
generic currently means an export-only convenience target (~/Desktop/agents-export/ by default), not a verified first-class platform integration.
Coming soon:
cursor: official docs currently point to.cursor/rulesandAGENTS.md, not a verified.cursor/agents/runtime.continue: official docs currently point to.continue/rules, not a subagent runtime directory.codexagents: current Codex docs emphasizeAGENTS.mdand skills; anagentsruntime folder is not verified here yet.windsurfagents: Windsurf exposes rules, skills, workflows, andAGENTS.md;apmdoes not yet model Windsurf rules as a first-class managed target.geminiskills: Gemini CLI documents subagents in.gemini/agents/, but a SKILL.md-based skill runtime is not verified here yet.
apm supports two different symlink-based workflows:
installwithINSTALL_MODE=symlink:apmwrites the generated runtime file into~/.agents/and symlinks the tool-specific runtime path back to that managed file. This keeps frontmatter likeapm.id,installed-at, and deploy metadata intact.--mode skills install:apmcreates a directory symlink from the selected verified skill target back to the canonical skill folder inSKILLS_DB.link/unlink:apm link <id>creates a runtime symlink that points directly at the resolved split instruction body in your library. This is useful when you want runtime to follow the library body exactly without generating a runtime wrapper file.
Examples:
apm install agent-mentor # normal copy install
INSTALL_MODE=symlink apm install agent-mentor
apm --mode skills --platform claude-code install browser-use
apm link agent-mentor
apm link agent-mentor --as review-helper
apm links
apm unlink agent-mentor --allNotes:
linkresolves the active body using the normal platform precedence:<id>.<platform>@latest.md, then<id>@latest.md, then the root file body.- If the split file does not exist yet,
apm linkcan generateinstructions/<id>.<platform-alias>@latest.mdfrom the root body. unlinkremoves only tracked symlinks and refuses to delete regular files.- Plain
unlinktargets the current scope. Use--project,--global, or--allto be explicit when needed.
Two modes:
- monorepo — all agents in one repo, each in a subdirectory
- per-agent — each agent has its own repo
apm github connect # configure mode, owner, repo
apm github push --all # push everything
apm github pull agent-mentor # pull one agent (staged by default)| Command | Description |
|---|---|
setup |
Interactive config wizard |
config |
Show resolved configuration |
list |
List agents with sync state and category |
status |
Count summary by state |
validate [id] |
Validate agent(s) in library |
diff <id> |
Show library vs runtime diff |
install <id> [id…] |
Install agents, or in --mode skills create skill symlinks |
install --all |
Install every ready/outdated agent or skill |
install --cat <name> |
Install all agents in a category |
link <id> |
Symlink agent body directly into the runtime dir |
unlink <id> |
Remove tracked symlink(s) for an agent |
links [id] |
List tracked symlinks for one agent or all agents |
remove <id> |
Remove agent runtime file, or in --mode skills remove the skill symlink |
update [id] |
Reinstall outdated agent(s) — omit for all |
import |
Pick from unmanaged runtime agents (interactive) |
import [id] |
Import specific agent, or --all for everything |
github connect |
Configure GitHub sync |
github status |
Show library vs GitHub sync state |
github push <id> |
Push agent to GitHub, or --all for everything |
github pull <id> |
Pull agent from GitHub, or --all for everything |
github diff <id> |
Diff library vs GitHub |
| (no args) | Interactive REPL dashboard |
--db <path> Override library path
--platform <name> Override platform (claude-code, cursor, codex, gemini, generic)
--install-mode Override install mode (`copy` or `symlink`)
--json Machine-readable JSON output
--dry-run Preview without writing
--force Skip confirmation prompts
| Symbol | State | Meaning |
|---|---|---|
✓ |
in-sync | Runtime matches library |
⤷ |
linked | Runtime is a direct symlink to the active library body or skill dir |
⤸ |
linked-outdated | Runtime is a symlink, but points to the wrong target |
~ |
outdated | Runtime installed but behind library |
○ |
ready | In library, not yet installed |
! |
unmanaged | Runtime file with no library entry |
? |
orphan | Has apm.id but library entry missing |
- |
no-deploy | No deploy config for current platform |
x |
collision | Canonical ID conflict |
docs/TUTORIAL.md— practical getting-started guide for normal usersdocs/ARCHITECTURE.md— module boundaries and data flowdocs/WORKFLOWS.md— usability Q&A and edge casesdocs/AGENT_ENTRY_SCHEMA.md— library metadata and deploy schema referencedocs/DATABASE_LIBRARY.md— canonical database layout guidedocs/CHANGELOG.md— version historydocs/CONTRIBUTING.md— how to contribute
A safe, resettable test database lives in tests/fakeagents-db/ with two fake agents (gino, pino) synced to a private GitHub monorepo at <user>/fakeagents-db.
# One-time config setup (recreate after reboot)
mkdir -p /tmp/apm-fake-config && cat > /tmp/apm-fake-config/config.sh <<EOF
AGENTS_DB="$(pwd)/tests/fakeagents-db"
APM_PLATFORM="claude-code"
APM_GITHUB_MODE="monorepo"
APM_GITHUB_OWNER="<user>"
APM_GITHUB_MONOREPO="fakeagents-db"
APM_GITHUB_BRANCH="main"
EOF
# Session env
export AGENTS_DB="$(pwd)/tests/fakeagents-db"
export APM_CONFIG_DIR=/tmp/apm-fake-config
export CLAUDE_AGENTS=/tmp/fake-rt && mkdir -p \$CLAUDE_AGENTS
# Try it out
bash apm --platform claude-code list
bash apm --platform claude-code install gino
bash apm --platform claude-code github status
# Reset library to committed state
git checkout tests/fakeagents-db/make test # run all 9 test suites (~127 tests)
make lint # static checks (bash -n, py_compile)
make install # install to ~/.local/bin
make uninstall # remove symlink