Satchel
Satchel lets agent plugin authors build multi-target extensions from one source package.
Quick Start | Features | Usage | Release Readiness
Status: public alpha. Satchel can generate and check Codex, Claude, and GitHub Copilot plugin manifests and marketplace files today. ChatGPT app and Anthropic Connectors Directory release artifacts are available as metadata/checklist targets. Antigravity output is available as an experimental target while its host install flow stabilizes.
Note: the
claudetarget builds a Claude Code plugin; theanthropictarget builds an Anthropic Connectors Directory submission (a remote MCP server listing). They are different distribution channels.
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
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:
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:
claude plugin marketplace add parkerhancock/satchel
claude plugin install satchel@satchel-marketplace
Codex:
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:
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, ChatGPT, 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:
uv tool install satchel-agent
satchel --version
For one-off use without installing:
uvx --from satchel-agent satchel --help
Create a package:
uv run satchel init my-plugin
Generate host manifests:
uv run satchel generate my-plugin
Check source validity and generated-file drift:
uv run satchel check my-plugin
Run host-aware validation when the host CLIs are installed:
uv run satchel check my-plugin --host
Run release installability checks before publishing:
uv run satchel check my-plugin --release
Write machine-readable diagnostics:
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:
uv run satchel smoke my-plugin
uv run satchel smoke my-plugin --target claude
Build a target-specific archive without mutating the source tree:
uv run satchel pack my-plugin --target claude --release
Print a portability report:
uv run satchel report my-plugin
Manifest
Minimal satchel.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
chatgpt:
enabled: false
manifest: ./chatgpt/app.json
app:
displayName: My App
shortDescription: Shared agent extension.
mcpUrl: https://example.com/mcp
privacyUrl: https://example.com/privacy
termsUrl: https://example.com/terms
supportUrl: https://example.com/support
compatibility:
requireReadOnlyHints: true
requireSearchFetch: false
Output Model
| Source | Codex | Claude | Copilot | ChatGPT | Antigravity | Anthropic |
|---|---|---|---|---|---|---|
name, version, description |
.codex-plugin/plugin.json |
.claude-plugin/plugin.json |
.github/plugin/plugin.json |
chatgpt/app.json |
plugin.json in the generated package root |
anthropic/connector.json |
components.skills.path |
skills field |
skills field |
skills field |
ignored | copied to skills/ |
ignored (skills ship via claude) |
components.mcp.path |
mcpServers field |
default .mcp.json |
mcpServers field |
runtime is targets.chatgpt.app.mcpUrl |
copied to mcp_config.json |
runtime is targets.anthropic.connector.mcpUrl |
components.hooks.path |
hooks field |
default hooks/hooks.json |
hooks field |
ignored | copied to hooks.json |
ignored |
targets.codex.interface |
interface object |
not emitted | not emitted | not emitted | not emitted | not emitted |
targets.claude.displayName |
not emitted | displayName |
not emitted | not emitted | not emitted | not emitted |
targets.chatgpt.app |
not emitted | not emitted | not emitted | app metadata + submission checklist | not emitted | not emitted |
targets.anthropic.connector |
not emitted | not emitted | not emitted | not emitted | not emitted | connector metadata + submission checklist |
| target marketplace config | .agents/plugins/marketplace.json |
.claude-plugin/marketplace.json |
.github/plugin/marketplace.json |
not an install manifest | not supported yet | not an install manifest |
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 standards check <path> |
Compare upstream host standards sources with committed snapshots. |
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. |
| Standards watch | standards/sources.yaml, satchel standards check, and .github/workflows/standards-watch.yml track upstream host docs and open an issue on drift. |
| Claude PR workflow | .github/workflows/standards-claude-pr.yml lets a maintainer label a standards issue with standards:generate-pr so the official Claude app can draft a reviewed PR. |
| 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 verifyintegration - concrete host validators as more CLIs expose non-mutating plugin validation
Development
uv run ruff check .
uv run pytest
uv run satchel check .
uv run satchel smoke .
uv run satchel standards check .
uv run satchel report examples/basic
License
Satchel is released under the MIT License.
Release files for satchel-agent 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| satchel_agent-0.3.0.tar.gz | 70.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| satchel_agent-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:107.9 kB
Release files / satchel_agent-0.3.0.tar.gz
| Download URL | satchel_agent-0.3.0.tar.gz |
|---|---|
| Size | 70.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c412dc9b4bc347e8619a457c30bc79277f7b6cfd5e2343ae47328b8c3a1cf676
|
|
BLAKE2b-256 checksum How to use checksums |
d97857d881cdf34d9f8781c83d6727c056ca52eb01e0fa6d0ccbec8eae9f9d7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 31, 2026.
Transparency logRelease files / satchel_agent-0.3.0-py3-none-any.whl
| Download URL | satchel_agent-0.3.0-py3-none-any.whl |
|---|---|
| Size | 37.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b702a36bac4754fd8c6c63ed3ce5dee8936fe73ca6edd5030687fd3a7e4a1244
|
|
BLAKE2b-256 checksum How to use checksums |
3cc64ba641b5bb1df89fb1406731db4c22ba4575014631814d1ede47ae90ec17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 31, 2026.
Transparency log