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 +8 -4
- package/SKILL.md +363 -0
- package/dist/cli/index.js +31 -331
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
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
|
|
285
|
+
# Overwrite entire file instead of merging
|
|
284
286
|
promptopskit skill --force
|
|
285
287
|
```
|
|
286
288
|
|
|
287
|
-
|
|
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`
|