Fetch and deploy AI agent resources from git repos to local tool directories
Project description
agpack
Declare your AI agent resources in a YAML file, run agpack sync, and they get deployed to every coding tool you use.
agpack fetches skills, commands, agents, and MCP server configs from git repos and copies them to the right places for Claude Code, OpenCode, Codex, Cursor, and GitHub Copilot.
Why
Every AI coding tool has its own directory structure for skills, its own config format for MCP servers, its own spot for custom commands. If you use more than one tool -- or share resources across projects -- you end up manually copying files and keeping multiple configs in sync.
agpack replaces that with a single agpack.yml that describes what you want and where it comes from.
Install
pipx install agpack # or: uv tool install agpack
Requires Python 3.11+ and git on PATH.
Quick start
agpack init # creates agpack.yml with commented-out examples
Edit agpack.yml:
targets:
- claude
- opencode
dependencies:
skills:
- url: https://github.com/owner/repo
path: skills/my-skill
commands:
- url: https://github.com/owner/repo
path: commands/review.md
agents:
- url: https://github.com/owner/repo
path: agents/backend-expert.md
mcp:
- name: filesystem
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
agpack sync
Skills get copied to .claude/skills/, .opencode/skills/, etc. Commands and agents go to their respective directories. MCP server definitions get merged into each tool's config file. Run agpack sync again after editing the config -- removed dependencies get cleaned up automatically.
Dependencies
URLs and pinning
The url field takes any valid git clone URL -- HTTPS, SSH, local paths, whatever git understands. Authentication is handled by your system git config (SSH keys, credential helpers, etc.).
Use ref to pin a dependency to a specific tag or commit:
- url: https://github.com/owner/repo
path: skills/my-skill
ref: v1.2.0
- url: git@gitlab.com:myorg/myrepo.git
path: skills/my-skill
ref: abc1234
Directory expansion
The path field can point to a single file, a single folder, or a parent directory containing multiple items. When it points at a directory, agpack figures out what's inside:
- Skills -- a directory with top-level files is deployed as one skill. A directory containing only subdirectories deploys each subfolder as a separate skill.
- Commands & Agents -- every non-hidden file is deployed individually. If the directory only contains subdirectories, files inside those are collected instead.
skills:
- url: https://github.com/owner/repo
path: skills/my-skill # deploys one skill
- url: https://github.com/owner/repo
path: skills # deploys each subfolder as a separate skill
commands:
- url: https://github.com/owner/repo
path: commands/review.md # deploys one file
- url: https://github.com/owner/repo
path: commands # deploys every file inside
If the directory contains no deployable files, sync fails with an error.
Environment variables
Use ${VAR_NAME} in any string value to reference environment variables. This works in URLs, paths, refs, MCP commands, args, env values, and server URLs.
dependencies:
skills:
- url: https://github.com/${GITHUB_ORG}/shared-skills
path: skills/my-skill
mcp:
- name: context7
command: npx
args: ["-y", "@context7/mcp-server"]
env:
CONTEXT7_API_KEY: ${CONTEXT7_API_KEY}
Variables are resolved from up to three sources (highest priority first):
.envin the project root (same directory asagpack.yml).envin the global config directory (~/.config/agpack/)- Shell environment
If a referenced variable is not found in any source, sync fails with an error. The .env parser supports KEY=VALUE, quoted values, # comments, blank lines, and export prefixes.
Global config
A global config defines dependencies shared across all your projects -- skills, agents, or MCP servers you want everywhere without repeating them in each agpack.yml.
agpack init --global # creates ~/.config/agpack/agpack.yml
The global config uses the same dependencies block but has no targets (those are always per-project):
# ~/.config/agpack/agpack.yml
dependencies:
skills:
- url: https://github.com/owner/shared-skills
path: skills/my-standard-skill
mcp:
- name: context7
command: npx
args: ["-y", "@upstash/context7-mcp@latest"]
env:
CONTEXT7_API_KEY: ${CONTEXT7_API_KEY}
Global dependencies are merged with the project config during sync. If the same dependency or MCP server appears in both, the project version wins.
To skip the global config, either pass --no-global on the command line or add global: false to your project's agpack.yml. The default path (~/.config/agpack/agpack.yml) can be overridden with the AGPACK_GLOBAL_CONFIG environment variable.
Target mapping
| Target | Skills | Commands | Agents | MCP Config |
|---|---|---|---|---|
| Claude | .claude/skills/<name>/ |
.claude/commands/<file> |
.claude/agents/<file> |
.mcp.json |
| OpenCode | .opencode/skills/<name>/ |
.opencode/commands/<file> |
.opencode/agents/<file> |
opencode.json |
| Codex | .agents/skills/<name>/ |
-- | -- | .codex/config.toml |
| Cursor | .cursor/skills/<name>/ |
-- | .cursor/agents/<file> |
.cursor/mcp.json |
| Copilot | .github/skills/<name>/ |
.github/prompts/<file> |
.github/agents/<file> |
.vscode/mcp.json |
Unsupported resource types are skipped silently. MCP definitions are merged into each tool's config file without touching servers agpack didn't create.
Commands
agpack init [--config PATH] [--global] Scaffold a new config file
agpack sync [--config PATH] [--no-global] Fetch and deploy all dependencies
[--dry-run] [--verbose]
agpack status [--config PATH] [--no-global] Show installed vs configured state
How it works
- Loads
agpack.ymland the global config (if present), merges them - Resolves
${VAR}references from.envfiles and the shell - Reads
.agpack.lock.ymlto diff against the previous state - Cleans up files from removed dependencies
- Shallow-clones each repo (sparse checkout when
pathis set), copies files to all target directories - Merges MCP configs into each tool's config file
- Writes an updated lockfile
Every file write is atomic (write-to-temp-then-rename). agpack never partially writes a file and never deletes anything it didn't create.
License
GPL-3.0 -- see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agpack-0.3.0.tar.gz.
File metadata
- Download URL: agpack-0.3.0.tar.gz
- Upload date:
- Size: 97.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50f9841698e1dbe51cd92119d07ae415638cb1d5bd446a9f8685ddc2e8b4c2b0
|
|
| MD5 |
1c2cf154afc49442851c910840a52ef8
|
|
| BLAKE2b-256 |
cfe77b4dc8e79e8d7d362d57f3c8b8633f70b5ba50c898e3e5a171a968737aeb
|
Provenance
The following attestation bundles were made for agpack-0.3.0.tar.gz:
Publisher:
release.yml on PhilippTh/agpack
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agpack-0.3.0.tar.gz -
Subject digest:
50f9841698e1dbe51cd92119d07ae415638cb1d5bd446a9f8685ddc2e8b4c2b0 - Sigstore transparency entry: 1239335408
- Sigstore integration time:
-
Permalink:
PhilippTh/agpack@074dc57953e2cdd7a750c6bfd140279aa7e164e3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/PhilippTh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@074dc57953e2cdd7a750c6bfd140279aa7e164e3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agpack-0.3.0-py3-none-any.whl.
File metadata
- Download URL: agpack-0.3.0-py3-none-any.whl
- Upload date:
- Size: 38.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
795435fd8cd9863a161046dac870bcf34f55a41857598804a1e99ab2dae5a48b
|
|
| MD5 |
a4605c9e922019ee6bbb466f75b7bb5f
|
|
| BLAKE2b-256 |
50078528a12025aa91be53b5339c5100a2126d6da30da8e9991ebfe5cf0551ae
|
Provenance
The following attestation bundles were made for agpack-0.3.0-py3-none-any.whl:
Publisher:
release.yml on PhilippTh/agpack
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agpack-0.3.0-py3-none-any.whl -
Subject digest:
795435fd8cd9863a161046dac870bcf34f55a41857598804a1e99ab2dae5a48b - Sigstore transparency entry: 1239335409
- Sigstore integration time:
-
Permalink:
PhilippTh/agpack@074dc57953e2cdd7a750c6bfd140279aa7e164e3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/PhilippTh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@074dc57953e2cdd7a750c6bfd140279aa7e164e3 -
Trigger Event:
push
-
Statement type: