Skip to content
Musher Docs

Python SDK

The Musher Python SDK lets you pull bundles, inspect manifests, and access typed assets from Python applications. It provides both synchronous and asynchronous clients with automatic credential discovery, SHA-256 verification, and local caching.

Prerequisites

  • Python 3.13 or later
  • A Musher API key — create one in the Console

Installation

Install the package

bash
pip install musher-sdk

Set your API key

bash
export MUSHER_API_KEY="mush_..."

Authentication

The SDK discovers credentials automatically, checking these sources in order:

  1. Programmatic — pass a token directly via configure() or the client constructor
  2. MUSHER_API_KEY environment variable
  3. OS keyring (musher/<host>)
  4. Credential file (~/.local/share/musher/credentials/<host>/api-key)

To pass a token programmatically:

python
import musher

musher.configure(token="mush_...")

Pull Your First Bundle

The pull() function downloads a bundle from the registry and returns a Bundle object with typed access to its contents.

python
import musher

bundle = musher.pull("acme/code-review-kit")

for fh in bundle.files():
    print(f"{fh.logical_path} ({fh.media_type or 'unknown'})")

Work with Typed Handles

Bundles provide typed handles for each asset category. Each handle gives you structured access to the asset content and metadata.

python
import musher

bundle = musher.pull("acme/code-review-kit")

# Access skills
for skill in bundle.skills():
    print(f"Skill: {skill.name}")
    print(skill.skill_md().text())

# Access prompts
for prompt in bundle.prompts():
    print(f"Prompt: {prompt.name}")
    print(prompt.text())

# Access toolsets
for toolset in bundle.toolsets():
    print(f"Toolset: {toolset.name}")
    print(toolset.parse_json())

# Access all files
for fh in bundle.files():
    print(f"{fh.logical_path} ({fh.media_type or 'unknown'})")

Resolve Without Pulling

Use resolve() to inspect a bundle's metadata without downloading its full contents. This is useful for checking versions, listing assets, or validating a reference.

python
import musher

result = musher.resolve("acme/code-review-kit:^1.0")

if result.manifest:
    for layer in result.manifest.layers:
        print(f"{layer.logical_path} ({layer.asset_type})")

Sync vs Async

The SDK provides both synchronous and asynchronous clients. Use the async variants in applications that already use asyncio.

Synchronous

python
from musher import Client, pull

# Using the convenience function
bundle = pull("acme/code-review-kit")

# Using the client directly
with Client() as client:
    bundle = client.pull("acme/code-review-kit")

Asynchronous

python
from musher import AsyncClient, pull_async

# Using the convenience function
bundle = await pull_async("acme/code-review-kit")

# Using the client directly
async with AsyncClient() as client:
    bundle = await client.pull("acme/code-review-kit")

Key Exports

ExportDescription
pull() / pull_async()Pull a bundle by reference
resolve() / resolve_async()Resolve metadata without downloading
configure()Set global SDK configuration (token, registry URL, cache, timeouts)
Client / AsyncClientSync and async bundle registry clients
BundleLoaded bundle with typed asset access via methods
ResolveResultManifest metadata returned by resolve()
MusherConfigConfiguration with credential discovery and cache settings
BundleRefParsed bundle reference (namespace, slug, version, digest)
Handle typesFileHandle, SkillHandle, PromptHandle, ToolsetHandle, AgentSpecHandle
Export typesClaudePluginExport, OpenAILocalSkill, OpenAIInlineSkill
MusherErrorBase exception — see Reference for full hierarchy

Next Steps