Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22]
node-version: [20, 22, 24]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
Expand Down
52 changes: 49 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Musher TypeScript SDK

Official TypeScript SDK for the [Musher](https://musher.dev) platform.
[![npm](https://img.shields.io/npm/v/@musher-dev/musher-sdk)](https://www.npmjs.com/package/@musher-dev/musher-sdk)
[![CI](https://github.com/musher-dev/typescript-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/musher-dev/typescript-sdk/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
![Node >= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)

Official TypeScript SDK for the [Musher](https://musher.dev) platform. Pull, cache, and load bundled AI agent assets — skills, prompts, toolsets, and agent specs — with typed handles, content-addressable caching, and platform adapters for Claude Code, OpenAI Agents, and VS Code.

## Packages

Expand Down Expand Up @@ -32,6 +37,8 @@ const file = bundle.file("prompts/system.md");
console.log(file?.text());
```

## More Capabilities

Resolve metadata without downloading:

```typescript
Expand All @@ -41,7 +48,7 @@ const meta = await resolve("acme/code-review-kit:1.2.0");
console.log(meta.version);
```

Use `MusherClient` directly when you need custom configuration:
Custom client configuration:

```typescript
import { MusherClient } from "@musher-dev/musher-sdk";
Expand All @@ -54,7 +61,46 @@ const client = new MusherClient({
const bundle = await client.pull("acme/code-review-kit:1.2.0");
```

See [`examples/`](./examples/) for more complete runnable examples including Claude, OpenAI, and VS Code integrations.
Cache management:

```typescript
const stats = await client.cache.stats();
console.log(stats.entryCount, stats.blobSizeBytes);
await client.cache.clean();
```

Filter and materialize a subset:

```typescript
const selection = bundle.select({ skills: ["lint-rules"], prompts: ["system"] });
await selection.materialize("./output");
```

Error handling:

```typescript
import { pull, NotFoundError, MusherError } from "@musher-dev/musher-sdk";

try {
await pull("acme/missing:1.0.0");
} catch (err) {
if (err instanceof NotFoundError) console.error(err.problem.detail);
}
```

## Authentication

Set `MUSHER_API_KEY` in your environment, or see the [package docs](./packages/musher/README.md#authentication) for all credential resolution options.

## Platform Adapters

Install bundles directly into your AI toolchain:

- **Claude Code** — `installClaudeSkills()`, `exportClaudePlugin()` ([examples](./examples/claude/))
- **OpenAI Agents** — `exportOpenAILocalSkill()`, `exportOpenAIInlineSkill()` ([examples](./examples/openai/))
- **VS Code** — `installVSCodeSkills()` ([examples](./examples/ide/))

See [`examples/`](./examples/) for 15 runnable examples covering basic operations and platform integrations.

## Development

Expand Down
9 changes: 9 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ tasks:
cmds:
- pnpm -r check:attw

ci:
desc: Run full CI pipeline (check + build + publish validation)
cmds:
- task: check
- task: check:exports
- task: build
- pnpm -r check:publint
- pnpm -r check:attw

clean:
desc: Clean build artifacts
cmds:
Expand Down
31 changes: 14 additions & 17 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"organizeImports": {
"enabled": true
},
"$schema": "https://biomejs.dev/schemas/2.4.10/schema.json",
"assist": { "actions": { "source": { "organizeImports": "on" } } },
"formatter": {
"enabled": true,
"indentStyle": "tab",
Expand All @@ -11,16 +9,23 @@
"linter": {
"enabled": true,
"rules": {
"all": true,
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": "warn",
"useLiteralKeys": "off"
},
"correctness": {
"noNodejsModules": "off",
"noUndeclaredDependencies": "off",
"noUnusedImports": "error",
"noUnusedVariables": "error"
},
"performance": {
"noBarrelFile": "off",
"noNamespaceImport": "off"
},
"style": {
"noDefaultExport": "off",
"noNamespaceImport": "off",
"noNonNullAssertion": "error",
"noParameterProperties": "off",
"useConst": "error",
Expand All @@ -32,27 +37,19 @@
"suspicious": {
"noExplicitAny": "error",
"useAwait": "off"
},
"complexity": {
"noExcessiveCognitiveComplexity": "warn",
"useLiteralKeys": "off"
},
"performance": {
"noBarrelFile": "off"
}
}
},
"files": {
"ignore": ["**/dist/**", "**/node_modules/**", "**/.svelte-kit/**"]
"includes": ["**", "!**/dist", "!**/node_modules", "!**/.svelte-kit"]
},
"overrides": [
{
"include": ["examples/**"],
"includes": ["**/examples/**"],
"linter": {
"rules": {
"suspicious": {
"noConsole": "off",
"noConsoleLog": "off"
"noConsole": "off"
}
}
}
Expand Down
57 changes: 43 additions & 14 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Musher SDK Examples

Runnable TypeScript examples for `@musher-dev/musher-sdk`.
Runnable TypeScript examples for [`@musher-dev/musher-sdk`](../packages/musher/).

Examples are organized into four categories: **basics** (core SDK operations), **claude** (Claude Code integration), **openai** (OpenAI Agents integration), and **ide** (VS Code integration).

## Prerequisites

Expand All @@ -20,19 +22,33 @@ npx tsx examples/basics/pull-bundle.ts

## Examples

| File | Status | Description |
|------|--------|-------------|
| `basics/pull-bundle.ts` | Working | Pull a bundle and access files, prompts, and skills |
| `basics/resolve-bundle.ts` | Working | Resolve metadata without downloading |
| `basics/verify-and-lock-bundle.ts` | Working | Verify SHA-256 integrity and write a lockfile |
| `claude/install-project-skills.ts` | Working | Install skills into `.claude/skills/` |
| `claude/export-plugin.ts` | Working | Export a Claude Code plugin directory |
| `openai/local-shell-skill.ts` | Working | Export a skill as local files for OpenAI Agents |
| `openai/hosted-inline-skill.ts` | Working | Export a skill as an inline base64 ZIP |
| `openai/local-shell-agent.ts` | Working | Full agent with local shell skill via `@openai/agents` |
| `openai/container-inline-agent.ts` | Working | Agent with inline skill in `container_auto` |
| `openai/container-skill-ref.ts` | Working | Upload a skill and use as a `skill_reference` |
| `ide/install-vscode-skills.ts` | Working | Install skills into a VS Code skill tree |
| File | Bundle | Status | Description |
|------|--------|--------|-------------|
| `basics/pull-bundle.ts` | `code-review-kit` | Working | Pull a bundle and access files, prompts, and skills |
| `basics/resolve-bundle.ts` | `code-review-kit` | Working | Resolve metadata without downloading |
| `basics/verify-and-lock-bundle.ts` | `code-review-kit` | Working | Verify SHA-256 integrity and write a lockfile |
| `basics/explore-all-assets.ts` | `agent-toolkit` | Working | Enumerate skills, prompts, toolsets, and agent specs |
| `basics/select-and-materialize.ts` | `agent-toolkit` | Working | Filter a bundle to a subset and write to disk |
| `basics/cache-management.ts` | `code-review-kit` | Working | Inspect, invalidate, and clean the local cache |
| `basics/configure-client.ts` | `prompt-library` | Working | Configure the default client, binary and stream access |
| `claude/install-project-skills.ts` | `code-review-kit` | Working | Install skills into `.claude/skills/` |
| `claude/export-plugin.ts` | `code-review-kit` | Working | Export a Claude Code plugin directory |
| `openai/local-shell-skill.ts` | `code-review-kit` | Working | Export a skill as local files for OpenAI Agents |
| `openai/hosted-inline-skill.ts` | `code-review-kit` | Working | Export a skill as an inline base64 ZIP |
| `openai/local-shell-agent.ts` | `code-review-kit` | Working | Full agent with local shell skill via `@openai/agents` |
| `openai/container-inline-agent.ts` | `code-review-kit` | Working | Agent with inline skill in `container_auto` |
| `openai/container-skill-ref.ts` | `code-review-kit` | Working | Upload a skill and use as a `skill_reference` |
| `ide/install-vscode-skills.ts` | `code-review-kit` | Working | Install skills into a VS Code skill tree |

## Example bundles

These examples use public bundles from the [`musher-examples`](https://hub.musher.dev/) namespace:

| Bundle | Version | Asset Types |
|--------|---------|-------------|
| `musher-examples/code-review-kit` | 1.2.0 | Skills, Prompts |
| `musher-examples/agent-toolkit` | 2.0.0 | Skills, Prompts, Toolsets, Agent Specs, Configs, Rules |
| `musher-examples/prompt-library` | 1.2.0 | Prompts, Toolsets, Agent Specs |

## Runtime packages for integration examples

Expand All @@ -41,3 +57,16 @@ npx tsx examples/basics/pull-bundle.ts
| Claude | `@anthropic-ai/claude-agent-sdk` |
| OpenAI (agents) | `@openai/agents` |
| OpenAI (API client) | `openai` |

## Troubleshooting

| Problem | Fix |
|---------|-----|
| `AuthenticationError` | Set `MUSHER_API_KEY` in your environment or run `musher login` |
| `NotFoundError` | Check the bundle ref — examples use the `musher-examples/` namespace |
| `TimeoutError` or network failures | Check connectivity; override timeout via `new MusherClient({ timeout: 120000 })` |

## See also

- [SDK reference](../packages/musher/README.md) — full API documentation
- [Security policy](../SECURITY.md) — reporting vulnerabilities
53 changes: 53 additions & 0 deletions examples/basics/cache-management.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Inspect and manage the local bundle cache.
*
* After pulling bundles, `client.cache` provides methods to list
* entries, check freshness, view statistics, and clean up stale data.
*
* Prerequisites:
* export MUSHER_API_KEY="mush_..."
*
* Run:
* npx tsx examples/basics/cache-management.ts
*/

import { MusherClient } from "@musher-dev/musher-sdk";

const client = new MusherClient();

// Pull a bundle so there is something in the cache
await client.pull("musher-examples/code-review-kit:1.2.0");
console.log("Pulled code-review-kit into cache.\n");

// Check if a specific bundle is cached
const status = await client.cache.has("musher-examples", "code-review-kit", "1.2.0");
console.log("Cache status for code-review-kit:1.2.0:");
console.log(` cached: ${status.cached}`);
console.log(` fresh: ${status.fresh}`);

// List all cached bundles
const entries = await client.cache.list();
console.log(`\nCached bundles (${entries.length}):`);
for (const entry of entries) {
console.log(
` ${entry.namespace}/${entry.slug}:${entry.version}` +
` fresh=${entry.fresh} size=${entry.sizeBytes} bytes`,
);
}

// Aggregate statistics
const stats = await client.cache.stats();
console.log("\nCache statistics:");
console.log(
` entries: ${stats.entryCount} (${stats.freshCount} fresh, ${stats.staleCount} stale)`,
);
console.log(` blobs: ${stats.blobCount} (${stats.blobSizeBytes} bytes)`);
console.log(` refs: ${stats.refCount}`);

// Mark a bundle as stale (next pull will re-fetch)
const invalidated = await client.cache.invalidate("musher-examples", "code-review-kit", "1.2.0");
console.log(`\nInvalidated ${invalidated} entry (now stale).`);

// Clean up expired entries
await client.cache.clean();
console.log("Cleaned expired entries.");
50 changes: 50 additions & 0 deletions examples/basics/configure-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Configure the module-level client and access binary content.
*
* `configure()` sets options for the default client used by the
* top-level `pull()` and `resolve()` functions. This example also
* demonstrates `FileHandle.bytes()` and `FileHandle.stream()` for
* binary-safe content access.
*
* Prerequisites:
* export MUSHER_API_KEY="mush_..."
*
* Run:
* npx tsx examples/basics/configure-client.ts
*/

import { configure, getClient, pull } from "@musher-dev/musher-sdk";

// Configure the default client with a custom cache directory
configure({ cacheDir: "/tmp/musher-examples-cache" });

// Verify the configured client is returned by getClient()
const client = getClient();
console.log(`Client configured (cache API available: ${typeof client.cache.list === "function"}).`);

// pull() uses the configured client automatically
const bundle = await pull("musher-examples/prompt-library:1.2.0");

// List all prompts in the bundle
console.log(`\nPrompts in ${bundle.ref.toString()}:`);
for (const prompt of bundle.prompts()) {
console.log(` ${prompt.name} (${prompt.file().sizeBytes} bytes)`);
}

// Demonstrate binary access via bytes()
const file = bundle.prompt("system").file();
const bytes = file.bytes();
console.log(`\nBinary access — "system" prompt: ${bytes.byteLength} bytes (Uint8Array)`);

// Demonstrate streaming access via stream()
const stream = file.stream();
const reader = stream.getReader();
let totalStreamBytes = 0;
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
totalStreamBytes += value.byteLength;
}
console.log(`Stream access — "system" prompt: ${totalStreamBytes} bytes read`);
Loading
Loading