promptopskit 0.2.3 → 0.2.5

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/README.md CHANGED
@@ -34,6 +34,7 @@ npm install promptopskit
34
34
 
35
35
  ```bash
36
36
  npx promptopskit init ./prompts
37
+ npx promptopskit skill
37
38
  ```
38
39
 
39
40
  This creates:
@@ -246,8 +247,9 @@ prompts/
246
247
  ## CLI
247
248
 
248
249
  ```bash
249
- # Scaffold starter prompts
250
+ # Scaffold starter prompts and deploy AI agent instructions
250
251
  promptopskit init [dir]
252
+ promptopskit skill
251
253
 
252
254
  # Validate all .md files in a directory
253
255
  promptopskit validate <dir> [--strict]
@@ -267,7 +269,7 @@ promptopskit skill [--target agents|claude|copilot|cursor] [--force]
267
269
 
268
270
  ## AI Agent Instructions
269
271
 
270
- The `skill` command deploys instruction files so AI coding assistants automatically understand how to create and manage prompts with promptopskit. By default it generates files for **all** major vendors:
272
+ The `skill` command deploys instruction files so AI coding assistants automatically understand how to create and manage prompts with promptopskit. Each file references the full guide at `node_modules/promptopskit/SKILL.md`, so instructions stay in sync with the installed version. By default it generates files for **all** major vendors:
271
273
 
272
274
  ```bash
273
275
  # Deploy for all AI coding assistants (default)
@@ -280,11 +282,13 @@ promptopskit skill
280
282
  # Deploy only a specific target
281
283
  promptopskit skill --target copilot
282
284
 
283
- # Overwrite existing instructions files
285
+ # Overwrite entire file instead of merging
284
286
  promptopskit skill --force
