npm package: @openbooklet/sdk
Description: Official OpenBooklet SDK for programmatic skill fetching, search, and publishing
Latest version: 0.2.0

# @openbooklet/sdk

The official OpenBooklet SDK for Node.js and TypeScript. Fetch, search, publish, and manage AI skills, workflows, and memory packs programmatically.

- Zero runtime dependencies (uses native `fetch`)
- Full TypeScript support with detailed type definitions
- Clean error handling with typed error classes
- Requires Node.js 18+

## Installation

```bash
npm install @openbooklet/sdk
```

## Quick Start

```typescript
import { OpenBooklet } from "@openbooklet/sdk";

const ob = new OpenBooklet();

// Fetch a skill
const skill = await ob.getSkill("code-review-pro");
console.log(skill.name, skill.version);

// Pull raw content
const content = await ob.pullSkill("code-review-pro");
console.log(content);
```

## Authentication

An API key is required for publishing, rating, and policy management. Public endpoints (fetching, searching) work without one.

```typescript
const ob = new OpenBooklet({ apiKey: "ob_live_..." });
```

You can also point the SDK at a custom API endpoint:

```typescript
const ob = new OpenBooklet({
  apiKey: "ob_live_...",
  baseUrl: "https://my-instance.example.com/api/v1",
});
```

## API Reference

### Fetching Skills

#### `getSkill(name, options?)`

Fetch a skill by name. Returns the full `Skill` object.

```typescript
const skill = await ob.getSkill("code-review-pro");

// Fetch a specific version
const skill = await ob.getSkill("code-review-pro", { version: "2.1.0" });
```

#### `pullSkill(name, options?)`

Pull the raw content of a skill as a string.

```typescript
const content = await ob.pullSkill("code-review-pro");
```

#### `getSkillInfo(name)`

Get skill metadata without the full content payload.

```typescript
const info = await ob.getSkillInfo("code-review-pro");
console.log(info.publisher.displayName, info.stats.totalPulls);
```

### Searching

#### `searchSkills(query, options?)`

Search for skills by keyword.

```typescript
const results = await ob.searchSkills("code review", {
  category: "code-quality",
  limit: 10,
});

for (const item of results.results) {
  console.log(`${item.name} — ${item.description}`);
}
```

#### `semanticSearch(query, options?)`

Search using natural language with embedding-based similarity.

```typescript
const results = await ob.semanticSearch("help me write better tests", {
  threshold: 0.7,
  limit: 5,
});
```

#### `getTrending(options?)`

Get trending skills.

```typescript
const { trending } = await ob.getTrending({ limit: 10 });

for (const skill of trending) {
  console.log(`${skill.name} — ${skill.weeklyPulls} pulls this week`);
}
```

### Dependency Resolution

#### `resolveDependencies(skills)`

Resolve the dependency tree for a list of skills and get them in installation order.

```typescript
const deps = await ob.resolveDependencies([
  "full-stack-review",
  "security-audit",
]);

console.log("Install order:", deps.installOrder);

for (const [name, data] of Object.entries(deps.skills)) {
  console.log(`${name}@${data.version}`);
}
```

### Publishing

Requires an API key.

#### `publishSkill(input)`

Publish a new skill or update an existing one.

```typescript
const ob = new OpenBooklet({ apiKey: "ob_live_..." });

const result = await ob.publishSkill({
  name: "my-skill",
  displayName: "My Skill",
  description: "Does cool things",
  content: "You are an expert at...",
  category: "general",
  tags: ["productivity", "coding"],
  license: "MIT",
  versionBump: "minor",
  changelog: "Added new capabilities",
});

console.log(`Published ${result.skill.name}@${result.skill.version}`);
```

### Ratings

Requires an API key.

#### `rateSkill(skillName, ratings)`

Rate a skill across multiple dimensions (1-5 scale).

```typescript
const result = await ob.rateSkill("code-review-pro", {
  effectiveness: 5,
  reliability: 4,
  compatibility: 5,
  documentation: 4,
});

console.log(`Overall: ${result.overall} (${result.totalRatings} ratings)`);
```

### Update Policies

Requires an API key. Control how skills are updated in your environment.

#### `setUpdatePolicy(skillName, policy)`

```typescript
// Pin to a specific version
await ob.setUpdatePolicy("code-review-pro", {
  policy: "pinned",
  pinnedVersion: "2.1.0",
});

// Allow patch updates only
await ob.setUpdatePolicy("code-review-pro", {
  policy: "patch",
});
```

#### `getUpdatePolicies()`

```typescript
const policies = await ob.getUpdatePolicies();

for (const p of policies) {
  console.log(`${p.skillName}: ${p.policy}`);
}
```

## Error Handling

The SDK throws typed errors that you can catch and handle individually.

```typescript
import {
  OpenBooklet,
  NotFoundError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  OpenBookletError,
} from "@openbooklet/sdk";

const ob = new OpenBooklet({ apiKey: "ob_live_..." });

try {
  const skill = await ob.getSkill("nonexistent-skill");
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log("Skill not found");
  } else if (error instanceof AuthenticationError) {
    console.log("Invalid or missing API key");
  } else if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
  } else if (error instanceof ValidationError) {
    console.log(`Invalid request: ${error.message}`);
  } else if (error instanceof OpenBookletError) {
    console.log(`API error ${error.status}: ${error.message}`);
  }
}
```

All error classes extend `OpenBookletError`, which includes:

| Property | Type | Description |
|----------|------|-------------|
| `message` | `string` | Human-readable error message |
| `status` | `number` | HTTP status code |
| `code` | `string` | Machine-readable error code |

`RateLimitError` also includes `retryAfter` (seconds to wait).

## TypeScript

All types are exported and available for use:

```typescript
import type { Skill, SearchResult, PublishInput } from "@openbooklet/sdk";
```

## License

MIT