Pulling Bundles
Musher bundles are OCI artifacts hosted at bundles.musher.dev. You can pull them with
the Musher CLI, an SDK, or any HTTP client.
Quick start
musher load acme/code-reviewimport musher
bundle = musher.pull("acme/code-review")
for skill in bundle.skills():
print(skill.path, len(skill.content))import { pull } from "@musher-dev/musher-sdk";
const bundle = await pull("acme/code-review");
for (const skill of bundle.skills()) {
console.log(skill.name, skill.content.length);
}# Step 1: Resolve the bundle to get the OCI reference (no auth needed for public bundles)
curl -s https://api.musher.dev/v1/namespaces/acme/bundles/code-review:resolve
# Step 2: Pull using any OCI client (e.g. oras)
oras pull bundles.musher.dev/acme/code-review:1.0.0Authentication
Public bundles can be pulled without credentials. Private bundles require an API key or access token.
# Interactive login (stores credential in keyring)
musher auth login
# Or set an environment variable
export MUSHER_API_KEY="mush_..."
musher load acme/private-bundleimport musher
# Option 1: Environment variable (automatic)
# export MUSHER_API_KEY="mush_..."
bundle = musher.pull("acme/private-bundle")
# Option 2: Programmatic
musher.configure(token="mush_...")
bundle = musher.pull("acme/private-bundle")import { pull, MusherClient } from "@musher-dev/musher-sdk";
// Option 1: Environment variable (automatic)
// export MUSHER_API_KEY="mush_..."
const bundle = await pull("acme/private-bundle");
// Option 2: Programmatic
const client = new MusherClient({ apiKey: "mush_..." });
const bundle2 = await client.pull("acme/private-bundle");curl -s https://api.musher.dev/v1/namespaces/acme/bundles/private-bundle:resolve \
-H "Authorization: Bearer mush_..."All tools discover credentials automatically in this order:
MUSHER_API_KEYenvironment variable- OS keyring (set by
musher auth login) - Credentials file (
~/.local/share/musher/credentials/)
Version pinning
Append a version tag with : to pull a specific version. Without a tag, latest is used.
# Latest version (default)
musher load acme/code-review
# Specific version
musher load acme/code-review:1.0.0
# Specific tag
musher load acme/code-review:stable# Latest version (default)
bundle = musher.pull("acme/code-review")
# Specific version
bundle = musher.pull("acme/code-review:1.0.0")
# Specific tag
bundle = musher.pull("acme/code-review:stable")// Latest version (default)
const bundle = await pull("acme/code-review");
// Specific version
const pinned = await pull("acme/code-review:1.0.0");
// Specific tag
const stable = await pull("acme/code-review:stable");# Resolve a specific version
curl -s "https://api.musher.dev/v1/namespaces/acme/bundles/code-review:resolve?version=1.0.0" \
-H "Authorization: Bearer $MUSHER_API_KEY"CLI options
| Flag | Default | Description |
|---|---|---|
--output-dir, -o | Local cache | Extract bundle to a specific directory instead of the cache |
--force | false | Re-download even if the bundle is already cached |
--json | false | Output structured JSON with bundle metadata and file paths |
SDK configuration
import musher
musher.configure(
cache_dir="/tmp/musher-cache", # Custom cache location
verify_checksums=True, # SHA-256 verification (default: True)
timeout=30.0, # Request timeout in seconds (default: 30)
max_retries=2, # Retry count (default: 2)
)import { MusherClient } from "@musher-dev/musher-sdk";
const client = new MusherClient({
cacheDir: "/tmp/musher-cache", // Custom cache location
manifestTtlSeconds: 86400, // Manifest cache TTL (default: 24h)
timeout: 60000, // Request timeout in ms (default: 60s)
retries: 3, // Retry count (default: 3)
});What happens when you pull
When you pull a bundle, the tool performs these steps:
- Resolve — looks up the bundle in the registry to find the matching version and its OCI manifest.
- Download — fetches any assets not already in the local cache from the registry.
- Verify — computes SHA-256 checksums and compares them against the manifest to ensure integrity.
- Cache — stores the verified assets locally so subsequent pulls are instant.
Troubleshooting
Authentication errors (401 / 403)
Verify your API key is set correctly and has not expired. Run musher auth login to
re-authenticate, or check MUSHER_API_KEY.
Version not found
Ensure the version tag exists. Use musher hub info acme/code-review to check available
versions.
Network timeouts
Increase the timeout in your SDK configuration. For the CLI, check your network connectivity and retry.