promptopskit 0.1.0 → 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.
Files changed (37) hide show
  1. package/LICENSE +211 -211
  2. package/README.md +382 -382
  3. package/dist/{chunk-FSOJVXC4.js → chunk-5BI5FP5L.js} +2 -2
  4. package/dist/chunk-5BI5FP5L.js.map +1 -0
  5. package/dist/{chunk-HEFOFQ2K.js → chunk-6KGBPHSY.js} +1 -1
  6. package/dist/chunk-6KGBPHSY.js.map +1 -0
  7. package/dist/{chunk-YCRWYE6N.js → chunk-PU3UPUND.js} +2 -2
  8. package/dist/chunk-PU3UPUND.js.map +1 -0
  9. package/dist/{chunk-HMYPMHTG.js → chunk-QDGJFINW.js} +1 -1
  10. package/dist/chunk-QDGJFINW.js.map +1 -0
  11. package/dist/{chunk-V375NQ6C.js → chunk-UYTUGV7Z.js} +2 -2
  12. package/dist/chunk-UYTUGV7Z.js.map +1 -0
  13. package/dist/{chunk-B5UFGNDV.js → chunk-VYVEVJC3.js} +2 -2
  14. package/dist/chunk-VYVEVJC3.js.map +1 -0
  15. package/dist/cli/index.js +0 -0
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.js +6 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/providers/anthropic.cjs.map +1 -1
  21. package/dist/providers/anthropic.js +2 -2
  22. package/dist/providers/gemini.cjs.map +1 -1
  23. package/dist/providers/gemini.js +2 -2
  24. package/dist/providers/openai.cjs.map +1 -1
  25. package/dist/providers/openai.js +2 -2
  26. package/dist/providers/openrouter.cjs.map +1 -1
  27. package/dist/providers/openrouter.js +3 -3
  28. package/dist/testing.cjs.map +1 -1
  29. package/dist/testing.js +1 -1
  30. package/dist/testing.js.map +1 -1
  31. package/package.json +117 -117
  32. package/dist/chunk-B5UFGNDV.js.map +0 -1
  33. package/dist/chunk-FSOJVXC4.js.map +0 -1
  34. package/dist/chunk-HEFOFQ2K.js.map +0 -1
  35. package/dist/chunk-HMYPMHTG.js.map +0 -1
  36. package/dist/chunk-V375NQ6C.js.map +0 -1
  37. package/dist/chunk-YCRWYE6N.js.map +0 -1
package/README.md CHANGED
@@ -1,382 +1,382 @@
1
- # PromptOpsKit
2
-
3
- [![npm version](https://img.shields.io/npm/v/promptopskit.svg)](https://www.npmjs.com/package/promptopskit)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
- [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](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
+ [![npm version](https://img.shields.io/npm/v/promptopskit.svg)](https://www.npmjs.com/package/promptopskit)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](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)