{"id":"0e0030e6-148f-48ee-b2f8-e9d51f29591d","slug":"equipr","kind":"mcp","name":"equipr","summary":"Installs skills, commands, and MCP servers from marketplaces and Agent Plugins (AP) sources into your coding agents","owner":"maquina-app","repoUrl":"https://github.com/maquina-app/equipr","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-08-08T20:47:11.000Z","addedAt":"2026-10-22T03:23:57.660Z","logoUrl":"https://avatars.githubusercontent.com/u/182708901?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":[],"runtime":"go","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-27T21:45:10.381Z","sample":false,"url":"https://conduits.dev/tools/equipr","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# equipr\n\n`equipr` installs skills, commands, and MCP servers from **marketplaces** and\n**Agent Plugins (AP)** sources into your coding agents:\n\n| Agent | Detected by | Install mechanism |\n|-------|-------------|-------------------|\n| `claude-code` | `~/.claude/` or `claude` on `$PATH` | copy |\n| `codex` | `~/.codex/` or `codex` on `$PATH` | copy |\n| `opencode` | `~/.config/opencode/` or `opencode` on `$PATH` | symlink (individual components) |\n| `pi` | `~/.pi/agent/` or `pi` on `$PATH` | symlink (individual components) |\n\nAn agent is offered as an install target when **either** signal is present: a\nnewly installed agent has no config dir until its first run, and a config dir\noutlives an uninstalled agent. The interactive picker lists every agent it found,\nlabelled with the evidence (`configured`, `on PATH`, or both), and pre-checks the\nones on `$PATH` — a config dir left behind by an uninstalled agent should not be\na default target. If nothing is on `$PATH`, everything is pre-checked instead.\n\nIt never registers as a native plugin and never touches a config key it doesn't\nown: every write into a shared agent config file (`~/.claude.json`,\n`~/.codex/config.toml`, `~/.config/opencode/opencode.json`,\n`~/.config/mcp/mcp.json`) is a targeted single-key merge, so every unrelated\nbyte is preserved.\n\n## Install\n\n```sh\n# Homebrew (macOS / Linux)\nbrew install maquina-app/tap/equipr\n\n# or the install script — latest release, checksum-verified;\n# installs to /usr/local/bin when writable, else ~/.local/bin\ncurl -fsSL https://github.com/maquina-app/equipr/releases/latest/download/install.sh | sh\n```\n\n`.deb` / `.rpm` packages and raw archives (darwin, linux, windows × amd64,\narm64) are on the [releases page](https://github.com/maquina-app/equipr/releases).\n\n### Build it yourself\n\nGo 1.24+, matching `go.mod`. To build and install in one step, straight onto\nyour `PATH`:\n\n```sh\ngo build -o ~/.local/bin/equipr ./cmd/equipr   # or any directory on your PATH\n```\n\n`go install ./cmd/equipr` works too, but it lands in `$(go env GOPATH)/bin`,\nwhich is not on everyone's `PATH`.\n\nJust to try it, without installing anywhere:\n\n```sh\ngo build -o equipr ./cmd/equipr && ./equipr --version\n```\n\n## Commands\n\n```\nequipr add <origin>                       add a source (marketplace, AP repo, npm, or archive)\nequipr list [source-id|source-id/plugin]  list sources and their plugins\nequipr show <source-id>[/plugin]          show source or plugin details\nequipr install <source>/<plugin>[:<comp>] install into detected agents\nequipr update                             re-fetch sources + re-apply installs\nequipr remove <source-id> [--purge]       remove a source (optionally purge)\nequipr uninstall <source>/<plugin>[:<comp>] remove installed files + records\nequipr doctor                             check install health + cache integrity\nequipr status                             report every recorded install\n```\n\n## Usage examples\n\nAdd a source — the origin form is detected for you:\n\n```sh\n# a marketplace repo (git)\nequipr add https://github.com/coreyhaines31/marketingskills\n\n# an Agent Plugins repo (git) — local path or URL\nequipr add ./path/to/ap-repo\n\n# an npm package (fetched via `npm pack`)\nequipr add some-package\n#   or an explicit npm spec / a local package dir\n#   (a local dir with package.json and no .git is auto-detected as npm)\nequipr add npm:@scope/plugin@1.2.3\n\n# an archive URL (zip / tar.gz / tgz, extracted from its single top-level dir)\nequipr add https://example.com/releases/plugin-1.0.0.zip\n```\n\n### A walkthrough\n\nAdd a marketplace — here `coreyhaines31/marketingskills`, a single-plugin one:\n\n```console\n$ equipr add https://github.com/coreyhaines31/marketingskills\nFetching https://github.com/coreyhaines31/marketingskills\nAdded marketingskills (marketplace, fetched via git) with 1 plugin(s)\n  - marketing-skills 2.10.0\n```\n\n`list` shows every source with the plugins inside it and what each one holds, so\nyou can tell whether a source is worth opening without a second command:\n\n```console\n$ equipr list\nmarketingskills     marketplace\n  marketing-skills  2.10.0  49 skills\n```\n\n`--components` (`-c`) expands each plugin to its component names — these are the\nnames you pass to `install`:\n\n```console\n$ equipr list marketingskills --components\nmarketingskills (marketplace)\n  marketing-skills  2.10.0  49 skills\n    skill           ab-testing\n    skill           ad-creative\n    skill           ads\n    skill           ai-seo\n    ...\n```\n\n`list` also accepts the `<source>/<plugin>` form, which prints what `show`\nprints — a plugin's description, author, and every component it ships:\n\n```console\n$ equipr list marketingskills/marketing-skills\nPlugin: marketing-skills\n  Version:    2.10.0\n  Description: Marketing skills for AI agents — conversion optimization, ...\n  Author:     Corey Haines\n  Skills (49):\n    - ab-testing\n    - ad-creative\n    ...\n```\n\nInstall one skill. With no `--yes`, equipr prompts for the agents to install\ninto. Agents on `$PATH` are pre-checked; a config-only agent is listed but left\nunchecked — space toggles, enter confirms:\n\n```console\n$ equipr install marketingskills/marketing-skills:seo-audit\n  Install into which agents?\n  Agents on $PATH are pre-checked; space toggles, enter confirms\n  > ✓ claude-code (configured, on PATH)\n      codex (configured)\n    ✓ opencode (configured, on PATH)\n    ✓ pi (configured, on PATH)\n\nInstalled 1 component(s) into 3 agent(s):\n  [claude-code] seo-audit (copy -> ~/.claude/skills/seo-audit)\n  [opencode] seo-audit (symlink -> ~/.config/opencode/skills/seo-audit)\n  [pi] seo-audit (symlink -> ~/.pi/agent/skills/seo-audit)\n```\n\n`configured` means the agent's config directory exists; `on PATH` means its\nbinary is installed. Either is enough to be *offered* — a freshly installed\nagent has no config directory until its first run — but only `on PATH` is enough\nto be *pre-checked*, which is why `codex` above is listed and skipped.\n\n`status` reports every recorded install, and `doctor` checks their health:\n\n```console\n$ equipr status\nSTATE  COMPONENT     SOURCE/PLUGIN                     AGENT        MECH     TARGET\nok     seo-audit(s)  marketingskills/marketing-skills  claude-code  copy     ~/.claude/skills/seo-audit\nok     seo-audit(s)  marketingskills/marketing-skills  codex        copy     ~/.codex/skills/seo-audit\nok     seo-audit(s)  marketingskills/marketing-skills  opencode     symlink  ~/.config/opencode/skills/seo-audit\nok     seo-audit(s)  marketingskills/marketing-skills  pi           symlink  ~/.pi/agent/skills/seo-audit\n\n$ equipr doctor\nNo issues found.\n```\n\nOrigin detection: an explicit `npm:` prefix is npm; a URL ending\nin `.zip`/`.tar.gz`/`.tgz` is an archive; a git URL / `git@` / `.git` / an\nexisting git repo is git; an existing dir with `package.json` and no `.git` is an\nnpm package; anything else is an npm package name.\n\nArchives are extracted with path containment enforced — an entry that would\nwrite outside the cache directory aborts the fetch — and are capped at 512 MiB.\n\n### What equipr reads from a source\n\nA source is either a **marketplace** (`.claude-plugin/marketplace.json` at the\nrepo root, plugins in subdirectories) or a single **Agent Plugins** package\n(`plugin.json` at the root). An origin may name a **subdirectory** of the\nfetched tree, which is how a repository holding several independent AP packages\nis added one package at a time:\n\n```sh\n# explicit form — canonical, works for git, archive, and npm origins\nequipr add https://github.com/mariochavez/skills#plugins/claude-md-auditor\nequipr add https://github.com/mariochavez/skills#plugins/recuerd0-memory-graph\n\n# a forge URL copied out of the browser works too (http/https only)\nequipr add https://github.com/mariochavez/skills/tree/main/plugins/claude-md-auditor\n```\n\nOnly the part before the `#` is fetched; the subpath selects which plugin inside\nit the source refers to, and becomes the source's identity — so two plugins from\none repository do not collide on the repository name. The Agent Plugins spec\nroots a plugin at a directory and defines no multi-plugin index, so this lives\nentirely in the origin: the repository stays a plain collection of spec-clean\npackages with nothing equipr-specific in it.\n\nThe `/tree/<ref>/<path>` form is resolved after cloning, against the refs the\nclone actually has, so a branch name containing a slash splits correctly. equipr\nfetches the default branch only; a URL naming any other ref is rejected with a\npointer to the explicit form rather than silently resolving against the default\nbranch's tree. On a local path a directory named `tree` is just a directory.\n\nWithin each plugin, equipr discovers:\n\n| Component | Discovered at | Installed as |\n|---|---|---|\n| skills | any directory under `skills/` holding a `SKILL.md` | `<agent skills dir>/<name>/` |\n| commands | any `.md` file under `commands/` | `<agent skills dir>/<name>/SKILL.md` |\n| MCP servers | `mcp.json` at the plugin root (`{\"mcpServers\": {...}}`) | a single key merged into the agent's own MCP config |\n\nBoth trees are walked, so a plugin may group its components in category\ndirectories (`skills/engineering/tdd/SKILL.md`). `<name>` is the component's own\ndirectory or file — `tdd`, not `engineering-tdd` — and the walk stops descending\nat a directory holding a `SKILL.md`, so a skill's own bundled files are not\nmistaken for skills. Since that name is what it installs as, two components\nresolving to the same name are reported as an error rather than one overwriting\nthe other.\n\nCommands are normalized to `<name>/SKILL.md` for every agent, so a plugin's\ncommand files and its skills land in the same place and are discovered the same\nway.\n\nInstall into the agents you pick:\n\n```sh\n# interactive: pick agents (those on $PATH pre-checked) and components\nequipr install marketingskills/marketing-skills\n\n# non-interactive: every present agent, every component, auto-accept conflicts\nequipr install marketingskills/marketing-skills --yes\n\n# a single component into one agent (\":name\" and \"-c name\" are equivalent)\nequipr install marketingskills/marketing-skills:seo-audit -a claude-code\nequipr install marketingskills/marketing-skills -c seo-audit -a claude-code\n\n# repeat -a to target several agents\nequipr install marketingskills/marketing-skills:seo-audit -a claude-code -a pi\n\n# override the fixed per-agent mechanism (copy/symlink)\nequipr install marketingskills/marketing-skills --mechanism symlink\n```\n\nPropagate updates from the source:\n\n```sh\nequipr update                       # pull sources + re-apply every install\nequipr update --dry-run             # report what would change, write nothing\nequipr update --on-conflict=skip    # leave locally-modified targets alone\nequipr update --on-conflict=fail    # abort on the first local modification\n```\n\nRemove and clean up:\n\n```sh\nequipr remove marketingskills          # drop the source; records become orphaned\nequipr doctor                          # flag orphaned records / broken symlinks\nequipr uninstall marketingskills/marketing-skills  # remove files + records (works post-remove)\nequipr remove marketingskills --purge  # drop source + records + files + cache\n```\n\nHealth and status:\n\n```sh\nequipr status                       # ok / modified / missing per record\nequipr doctor                       # No issues found (exit 0)\n```\n\n`doctor` is read-only and reports four classes of problem:\n\n- `orphaned-record` — an install record whose source is no longer registered\n  (left behind by `equipr remove` without `--purge`)\n- `vanished-config-dir` — the target agent's config dir no longer exists\n- `broken-symlink` — a symlinked component points at a path that is gone\n- `modified-cache` — a source's cached tree no longer matches the digest\n  recorded when it was added\n\n## Scripting: `--json`\n\nEvery command accepts `--json` for machine-readable output — `list`, `show`,\n`status`, `doctor`, `update` (report), and `add`/`install`/`uninstall`/`remove`\n(confirmation). Progress messages go to stderr, so stdout is pure JSON:\n\n```sh\nequipr list --json\nequipr show marketingskills/marketing-skills --json\nequipr status --json\nequipr update --json\n# add/install/uninstall/remove also accept --json\nequipr add https://example.com/releases/plugin-1.0.0.zip --json\n```\n\n`--yes` / `-y` skips every interactive prompt: it installs into all detected\nagents, installs all components, and resolves conflict prompts as *overwrite*\n(an explicit `--on-conflict` still wins).\n\n## Exit codes\n\nThese are equipr's documented, stable choices — safe to branch on in scripts:\n\n| Code | Meaning |\n|------|---------|\n| `0` | success (including `doctor` with no issues) |\n| `1` | generic or usage error |\n| `2` | source / plugin / component not found (or nothing to uninstall) |\n| `3` | conflict (`--on-conflict=fail`, or a declined overwrite that stopped the run) |\n| `4` | environment / usage (`HOME` unset, no agents detected) |\n| `5` | `doctor` found issues |\n\n## Layout\n\nState, config, and cache follow the XDG Base Directory layout:\n\n- `$XDG_STATE_HOME/equipr/` — `sources.json`, `installs.json`, `equipr.lock`\n- `$XDG_CONFIG_HOME/equipr/` — reserved for `config.toml` (created, not yet used)\n- `$XDG_CACHE_HOME/equipr/` — fetched source clones\n\n`installs.json` records carry a content hash so `update` can detect local\nmodifications before overwriting anything. The check is mechanism-aware: for\ncopied targets equipr compares content hashes, and for symlinked targets it\ntreats \"the user replaced the symlink with a real file or directory\" as the\nlocal modification.\n\n## Shell completions\n\ncobra generates completion scripts for bash, zsh, fish, and PowerShell:\n\n```sh\n# bash\nsource <(equipr completion bash)\n# zsh\nsource <(equipr completion zsh)\n# fish\nequipr completion fish | source\n```\n\nPersist it by appending the output to your shell's rc file, or install to the\nstandard location (zsh): `equipr completion zsh > ${fpath[1]}/_equipr`.\n\n## Known limitations\n\n- **MCP manifests** are read from `mcp.json` only. A Claude Code plugin that\n  declares its servers in `.mcp.json` or inline in `plugin.json` will show no\n  MCP components.\n- **Marketplace plugin sources** are resolved only when they point inside the\n  fetched tree — a relative path (`\"source\": \"./path\"`) or a `git-subdir`-style\n  object carrying one. Entries pointing at a separate `github`/`npm`/`archive`\n  source are skipped and reported; the rest of the marketplace still installs.\n- **No ref pinning.** Git sources are shallow-cloned from the default branch;\n  there is no way to pin a tag, branch, or commit.\n- **Skills are installed globally only** (each agent's personal skills dir).\n  Project-scoped installs are not supported.\n- **Subagents are not a component type.** A plugin whose content is an `agents/`\n  directory (Claude Code subagents) resolves with no installable components;\n  equipr handles skills, commands, and MCP servers.\n\n## Releases\n\nReleases are cut **manually and locally from a Mac** with GoReleaser — there is\nno release CI workflow. A release publishes cross-platform binaries, a Homebrew\ncask, `.deb`/`.rpm` packages, and `install.sh`; macOS binaries are ad-hoc\ncodesigned so they run on Apple Silicon.\n\nSee `CLAUDE.md` → **Release procedure** for the full steps. The goreleaser\nsetup mirrors `maquina-app/recuerd0-cli`.\n\n## Examples\n\nReady-to-use manifests live in [`examples/`](examples/): a single-plugin Agent\nPlugins package (`ap-plugin/`) and a Claude Code marketplace (`marketplace/`).\nUse them to try `equipr add` against a local path without a network fetch.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n"}