Metadata-Version: 2.4
Name: satchel-agent
Version: 0.2.0
Summary: Product-agnostic build tooling for agent plugin packages.
Project-URL: Homepage, https://github.com/parkerhancock/satchel
Project-URL: Repository, https://github.com/parkerhancock/satchel
Project-URL: Issues, https://github.com/parkerhancock/satchel/issues
Project-URL: Documentation, https://github.com/parkerhancock/satchel#readme
Author-email: Parker Hancock <parker@hancock.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,antigravity,claude,codex,copilot,mcp,plugins,skills
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.11
Requires-Dist: pyyaml>=6.0
Description-Content-Type: text/markdown

<p align="center">
  <img src="assets/logo.svg" alt="Satchel logo" width="112" />
</p>

<p align="center">
  <img src="assets/cover.svg" alt="Satchel builds multi-target agent plugin outputs from one satchel.yaml source package" width="760" />
</p>

<h1 align="center">Satchel</h1>

<p align="center">
  <strong>Satchel lets agent plugin authors build multi-target extensions from one source package.</strong>
</p>

<p align="center">
  <a href="https://github.com/parkerhancock/satchel/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/parkerhancock/satchel/actions/workflows/ci.yml/badge.svg" /></a>
  <a href="https://pypi.org/project/satchel-agent/"><img alt="PyPI" src="https://img.shields.io/pypi/v/satchel-agent.svg" /></a>
  <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg" /></a>
</p>

<p align="center">
  <a href="#quick-start">Quick Start</a> |
  <a href="#features">Features</a> |
  <a href="#usage">Usage</a> |
  <a href="#release-readiness">Release Readiness</a>
</p>

> Status: public alpha. Satchel can generate and check Codex, Claude, and
> GitHub Copilot plugin manifests and marketplace files today. Antigravity
> output is available as an experimental target while its host install flow
> stabilizes.

## Why Satchel

Modern agent plugins share useful building blocks: skills, `SKILL.md`
metadata, supporting files, MCP configuration, hooks, and subagent definitions.
Their manifests and marketplace catalogs are different enough that multi-target
plugin repos can drift.

Satchel makes `satchel.yaml` the source of truth. Authors edit one portable
package, then generate host-specific files and fail CI when generated outputs
are stale.

## Quick Start

```bash
uvx --from satchel-agent satchel init my-plugin
uvx --from satchel-agent satchel generate my-plugin
uvx --from satchel-agent satchel check my-plugin
uvx --from satchel-agent satchel smoke my-plugin
```

The generated files live at:

```text
my-plugin/.codex-plugin/plugin.json
my-plugin/.claude-plugin/plugin.json
my-plugin/.github/plugin/plugin.json
my-plugin/.github/plugin/marketplace.json
```

## Plugin Install

Satchel is packaged with Satchel. The repository root contains `satchel.yaml`,
the generated host manifests, generated marketplace files, and a shared
`skills/satchel/SKILL.md`.

Claude Code:

```bash
claude plugin marketplace add parkerhancock/satchel
claude plugin install satchel@satchel-marketplace
```

Codex:

```bash
codex plugin marketplace add parkerhancock/satchel
```

Then restart Codex, open the plugin directory, choose the Satchel marketplace,
and install the Satchel plugin. Codex can also read the generated repo
marketplace at `.agents/plugins/marketplace.json`, which points back to the
Git-backed Satchel plugin source.

GitHub Copilot CLI:

```bash
copilot plugin marketplace add parkerhancock/satchel
copilot plugin install satchel@satchel-marketplace
```

Antigravity support is experimental. The adapter can generate a local package
layout under `.agents/plugins/`, but install and marketplace behavior should be
verified against the current Antigravity CLI or IDE before relying on it.

## Features

| Feature | What it does |
| --- | --- |
| **Neutral manifest** | Reads `satchel.yaml` as the package source of truth. |
| **Target adapters** | Emits deterministic Codex, Claude, Copilot, and experimental Antigravity outputs through pluggable adapters. |
| **Drift checks** | Fails when generated outputs are missing or stale. |
| **Smoke tests** | Copies a package to a temporary directory, regenerates output, and validates the clean copy. |
| **Host validation** | Runs non-mutating host validators where available, including `claude plugin validate`. |
| **Marketplace patching** | Preserves host-owned marketplace metadata when `marketplace.patch: true` is set. |
| **Path safety** | Rejects component and output paths that escape the package root. |
| **Skill validation** | Checks each skill directory for `SKILL.md`, `name`, and `description`. |
| **Fixture suite** | Exercises skills-only, MCP, target-rich, Antigravity, and unsupported-target packages. |
| **Portability report** | Summarizes target support and shared components. |

## Usage

Install from PyPI:

```bash
uv tool install satchel-agent
satchel --version
```

For one-off use without installing:

```bash
uvx --from satchel-agent satchel --help
```

Create a package:

```bash
uv run satchel init my-plugin
```

Generate host manifests:

```bash
uv run satchel generate my-plugin
```

Check source validity and generated-file drift:

```bash
uv run satchel check my-plugin
```

Run host-aware validation when the host CLIs are installed:

```bash
uv run satchel check my-plugin --host
```

Run release installability checks before publishing:

```bash
uv run satchel check my-plugin --release
```

Write machine-readable diagnostics:

```bash
uv run satchel check my-plugin --json
```

