From purlin
Creates or edits feature specs in structured 3-section format. Extracts specs from plain English, PRDs, or code; includes mode for rule quality review.
How this skill is triggered — by the user, by Claude, or both
Slash command
/purlin:specThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create or edit a spec from any input — plain English, PRDs, customer feedback, code files, or existing specs. The agent extracts structured rules from unstructured input. The user describes what they want; the agent writes the spec.
Create or edit a spec from any input — plain English, PRDs, customer feedback, code files, or existing specs. The agent extracts structured rules from unstructured input. The user describes what they want; the agent writes the spec.
For syntax: references/formats/spec_format.md. For quality: references/spec_quality_guide.md.
purlin:spec <name> Create or edit a spec
purlin:spec <name> --anchor Delegate to purlin:anchor create
purlin:spec <name> --review Review an existing spec for rule quality
purlin:spec (no name — extract from user's input)
Lightweight rule quality check. Reads an existing spec and evaluates each rule — no test execution, no file modifications, no proof files. Use this to catch quality problems before anyone writes tests.
Find specs/**/<name>.md. If not found, error: "Spec not found. Run purlin:spec <name> to create it."
Read the spec in full. Also read the source files listed in > Scope: (if any) for context on what the code actually does.
For each RULE-N: line, apply the three tests from references/spec_quality_guide.md ("The rebuild test"):
NOISE.IMPLEMENTATION.OVERLAP and name the paired rule.Also check:
> Scope: and identify behavioral aspects not covered by any rule. Flag each as GAP with a suggested rule.VAGUE.Spec review: <name> (<N> rules)
✓ RULE-1: Returns 200 with JWT on valid credentials
✓ RULE-2: Returns 401 on invalid password
⚠ RULE-3: Uses bcrypt for password hashing — IMPLEMENTATION (names library; rewrite as: "Passwords are hashed before storage")
⚠ RULE-4: Locks account after 5 failures — OVERLAP with RULE-5 (same trigger condition)
✗ RULE-5: Handles rate limiting — VAGUE (what status code? what error message? what threshold?)
Suggested rules (GAP):
+ "Returns 429 with Retry-After header when rate limit exceeded" (rate limit response not specified)
+ "Login audit log records every attempt with timestamp, IP, and success/failure" (audit trail in code but not in spec)
Summary: 2 clean, 2 warnings, 1 vague, 2 gaps suggested
For bad→good rewrite examples, reference references/rule_examples.md.
This mode is read-only. It does not modify the spec, create files, or run tests. The user takes the findings and applies them manually or via purlin:spec <name>.
Accept ANY of these input types without asking which format it is:
If a spec name was given, search specs/**/<name>.md:
sync_status for coverage. Go to Step 7 (Update Existing Spec).If no name was given, read the user's input and infer the feature name from the topic.
If the input is substantial (more than a sentence or two), extract as much as possible BEFORE asking any questions:
references/spec_quality_guide.md ("Spec Categories"):
security/ or component dir with security_ anchorschema/instructions/integration/specs/ for matching anchors to reference via > Requires:Present the complete draft spec to the user, followed by the approval block. Assumed rules should be visually obvious in the draft:
RULE-1: Fetches weather from OpenWeatherMap
RULE-2: Shows temperature in Fahrenheit
RULE-3: Cache results for 10 minutes (assumed — user said "don't hit the API too much")
RULE-4: Show error message on API failure
The PM sees the assumed tag and either confirms, changes the value, or asks a gap question.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚡ REVIEW DRAFT — Does this look right?
[y] Looks good — continue to metadata
[n] Start over
[edit] I want to change specific rules or proofs
Waiting for your response...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Use AskUserQuestion to pause and wait. Do NOT skip this step. Then go to Step 3 for gap questions.
After presenting the draft, ask ONLY about gaps — don't re-ask things the input already answered:
Questions must be specific and gap-filling, not generic ("what are the rules?" or "what are your requirements?").
If the input is vague or minimal (e.g., "write a spec for password reset" with no details), show a brief example BEFORE generating:
Here's what a spec looks like:
Feature: password_reset
What it does — Allows users to reset their password via a time-limited email link.
Rules:
- RULE-1: POST /reset with valid email sends a reset link
- RULE-2: Reset link expires after 24 hours
- RULE-3: Clicking a valid link allows setting a new password
- RULE-4: Clicking an expired link shows an error message
Proofs:
- PROOF-1 (RULE-1): POST /reset with registered email; verify 200 and email sent @integration
- PROOF-2 (RULE-2): Create a link, advance clock 24h; verify link returns 410 Gone
- PROOF-3 (RULE-3): Click valid link, submit new password; verify password changed @integration
- PROOF-4 (RULE-4): Click expired link; verify error message displayed
Now tell me about your feature and I'll draft the spec.
Skip the example if the input is already detailed (PRD, substantial description, pasted requirements).
When extracting rules from unstructured input, look for:
| Signal in input | Rule type | Example |
|---|---|---|
| "must", "should", "needs to", "has to" | Direct constraint | RULE: Return 200 with session token on valid login |
| "never", "don't", "cannot", "forbidden" | FORBIDDEN pattern | RULE: FORBIDDEN — No plaintext password storage |
| Error cases, "what if", "fails when" | Error handling | RULE: Return 404 when user ID does not exist |
| "fast", "under N seconds", "real-time" | Boundary condition | RULE: API response time under 200ms at p95 |
| "first... then... finally" | Multi-step workflow | RULE: After email verification, account status changes to active |
| "only admins", "users with role X" | Access control | RULE: Only users with admin role can delete accounts |
| "stores", "saves", "records", "tracks" | Data persistence | RULE: Audit log records every login attempt with timestamp and IP |
| Sequences with conditions | State machine | RULE: Order status transitions: pending → paid → shipped → delivered |
For each extracted rule, generate an observable proof description with concrete inputs and expected outputs. Apply tier tags per references/spec_quality_guide.md ("Tier Tags on Proofs").
Assumption tagging (mandatory): After extracting rules, review each one. If the rule contains a specific number, threshold, algorithm, or constraint that the user did NOT explicitly state, add the (assumed) tag with context:
RULE-3: Under 500ms (assumed — user said "fast")RULE-4: bcrypt hashing (assumed — user said "secure")RULE-5: Returns 500 with error body (assumed — user said "handles errors")If the user WAS explicit, no tag:
RULE-3: Under 200ms (no tag)RULE-4: argon2 hashing (no tag)After the core spec (What it does, Rules, Proof) is solid, add metadata:
specs/ and suggest > Requires: based on scope overlap:
specs/_anchors/), read its > Scope: patterns> Scope: files overlap with the anchor's scope, suggest requiring it> Requires:)Suggested > Requires: based on file overlap:
api_rest_conventions — your Scope overlaps with src/api/
security_no_eval — global anchor (auto-applied, no action needed)
Add api_rest_conventions to > Requires:? [y/n]
> Scope: (verify paths exist)> Stack:references/spec_quality_guide.mdreferences/spec_quality_guide.md ("Spec Categories")Rule quality check (mandatory): Before presenting, apply the --review logic internally: evaluate every rule against the rebuild/behavior/overlap tests. Fix any IMPLEMENTATION or NOISE rules in the draft — don't present rules that fail the rebuild test.
Present the enhanced spec with metadata added and ask "anything to adjust?"
After drafting the rules and proofs, if the spec covers files in references/, skills/, or agents/ (instruction files), check: are ALL proofs grep-based or existence checks? If yes, suggest adding behavioral rules to this same spec — not a separate spec:
All proofs for this spec are structural (grep/existence checks). This catches
deletions and drift but doesn't prove the instructions work.
Consider adding behavioral rules to this spec. For example:
RULE-N: Agent follows the core loop when given "build X" @e2e
RULE-N+1: Agent uses purlin:spec when asked to "update the spec" @e2e
Tests must prove rules in the feature they validate — not in a separate spec.
Do NOT create specs whose sole purpose is to be a container for tests (e.g., e2e_feature_scoped_overwrite, e2e_audit_cache_pipeline). If a test validates that proof plugins preserve other features during overwrite, that test proves proof_common RULE-4 — wire it there.
When the user asks for "an e2e spec" or "integration tests for X":
## Proof sectionIf the rule already exists in the target spec, the test just needs a proof marker pointing to it — no new rule or spec needed.
Before committing, verify:
## What it does has at least one full sentence## Rules has at least one RULE-N: line, all numbered sequentially## Proof has at least one PROOF-N (RULE-N): line, each mapping to a rulereferences/spec_quality_guide.md ("Tier Tags on Proofs")@e2e proof describes an observable flow (arrange → act → observe through the real running app) and does not name a source file or internal function, per references/spec_quality_guide.md ("E2E proof descriptions") — rewrite as a boundary observation or retag if not> Scope: file paths exist on disk> Requires: validation (blocking): For EACH reference in > Requires:, glob specs/**/<name>.md. If any referenced spec does not exist on disk, DO NOT commit the spec with the broken reference. Remove the broken reference from > Requires: and print: Removed > Requires: <name> — spec not found. Create it first with purlin:spec <name>, then add the reference back.After the spec is approved, commit immediately. Do not batch with other changes.
git add specs/<category>/<name>.md
git commit -m "spec(<name>): <description of change>"
This commit is mandatory — drift detection and staleness checks depend on committed spec state. Do not skip or defer.
When updating a spec that already exists on disk:
drift MCP tool to see what changed since the last verification> Scope:Compare the current spec against the code changes. Categorize each finding:
| Category | What it means | Action |
|---|---|---|
| NEW RULE NEEDED | Code added behavior not covered by any existing rule | Propose adding a new RULE-N |
| RULE OUTDATED | Existing rule describes behavior that changed | Propose updating the rule text |
| RULE OBSOLETE | Existing rule describes behavior that was removed | Propose removing the rule |
| PROOF OUTDATED | Proof description no longer matches the rule | Propose updating the proof text |
| METADATA STALE | > Scope: or > Stack: no longer accurate | Propose updating metadata |
| NO CHANGE | Existing rule still matches code | Keep as-is (explicitly note this) |
Show the user EXACTLY what will change and what will stay:
Spec: specs/mcp/sync_status.md (15 rules currently)
KEEPING (unchanged):
RULE-1: sync_status tool returns valid report ✓
RULE-2: Proof files are parsed correctly ✓
RULE-3: Coverage is computed for all features ✓
...
ADDING:
RULE-23 (new): sync_status scans specs/_anchors/ for anchor specs
Reason: Anchor directory support added
Proposed proof: PROOF-23 (RULE-23): Create anchor in specs/_anchors/, run sync_status, verify anchor rules appear
UPDATING:
RULE-20 (changed): Global anchors auto-apply to all features
Was: "Global specs with > Global: true auto-apply"
Now: "Anchor specs in specs/_anchors/ with > Global: true auto-apply to all non-anchor features"
Reason: Anchor unification
REMOVING:
(none)
METADATA:
▎ Stack: unchanged
▎ Scope: unchanged
▎ Requires: unchanged
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚡ APPROVAL REQUIRED — Review the changes above.
[y] Approve and apply all changes
[n] Cancel — make no changes
[edit] I want to adjust specific items
Waiting for your response...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
This approval block is MANDATORY. The agent MUST use AskUserQuestion to pause and wait for the user's response. Do NOT auto-approve. Do NOT proceed without an explicit answer. The bordered block above is the exact format to use — it must be visually distinct from the rest of the output so the user doesn't scroll past it.
references/spec_quality_guide.md@manual stamps — do NOT remove manual proof stamps unless the rule they reference was removed(assumed), (confirmed), (deferred) stay as-is(confirmed), change the tag to (assumed) since the new value hasn't been confirmed yet> Scope: if new files were added to the feature> Stack: if new dependencies were introducedSame validation as new specs: no empty sections, sequential numbering, observable proofs, valid references, tier tags.
After the spec update is approved, commit immediately. Do not batch with other changes.
git add specs/<category>/<name>.md
git commit -m "spec(<name>): update rules for <description>"
This commit is mandatory — drift detection and staleness checks depend on committed spec state. Do not skip or defer.
@manual stamps unless the rule was deleted.When --anchor is specified, delegate to purlin:anchor create with the same arguments. Do not create the anchor directly in this skill.
See references/formats/anchor_format.md for format, references/spec_quality_guide.md for when to create anchors and FORBIDDEN pattern guidance.
When the user provides an image (screenshot, mockup, design comp, whiteboard photo):
Save the image to specs/_anchors/screenshots/<name>.png (create the screenshots directory if needed).
Compute and store the image hash in the spec metadata:
> Visual-Reference: ./specs/_anchors/screenshots/<name>.png
> Visual-Hash: sha256:a1b2c3d4e5f6...
This enables staleness detection — if the image is later replaced, sync_status will warn that the anchor may need review.
Create an anchor spec with:
> Visual-Reference: and > Visual-Hash: as above> Scope: pointing to the code files that will implement the designRULE-1: Implementation must visually match the reference image@e2eCommit the image AND the spec together.
The spec operation is NOT complete until all of the following are true. Verify each one before responding to the user.
git status. If the spec .md file is uncommitted, commit it now per the commit instructions above.git status must not show any modified or untracked specs/**/*.md files from this session.If any criterion is not met, fix it before completing. Do not respond to the user with "done" or "complete" until both are verified.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub rlabarca/purlin --plugin purlin