Working with Typed Handles
After pulling a bundle, you access its contents through typed handles — objects that provide structured access to each asset's metadata and content.
Asset Categories
Each bundle organizes assets into categories. Use the corresponding accessor method to get a list of typed handles:
| Method | Returns | Content access |
|---|---|---|
files() | list[FileHandle] | .text(), .bytes() |
skills() | list[SkillHandle] | .skill_md(), .files() |
prompts() | list[PromptHandle] | .text() |
toolsets() | list[ToolsetHandle] | .text(), .parse_json() |
agent_specs() | list[AgentSpecHandle] | .text(), .parse_json() |
| Method | Returns | Content access |
|---|---|---|
files() | FileHandle[] | .text(), .bytes(), .stream() |
skills() | SkillHandle[] | .content, .files() |
prompts() | PromptHandle[] | .content |
toolsets() | ToolsetHandle[] | .content |
agentSpecs() | AgentSpecHandle[] | .content |
Iterate All Assets
python
import musher
bundle = musher.pull("acme/code-review-kit")
# All files (every asset, regardless of type)
for fh in bundle.files():
print(f"{fh.logical_path} ({fh.media_type or 'unknown'})")
# Skills only
for skill in bundle.skills():
print(f"Skill: {skill.name}")
print(f" Description: {skill.description}")
# Prompts only
for prompt in bundle.prompts():
print(f"Prompt: {prompt.name}")
print(prompt.text())
# Toolsets (JSON content)
for toolset in bundle.toolsets():
print(f"Toolset: {toolset.name}")
config = toolset.parse_json()
print(config)typescript
import { pull } from "@musher-dev/musher-sdk";
const bundle = await pull("acme/code-review-kit");
// All files (every asset, regardless of type)
for (const fh of bundle.files()) {
console.log(`${fh.logicalPath} (${fh.mediaType ?? "unknown"})`);
}
// Skills only
for (const skill of bundle.skills()) {
console.log(`Skill: ${skill.name}`);
console.log(` Description: ${skill.description}`);
console.log(skill.content);
}
// Prompts only
for (const prompt of bundle.prompts()) {
console.log(`Prompt: ${prompt.name}`);
console.log(prompt.content);
}
// Toolsets
for (const toolset of bundle.toolsets()) {
console.log(`Toolset: ${toolset.name}`);
console.log(toolset.content);
}
// Agent specs
for (const spec of bundle.agentSpecs()) {
console.log(`Agent Spec: ${spec.name}`);
}Look Up a Single Asset
Use singular accessor methods to look up a specific asset by name. These raise KeyError (Python) or throw BundleAssetNotFoundError (TypeScript) if the asset
is not found.
python
bundle = musher.pull("acme/code-review-kit")
# Look up by name (raises KeyError if not found)
skill = bundle.skill("code-review")
prompt = bundle.prompt("review-template")
toolset = bundle.toolset("lint-rules")
# Look up a file by logical path (returns None if not found)
readme = bundle.file("README.md")
if readme:
print(readme.text())typescript
const bundle = await pull("acme/code-review-kit");
// Look up by name (throws BundleAssetNotFoundError if not found)
const skill = bundle.skill("code-review");
const prompt = bundle.prompt("review-template");
const toolset = bundle.toolset("lint-rules");
const spec = bundle.agentSpec("reviewer");
// Look up a file by logical path (returns undefined if not found)
const readme = bundle.file("README.md");
if (readme) {
console.log(readme.text());
}Select a Subset
Use select() to filter a bundle to only the assets you need. This returns a filtered view
with the same typed accessors but limited to the selected assets.
python
bundle = musher.pull("acme/code-review-kit")
# Select specific skills and prompts
selection = bundle.select(
skills=["code-review", "security-scan"],
prompts=["review-template"],
)
for skill in selection.skills():
print(skill.name)typescript
const bundle = await pull("acme/code-review-kit");
// Select specific skills and prompts
const selection = bundle.select({
skills: ["code-review", "security-scan"],
prompts: ["review-template"],
});
for (const skill of selection.skills()) {
console.log(skill.name);
}Skill Handles in Depth
SkillHandle is the richest handle type. Beyond the name and description, it provides access
to the skill's content and supporting files:
python
skill = bundle.skill("code-review")
# The skill's SKILL.md content
skill_md = skill.skill_md()
print(skill_md.text())
# All files within the skill directory
for fh in skill.files():
print(f" {fh.logical_path}")
# Look up a specific file within the skill
config = skill.file("config.json")
if config:
print(config.text())typescript
const skill = bundle.skill("code-review");
// The skill's SKILL.md content
console.log(skill.content);
// Skill metadata
console.log(`Name: ${skill.name}`);
console.log(`Description: ${skill.description}`);
// All files within the skill directory
for (const fh of skill.files()) {
console.log(` ${fh.logicalPath}`);
}
// Look up a specific file within the skill
const config = skill.file("config.json");
if (config) {
console.log(config.text());
}