See `docs/diagnostics.md` for diagnostic codes and remediation guidance.
See `docs/marketplaces.md` for marketplace installability workflows.
See `docs/host-validators.md` for host validator behavior.

Run a clean-copy smoke test:

```bash
uv run satchel smoke my-plugin
uv run satchel smoke my-plugin --target claude
```

Build a target-specific archive without mutating the source tree:

```bash
uv run satchel pack my-plugin --target claude --release
```

Print a portability report:

```bash
uv run satchel report my-plugin
```

## Manifest

Minimal `satchel.yaml`:

```yaml
schema: satchel/v0
name: my-plugin
version: 0.1.0
description: Shared agent extension.
author:
  name: Your Team

components:
  skills:
    path: ./skills
  mcp:
    path: ./.mcp.json

targets:
  codex:
    enabled: true
    manifest: ./.codex-plugin/plugin.json
    interface:
      displayName: My Plugin
      shortDescription: Shared agent extension.
      category: Productivity
      capabilities:
        - Read

  claude:
    enabled: true
    manifest: ./.claude-plugin/plugin.json
    displayName: My Plugin

  copilot:
    enabled: true
    manifest: ./.github/plugin/plugin.json
    marketplace:
      path: ./.github/plugin/marketplace.json
      patch: true

  antigravity:
    enabled: false
    experimental: true
    output: ./.agents/plugins/my-plugin
```

## Output Model

| Source | Codex | Claude | Copilot | Antigravity |
| --- | --- | --- | --- | --- |
| `name`, `version`, `description` | `.codex-plugin/plugin.json` | `.claude-plugin/plugin.json` | `.github/plugin/plugin.json` | `plugin.json` in the generated package root |
| `components.skills.path` | `skills` field | `skills` field | `skills` field | copied to `skills/` |
| `components.mcp.path` | `mcpServers` field | default `.mcp.json` | `mcpServers` field | copied to `mcp_config.json` |
| `components.hooks.path` | `hooks` field | default `hooks/hooks.json` | `hooks` field | copied to `hooks.json` |
| `targets.codex.interface` | `interface` object | not emitted | not emitted | not emitted |
| `targets.claude.displayName` | not emitted | `displayName` | not emitted | not emitted |
| target marketplace config | `.agents/plugins/marketplace.json` | `.claude-plugin/marketplace.json` | `.github/plugin/marketplace.json` | not supported yet |

Generated manifests should be treated as build outputs. Edit `satchel.yaml`
instead. If a marketplace file must retain host-owned fields, set
`targets.<target>.marketplace.patch: true`; Satchel will update the generated
plugin entry while preserving unrelated plugin entries and unknown metadata.

## Commands

| Command | Purpose |
| --- | --- |
| `satchel init <path>` | Create a minimal package with `satchel.yaml` and one skill. |
| `satchel generate <path>` | Generate enabled host manifests. |
| `satchel check <path>` | Validate source and fail on stale generated files. |
| `satchel check <path> --host` | Add non-mutating host validators when available. |
| `satchel check <path> --release` | Require remote marketplace sources for release installability. |
| `satchel check <path> --json` | Write machine-readable diagnostics with stable codes. |
| `satchel smoke <path>` | Validate a regenerated temporary copy without mutating the source tree. |
| `satchel smoke <path> --target <target>` | Validate only one enabled target in a clean temporary copy. |
| `satchel pack <path> --target <target>` | Build `dist/<name>-<version>-<target>.zip` from a clean regenerated copy. |
| `satchel report <path>` | Print a simple portability report. |
| `satchel --version` | Print the installed Satchel version. |

## Release Readiness

The repo now includes the release-readiness pieces needed for a public alpha:

| Area | Status |
| --- | --- |
| Host validation | `satchel check --host` uses a host validator registry, runs `claude plugin validate` when available, and reports structural fallbacks for hosts without stable validators. |
| Clean smoke tests | `satchel smoke` regenerates and validates a temporary package copy; `--target` scopes the smoke run to one host. |
| CI | `.github/workflows/ci.yml` runs lint, tests, schema-doc checks, release checks, host-aware smoke tests, and target archive builds. |
| Packaging | `satchel pack --target` builds target-specific plugin archives; `pyproject.toml` and `.github/workflows/publish.yml` handle the Python package release. |
| Project hygiene | `CONTRIBUTING.md`, `SECURITY.md`, `ROADMAP.md`, and issue templates are present. |
| Schema docs | `docs/schema.md`, generated `docs/schema-reference.md`, and `schemas/satchel.schema.json` document the manifest. |
| Fixtures | `fixtures/` covers skills-only, skills-and-MCP, Claude-rich, Codex-rich, Copilot-rich, Antigravity-rich, and unsupported-target packages. |
| Demo | `examples/release-auditor/` is a non-trivial generated multi-target plugin. |

Operational release steps are documented in `docs/release.md`: configure PyPI
trusted publishing, cut a GitHub release, then verify
`uv tool install satchel-agent` or `pipx install satchel-agent` after
publishing. The installed CLI command is still `satchel`.

Good follow-up work after public alpha:

- optional `plugin-scanner verify` integration
- a standards watch process for fast-moving host plugin and marketplace specs

## Development

```bash
uv run ruff check .
uv run pytest
uv run satchel check .
uv run satchel smoke .
uv run satchel report examples/basic
```

## License

Satchel is released under the [MIT License](LICENSE).
