agentbundle
The installer for agent-ready-repo. Think npm, but for the skills, subagents, and hooks your coding agent runs on. One pack, one command, every major agent — Claude Code, Codex, Cursor, Copilot, Gemini, and Kiro (both the CLI and the IDE).
Quick start
python -m pip install agentbundle
Requires Python 3.11+. Runs on macOS, Linux, and Windows.
What's new in 0.33.1
If you maintain a catalogue with repository-level tests, agentbundle catalogue verify --root . now recognizes the top-level tests/ tree as
repository-owned. Those paths no longer produce [info] unclassified notices;
genuinely unknown paths still do, and the notices remain informational.
Install into a repo — so everyone who clones it gets the pack. core is the flagship pack, the loop itself:
agentbundle install --pack core
No catalogue argument needed: it defaults to the agent-ready-repo catalogue. It lands in the repo's agent config — subagents and skills included — and you commit it like any other project file. This is the default scope: the pack belongs to the project and the whole team.
Install for yourself, everywhere — so a pack follows you across every project, with no per-repo setup:
agentbundle install --pack desk-research --scope user
User-scope packs land in your home directory, not the repo — they're yours, not the team's, and they're there in every project you open.
Try a pack without committing it — so the pack is live in this clone while
git status stays clean:
agentbundle install --pack core --scope local
Local scope projects the same runtime files as repo scope, then records them in
.git/info/exclude. It requires a Git work tree. Uninstalling removes both the
projected files and the managed exclude entries; local and repo installs of the
same pack cannot coexist.
The install auto-detects your agent (--adapter overrides). Multi-IDE? Install the same pack for each agent at the same scope — they coexist, and the agents that read .agents/skills/ (codex, cursor, gemini, copilot) share one skill copy instead of fighting over it. To install from a different catalogue, pass it as a trailing argument — a git URL or a local path (agentbundle install --pack core <catalogue>); a config set source <catalogue> makes that the default, and an editable clone (pip install -e) defaults to itself.
Claude Code marketplace
Claude Code users can install any pack that permits user scope without first installing this CLI:
claude plugin marketplace add eugenelim/agent-ready-repo
claude plugin install architect@agent-ready-repo
The marketplace excludes repo-only packs because Claude plugins live in a
global cache. Install core and other repo-only packs with agentbundle so
their files land in the project. For hook-bearing user-scope packs, the
generated marketplace description lists the authored hook event, matcher,
timeout, interpreter, and body path before publication.
More commands
# See what the catalogue offers (bare uses the default; or name one explicitly)
agentbundle list-packs
agentbundle list-profiles
# See what a single pack contains — skills and agents, derived live from its tree
agentbundle show core
agentbundle show core --format json # stable object for scripts/agents
# See what YOU have installed — pack, adapter, scope, version, and whether
# an upgrade is available (both scopes by default)
agentbundle list-installed
agentbundle list-installed --no-check # skip the catalogue check (offline, fast)
agentbundle list-installed --check-drift # also count locally edited files
agentbundle list-installed --format json # machine-readable JSON (schema_version 1)
agentbundle list-installed --updates-only # show only rows needing attention
# Install a whole curated profile — a single-scope set of packs — in one command
agentbundle install --profile inception
# Preview any install without writing a file
agentbundle install --pack core --dry-run
# Upgrade to the version the catalogue ships — shows installed → target, asks first
agentbundle upgrade --pack core
agentbundle upgrade --pack core --yes # skip the prompt (CI)
# Uninstall — previews remove (Tier-1) vs keep (your edits), asks first
agentbundle uninstall --pack core --dry-run
agentbundle uninstall --pack core --yes
list-installed reads your state files (not the catalogue) and reports every installed (pack, adapter) at each scope with its version and a four-value status — up-to-date, upgrade-available, ahead (installed version is newer than catalogue), or unknown; it degrades to unknown (never an error) when the catalogue can't be resolved, and --no-check skips the check entirely. --format json emits a stable JSON contract (schema_version: 1) to stdout — useful for CI automation of upgrade decisions. --updates-only hides up-to-date rows.
show <pack> answers "what skills and agents does this pack contain?" by walking the pack's source tree live on each call — so the answer can't drift, and nothing is persisted. --format json emits a stable object (name, version, description, skills, agents, source) for scripts and agents. When the catalogue can't be resolved, an installed pack still reports its inventory from your state files (marked source: installed-state); a not-installed pack errors.
A profile is a catalogue-curated, single-scope set of packs you install in one command — it declares its own scope, so --scope doesn't apply. Upgrade takes no version — the target is whatever the catalogue you point at declares; to pin a past version, point the catalogue at that git ref. Install a pack that's already there and agentbundle offers to upgrade it instead (--yes runs it straight away).
Mutating commands ask first. uninstall, the --force cleanup, and the upgrade offer all preview what they'll do and confirm before touching anything; --dry-run previews without writing, and --yes skips the prompt for non-interactive / CI use (where, without it, they refuse rather than hang).
Enterprise distribution
For organizations running an internal Artifactory mirror or any static HTTPS server, agentbundle's enterprise distribution capabilities handle the full adoption loop — from org-wide channel configuration to CI-driven bulk upgrades.
Install from an internal Artifactory channel:
# Point agentbundle at your org's channel descriptor (one-time per machine,
# or pre-configured in your org fork — see Org bootstrap below)
agentbundle config set source catalogue+https://artifactory.example.test/agentbundle/catalogues/core/channels/stable.json
agentbundle install --pack core
The channel descriptor points to an immutable versioned archive; agentbundle
fetches, verifies its SHA-256 digest, and installs. Pass a bearer token via
AGENTBUNDLE_HTTP_BEARER_TOKEN — it is never stored in state, never printed, and
never forwarded to a different host.
JSON output for CI pipelines:
# See what's installed and what needs upgrading — machine-readable
agentbundle list-installed --format json
agentbundle list-installed --format json --updates-only
Returns a stable JSON contract (schema_version 1) with per-row status
(up-to-date / upgrade-available / ahead / unknown) and machine-readable
reason codes for unknown rows. Pipe into jq or your CI annotation step.
Bulk upgrade in one scoped command:
# Upgrade all installed packs in a scope — preflights before any write
agentbundle upgrade --all --scope repo --yes
agentbundle upgrade --all --scope user --format json --yes
Preflights all rows before writing anything; a blocked row stops the run before the
filesystem is touched. Partial failure is reported honestly — not described as a
rollback. Never silently downgrades an ahead row.
Package your catalogue for Artifactory:
agentbundle catalogue package \
--root /path/to/catalogue \
--bundle my-packs \
--release 1.0.0 \
--channel stable \
--output dist/
Produces a deterministic, reproducible gzip archive (versioned) and a mutable channel
descriptor JSON (stable.json), ready to upload to Artifactory. Identical inputs
produce byte-identical archives (honors SOURCE_DATE_EPOCH).
Build residue is excluded, so it does not matter whether you packaged a working
tree you had just tested or npm-installed in. Pruned at every level of a pack:
__pycache__, .pytest_cache, .mypy_cache, .ruff_cache, .tox,
.hypothesis, htmlcov, node_modules, .venv, venv — plus *.pyc,
*.pyo, .DS_Store, coverage.xml and .coverage* shards. The drop is
silent, so do not name a directory you mean to ship after one of those.
Source distribution for air-gapped or self-hosted catalogues:
agentbundle catalogue package \
--root /path/to/catalogue \
--bundle my-packs \
--release 1.0.0 \
--flavor source \
--output dist/
Produces a catalogue-source-<release>.tar.gz from a positive allowlist
(catalogue.toml, packs, profiles, guides, a marketplace manifest when
present, and legal files), with the same build-residue exclusions as the
default flavour. Includes a self-hosted-source-manifest.json with per-file
SHA-256 digests and provenance fields. agentbundle install refuses to install
a source archive, preventing accidental misuse.
Org bootstrap — ship the default channel in your fork:
Add an [organization.artifactory] block to
agentbundle/_data/install-defaults.toml in your org's agentbundle fork:
[organization.artifactory]
enabled = true
base-url = "https://artifactory.example.test"
repository = "agentbundle"
bundle = "core"
channel = "stable"
Developers installing from your fork get the internal channel without a manual
config set source step. The block ships enabled = false in the public package.
A malformed enabled = true config fails closed — no silent fallback to the public
source.
Offline and air-gapped hosts: set AGENTBUNDLE_NO_REMOTE=1 to skip the org
Artifactory bootstrap and editable-install detection entirely. agentbundle falls
straight through to the packaged default, so hosts without network access to Artifactory
still resolve a source without errors.
See Configure catalogue enterprise distribution for channel setup, authentication, CI upgrades, disconnected hosts, and the security boundary.
Build your own catalogue
agentbundle isn't tied to the agent-ready-repo catalogue. A catalogue source
has two required root markers: a valid catalogue.toml and a literal packs/
directory. A custom catalogue.paths.packs value controls where pack content
is read from; it does not replace the root packs/ marker.
Bootstrap a new catalogue in an empty directory:
agentbundle catalogue init --target /path/to/new-catalogue
Scaffolds catalogue.toml, the required directory tree (packs/, profiles/, contracts/, .claude-plugin/), and a starter marketplace.json. Skips files that already exist; reports conflicts without overwriting. Pass --dry-run to preview.
Bootstrap a self-hosted enterprise catalogue from an existing source:
agentbundle catalogue init \
--preset self-hosted \
--source /path/to/source-catalogue.tar.gz \
--tooling vendored \
--attribution white-label \
--repository-url https://github.com/your-org/your-catalogue \
--owner-email admin@example.com
Copies selected packs and profiles from the source archive, generates catalogue.toml with your identity, runs a fail-closed leak check, and writes .agentbundle/self-host-state.json to track managed files. --tooling vendored also copies the agentbundle source and catalogue-curation pack into .agentbundle/tooling/ for air-gapped deployments. Re-run to apply updates; stale owned files are removed (sha256-guarded, user-modified files are skipped).
A pack is a directory:
my-pack/
pack.toml # name, version, adapter-contract, install scope,
# plus rich metadata (license, maintainers, links,
# categories, keywords) and a README pointer
.claude-plugin/
plugin.json # Claude Code plugin manifest (hand-authored)
README.md # the pack's portable doc — projected with the pack
.apm/ # runtime — projected by the build pipeline
skills/<name>/
SKILL.md # the skill body; one folder per skill
scripts/ # helper code the skill invokes
references/ # progressive-disclosure docs, loaded on demand
assets/ # templates the skill copies into the repo
evals/ # activation + output-quality evals, skill-local
agents/<name>.md # subagents
hooks/<name>.py # lifecycle hooks
hook-wiring/<name>.toml # adapter event wiring for a shipped hook body
tests/ # implementation tests — NEVER projected
skills/<name>/
hooks/
pack/
seeds/ # files scaffolded into the adopter repo
Three boundaries: the pack owns and executes its tests, .apm/ is the
runtime export boundary, and a skill owns its eval fixtures. Only .apm/
and seeds/ are projected into an installed environment — tests/ is visible
in a catalogue archive, so an extracted pack can verify itself, but install
never places it. Keep tests out of .apm/ even though the installer would
ignore them there; the separation is structural, not incidental.
pack.toml is the single source of truth for a pack's metadata. Declare
license, [[pack.maintainers]], [pack.links], categories, and
keywords once; the build projects the cleanly-mappable subset — plus the
pack's README.md — into each distribution route's manifest (the plugin.json
/ marketplace.json entry), so the catalogue describes each pack richly rather
than with a single sentence. The Claude-plugin route carries only packs whose
[pack.install] allowed-scopes admits user: a plugin's code lands in the
adopter's global cache, so a repo-only pack gets no marketplace.json entry
and is reached with agentbundle install instead. A marketplace entry's source is a git-subdir
object (url, path, and one of ref/sha) pointing at the pack's directory
on the published distribution branch, and every entry is schema-validated at
build time against marketplace-entry.schema.json. Extra fields stay in pack.toml; the projection
is deliberately lossy per tool.
A hook-bearing pack that permits user scope must explicitly set
[pack.install] user-scope-hooks = true. On the Claude-plugin route,
agentbundle compiles supported Claude-shaped wiring into native plugin hooks
and rejects unsafe event, matcher, timeout, command, or body-path shapes before
creating output. Direct CLI installs keep their adapter-native wiring contract.
Point a catalogue URI (a git URL or a local path) at the repo that holds your packs. Then validate a pack against the adapter contract, render it to preview the projection, and install it into a target repo. scaffold drops a pack's seeds into a fresh directory to start from. The build pipeline (agentbundle.build) is the same engine make build runs.
Org adapter default: If your org ships a private agentbundle wheel (or a fork pinned to your internal catalogue), you can set a default adapter for all developers without requiring them to run agentbundle config set or pass --adapter on every install. Add an [organization] table to _data/install-defaults.toml in your fork:
[organization]
preferred_adapter = "cursor"
The org hint fires after the user-config but before the on-disk IDE probe — so --adapter, user-config, and upgrade state-hints all take priority. An invalid value exits 1 before writing anything. See the agentbundle reference for the full cascade.
Bundled contracts — the wheel ships the machine contracts used for offline validation:
pack.schema.json, skill.schema.json, guide.schema.json, skill-manifest.schema.json,
profile.schema.json, catalogue.schema.json, plugin-manifest.schema.json,
plugin-manifest.derived.schema.json, marketplace-entry.schema.json,
target-vocab.toml, and the adapter contract files. All are available without network access via importlib.resources.
Lint your catalogue — shallow structural checks run without extra dependencies:
agentbundle catalogue lint --root .
Lint validates both source markers and then checks the configured pack content.
It requires .claude-plugin/marketplace.json only when the effective self-host
adapters include claude-code. A Kiro-only catalogue can omit that Claude
artifact; the default Claude Code and Codex projection still requires it.
For full agentskills.io spec compliance (frontmatter key set, description policy, encoding, evals schema), install the lint extra and run with --deep:
pip install 'agentbundle[lint]'
agentbundle catalogue lint --root . --deep
Verify a catalogue before you ship it — runs the full read-only contract and self-host checks in one command:
agentbundle catalogue verify --root .
For a self-host-enabled catalogue with .adapt-discovery.toml, that includes the
self-host classifier. It treats generated targets as projected and known
repository-owned paths as excluded from projection. A genuinely unknown Git-visible
path remains an informational unclassified notice; it does not fail an otherwise
clean catalogue. Missing, modified, or orphaned projections do fail verification,
including generated executables under .agentbundle/bin/ and vendored user libraries
under .agentbundle/lib/. Git filenames are read losslessly, and a failed Git listing
is reported as a warning rather than mistaken for a fully classified inventory.
To check only self-host projection drift, or to regenerate projected files locally:
agentbundle catalogue self-host --check --root .
agentbundle catalogue self-host --write --root .
Both check commands are safe to run in CI. The write command changes projected files.
By default projects for claude-code and codex. Downstream repos that use a single adapter (e.g. kiro-ide) can declare it in catalogue.toml — only that adapter is then projected, and its output files participate in the drift check:
[distribution.agentbundle]
preferred-adapter = "kiro-ide"
When preferred-adapter names an adapter not in the upstream SELF_HOST_ADAPTERS list, the self-host engine switches to single-adapter mode: only the named adapter is projected; Claude Code-specific artifacts (.claude/, .codex/, .claude-plugin/, CLAUDE.md) are neither written nor drift-checked.
Run Tier-A activation evals to measure whether each covered skill fires on the prompts it should:
agentbundle pack evals run --pack <pack-name> --catalogue-root .
See the pack layout reference and authoring a skill.
Catalogue defaults and pack config API
Catalogue defaults let operators ship sensible starting values for every pack they distribute. Add a [pack-defaults.<pack-name>] table to catalogue.toml and the defaults are baked in at publish time. They slot into the three-layer cascade: pack-source defaults → operator defaults → user config. A custom install root is also supported via [catalogue] user-dir = "~/custom/path".
Pack scripts can resolve their user-scope directory and read the merged config at runtime using the agentbundle.config API:
from agentbundle.config import pack_dir, load_pack_config
directory = pack_dir("my-pack") # ~/.agentbundle/my-pack/
config = load_pack_config("my-pack") # merged dict: pack defaults + operator + user
Operation log — scripts can append structured JSONL records to <pack_dir>/ops.jsonl for lightweight audit trails:
from agentbundle.oplog import write_entry
write_entry("my-pack", "install", src="git+https://example.com/my-pack")
CLI commands to read, write, and inspect pack config and operation logs:
agentbundle pack-config show my-pack # all config values for a pack
agentbundle pack-config get my-pack api-key # single value
agentbundle pack-config set my-pack api-key v # write to user config.toml
agentbundle oplog show my-pack # JSONL operation history
agentbundle oplog clear my-pack # wipe history (asks first)
Per-session MCP server (workspace-mcp)
The core pack ships a per-session MCP server that a control harness can inject into
each Claude Code session. It exposes six tools over MCP stdio:
| Tool | What it does |
|---|---|
workspace_status |
Returns the queue (ready / blocked / active / shaping items) and active-run state — current phase, whether a gate is pending, and the gate question |
elicit |
Sends a question to the operator and blocks until they respond (300 s timeout) |
git_status |
Returns uncommitted changes (git status --short) |
git_branch |
Creates and checks out a feature branch scoped to the dispatched item |
git_commit |
Stages and commits only files under the item's configured output paths |
git_push |
Pushes the session branch to origin |
Spawn it (the harness does this, not the agent):
python3 -m agentbundle.workspace_mcp
Trusted checkout only. This form runs whichever
agentbundleis onsys.path. If the repo uses an editable install (pip install -e .), it runs the local checkout's code. Use only on repos you trust. An isolated spawn mode (python3 -I -m agentbundle.workspace_mcp) is planned for Stage 2 and will require a stable non-editable install.
Inject the session instruction so the agent knows to use the tools:
from agentbundle.workspace_mcp import DEFAULT_SESSION_INSTRUCTION
Pass exactly one environment variable when spawning to set the session mode:
WORKSPACE_MCP_SPEC_PATH (path to the spec directory) for FSM/work-loop items,
or WORKSPACE_MCP_DISPATCHED_ITEM (ini_slug/type:slug) for non-FSM shaping
items. Setting neither gives discovery-only mode (git writes disabled). Setting
both is unsupported — only one selects the mode.
Credentials
agentbundle doesn't resolve secrets. Credentialed skills use credbroker, a standalone resolver that keeps cleartext out of the model's reach.
Learn more
The full story — the loop, the reviewers, the pack catalogue — is in the agent-ready-repo README.
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 agentbundle-0.33.1.tar.gz.
File metadata
- Download URL: agentbundle-0.33.1.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5733109b8aa33acd252450939445fadd7d03075b78d5b7c7d64aa703f956dda6
|
|
| MD5 |
df3232ac39b8d7d168faefa4575011aa
|
|
| BLAKE2b-256 |
3f30488e033d31c34059cc5e5a9ed74819465f22ef139613a54c58b86eecfce6
|
Provenance
The following attestation bundles were made for agentbundle-0.33.1.tar.gz:
Publisher:
release-agentbundle.yml on eugenelim/agent-ready-repo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentbundle-0.33.1.tar.gz -
Subject digest:
5733109b8aa33acd252450939445fadd7d03075b78d5b7c7d64aa703f956dda6 - Sigstore transparency entry: 2432464401
- Sigstore integration time:
-
Permalink:
eugenelim/agent-ready-repo@864c738fba902566a8e6c931e9b1ac222d74ce91 -
Branch / Tag:
refs/tags/agentbundle-v0.33.1 - Owner: https://github.com/eugenelim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-agentbundle.yml@864c738fba902566a8e6c931e9b1ac222d74ce91 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentbundle-0.33.1-py3-none-any.whl.
File metadata
- Download URL: agentbundle-0.33.1-py3-none-any.whl
- Upload date:
- Size: 596.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4afbed3da50f03982be383220c1731a7918c9a7928758dfc72ad16a65a766c29
|
|
| MD5 |
e55ce13ec3c8b4538c136d86bd4cf8a6
|
|
| BLAKE2b-256 |
a585f24e605d1bc0535cc10529c37df4d8b49df08aa151a91c28d50f1fa05b5a
|
Provenance
The following attestation bundles were made for agentbundle-0.33.1-py3-none-any.whl:
Publisher:
release-agentbundle.yml on eugenelim/agent-ready-repo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentbundle-0.33.1-py3-none-any.whl -
Subject digest:
4afbed3da50f03982be383220c1731a7918c9a7928758dfc72ad16a65a766c29 - Sigstore transparency entry: 2432464460
- Sigstore integration time:
-
Permalink:
eugenelim/agent-ready-repo@864c738fba902566a8e6c931e9b1ac222d74ce91 -
Branch / Tag:
refs/tags/agentbundle-v0.33.1 - Owner: https://github.com/eugenelim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-agentbundle.yml@864c738fba902566a8e6c931e9b1ac222d74ce91 -
Trigger Event:
push
-
Statement type: