{"id":"4495dde1-51d2-4021-a91a-920c5da66619","slug":"prompt-engineer-skill","kind":"skill","name":"prompt-engineer-skill","summary":"Agent skill for structured prompts, artifact routing and evaluation. Includes a linter and a published benchmark.","owner":"AdrianAdem","repoUrl":"https://github.com/AdrianAdem/prompt-engineer-skill","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-08-24T17:14:17.000Z","addedAt":"2026-10-21T10:23:10.614Z","logoUrl":"https://avatars.githubusercontent.com/u/79639842?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools"],"tags":["ai-agents","anthropic","claude-code","evals","llm","prompt-engineering","prompt-optimization"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-27T02:08:41.314Z","sample":false,"url":"https://conduits.dev/tools/prompt-engineer-skill","language":"Python","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n\n<img src=\"docs/hero-v2.png\" alt=\"prompt-engineer — From a rough request to a structured prompt, test cases and evaluation criteria.\" width=\"100%\"/>\n\n<br>\n\n### From a rough request to a structured prompt, test cases and evaluation criteria.\n\n<br>\n\n<a href=\"#install\"><img src=\"https://img.shields.io/badge/Agent%20skill-Claude%20Code-548BEE?style=for-the-badge&logo=anthropic&logoColor=white\" alt=\"Agent skill: Claude Code\"/></a> <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/License-MIT-548BEE?style=for-the-badge\" alt=\"License: MIT\"/></a> <a href=\"#running-the-evals\"><img src=\"https://img.shields.io/badge/Includes-Linter%20%2B%20evals-548BEE?style=for-the-badge\" alt=\"Includes: Linter + evals\"/></a> <a href=\"https://github.com/AdrianAdem/prompt-engineer-skill\"><img src=\"https://img.shields.io/badge/Source-GitHub-737C88?style=for-the-badge&logo=github&logoColor=white\" alt=\"Source: GitHub\"/></a>\n\n<br><br>\n\n<a href=\"#does-it-work\">Does it work</a> &nbsp; · &nbsp; <a href=\"#install\">Get started</a> &nbsp; · &nbsp; <a href=\"#license\">License</a>\n\n<br><br>\n\n</div>\n\nAn Agent Skill that turns a request into a structured prompt, together with\nthe test cases and success criteria needed to tell whether it works. It also\nworks the other way round: when the request is the work itself, the skill\nsupplies the structure for doing it and for briefing subagents, without handing\nback a document about it.\n\n    /prompt an extractor for support tickets, running at volume\n\nWithout the skill you get a prompt. With it you get a prompt that names its\ntarget model class and effort setting, delegates schema enforcement to the API\ninstead of asking for JSON in prose, carries an uncertainty field because nobody\nre-reads three thousand classifications a day, and ships with a seed set sized\nto the volume rather than three illustrative cases.\n\nBefore any of that it asks a question the other skills skip: is a prompt the\nright artifact at all? A rule that must hold every time is a hook, not a\nparagraph in a config file. Something you intend to paste again next week is a\nskill, not a prompt that drifts across copies.\n\n<br>\n\n## Four modes\n\n**Create** writes a new prompt. **Revise** improves an existing one and shows a\nchangelog rather than silently rewriting it, because odd-looking lines often\nencode a requirement learned from a failure. **Migrate** moves a working prompt\nto a different model without conflating the model change with prompt changes.\n**Execute** is for the agent itself: the person asked for the work, not for a\ndocument about it.\n\n<br>\n\n## What it does that other prompt skills do not\n\n- **Routes before it writes.** Prompt, hook, skill, subagent, or config file.\n  The placement decides whether an instruction takes effect at all, and it is\n  the most expensive thing to get wrong in an agent harness.\n- **Treats model class as model times effort.** A frontier model pinned to\n  minimal reasoning wants explicit steps, not goal-level guidance, and defaults\n  shift between model generations. An unpinned effort setting is an unknown\n  class, not an assumed one.\n- **Separates a model change from a prompt change.** Migrate mode switches the\n  model with the prompt untouched, pins effort, takes a baseline, and only then\n  tunes, one change per measurement.\n- **Ships code, not only prose.** A linter that catches the anti-patterns a\n  regex can see, and a flattener that turns the skill into a single system\n  prompt for platforms with no skill mechanism.\n- **Ships its own evals**, and a benchmark that reports its losses.\n\n<br>\n\n## Does it work\n\n[`benchmark/`](benchmark/) holds three rounds against three other public prompt-engineering\nskills, on the same two tasks, with a blinded LLM judge and documented rubric versions. The\nraw answers and the task prompts are in the repo.\n\nTwo results worth knowing before you install anything.\n\n**This skill wins the routing task and loses the eval-design task.** On \"enforce\na rule on every commit so an agent cannot route around it\" it placed first under\nboth Opus judges, and the judge's reason was the artifact routing: the agent hook\nand the git hook call the same script, `--no-verify` is blocked, and the test\ncase requires the bypass to fail. On \"build a classifier prompt for volume\" it\nlost to Jeffallan's skill in all three rounds.\n\n**The aggregate ranking from that benchmark is noise, and the benchmark says\nso.** Rounds 1 and 2 used the same answers and the same rubric and differed only\nin the judge instance and the labels; three of four positions moved. The same\nunchanged answer went from first to third when the judge's model changed. Only\nbefore-and-after comparisons inside one run mean anything, which is exactly how\nthe one attributable improvement was measured: rewriting\n[`references/evaluation.md`](prompt-engineer/references/evaluation.md) moved this skill's answer from last place to second,\nsame run, same judge.\n\n<br>\n\n## Install\n\nCopy the `prompt-engineer/` directory into your skills directory.\n\n    # Claude Code, project-scoped\n    cp -r prompt-engineer .claude/skills/\n\n    # Claude Code, user-scoped\n    cp -r prompt-engineer ~/.claude/skills/\n\nThe optional slash command lives in `commands/prompt.md`. Copy it to\n`.claude/commands/` to invoke the skill explicitly:\n\n    /prompt an extractor for support tickets, running at volume\n    /prompt revise <existing prompt>\n    /prompt migrate <target model> <existing prompt>\n\nThe command is for when you know you are working on a prompt. The skill also\ntriggers on its own description, which covers the case where you do not think of\nyour task as a prompting task at all.\n\n<br>\n\n## Layout\n\n    prompt-engineer/\n    ├── SKILL.md                        core workflow and anti-patterns\n    ├── references/\n    │   ├── artifact-routing.md         prompt vs hook vs skill vs subagent\n    │   ├── model-classes.md            capability signatures and effort settings\n    │   ├── delivery-mechanics.md       turn placement, structured output, caching\n    │   ├── agentic-prompts.md          phased builds and multi-window work\n    │   ├── examples.md                 coverage, ordering, when examples hurt\n    │   ├── self-and-subagents.md       using it on your own work, briefing agents\n    │   └── evaluation.md               success criteria, edge cases, grading\n    ├── scripts/\n    │   ├── lint_prompt.py              mechanical anti-pattern check\n    │   ├── lint_all.sh                 lints every file the skill ships\n    │   └── build_system_prompt.py      flatten to one file for other platforms\n    ├── hooks/\n    │   ├── restate-brief.py            optional, see below\n    │   ├── settings-snippet.json\n    │   └── README.md\n    ├── commands/prompt.md              optional slash command\n    └── evals/\n        ├── evals.json                  behaviour and triggering cases\n        └── run_evals.py                runner, rubric grading, --self-test\n\n    benchmark/\n    ├── README.md                       method, results, and what the data does not support\n    ├── tasks.md                        both task prompts and both rubric versions\n    └── answers/                        all five responses as the judge saw them\n\nReference files load only when the task needs them, so the always-on cost is the\ndescription alone.\n\n<br>\n\n## What the skill actually enforces\n\nThree things it gets right that are easy to get wrong by hand.\n\n**Class is model times effort, not model alone.** A frontier model pinned to\nminimal reasoning wants explicit steps, not goal-level guidance, and defaults\nshift between model generations. An unpinned effort setting is treated as an\nunknown class rather than assumed.\n\n**Multi-session work gets two prompts, not one.** A single prompt repeated per\nsession fails predictably: the first session tries to one-shot the whole thing\nand runs out of context mid-feature, and a later session sees progress and\ndeclares the job done. The initializer builds the environment, the worker takes\nexactly one item per session and may only flip a status field.\n\n**Verification means the real surface.** A green unit test and a successful curl\nagainst a dev server say nothing about whether a user can use the feature.\n\n<br>\n\n## Using it on your own work\n\n`references/self-and-subagents.md` covers the case where you are the one doing\nthe work rather than writing a prompt for someone else. The rule that matters is\nabout size, not about whether to think: for a single session, a written prompt\naddressed to yourself costs a turn and gains nothing, so state the phases and\nacceptance criteria in a paragraph and build. For work spanning sessions, the\nwritten artifacts are the only state that survives, and they belong in the repo.\n\nFor subagent briefs it gives four required parts, the mapping from the agent's\nmodel tier to the register of the brief, and one rule worth singling out: never\nput your own conclusion in a review brief. \"Check whether this is safe, I think\nit is\" gets you agreement, which destroys the independence you delegated for.\n\n<br>\n\n## Linting a prompt\n\n    python scripts/lint_prompt.py myprompt.md\n    python scripts/lint_prompt.py myprompt.md --class 2\n    python scripts/lint_prompt.py myprompt.md --json\n\nCatches the anti-patterns a regex can see: reasoning-reproduction instructions,\nprefill patterns, prompt-text JSON enforcement, roles asserting seniority or\nexperience instead of domain, vague quality words, undated model names,\nprohibition-heavy phrasing, and sentinel conflicts, where one line permits\n`null` for a missing field and another says a null breaks the consumer. It exits non-zero on errors, so it drops into a\npre-commit hook or CI.\n\nA file can waive checks it discusses rather than commits:\n\n    <!-- lint-disable: prefill, vague-quality -->\n\nand a single line can waive everything with a trailing `lint-ignore`. For whole\nfiles that are documentation about prompting rather than prompts, use `--docs`,\nwhich disables the six checks that fire on merely naming a pattern. The skill's\nown reference files are linted that way; `SKILL.md` and the slash command are\nlinted normally, because they are instructions.\n\nThe model-name check is deliberately not part of `--docs`: reference\ndocumentation is the first thing to go stale, so it stays live everywhere and is\nsatisfied by recording a date, not by an exemption.\n\n    ./scripts/lint_all.sh\n\nruns every prose file the skill ships in the mode that fits it, and validates\nthe two JSON files structurally. Exit 0 means the whole package is clean, not\njust one file.\n\nFenced code blocks are scanned in normal mode and stripped in `--docs` mode.\nThe reason is which text is the object under test: a prompt sent for review sits\ninside a fence, while a fence inside documentation holds a quoted example of the\nanti-pattern being explained. `--scan-code` and `--skip-code` override the\ndefault either way.\n\nIt deliberately does not judge altitude, whether constraints carry their reasons,\nor whether examples are anchoring creative work. Those need a model. Agentic\nbuild prompts are exempt from the placeholder check, since they are parameterless\nby design.\n\n<br>\n\n## Running the evals\n\n    export ANTHROPIC_API_KEY=...\n    python evals/run_evals.py                  # the automatable cases\n    python evals/run_evals.py --manual         # the triggering checklist\n    python evals/run_evals.py --dry-run        # print prompts, call nothing\n\nEach case carries machine-checkable assertions rather than a prose expectation,\nso a run gives a pass count instead of something to read and judge. Failures\nwrite the full output to `evals/out_<id>.txt`.\n\nTwo cases test whether the skill *triggers*, and those are printed as a manual\nchecklist instead of being run. Triggering is a property of the harness that\nloads the skill; no API call reproduces it. Pretending otherwise would be the\nexact failure this skill warns about, a green result that proves nothing.\n\n<br>\n\n## Using it outside Claude\n\nThe skill *format* is Anthropic's: Claude Code, Claude.ai, Cowork, and the Agent\nSDK read it. The *content* is deliberately cross-provider, with sections on\nOpenAI, Gemini, and open-weight conventions, and model classes defined by\ncapability signature rather than by vendor.\n\nFor a platform with no skill mechanism, flatten it into one system prompt:\n\n    python scripts/build_system_prompt.py -o system-prompt.md\n    python scripts/build_system_prompt.py --provider openai -o system-prompt.md\n    python scripts/build_system_prompt.py --core -o system-prompt.md\n\nThe full build is roughly 12,000 tokens and the core alone roughly 3,800,\nmeasured on the current tree; both grow as reference files are added, so\nregenerate rather than trusting these numbers. The\n`--provider` flag drops reference *sections* tagged for a different vendor. It\ndoes not rewrite `SKILL.md`, which carries no section tags, so a few\nprovider-scoped statements survive it, notably the prefill entry in the\nanti-pattern list. Those name their scope inline rather than asserting it\ngenerally, but a section-level filter is what this is, and that is its limit.\nEvery\nsection in `delivery-mechanics.md` carries a `[universal]`, `[anthropic]`, or\n`[varies]` tag for exactly this reason; that file moves fastest and is the one to\ndistrust first when something reads as out of date.\n\nBoth scripts are standard library only, Python 3.8 or later, no install step.\n\n<br>\n\n## Optional: the restate hook\n\n`hooks/restate-brief.py` is a `UserPromptSubmit` hook for Claude Code. It exists\nbecause a skill is *selected*, so it fires some of the time, and some things\nshould fire every time the condition holds.\n\nWhen a request looks like a commission for multi-step work, it injects about 150\ntokens asking for a short restatement first: the understood goal, the\nassumptions the request did not specify, and the acceptance criteria. It asks\nfor the content and deliberately not for a length or a register, so whatever\nresponse style is already in force keeps applying. That is the\ncheapest possible place to catch a misread brief, and it is a fortieth of the\ncost of writing a full prompt artifact.\n\nIt stays silent on questions, lookups, single edits, one-word replies, and\nrequests already long enough to be fully specified. The verb lists are heuristics\nand are meant to be edited to match how you actually write. It exits zero on any\nmalformed input, because a hook that blocks a turn is worse than one that does\nnothing.\n\nIt ships inside the skill directory so one copy step installs everything, but a\nhook is not loaded from there. Copy it to `~/.claude/hooks/` and merge\n`settings-snippet.json` into your `settings.json`. Check the payload field name against your Claude Code\nversion; the script tries four common variants.\n\n<br>\n\n## Scope and limits\n\nThe advice is distilled from published prompting guidance from Anthropic, OpenAI,\nand Google, plus practical failure modes seen in real use. It is written in the\nauthor's own words rather than copied.\n\nTwo honest caveats.\n\nThe **named example models are dated August 2026** and will go stale. The skill\nclassifies by capability signature rather than by model name precisely so the\nstructure survives that, but the examples in `model-classes.md` will need\nrefreshing.\n\nThe **Class 3 guidance for small and open-weight models is the least\nwell-sourced** section. It is marked as such in the file. Treat it as a starting\npoint and rely on evals more heavily there.\n\n<br>\n\n## Contributing\n\nCorrections to model behaviour claims are especially welcome, particularly with a\nreproducible case. The most useful contribution is a prompt this skill handled\nbadly, along with what you expected instead.\n\n<br>\n\n## License\n\nMIT. See `LICENSE`.\n"}