Skip to content

Commit fe1cf3f

Browse files
IMPROVEMENT: Reduced size of the skill files by referencing one in node_modules
1 parent 6dd77fa commit fe1cf3f

5 files changed

Lines changed: 385 additions & 344 deletions

File tree

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ npm install promptopskit
3434

3535
```bash
3636
npx promptopskit init ./prompts
37+
npx promptopskit skill
3738
```
3839

3940
This creates:
@@ -246,8 +247,9 @@ prompts/
246247
## CLI
247248

248249
```bash
249-
# Scaffold starter prompts
250+
# Scaffold starter prompts and deploy AI agent instructions
250251
promptopskit init [dir]
252+
promptopskit skill
251253

252254
# Validate all .md files in a directory
253255
promptopskit validate <dir> [--strict]
@@ -267,7 +269,7 @@ promptopskit skill [--target agents|claude|copilot|cursor] [--force]
267269

268270
## AI Agent Instructions
269271

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:
271273

272274
```bash
273275
# Deploy for all AI coding assistants (default)
@@ -280,11 +282,13 @@ promptopskit skill
280282
# Deploy only a specific target
281283
promptopskit skill --target copilot
282284

283-
# Overwrite existing instructions files
285+
# Overwrite entire file instead of merging
284286
promptopskit skill --force
285287
```
286288

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.
288292

289293
## Inline Source
290294

SKILL.md

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

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@
7272
}
7373
},
7474
"files": [
75-
"dist"
75+
"dist",
76+
"SKILL.md"
7677
],
7778
"scripts": {
7879
"build": "tsup",

0 commit comments

Comments
 (0)