promptopskit 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +211 -211
- package/README.md +382 -382
- package/dist/{chunk-FSOJVXC4.js → chunk-5BI5FP5L.js} +2 -2
- package/dist/chunk-5BI5FP5L.js.map +1 -0
- package/dist/{chunk-HEFOFQ2K.js → chunk-6KGBPHSY.js} +1 -1
- package/dist/chunk-6KGBPHSY.js.map +1 -0
- package/dist/{chunk-YCRWYE6N.js → chunk-PU3UPUND.js} +2 -2
- package/dist/chunk-PU3UPUND.js.map +1 -0
- package/dist/{chunk-HMYPMHTG.js → chunk-QDGJFINW.js} +1 -1
- package/dist/chunk-QDGJFINW.js.map +1 -0
- package/dist/{chunk-V375NQ6C.js → chunk-UYTUGV7Z.js} +2 -2
- package/dist/chunk-UYTUGV7Z.js.map +1 -0
- package/dist/{chunk-B5UFGNDV.js → chunk-VYVEVJC3.js} +2 -2
- package/dist/chunk-VYVEVJC3.js.map +1 -0
- package/dist/cli/index.js +0 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.js +2 -2
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.js +3 -3
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/package.json +117 -117
- package/dist/chunk-B5UFGNDV.js.map +0 -1
- package/dist/chunk-FSOJVXC4.js.map +0 -1
- package/dist/chunk-HEFOFQ2K.js.map +0 -1
- package/dist/chunk-HMYPMHTG.js.map +0 -1
- package/dist/chunk-V375NQ6C.js.map +0 -1
- package/dist/chunk-YCRWYE6N.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,382 +1,382 @@
|
|
|
1
|
-
# PromptOpsKit
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/promptopskit)
|
|
4
|
-
[](LICENSE)
|
|
5
|
-
[](https://nodejs.org)
|
|
6
|
-
|
|
7
|
-
**Centralize prompts, system instructions, tools, and model settings — without leaving your codebase.**
|
|
8
|
-
|
|
9
|
-
Your prompts are already in Git. PromptOpsKit makes them manageable. It replaces hardcoded strings and scattered provider-specific glue with structured Markdown files where prompt text, model settings, sampling parameters, tool bindings, environment overrides, and composable shared instructions all live together — diffable, reviewable, and release-aware.
|
|
10
|
-
|
|
11
|
-
Provider adapters for OpenAI, Anthropic, Gemini, and OpenRouter produce a ready-to-send **request body only** — no HTTP client, no auth, no headers. Your application owns transport, so PromptOpsKit slots into any stack without opinions about how you call the API.
|
|
12
|
-
|
|
13
|
-
### Why PromptOpsKit?
|
|
14
|
-
|
|
15
|
-
- **Centralized, not scattered** — each prompt is a single Markdown file that captures prompt text, model config, tool bindings, and context rules together.
|
|
16
|
-
- **Operational, not just templated** — model name, temperature, reasoning effort, tools, and response format are declared alongside the prompt they govern.
|
|
17
|
-
- **Reusable, not duplicated** — `includes` lets you define shared tone, policy, or safety instructions once and compose them into any prompt.
|
|
18
|
-
- **Layered defaults, not repetition** — `defaults.md` in any folder sets shared `metadata` and `# System instructions` for that subtree, with nearest-folder override behavior.
|
|
19
|
-
- **Release-aware, not ad hoc** — environment and tier overrides swap models and parameters without forking prompt files.
|
|
20
|
-
- **Provider-portable** — write once, render for OpenAI, Anthropic, Gemini, or OpenRouter with correct body shapes.
|
|
21
|
-
- **Validate early** — Zod schema validation, Levenshtein-based "did you mean?" suggestions for typos, and variable usage checks catch mistakes before runtime.
|
|
22
|
-
- **Compile for production** — pre-compile `.md` to JSON or ESM so deployments skip parsing entirely.
|
|
23
|
-
- **Repo-native, not dashboard-native** — no hosted service, no external admin tool. Everything lives in source control.
|
|
24
|
-
|
|
25
|
-
## Install
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
npm install promptopskit
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Quick Start
|
|
32
|
-
|
|
33
|
-
### 1. Scaffold starter prompts
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npx promptopskit init ./prompts
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
This creates:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
prompts/
|
|
43
|
-
├── hello.md # Sample prompt with variables
|
|
44
|
-
├── hello.test.yaml # Test sidecar with sample inputs
|
|
45
|
-
└── shared/
|
|
46
|
-
└── tone.md # Shared system instructions (included via composition)
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 2. Write a prompt
|
|
50
|
-
|
|
51
|
-
```markdown
|
|
52
|
-
---
|
|
53
|
-
id: support.reply
|
|
54
|
-
schema_version: 1
|
|
55
|
-
provider: openai
|
|
56
|
-
model: gpt-5.4
|
|
57
|
-
reasoning:
|
|
58
|
-
effort: medium
|
|
59
|
-
sampling:
|
|
60
|
-
temperature: 0.7
|
|
61
|
-
context:
|
|
62
|
-
inputs:
|
|
63
|
-
- user_message
|
|
64
|
-
- app_context
|
|
65
|
-
includes:
|
|
66
|
-
- ./shared/tone.md
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
# System instructions
|
|
70
|
-
|
|
71
|
-
You are a helpful support assistant working in {{ app_context }}.
|
|
72
|
-
|
|
73
|
-
# Prompt template
|
|
74
|
-
|
|
75
|
-
{{ user_message }}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### 3. Render for a provider
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
import { createPromptOpsKit } from 'promptopskit';
|
|
82
|
-
|
|
83
|
-
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
84
|
-
|
|
85
|
-
const result = await kit.renderPrompt({
|
|
86
|
-
path: 'support/reply',
|
|
87
|
-
provider: 'openai',
|
|
88
|
-
variables: {
|
|
89
|
-
user_message: 'How do I reset my password?',
|
|
90
|
-
app_context: 'Account settings page',
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// result.request.body is ready for fetch()
|
|
95
|
-
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
96
|
-
method: 'POST',
|
|
97
|
-
headers: {
|
|
98
|
-
'Content-Type': 'application/json',
|
|
99
|
-
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
|
|
100
|
-
},
|
|
101
|
-
body: JSON.stringify(result.request.body),
|
|
102
|
-
});
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Features
|
|
106
|
-
|
|
107
|
-
- **Prompts as Markdown** — YAML front matter for settings, H1 headings for sections (`# System instructions`, `# Prompt template`, `# Notes`)
|
|
108
|
-
- **Variable interpolation** — `{{ variable }}` syntax with strict and permissive modes
|
|
109
|
-
- **Composition** — `includes` to share system instructions across prompts, with circular detection
|
|
110
|
-
- **Folder defaults** — `defaults.md` inheritance for shared metadata and system instructions
|
|
111
|
-
- **Overrides** — Environment and tier-based overrides (base → env → tier → runtime)
|
|
112
|
-
- **4 provider adapters** — OpenAI, Anthropic, Gemini, OpenRouter — body-only output
|
|
113
|
-
- **Validation** — Zod schema validation, Levenshtein-based "did you mean?" for typos, variable usage checks
|
|
114
|
-
- **Caching** — LRU cache with mtime-based invalidation
|
|
115
|
-
- **CLI** — init, validate, compile, render, inspect, skill
|
|
116
|
-
- **Compiled artifacts** — Pre-compile `.md` → JSON or ESM for production
|
|
117
|
-
|
|
118
|
-
## Provider Adapters
|
|
119
|
-
|
|
120
|
-
Each adapter produces a `{ body, provider, model }` object shaped for the target API. You handle the HTTP call.
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// OpenAI
|
|
124
|
-
import { createPromptOpsKit } from 'promptopskit';
|
|
125
|
-
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
126
|
-
const { request } = await kit.renderPrompt({
|
|
127
|
-
path: 'hello',
|
|
128
|
-
provider: 'openai',
|
|
129
|
-
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
130
|
-
});
|
|
131
|
-
// request.body → { model, messages, temperature, reasoning_effort, ... }
|
|
132
|
-
|
|
133
|
-
// Anthropic — system is a top-level field, max_tokens defaults to 4096
|
|
134
|
-
const { request } = await kit.renderPrompt({
|
|
135
|
-
path: 'hello',
|
|
136
|
-
provider: 'anthropic',
|
|
137
|
-
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
138
|
-
});
|
|
139
|
-
// request.body → { model, messages, system, max_tokens, ... }
|
|
140
|
-
|
|
141
|
-
// Gemini — contents/systemInstruction/generationConfig structure
|
|
142
|
-
const { request } = await kit.renderPrompt({
|
|
143
|
-
path: 'hello',
|
|
144
|
-
provider: 'gemini',
|
|
145
|
-
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
146
|
-
});
|
|
147
|
-
// request.body → { contents, systemInstruction, generationConfig, ... }
|
|
148
|
-
|
|
149
|
-
// OpenRouter — same shape as OpenAI, different provider label
|
|
150
|
-
const { request } = await kit.renderPrompt({
|
|
151
|
-
path: 'hello',
|
|
152
|
-
provider: 'openrouter',
|
|
153
|
-
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
154
|
-
});
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Provider adapters are also available as direct imports:
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
import { openaiAdapter } from 'promptopskit/openai';
|
|
161
|
-
import { anthropicAdapter } from 'promptopskit/anthropic';
|
|
162
|
-
import { geminiAdapter } from 'promptopskit/gemini';
|
|
163
|
-
import { openrouterAdapter } from 'promptopskit/openrouter';
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Overrides
|
|
167
|
-
|
|
168
|
-
Define environment and tier overrides in front matter. Precedence: **base → environment → tier → runtime**. Scalars and arrays are replaced, not merged.
|
|
169
|
-
|
|
170
|
-
```markdown
|
|
171
|
-
---
|
|
172
|
-
id: support.reply
|
|
173
|
-
schema_version: 1
|
|
174
|
-
provider: openai
|
|
175
|
-
model: gpt-5.4
|
|
176
|
-
sampling:
|
|
177
|
-
temperature: 0.7
|
|
178
|
-
environments:
|
|
179
|
-
dev:
|
|
180
|
-
model: gpt-5.4-mini
|
|
181
|
-
sampling:
|
|
182
|
-
temperature: 0.2
|
|
183
|
-
prod:
|
|
184
|
-
model: gpt-5.4
|
|
185
|
-
tiers:
|
|
186
|
-
free:
|
|
187
|
-
model: gpt-5.4-mini
|
|
188
|
-
pro:
|
|
189
|
-
model: gpt-5.4
|
|
190
|
-
---
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
const result = await kit.renderPrompt({
|
|
195
|
-
path: 'support/reply',
|
|
196
|
-
provider: 'openai',
|
|
197
|
-
environment: 'dev',
|
|
198
|
-
tier: 'pro',
|
|
199
|
-
variables: { user_message: '...' },
|
|
200
|
-
});
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## Composition
|
|
204
|
-
|
|
205
|
-
Share system instructions across prompts using `includes`. Included system instructions are prepended before local ones.
|
|
206
|
-
|
|
207
|
-
```markdown
|
|
208
|
-
---
|
|
209
|
-
id: support.reply
|
|
210
|
-
schema_version: 1
|
|
211
|
-
includes:
|
|
212
|
-
- ./shared/tone.md
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
# System instructions
|
|
216
|
-
|
|
217
|
-
Handle support requests carefully.
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## Folder defaults
|
|
221
|
-
|
|
222
|
-
Define a `defaults.md` file in `prompts/` (and optional subfolders) to provide inherited defaults for prompts:
|
|
223
|
-
|
|
224
|
-
- Shared `metadata` defaults in front matter
|
|
225
|
-
- Shared `# System instructions` in body
|
|
226
|
-
- Nearest subfolder `defaults.md` overrides parent defaults
|
|
227
|
-
- Prompt-local values always win over defaults
|
|
228
|
-
- Included files (`includes`) are not affected by folder defaults
|
|
229
|
-
|
|
230
|
-
> `promptopskit init` scaffolds a starter `defaults.md` in the prompts root.
|
|
231
|
-
|
|
232
|
-
```text
|
|
233
|
-
prompts/
|
|
234
|
-
├── defaults.md
|
|
235
|
-
└── support/
|
|
236
|
-
├── defaults.md
|
|
237
|
-
└── reply.md
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## CLI
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
# Scaffold starter prompts
|
|
244
|
-
promptopskit init [dir]
|
|
245
|
-
|
|
246
|
-
# Validate all .md files in a directory
|
|
247
|
-
promptopskit validate <dir> [--strict]
|
|
248
|
-
|
|
249
|
-
# Compile .md → JSON/ESM artifacts
|
|
250
|
-
promptopskit compile <src> <out> [--dry-run] [--format json|esm] [--no-clean]
|
|
251
|
-
|
|
252
|
-
# Render a prompt preview (auto-loads .test.yaml sidecar)
|
|
253
|
-
promptopskit render <file> [--env <name>] [--tier <name>] [--vars <file>] [--json]
|
|
254
|
-
|
|
255
|
-
# Print normalized asset as JSON
|
|
256
|
-
promptopskit inspect <file>
|
|
257
|
-
|
|
258
|
-
# Deploy AI agent instructions into your project
|
|
259
|
-
promptopskit skill [--target copilot|cursor|generic] [--force]
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
## AI Agent Instructions
|
|
263
|
-
|
|
264
|
-
The `skill` command deploys a comprehensive instructions file so AI coding assistants (GitHub Copilot, Cursor, etc.) automatically understand how to create and manage prompts with promptopskit.
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
# Deploy for GitHub Copilot (default)
|
|
268
|
-
promptopskit skill
|
|
269
|
-
# → .github/instructions/promptopskit.instructions.md
|
|
270
|
-
|
|
271
|
-
# Deploy for Cursor
|
|
272
|
-
promptopskit skill --target cursor
|
|
273
|
-
# → .cursor/rules/promptopskit.mdc
|
|
274
|
-
|
|
275
|
-
# Deploy a generic instructions file
|
|
276
|
-
promptopskit skill --target generic
|
|
277
|
-
# → .ai/promptopskit-skill.md
|
|
278
|
-
|
|
279
|
-
# Overwrite an existing instructions file
|
|
280
|
-
promptopskit skill --force
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
The deployed file covers the prompt format, front matter schema, variable interpolation, includes, overrides, the TypeScript API, provider adapters, and project conventions — everything an AI agent needs to write correct prompts on the first try.
|
|
284
|
-
|
|
285
|
-
## Inline Source
|
|
286
|
-
|
|
287
|
-
Render prompts from strings without files:
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
const result = await kit.renderPrompt({
|
|
291
|
-
source: `---
|
|
292
|
-
id: inline
|
|
293
|
-
schema_version: 1
|
|
294
|
-
provider: openai
|
|
295
|
-
model: gpt-5.4
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
# Prompt template
|
|
299
|
-
|
|
300
|
-
Hello {{ name }}!`,
|
|
301
|
-
provider: 'openai',
|
|
302
|
-
variables: { name: 'World' },
|
|
303
|
-
});
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
## Testing Helpers
|
|
307
|
-
|
|
308
|
-
```typescript
|
|
309
|
-
import { createMockAsset, createMockResolvedAsset, parseTestPrompt } from 'promptopskit/testing';
|
|
310
|
-
|
|
311
|
-
const asset = createMockAsset({ model: 'gpt-5.4' });
|
|
312
|
-
const resolved = createMockResolvedAsset();
|
|
313
|
-
const parsed = parseTestPrompt('---\nid: test\nschema_version: 1\n---\n\nHello');
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
## API Reference
|
|
317
|
-
|
|
318
|
-
### `createPromptOpsKit(config)`
|
|
319
|
-
|
|
320
|
-
Creates a `PromptOpsKit` instance.
|
|
321
|
-
|
|
322
|
-
| Option | Type | Default | Description |
|
|
323
|
-
|--------|------|---------|-------------|
|
|
324
|
-
| `sourceDir` | `string` | — | Path to prompt `.md` files (required) |
|
|
325
|
-
| `compiledDir` | `string` | — | Path to compiled artifacts |
|
|
326
|
-
| `mode` | `'auto' \| 'compiled-only' \| 'source-only'` | `'auto'` | Resolution strategy |
|
|
327
|
-
| `cache` | `boolean` | `true` | Enable LRU cache with mtime invalidation |
|
|
328
|
-
|
|
329
|
-
### `kit.renderPrompt(options)`
|
|
330
|
-
|
|
331
|
-
Renders a prompt for a specific provider. Returns `{ resolved, request, warnings }`.
|
|
332
|
-
|
|
333
|
-
| Option | Type | Description |
|
|
334
|
-
|--------|------|-------------|
|
|
335
|
-
| `path` | `string` | Prompt path (no extension), e.g. `'support/reply'` |
|
|
336
|
-
| `source` | `string` | Inline prompt source (alternative to path) |
|
|
337
|
-
| `provider` | `string` | `'openai'`, `'anthropic'`, `'gemini'`, `'openrouter'` |
|
|
338
|
-
| `variables` | `Record<string, string>` | Template variables |
|
|
339
|
-
| `environment` | `string` | Environment override name |
|
|
340
|
-
| `tier` | `string` | Tier override name |
|
|
341
|
-
| `history` | `Array<{ role, content }>` | Conversation history |
|
|
342
|
-
| `strict` | `boolean` | Fail on missing variables |
|
|
343
|
-
|
|
344
|
-
### `kit.loadPrompt(path)` / `kit.resolvePrompt(path, options)` / `kit.validatePrompt(path)`
|
|
345
|
-
|
|
346
|
-
Lower-level methods for loading, resolving (includes + overrides), and validating individual prompts.
|
|
347
|
-
|
|
348
|
-
### Standalone Functions
|
|
349
|
-
|
|
350
|
-
```typescript
|
|
351
|
-
import { parsePrompt, interpolate, extractVariables, resolveIncludes, applyOverrides, validateAsset, getAdapter } from 'promptopskit';
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
## Schema
|
|
355
|
-
|
|
356
|
-
Prompt files use YAML front matter with these fields:
|
|
357
|
-
|
|
358
|
-
| Field | Type | Description |
|
|
359
|
-
|-------|------|-------------|
|
|
360
|
-
| `id` | `string` | Unique prompt identifier (required) |
|
|
361
|
-
| `schema_version` | `number` | Schema version, currently `1` |
|
|
362
|
-
| `provider` | `string` | `openai`, `anthropic`, `gemini` (or `google`), `openrouter`, `any` |
|
|
363
|
-
| `model` | `string` | Model name |
|
|
364
|
-
| `fallback_models` | `string[]` | Fallback model list |
|
|
365
|
-
| `reasoning` | `object` | `{ effort, budget_tokens }` |
|
|
366
|
-
| `sampling` | `object` | `{ temperature, top_p, frequency_penalty, presence_penalty, stop, max_output_tokens }` |
|
|
367
|
-
| `response` | `object` | `{ format, stream }` |
|
|
368
|
-
| `tools` | `array` | Tool references (string names or inline definitions) |
|
|
369
|
-
| `mcp` | `object` | MCP server references |
|
|
370
|
-
| `context` | `object` | `{ inputs, history }` — declare expected variables |
|
|
371
|
-
| `includes` | `string[]` | Paths to included prompt files |
|
|
372
|
-
| `environments` | `object` | Named environment overrides |
|
|
373
|
-
| `tiers` | `object` | Named tier overrides |
|
|
374
|
-
| `metadata` | `object` | `{ owner, tags, review_required, stable }` |
|
|
375
|
-
|
|
376
|
-
## Website
|
|
377
|
-
|
|
378
|
-
The `website/` directory contains a standalone marketing website for PromptOpsKit.
|
|
379
|
-
|
|
380
|
-
## License
|
|
381
|
-
|
|
382
|
-
[MIT](LICENSE)
|
|
1
|
+
# PromptOpsKit
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/promptopskit)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
**Centralize prompts, system instructions, tools, and model settings — without leaving your codebase.**
|
|
8
|
+
|
|
9
|
+
Your prompts are already in Git. PromptOpsKit makes them manageable. It replaces hardcoded strings and scattered provider-specific glue with structured Markdown files where prompt text, model settings, sampling parameters, tool bindings, environment overrides, and composable shared instructions all live together — diffable, reviewable, and release-aware.
|
|
10
|
+
|
|
11
|
+
Provider adapters for OpenAI, Anthropic, Gemini, and OpenRouter produce a ready-to-send **request body only** — no HTTP client, no auth, no headers. Your application owns transport, so PromptOpsKit slots into any stack without opinions about how you call the API.
|
|
12
|
+
|
|
13
|
+
### Why PromptOpsKit?
|
|
14
|
+
|
|
15
|
+
- **Centralized, not scattered** — each prompt is a single Markdown file that captures prompt text, model config, tool bindings, and context rules together.
|
|
16
|
+
- **Operational, not just templated** — model name, temperature, reasoning effort, tools, and response format are declared alongside the prompt they govern.
|
|
17
|
+
- **Reusable, not duplicated** — `includes` lets you define shared tone, policy, or safety instructions once and compose them into any prompt.
|
|
18
|
+
- **Layered defaults, not repetition** — `defaults.md` in any folder sets shared `metadata` and `# System instructions` for that subtree, with nearest-folder override behavior.
|
|
19
|
+
- **Release-aware, not ad hoc** — environment and tier overrides swap models and parameters without forking prompt files.
|
|
20
|
+
- **Provider-portable** — write once, render for OpenAI, Anthropic, Gemini, or OpenRouter with correct body shapes.
|
|
21
|
+
- **Validate early** — Zod schema validation, Levenshtein-based "did you mean?" suggestions for typos, and variable usage checks catch mistakes before runtime.
|
|
22
|
+
- **Compile for production** — pre-compile `.md` to JSON or ESM so deployments skip parsing entirely.
|
|
23
|
+
- **Repo-native, not dashboard-native** — no hosted service, no external admin tool. Everything lives in source control.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install promptopskit
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### 1. Scaffold starter prompts
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx promptopskit init ./prompts
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This creates:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
prompts/
|
|
43
|
+
├── hello.md # Sample prompt with variables
|
|
44
|
+
├── hello.test.yaml # Test sidecar with sample inputs
|
|
45
|
+
└── shared/
|
|
46
|
+
└── tone.md # Shared system instructions (included via composition)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Write a prompt
|
|
50
|
+
|
|
51
|
+
```markdown
|
|
52
|
+
---
|
|
53
|
+
id: support.reply
|
|
54
|
+
schema_version: 1
|
|
55
|
+
provider: openai
|
|
56
|
+
model: gpt-5.4
|
|
57
|
+
reasoning:
|
|
58
|
+
effort: medium
|
|
59
|
+
sampling:
|
|
60
|
+
temperature: 0.7
|
|
61
|
+
context:
|
|
62
|
+
inputs:
|
|
63
|
+
- user_message
|
|
64
|
+
- app_context
|
|
65
|
+
includes:
|
|
66
|
+
- ./shared/tone.md
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
# System instructions
|
|
70
|
+
|
|
71
|
+
You are a helpful support assistant working in {{ app_context }}.
|
|
72
|
+
|
|
73
|
+
# Prompt template
|
|
74
|
+
|
|
75
|
+
{{ user_message }}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. Render for a provider
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { createPromptOpsKit } from 'promptopskit';
|
|
82
|
+
|
|
83
|
+
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
84
|
+
|
|
85
|
+
const result = await kit.renderPrompt({
|
|
86
|
+
path: 'support/reply',
|
|
87
|
+
provider: 'openai',
|
|
88
|
+
variables: {
|
|
89
|
+
user_message: 'How do I reset my password?',
|
|
90
|
+
app_context: 'Account settings page',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// result.request.body is ready for fetch()
|
|
95
|
+
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: {
|
|
98
|
+
'Content-Type': 'application/json',
|
|
99
|
+
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
|
|
100
|
+
},
|
|
101
|
+
body: JSON.stringify(result.request.body),
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Features
|
|
106
|
+
|
|
107
|
+
- **Prompts as Markdown** — YAML front matter for settings, H1 headings for sections (`# System instructions`, `# Prompt template`, `# Notes`)
|
|
108
|
+
- **Variable interpolation** — `{{ variable }}` syntax with strict and permissive modes
|
|
109
|
+
- **Composition** — `includes` to share system instructions across prompts, with circular detection
|
|
110
|
+
- **Folder defaults** — `defaults.md` inheritance for shared metadata and system instructions
|
|
111
|
+
- **Overrides** — Environment and tier-based overrides (base → env → tier → runtime)
|
|
112
|
+
- **4 provider adapters** — OpenAI, Anthropic, Gemini, OpenRouter — body-only output
|
|
113
|
+
- **Validation** — Zod schema validation, Levenshtein-based "did you mean?" for typos, variable usage checks
|
|
114
|
+
- **Caching** — LRU cache with mtime-based invalidation
|
|
115
|
+
- **CLI** — init, validate, compile, render, inspect, skill
|
|
116
|
+
- **Compiled artifacts** — Pre-compile `.md` → JSON or ESM for production
|
|
117
|
+
|
|
118
|
+
## Provider Adapters
|
|
119
|
+
|
|
120
|
+
Each adapter produces a `{ body, provider, model }` object shaped for the target API. You handle the HTTP call.
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// OpenAI
|
|
124
|
+
import { createPromptOpsKit } from 'promptopskit';
|
|
125
|
+
const kit = createPromptOpsKit({ sourceDir: './prompts' });
|
|
126
|
+
const { request } = await kit.renderPrompt({
|
|
127
|
+
path: 'hello',
|
|
128
|
+
provider: 'openai',
|
|
129
|
+
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
130
|
+
});
|
|
131
|
+
// request.body → { model, messages, temperature, reasoning_effort, ... }
|
|
132
|
+
|
|
133
|
+
// Anthropic — system is a top-level field, max_tokens defaults to 4096
|
|
134
|
+
const { request } = await kit.renderPrompt({
|
|
135
|
+
path: 'hello',
|
|
136
|
+
provider: 'anthropic',
|
|
137
|
+
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
138
|
+
});
|
|
139
|
+
// request.body → { model, messages, system, max_tokens, ... }
|
|
140
|
+
|
|
141
|
+
// Gemini — contents/systemInstruction/generationConfig structure
|
|
142
|
+
const { request } = await kit.renderPrompt({
|
|
143
|
+
path: 'hello',
|
|
144
|
+
provider: 'gemini',
|
|
145
|
+
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
146
|
+
});
|
|
147
|
+
// request.body → { contents, systemInstruction, generationConfig, ... }
|
|
148
|
+
|
|
149
|
+
// OpenRouter — same shape as OpenAI, different provider label
|
|
150
|
+
const { request } = await kit.renderPrompt({
|
|
151
|
+
path: 'hello',
|
|
152
|
+
provider: 'openrouter',
|
|
153
|
+
variables: { name: 'World', app_context: 'Welcome screen' },
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Provider adapters are also available as direct imports:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { openaiAdapter } from 'promptopskit/openai';
|
|
161
|
+
import { anthropicAdapter } from 'promptopskit/anthropic';
|
|
162
|
+
import { geminiAdapter } from 'promptopskit/gemini';
|
|
163
|
+
import { openrouterAdapter } from 'promptopskit/openrouter';
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Overrides
|
|
167
|
+
|
|
168
|
+
Define environment and tier overrides in front matter. Precedence: **base → environment → tier → runtime**. Scalars and arrays are replaced, not merged.
|
|
169
|
+
|
|
170
|
+
```markdown
|
|
171
|
+
---
|
|
172
|
+
id: support.reply
|
|
173
|
+
schema_version: 1
|
|
174
|
+
provider: openai
|
|
175
|
+
model: gpt-5.4
|
|
176
|
+
sampling:
|
|
177
|
+
temperature: 0.7
|
|
178
|
+
environments:
|
|
179
|
+
dev:
|
|
180
|
+
model: gpt-5.4-mini
|
|
181
|
+
sampling:
|
|
182
|
+
temperature: 0.2
|
|
183
|
+
prod:
|
|
184
|
+
model: gpt-5.4
|
|
185
|
+
tiers:
|
|
186
|
+
free:
|
|
187
|
+
model: gpt-5.4-mini
|
|
188
|
+
pro:
|
|
189
|
+
model: gpt-5.4
|
|
190
|
+
---
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
const result = await kit.renderPrompt({
|
|
195
|
+
path: 'support/reply',
|
|
196
|
+
provider: 'openai',
|
|
197
|
+
environment: 'dev',
|
|
198
|
+
tier: 'pro',
|
|
199
|
+
variables: { user_message: '...' },
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Composition
|
|
204
|
+
|
|
205
|
+
Share system instructions across prompts using `includes`. Included system instructions are prepended before local ones.
|
|
206
|
+
|
|
207
|
+
```markdown
|
|
208
|
+
---
|
|
209
|
+
id: support.reply
|
|
210
|
+
schema_version: 1
|
|
211
|
+
includes:
|
|
212
|
+
- ./shared/tone.md
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
# System instructions
|
|
216
|
+
|
|
217
|
+
Handle support requests carefully.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Folder defaults
|
|
221
|
+
|
|
222
|
+
Define a `defaults.md` file in `prompts/` (and optional subfolders) to provide inherited defaults for prompts:
|
|
223
|
+
|
|
224
|
+
- Shared `metadata` defaults in front matter
|
|
225
|
+
- Shared `# System instructions` in body
|
|
226
|
+
- Nearest subfolder `defaults.md` overrides parent defaults
|
|
227
|
+
- Prompt-local values always win over defaults
|
|
228
|
+
- Included files (`includes`) are not affected by folder defaults
|
|
229
|
+
|
|
230
|
+
> `promptopskit init` scaffolds a starter `defaults.md` in the prompts root.
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
prompts/
|
|
234
|
+
├── defaults.md
|
|
235
|
+
└── support/
|
|
236
|
+
├── defaults.md
|
|
237
|
+
└── reply.md
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## CLI
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Scaffold starter prompts
|
|
244
|
+
promptopskit init [dir]
|
|
245
|
+
|
|
246
|
+
# Validate all .md files in a directory
|
|
247
|
+
promptopskit validate <dir> [--strict]
|
|
248
|
+
|
|
249
|
+
# Compile .md → JSON/ESM artifacts
|
|
250
|
+
promptopskit compile <src> <out> [--dry-run] [--format json|esm] [--no-clean]
|
|
251
|
+
|
|
252
|
+
# Render a prompt preview (auto-loads .test.yaml sidecar)
|
|
253
|
+
promptopskit render <file> [--env <name>] [--tier <name>] [--vars <file>] [--json]
|
|
254
|
+
|
|
255
|
+
# Print normalized asset as JSON
|
|
256
|
+
promptopskit inspect <file>
|
|
257
|
+
|
|
258
|
+
# Deploy AI agent instructions into your project
|
|
259
|
+
promptopskit skill [--target copilot|cursor|generic] [--force]
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## AI Agent Instructions
|
|
263
|
+
|
|
264
|
+
The `skill` command deploys a comprehensive instructions file so AI coding assistants (GitHub Copilot, Cursor, etc.) automatically understand how to create and manage prompts with promptopskit.
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# Deploy for GitHub Copilot (default)
|
|
268
|
+
promptopskit skill
|
|
269
|
+
# → .github/instructions/promptopskit.instructions.md
|
|
270
|
+
|
|
271
|
+
# Deploy for Cursor
|
|
272
|
+
promptopskit skill --target cursor
|
|
273
|
+
# → .cursor/rules/promptopskit.mdc
|
|
274
|
+
|
|
275
|
+
# Deploy a generic instructions file
|
|
276
|
+
promptopskit skill --target generic
|
|
277
|
+
# → .ai/promptopskit-skill.md
|
|
278
|
+
|
|
279
|
+
# Overwrite an existing instructions file
|
|
280
|
+
promptopskit skill --force
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The deployed file covers the prompt format, front matter schema, variable interpolation, includes, overrides, the TypeScript API, provider adapters, and project conventions — everything an AI agent needs to write correct prompts on the first try.
|
|
284
|
+
|
|
285
|
+
## Inline Source
|
|
286
|
+
|
|
287
|
+
Render prompts from strings without files:
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
const result = await kit.renderPrompt({
|
|
291
|
+
source: `---
|
|
292
|
+
id: inline
|
|
293
|
+
schema_version: 1
|
|
294
|
+
provider: openai
|
|
295
|
+
model: gpt-5.4
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
# Prompt template
|
|
299
|
+
|
|
300
|
+
Hello {{ name }}!`,
|
|
301
|
+
provider: 'openai',
|
|
302
|
+
variables: { name: 'World' },
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Testing Helpers
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
import { createMockAsset, createMockResolvedAsset, parseTestPrompt } from 'promptopskit/testing';
|
|
310
|
+
|
|
311
|
+
const asset = createMockAsset({ model: 'gpt-5.4' });
|
|
312
|
+
const resolved = createMockResolvedAsset();
|
|
313
|
+
const parsed = parseTestPrompt('---\nid: test\nschema_version: 1\n---\n\nHello');
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## API Reference
|
|
317
|
+
|
|
318
|
+
### `createPromptOpsKit(config)`
|
|
319
|
+
|
|
320
|
+
Creates a `PromptOpsKit` instance.
|
|
321
|
+
|
|
322
|
+
| Option | Type | Default | Description |
|
|
323
|
+
|--------|------|---------|-------------|
|
|
324
|
+
| `sourceDir` | `string` | — | Path to prompt `.md` files (required) |
|
|
325
|
+
| `compiledDir` | `string` | — | Path to compiled artifacts |
|
|
326
|
+
| `mode` | `'auto' \| 'compiled-only' \| 'source-only'` | `'auto'` | Resolution strategy |
|
|
327
|
+
| `cache` | `boolean` | `true` | Enable LRU cache with mtime invalidation |
|
|
328
|
+
|
|
329
|
+
### `kit.renderPrompt(options)`
|
|
330
|
+
|
|
331
|
+
Renders a prompt for a specific provider. Returns `{ resolved, request, warnings }`.
|
|
332
|
+
|
|
333
|
+
| Option | Type | Description |
|
|
334
|
+
|--------|------|-------------|
|
|
335
|
+
| `path` | `string` | Prompt path (no extension), e.g. `'support/reply'` |
|
|
336
|
+
| `source` | `string` | Inline prompt source (alternative to path) |
|
|
337
|
+
| `provider` | `string` | `'openai'`, `'anthropic'`, `'gemini'`, `'openrouter'` |
|
|
338
|
+
| `variables` | `Record<string, string>` | Template variables |
|
|
339
|
+
| `environment` | `string` | Environment override name |
|
|
340
|
+
| `tier` | `string` | Tier override name |
|
|
341
|
+
| `history` | `Array<{ role, content }>` | Conversation history |
|
|
342
|
+
| `strict` | `boolean` | Fail on missing variables |
|
|
343
|
+
|
|
344
|
+
### `kit.loadPrompt(path)` / `kit.resolvePrompt(path, options)` / `kit.validatePrompt(path)`
|
|
345
|
+
|
|
346
|
+
Lower-level methods for loading, resolving (includes + overrides), and validating individual prompts.
|
|
347
|
+
|
|
348
|
+
### Standalone Functions
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { parsePrompt, interpolate, extractVariables, resolveIncludes, applyOverrides, validateAsset, getAdapter } from 'promptopskit';
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Schema
|
|
355
|
+
|
|
356
|
+
Prompt files use YAML front matter with these fields:
|
|
357
|
+
|
|
358
|
+
| Field | Type | Description |
|
|
359
|
+
|-------|------|-------------|
|
|
360
|
+
| `id` | `string` | Unique prompt identifier (required) |
|
|
361
|
+
| `schema_version` | `number` | Schema version, currently `1` |
|
|
362
|
+
| `provider` | `string` | `openai`, `anthropic`, `gemini` (or `google`), `openrouter`, `any` |
|
|
363
|
+
| `model` | `string` | Model name |
|
|
364
|
+
| `fallback_models` | `string[]` | Fallback model list |
|
|
365
|
+
| `reasoning` | `object` | `{ effort, budget_tokens }` |
|
|
366
|
+
| `sampling` | `object` | `{ temperature, top_p, frequency_penalty, presence_penalty, stop, max_output_tokens }` |
|
|
367
|
+
| `response` | `object` | `{ format, stream }` |
|
|
368
|
+
| `tools` | `array` | Tool references (string names or inline definitions) |
|
|
369
|
+
| `mcp` | `object` | MCP server references |
|
|
370
|
+
| `context` | `object` | `{ inputs, history }` — declare expected variables |
|
|
371
|
+
| `includes` | `string[]` | Paths to included prompt files |
|
|
372
|
+
| `environments` | `object` | Named environment overrides |
|
|
373
|
+
| `tiers` | `object` | Named tier overrides |
|
|
374
|
+
| `metadata` | `object` | `{ owner, tags, review_required, stable }` |
|
|
375
|
+
|
|
376
|
+
## Website
|
|
377
|
+
|
|
378
|
+
The `website/` directory contains a standalone marketing website for PromptOpsKit.
|
|
379
|
+
|
|
380
|
+
## License
|
|
381
|
+
|
|
382
|
+
[MIT](LICENSE)
|