Prompt Artefact Directory Layout
eva beginner 4 min read
ELI5
Each prompt is a single shoebox on a shelf: the label (meta.yml), the recipe (prompt.xml), and optional pockets for sample ingredients, taste-tests, a doorman, and a sniff-test. EVA refuses to open a shoebox missing the label or recipe.
Technical Deep Dive
Layout
prompts/<id>/├── meta.yml # required├── prompt.xml # required├── examples/<case>/inputs.yml # optional, loaded by --case├── eval.yml # optional, eva eval reads this├── guard.sh # optional, executed pre-send├── verify.sh # optional, executed post-send├── aliases # optional, one shell verb per line└── .usage.jsonl # auto-managed; appended on every kick runbin/kick resolves prompts/<id>/{meta.yml, prompt.xml} and refuses if either is missing (bin/kick:130-131). No status subdirectories — meta.yml.status is the single source of truth (the historic prompts/{ready,tested,draft}/*.md layout is what eva migrate rewrites away from at bin/eva:887).
Class Diagram
classDiagram class PromptArtefact { +id : string +meta.yml +prompt.xml } class Examples { +cases/inputs.yml } class Eval { +cases[]; +triggering } class Guard { +stdout: KEY=VALUE } class Verify { +exit code } class Aliases { +shell verbs } class Usage { +jsonl rows } PromptArtefact "1" --> "0..*" Examples PromptArtefact --> Eval PromptArtefact --> Guard PromptArtefact --> Verify PromptArtefact --> Aliases PromptArtefact --> UsageResolution Flow
flowchart LR cli["kick <id> --case happy --send"] --> find["find_prompt() — bin/kick:24"] find -->|missing meta.yml| die1["die: prompt not found"] find --> xml{prompt.xml exists?} xml -- no --> die2["die: missing prompt.xml"] xml -- yes --> caseV["load examples/case/inputs.yml"] caseV --> guard["guard.sh hook"] guard --> render["render {{vars}}"] render --> claude["claude CLI"] --> verify["verify.sh hook"] --> log[".usage.jsonl"]Key Terms
- Artefact → a single self-contained prompt directory under
prompts/<id>/. - Case → a named subdirectory of
examples/whoseinputs.ymlbecomes vars under--case. - Aliases file → newline-separated shell-identifier verbs that
eva indexmaterialises inbin/kick-aliases.sh.
Q&A
Q: Which two files are the bare minimum for a runnable prompt?
A: meta.yml and prompt.xml. bin/kick dies at line 130–131 if either is missing.
Q: Where do per-case input variables live on disk?
A: prompts/<id>/examples/<case-name>/inputs.yml. Loaded by --case <name> at lower precedence than --var flags (bin/kick:150-159).
Q: How does kick locate the prompts directory without a config file?
A: It reads $PROMPT_LIB_ROOT if set, else walks one directory up from BASH_SOURCE[0] and uses <root>/prompts (bin/kick:15-20).
Examples
Listing the smallest valid artefact:
prompts/hello/├── meta.yml # 7 required fields└── prompt.xml # may contain {{name}} placeholderskick hello --var name=world renders to stdout; adding --send pipes through claude.
neighbors on the map
- meta.yml Schema & Required Fields authoring a new meta.yml
- eva doctor Validation Rules diagnosing a doctor FAIL line
- Choco Factory Architecture Map onboarding to a new choco service repo
- Three-Tier Architecture (Core → Choco → MERIDIAN) explaining the deployment model