Metadata-Version: 2.4
Name: agpack
Version: 0.2.1
Summary: Fetch and deploy AI agent resources from git repos to local tool directories
Project-URL: Homepage, https://github.com/PhilippTh/agpack
Project-URL: Funding, https://github.com/sponsors/PhilippTh
Author-email: Philipp Thumfart <philipp@thumfart.eu>
License-Expression: GPL-3.0-only
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.11
Requires-Dist: click>=8.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: tomli-w>=1.0
Description-Content-Type: text/markdown

# agpack

[![PyPI](https://img.shields.io/pypi/v/agpack)](https://pypi.org/project/agpack/)
[![CI](https://github.com/PhilippTh/agpack/actions/workflows/ci.yml/badge.svg)](https://github.com/PhilippTh/agpack/actions/workflows/ci.yml)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![mypy](https://img.shields.io/badge/type--checked-mypy-blue)](https://mypy-lang.org/)
[![License: GPL-3.0](https://img.shields.io/badge/license-GPL--3.0-green)](LICENSE)
[![Sponsor](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-ea4aaa)](https://github.com/sponsors/PhilippTh)

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

```bash
# Recommended: install as an isolated tool
pipx install agpack
# or
uv tool install agpack

# Or with plain pip
pip install agpack
```

Requires Python 3.11+ and `git` on PATH.

## Quick start

```bash
agpack init          # creates agpack.yml with commented-out examples
```

Edit `agpack.yml`:

```yaml
name: my-project
version: 0.1.0

targets:
  - claude
  - opencode

dependencies:
  skills:
    - url: https://github.com/PhilippTh/agent-assets
      path: skills/article-review
    - url: https://github.com/PhilippTh/agent-assets
      path: skills/deep-dive
      ref: v1.2.0

  commands:
    - url: https://github.com/PhilippTh/agent-assets
      path: commands/review.md

  agents:
    - url: https://github.com/PhilippTh/agent-assets
      path: agents/backend-expert.md

  mcp:
    - name: filesystem
      command: npx
      args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
```

Then:

```bash
agpack sync
```

That's it. 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.

## How dependencies work

The `url` field takes any valid `git clone` URL. HTTPS, SSH, local paths -- whatever git understands:

```yaml
# GitHub over HTTPS
- url: https://github.com/owner/repo
  path: skills/my-skill

# GitLab over SSH
- url: git@gitlab.com:myorg/myrepo.git
  path: skills/my-skill

# Azure DevOps
- url: https://dev.azure.com/myorg/myproject/_git/myrepo
  path: skills/my-skill

# Pinned to a tag
- url: https://github.com/owner/repo
  path: skills/my-skill
  ref: v1.0.0

# Pinned to a commit
- url: https://github.com/owner/repo
  path: skills/my-skill
  ref: abc1234
```

Authentication is handled entirely by your system git config -- SSH keys, credential helpers, whatever you already have set up.

The `path` field can point to a single file, a single skill folder, or a parent directory containing multiple items. When `path` points at a directory, agpack figures out what's inside:

- **Skills** -- a directory with top-level files is deployed as one skill. A directory that only contains subdirectories deploys each subfolder as a separate skill.
- **Commands & Agents** -- every non-hidden file in the directory is deployed individually. If the top level only has subdirectories, files inside those are collected instead.

```yaml
skills:
  # A single skill folder
  - url: https://github.com/owner/repo
    path: skills/my-skill

  # A directory of skills -- each subfolder becomes its own skill
  - url: https://github.com/owner/repo
    path: skills

commands:
  # A single command file
  - url: https://github.com/owner/repo
    path: commands/review.md

  # A directory of commands -- every file inside is deployed
  - url: https://github.com/owner/repo
    path: commands
```

If the directory contains no deployable files, sync fails with an error.

## Where things go

| 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 server definitions are merged into each tool's config file without touching servers agpack didn't create.

## Commands

### `agpack sync`

Fetches everything and deploys it. Run it again after changing `agpack.yml` -- removed dependencies get cleaned up automatically.

```
agpack sync [--dry-run] [--verbose] [--config PATH]
```

### `agpack status`

Shows what's installed vs what's configured:

```
Skills:
  ✓ article-review       (https://github.com/PhilippTh/agent-resources @ abc1234)
  ✗ new-skill            (not yet synced)

Commands:
  ✓ review.md            (https://github.com/PhilippTh/agent-resources @ abc1234)

MCP:
  ✓ filesystem           → .mcp.json, opencode.json
```

### `agpack init`

Creates a starter `agpack.yml` with commented-out examples.

## Environment variables

Use `${VAR_NAME}` syntax in config values to reference environment variables. agpack resolves them at sync time.

```yaml
mcp:
  - name: context7
    command: npx
    args: ["-y", "@context7/mcp-server"]
    env:
      CONTEXT7_API_KEY: ${CONTEXT7_API_KEY}
```

Variables are resolved from two sources, in order:

1. A `.env` file in the project root (same directory as `agpack.yml`)
2. Your shell environment

The `.env` file takes precedence when a variable is defined in both places. If a referenced variable is not found in either source, sync fails with an error.

Example `.env` file:

```
# API keys — add .env to .gitignore!
CONTEXT7_API_KEY=sk-abc123
OPENAI_API_KEY=sk-xyz789
```

The `.env` parser supports `KEY=VALUE`, `"quoted"` and `'quoted'` values, `# comments`, blank lines, and `export` prefixes.

## How it works under the hood

1. Loads `agpack.yml`, validates it
2. Reads `.agpack.lock.yml` to see what was previously installed
3. Cleans up files from dependencies you've removed
4. For each dependency: shallow-clones the repo (with sparse checkout when a `path` is set), copies files to all target directories
5. Merges MCP configs into each tool's config file
6. 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](LICENSE).
