npm package: @finalise/prmpt
Description: Type-safe prompt template engine for LLMs — powered by TypeScript and Zod.
Latest version: 0.1.0

# prmpt

> Type-safe prompt template engine for LLMs — powered by TypeScript and Zod.

Define your prompts like you define your schemas. Get autocomplete, compile-time validation, and clean separation between prompts and code.

---

## The Problem

```typescript
// ❌ Prompts scattered as raw strings. No type safety. No validation.
const prompt = `User: ${userName}
Age: ${age}
Consultation: ${consultation}
Please provide a fortune reading.`

// Forgot to pass `age`? No error. Wrong type? No error.
```

## The Solution

```typescript
// ✅ Type-safe, validated, and composable
const fortunePrompt = definePrompt({
  template: `
    User: {{userName}}
    Age: {{age}}
    Consultation: {{consultation}}
    Please provide a fortune reading.
  `,
  variables: {
    userName: z.string(),
    age: z.number().min(0).max(120),
    consultation: z.string().max(500),
  },
})

const prompt = fortunePrompt.build({
  userName: "Tanaka",
  age: 30,
  consultation: "Should I change jobs?",
  // Forgot a variable? TypeScript error at compile time.
})
```

---

## Installation

```bash
npm install prmpt zod
```

`zod` is a peer dependency. Use your own version.

---

## Usage

### `definePrompt`

Define a reusable, type-safe prompt template.

```typescript
import { definePrompt } from "prmpt"
import { z } from "zod"

const reviewPrompt = definePrompt({
  template: `
    Review the following pull request:
    Title: {{title}}
    Description: {{description}}
    Changed files: {{fileCount}}
    
    Provide a concise code review.
  `,
  variables: {
    title: z.string(),
    description: z.string().optional(),
    fileCount: z.number().int().positive(),
  },
})
```

### `.build(variables)`

Compile the template into a prompt string. Validates variables with Zod before building.

```typescript
const prompt = reviewPrompt.build({
  title: "Add user authentication",
  description: "Implements JWT-based auth flow",
  fileCount: 8,
})

// prompt => "Review the following pull request:\nTitle: Add user authentication\n..."
```

Validation errors are thrown at build time:

```typescript
reviewPrompt.build({
  title: "Fix bug",
  fileCount: -1, // throws ZodError: fileCount must be positive
})
```

### `.meta(metadata)`

Attach metadata to a prompt for documentation and traceability.

```typescript
const reviewPrompt = definePrompt({...}).meta({
  name: "pr-review",
  version: "1.0.0",
  description: "Reviews a GitHub pull request",
  author: "shogo",
})
```

### `.extend(overrides)`

Extend an existing prompt template without duplication.

```typescript
const detailedReviewPrompt = reviewPrompt.extend({
  template: `
    {{parent}}
    
    Also check for: security vulnerabilities, performance issues.
  `,
  variables: {
    // Inherits parent variables, add new ones
    securityLevel: z.enum(["low", "medium", "high"]).default("medium"),
  },
})
```

---

## With LLM SDKs

`prmpt` is SDK-agnostic. It outputs a plain `string` — use it with any LLM client.

**OpenAI:**
```typescript
import OpenAI from "openai"

const client = new OpenAI()
const prompt = reviewPrompt.build({ title: "...", fileCount: 3 })

const response = await client.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: prompt }],
})
```

**Anthropic:**
```typescript
import Anthropic from "@anthropic-ai/sdk"

const client = new Anthropic()
const prompt = fortunePrompt.build({ userName: "Tanaka", age: 30, consultation: "..." })

const response = await client.messages.create({
  model: "claude-opus-4-6",
  max_tokens: 1024,
  messages: [{ role: "user", content: prompt }],
})
```

---

## API Reference

### `definePrompt(config)`

| Parameter | Type | Description |
|-----------|------|-------------|
| `template` | `string` | Template string with `{{variableName}}` placeholders |
| `variables` | `ZodRawShape` | Zod schema for each variable |

Returns a `PromptTemplate` instance.

### `PromptTemplate`

| Method | Signature | Description |
|--------|-----------|-------------|
| `build` | `(variables: Inferred) => string` | Build and validate the prompt string |
| `meta` | `(metadata: PromptMeta) => this` | Attach metadata |
| `extend` | `(overrides: Partial<Config>) => PromptTemplate` | Create a derived template |

---

## Design Principles

- **Type-safe first** — Variables are fully typed via Zod inference. No `any`.
- **Validation at build time** — Bad inputs are caught before they reach the LLM.
- **SDK-agnostic** — Returns a plain `string`. Works with OpenAI, Anthropic, Gemini, or any local model.
- **Zero magic** — No global state, no singletons. Just functions and objects.
- **Prompts as code** — Version-controllable, reviewable, testable.

---

## Roadmap

- [x] Core `definePrompt` and `.build()`
- [x] Zod validation
- [x] `.meta()` and `.extend()`
- [ ] Prompt composition (system + user + assistant roles)
- [ ] Streaming helpers
- [ ] CLI: prompt linter / diff tool
- [ ] Prompt testing utilities (snapshot testing for prompts)

---

## Contributing

Issues and PRs are welcome.

```bash
git clone https://github.com/yourusername/prmpt
cd prmpt
npm install
npm test
```

---

## License

MIT