Card schema
The recipe-card Markdown and frontmatter format is a parser contract. Read this before changing card structure, headings, frontmatter fields, or the render/parse functions in src/store.ts — a mismatch silently corrupts every card in the user's library.From its SKILL.md
npx -y skills add ljf06853/keepfire --skill card-schemaAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.2 KB, 691 tokens by cl100k_base, as published. Nobody here has run it
Recipe cards are stored as one Markdown file per recipe under $KEEPFIRE_HOME/cards/ (default ~/.keepfire/cards/). The format is not a display detail — it is the on-disk database, and it is written and read by two hand-rolled functions that must agree exactly.
What must move in lockstep
Change any one of these and you must change all of them in the same edit:
renderCardMarkdowninsrc/store.ts— writes the card.parseCardMarkdowninsrc/store.ts— reads it back, by regex-matching exact##heading text.templates/card.md— the canonical shape shown to users and agents.- The
RecipeCardinterface insrc/types.ts. SKILL.md— if the change affects what agents are told to write, since agents can write cards directly when the CLI is absent.
Why a mismatch is dangerous, not just broken
rebuildIndex in src/store.ts wraps card parsing in a bare catch {} and skips anything that fails. So a renamed heading does not throw — it makes every existing card parse to empty or get silently dropped from the index. The user's library appears to lose recipes with no error. Any change here needs a test that round-trips a card through render → parse and asserts field-by-field equality, plus a check that existing cards on disk still parse.
Hard constraints
- Headings are the contract.
parseCardMarkdownmatches exact heading strings (## Raw prompt,## Skeleton,## Constraints,## Output contract,## Why it worked,## Anti-patterns,## Notes). Read the current regexes before assuming the list; do not rename a heading without updating them. raw_promptandskeletonlive inside```textfences. The parser expects the fence. Prompt bodies can themselves contain backticks and code fences — if you change fence handling, test with a prompt that contains a nested fence.- Frontmatter must stay flat and inline. It is parsed by
parseSimpleYaml, not a YAML library. It handles onlykey: value, inline[a, b]arrays, quoted strings, numbers, booleans, andnull. Nested maps, block arrays, and multiline scalars will not parse. Adding a structured field means either keeping it flat or upgrading the parser (and then handling every card written by the old one). - Cards are user data that already exists on disk. A format change is a migration, not a refactor. Either keep the parser backward-compatible with cards written by prior versions, or ship an explicit migration path —
keepfire reindexre-reads cards, it does not rewrite them.
Related invariants
improveCardderives the new id as`${parent.id}-v${nextVersion}`, so ids compound across generations (...-abcd-v2-v3). If you change the id scheme, existing parent/child links break.index.jsonis derived state and can always be rebuilt fromcards/*.mdviarebuildIndex. The Markdown files are the source of truth — never make the index authoritative.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.