285
287
  ```
286
288
 
287
- The `CLAUDE.md` file uses Claude Code's `@AGENTS.md` import syntax to avoid duplicating content. The deployed files cover 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.
289
+ If a target file already exists, the promptopskit section is merged in-place (or appended) rather than skipping or overwriting. Use `--force` to replace the entire file.
290
+
291
+ The `CLAUDE.md` file uses Claude Code's `@AGENTS.md` import syntax to avoid duplicating content.
288
292
 
289
293
  ## Inline Source
290
294
 
package/SKILL.md ADDED
@@ -0,0 +1,363 @@
1
+ ---
2
+ name: promptopskit
3
+ description: Guidance for creating and editing promptopskit prompt files, defaults, variables, and validation-safe templates.
4
+ ---
5
+
6
+ # promptopskit — Prompt Engineering Skill
7
+
8
+ This project uses **promptopskit** to manage LLM prompts as code.
9
+ Prompts live in markdown files with YAML front matter, are validated against
10
+ a schema, and render into provider-specific request bodies (OpenAI, Anthropic,
11
+ Gemini, OpenRouter). Follow these instructions when creating or editing prompts.
12
+
13
+ ---
14
+
15
+ ## Prompt file format
16
+
17
+ Every prompt is a `.md` file with two parts:
18
+
19
+ 1. **YAML front matter** — model settings, provider config, variables, overrides
20
+ 2. **Markdown body** — sections separated by H1 headings
21
+
22
+ ### Minimal example
23
+
24
+ ```markdown
25
+ ---
26
+ id: greeting
27
+ schema_version: 1
28
+ provider: openai
29
+ model: gpt-5.4
30
+ context:
31
+ inputs:
32
+ - name
33
+ ---
34
+
35
+ # System instructions
36
+
37
+ You are a helpful assistant.
38
+
39
+ # Prompt template
40
+
41
+ Hello {{ name }}, how can I help you?
42
+ ```
43
+
44
+ When creating a new prompt file with "just the necessary fields", include only
45
+ the fields required by that specific file:
46
+ - Always include `id` and `schema_version: 1`
47
+ - Include `provider` and `model` only if they are not inherited from `defaults.md`
48
+ - Include `context.inputs` whenever the body contains `{{ variable }}` placeholders
49
+ - Omit `context` entirely only when the body has no placeholders
50
+
51
+ ---
52
+
53
+ ## Front matter reference
54
+
55
+ | Field | Type | Required | Description |
56
+ |-------|------|----------|-------------|
57
+ | `id` | string | **yes** | Unique identifier for the prompt |
58
+ | `schema_version` | number | yes | Always `1` |
59
+ | `description` | string | no | Human-readable description |
60
+ | `provider` | enum | no | `openai`, `anthropic`, `google`, `gemini`, `openrouter`, or `any` |
61
+ | `model` | string | no | Model identifier (e.g. `gpt-5.4`, `claude-sonnet-4-20250514`) |
62
+ | `fallback_models` | string[] | no | Ordered fallback model list |
63
+ | `reasoning` | object | no | `{ effort: low|medium|high, budget_tokens: number }` |
64
+ | `sampling` | object | no | `{ temperature, top_p, frequency_penalty, presence_penalty, stop, max_output_tokens }` |
65
+ | `response` | object | no | `{ format: text|json|markdown, stream: boolean }` |
66
+ | `tools` | array | no | Tool names (strings) or inline definitions with `{ name, description, input_schema }` |
67
+ | `mcp` | object | no | `{ servers: [string | { name, config }] }` |
68
+ | `context.inputs` | string[] | no | Declared variable names used in templates |
69
+ | `context.history` | object | no | `{ max_items: number }` |
70
+ | `includes` | string[] | no | Relative paths to other prompt files to include |
71
+ | `environments` | object | no | Per-environment overrides (see Overrides) |
72
+ | `tiers` | object | no | Per-tier overrides (see Overrides) |
73
+ | `metadata` | object | no | `{ owner, tags, review_required, stable }` |
74
+
75
+ ---
76
+
77
+ ## Sections (markdown body)
78
+
79
+ Use H1 headings to define sections. The parser recognizes these headings
80
+ (case-insensitive):
81
+
82
+ | Heading | Maps to | Purpose |
83
+ |---------|---------|---------|
84
+ | `# System instructions` | `system_instructions` | System/developer message |
85
+ | `# Prompt template` | `prompt_template` | User message template |
86
+ | `# Notes` | `notes` | Documentation only — not sent to the model |
87
+
88
+ If the body has **no H1 headings**, the entire body becomes the `prompt_template`.
89
+
90
+ ---
91
+
92
+ ## Variable interpolation
93
+
94
+ Use `{{ variable_name }}` syntax in system instructions and prompt template
95
+ sections. Variables are replaced at render time.
96
+
97
+ Rules:
98
+ - Declare all variables in `context.inputs` — validation warns on undeclared usage
99
+ - Before finishing a new prompt file, scan the body for every `{{ variable }}` and
100
+ ensure each exact variable name appears in `context.inputs`
101
+ - Escape literal braces with `\{{` and `\}}`
102
+ - In strict mode, missing variables throw an error
103
+ - In permissive mode, unresolved placeholders are left intact
104
+
105
+ Example: this is the minimal valid shape for a prompt that references
106
+ `{{ pull_request }}` even when provider/model are inherited from defaults:
107
+
108
+ ```markdown
109
+ ---
110
+ id: summarizePullRequest
111
+ schema_version: 1
112
+ context:
113
+ inputs:
114
+ - pull_request
115
+ ---
116
+
117
+ # Prompt template
118
+
119
+ Summarize the following pull request:
120
+
121
+ {{ pull_request }}
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Includes (composition)
127
+
128
+ Compose prompts from shared fragments:
129
+
130
+ ```yaml
131
+ includes:
132
+ - ./shared/tone.md
133
+ - ./shared/safety.md
134
+ ```
135
+
136
+ Included files are parsed and their `system_instructions` are **prepended**
137
+ before the including file's own system instructions. Includes resolve
138
+ recursively. Circular includes are detected and rejected.
139
+
140
+ > **Note:** Included files do not inherit folder defaults. Only the top-level
141
+ > prompt that is loaded via `loadPromptFile` receives defaults.
142
+
143
+ ---
144
+
145
+ ## Folder defaults (`defaults.md`)
146
+
147
+ Define shared defaults for a prompt tree by adding a `defaults.md` file in any
148
+ folder:
149
+
150
+ ```text
151
+ prompts/
152
+ ├── defaults.md # global provider, model, metadata + system instructions
153
+ └── support/
154
+ ├── defaults.md # overrides for support/*
155
+ └── reply.md # inherits from support/defaults.md
156
+ ```
157
+
158
+ Supported default fields:
159
+ - `provider` (front matter) — default provider for the folder
160
+ - `model` (front matter) — default model for the folder
161
+ - `metadata` (front matter) — merged with prompt-local metadata
162
+ - `# System instructions` (body section) — used when the prompt has none
163
+
164
+ This lets you configure app-wide settings like `provider` and `model`
165
+ in a single root `defaults.md`, so individual prompts only declare what's unique to them.
166
+
167
+ Important: `defaults.md` does not declare or infer `context.inputs` for a prompt.
168
+ If a prompt body uses placeholders, the prompt file itself must declare them.
169
+
170
+ Rules:
171
+ - Nearest subfolder `defaults.md` overrides parent defaults
172
+ - Prompt-local values always take precedence over defaults
173
+ - `defaults.md` files are skipped during compilation and validation
174
+ - `loadPromptFile` defaults the search boundary to the file's own directory;
175
+ pass `defaultsRoot` to enable ancestor traversal
176
+
177
+ ---
178
+
179
+ ## Environment & tier overrides
180
+
181
+ Override model settings per environment or tier:
182
+
183
+ ```yaml
184
+ environments:
185
+ development:
186
+ model: gpt-4.1-mini
187
+ reasoning:
188
+ effort: low
189
+ sampling:
190
+ temperature: 0.9
191
+ production:
192
+ model: gpt-5.4
193
+ reasoning:
194
+ effort: high
195
+ sampling:
196
+ temperature: 0.3
197
+
198
+ tiers:
199
+ free:
200
+ model: gpt-4.1-mini
201
+ sampling:
202
+ max_output_tokens: 500
203
+ premium:
204
+ model: gpt-5.4
205
+ ```
206
+
207
+ Overridable fields: `model`, `fallback_models`, `reasoning`, `sampling`,
208
+ `response`, `tools`.
209
+
210
+ Override application order: **base → environment → tier → runtime**.
211
+
212
+ ---
213
+
214
+ ## Test sidecars
215
+
216
+ Create a `.test.yaml` file alongside a prompt to define test cases:
217
+
218
+ ```yaml
219
+ # greeting.test.yaml
220
+ cases:
221
+ - name: basic
222
+ variables:
223
+ name: "World"
224
+ - name: formal
225
+ variables:
226
+ name: "Dr. Smith"
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Using the library (TypeScript / JavaScript)
232
+
233
+ ### Quick start
234
+
235
+ ```typescript
236
+ import { createPromptOpsKit } from 'promptopskit';
237
+
238
+ const kit = createPromptOpsKit({ sourceDir: './prompts' });
239
+
240
+ // Load → resolve includes → apply overrides → render
241
+ const request = await kit.renderPrompt('greeting', {
242
+ variables: { name: 'Alice' },
243
+ environment: 'production',
244
+ });
245
+
246
+ // request.body is ready for the provider's API
247
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
248
+ method: 'POST',
249
+ headers: {
250
+ 'Content-Type': 'application/json',
251
+ Authorization: `Bearer ${apiKey}`,
252
+ },
253
+ body: JSON.stringify(request.body),
254
+ });
255
+ ```
256
+
257
+ ### Step-by-step API
258
+
259
+ ```typescript
260
+ import {
261
+ parsePrompt,
262
+ resolveIncludes,
263
+ applyOverrides,
264
+ getAdapter,
265
+ } from 'promptopskit';
266
+ import { readFileSync } from 'fs';
267
+
268
+ // 1. Parse a prompt file
269
+ const source = readFileSync('./prompts/greeting.md', 'utf-8');
270
+ const asset = parsePrompt(source, 'greeting.md');
271
+
272
+ // 2. Resolve includes
273
+ const resolved = await resolveIncludes(asset, './prompts');
274
+
275
+ // 3. Apply overrides
276
+ const configured = applyOverrides(resolved, {
277
+ environment: 'production',
278
+ tier: 'premium',
279
+ });
280
+
281
+ // 4. Get provider adapter and render
282
+ const adapter = getAdapter(configured.provider ?? 'openai');
283
+ const request = adapter.render(configured, {
284
+ variables: { name: 'Alice' },
285
+ history: [
286
+ { role: 'user', content: 'Previous message' },
287
+ { role: 'assistant', content: 'Previous response' },
288
+ ],
289
+ });
290
+ ```
291
+
292
+ ### Available provider adapters
293
+
294
+ | Provider | Import path | Provider request format |
295
+ |----------|------------|----------------------|
296
+ | OpenAI | `promptopskit` or `promptopskit/openai` | Chat Completions API |
297
+ | Anthropic | `promptopskit/anthropic` | Messages API |
298
+ | Gemini | `promptopskit/gemini` | GenerateContent API |
299
+ | OpenRouter | `promptopskit/openrouter` | OpenAI-compatible + extras |
300
+
301
+ ### Validation
302
+
303
+ ```typescript
304
+ import { validateAsset, parsePrompt } from 'promptopskit';
305
+
306
+ const asset = parsePrompt(source);
307
+ const result = validateAsset(asset);
308
+
309
+ if (!result.valid) {
310
+ console.error(result.errors); // Error codes: POK001-POK021
311
+ }
312
+ ```
313
+
314
+ ### Testing helpers
315
+
316
+ ```typescript
317
+ import { createMockAsset, parseTestPrompt } from 'promptopskit/testing';
318
+
319
+ // Create a mock asset for unit tests
320
+ const mock = createMockAsset({ model: 'gpt-4.1-mini' });
321
+
322
+ // Parse an inline prompt string for tests
323
+ const asset = parseTestPrompt(`
324
+ ---
325
+ id: test
326
+ schema_version: 1
327
+ provider: openai
328
+ model: gpt-5.4
329
+ ---
330
+
331
+ # Prompt template
332
+
333
+ Hello {{ name }}
334
+ `);
335
+ ```
336
+
337
+ ---
338
+
339
+ ## CLI commands
340
+
341
+ | Command | Description |
342
+ |---------|-------------|
343
+ | `promptopskit init [dir]` | Scaffold a prompts directory with starter files (including `defaults.md`) |
344
+ | `promptopskit validate <dir>` | Validate all prompt files in a directory |
345
+ | `promptopskit compile <src> <out>` | Compile .md prompts to JSON artifacts |
346
+ | `promptopskit render <file> [--set key=value]` | Render a prompt preview |
347
+ | `promptopskit inspect <file>` | Print the normalized prompt asset |
348
+
349
+ ---
350
+
351
+ ## Conventions to follow
352
+
353
+ 1. **One prompt per file** — each `.md` file is a single prompt asset
354
+ 2. **Always set `id` and `schema_version: 1`** in front matter (or inherit `schema_version` from `defaults.md`)
355
+ 3. **Declare all variables** in `context.inputs` that appear in templates; do not leave placeholders undeclared just because other settings come from `defaults.md`
356
+ 4. **Use includes** for shared system instructions (tone, safety, formatting)
357
+ 5. **Keep prompt templates focused** — compose behavior via includes, not duplication
358
+ 6. **Use environment overrides** for dev/staging/prod model differences
359
+ 7. **Add test sidecars** (`.test.yaml`) for critical prompts
360
+ 8. **Run `promptopskit validate`** before committing changes
361
+ 9. **Use `defaults.md`** to share provider, model, metadata, and system instructions across a folder
362
+ 10. **Variable names** should be `snake_case`
363
+ 11. **Prompt file names** should be `kebab-case.md`