| name | cookbook-config |
| description | Help author, validate, and edit mori/cookbook.dhall cookbook extension catalogs. Covers entry fields, content types, topics, imports, and validation rules. TRIGGER when: user wants to create, edit, or validate their mori/cookbook.dhall config.
|
| argument-hint | ["create|edit|validate"] |
| user-invocable | true |
Cookbook Config Skill
You are helping the user author, edit, and validate a mori/cookbook.dhall cookbook catalog
for the mori extension system.
What mori/cookbook.dhall does
The cookbook extension catalogs a project's code examples, step-by-step instructions,
reusable patterns, configuration templates, and scaffolding templates as structured metadata.
Each entry describes one resource with its content type, domain topics, related packages,
language, audience, and file location. This metadata powers three things: local browsing via
mori cookbook list and mori cookbook show, cross-project querying via
mori extension query cookbook, and agent context enrichment (agents receive the catalog
as structured data so they can recommend relevant resources).
File location and imports
The file lives at mori/cookbook.dhall relative to the project root. It must produce a
record with a single field entries containing a list of cookbook entries.
Every cookbook.dhall needs these imports:
let Schema =
https://raw.githubusercontent.com/shinzui/mori-schema/<commit>/package.dhall
sha256:<hash>
let Cookbook =
https://raw.githubusercontent.com/shinzui/mori-schema/<commit>/extensions/cookbook/package.dhall
sha256:<hash>
in Cookbook.CookbookCatalog::{
, entries =
[ -- entries go here
]
}
Schema re-exports the core types used in cookbook fields:
Schema.Language, Schema.DocAudience, Schema.DocLocation.
Cookbook re-exports the cookbook bundle records
(Cookbook.CookbookCatalog, Cookbook.CookbookEntry) and the
cookbook-specific enums (Cookbook.ContentType, Cookbook.Topic).
Entry fields
Each entry in the entries list is a Dhall record with these fields:
key (Text, required)
Unique identifier for this entry within the catalog. Use kebab-case (e.g., "event-sourcing-patterns"). Duplicate keys cause a validation error.
title (Text, required)
Human-readable title. Cannot be empty. Prefer task-oriented phrasing: "How to X" or verb-first (e.g., "Event Sourcing Patterns with Message-DB").
contentType (Cookbook.ContentType, required)
What form the content takes. One of:
Cookbook.ContentType.SampleCode — runnable or copy-pasteable code examples
Cookbook.ContentType.Instructions — step-by-step procedures to follow
Cookbook.ContentType.Pattern — reusable design or code patterns to adapt
Cookbook.ContentType.Configuration — config file templates or environment setup
Cookbook.ContentType.Template — project or file scaffolding templates
Cookbook.ContentType.Other "custom" — escape hatch for custom types
topics (List Cookbook.Topic, required)
Domain areas this entry covers. Must have at least one topic — an empty list causes a
validation error. Multiple topics are allowed. Values:
Cookbook.Topic.Database
Cookbook.Topic.API
Cookbook.Topic.Testing
Cookbook.Topic.ErrorHandling
Cookbook.Topic.Deployment
Cookbook.Topic.Security
Cookbook.Topic.Performance
Cookbook.Topic.Streaming
Cookbook.Topic.Effects
Cookbook.Topic.Migration
Cookbook.Topic.Observability
Cookbook.Topic.Other "custom" — escape hatch for custom topics
packages (List Text, required)
Related libraries or tools this entry uses (e.g., ["hasql", "hasql-pool"]). Can be an
empty list [] : List Text if no specific packages apply.
language (Schema.Language, required)
Target language or tool. Accessed via Schema.Language.X:
Haskell, TypeScript, JavaScript, Python, Go, Rust, Java, Kotlin, Swift,
Ruby, Elixir, Clojure, Scala, Dhall, Nix, SQL, Shell, Other "custom"
audience (Schema.DocAudience, required)
Who this entry is for. Accessed via Schema.DocAudience.X:
Module — module/library developers
User — end users of the API/library
API — API consumers
Internal — internal team members
Other "custom" — escape hatch
location (Schema.DocLocation, required)
Where the cookbook file lives. Accessed via Schema.DocLocation.X:
LocalFile "path" — relative path to a file from project root
LocalDir "path" — relative path to a directory
RepoPath "path" — path within a repo (for wrapper projects)
Url "https://..." — external URL
description (Optional Text, optional)
Brief summary. None Text is the published default, so you can
omit this line entirely to get no description. Use Some "text"
to provide one.
Complete example
let Schema =
https://raw.githubusercontent.com/shinzui/mori-schema/<commit>/package.dhall
sha256:<hash>
let Cookbook =
https://raw.githubusercontent.com/shinzui/mori-schema/<commit>/extensions/cookbook/package.dhall
sha256:<hash>
in Cookbook.CookbookCatalog::{
, entries =
[ Cookbook.CookbookEntry::{
, key = "event-sourcing-patterns"
, title = "Event Sourcing Patterns with Message-DB"
, contentType = Cookbook.ContentType.SampleCode
, topics = [ Cookbook.Topic.Database, Cookbook.Topic.Streaming ]
, packages = [ "message-db-hs", "tan-event-source" ]
, language = Schema.Language.Haskell
, audience = Schema.DocAudience.Module
, location = Schema.DocLocation.LocalFile "docs/event-sourcing.md"
, description = Some "Event types, stream naming, projections, and subscriptions"
}
, Cookbook.CookbookEntry::{
, key = "cli-command-pattern"
, title = "How to Add a CLI Command"
, contentType = Cookbook.ContentType.Instructions
, topics = [ Cookbook.Topic.API ]
, packages = [ "optparse-applicative" ]
, language = Schema.Language.Haskell
, audience = Schema.DocAudience.Module
, location = Schema.DocLocation.LocalFile "docs/architecture/CLI.md"
, description = Some "Step-by-step guide to creating a new CLI command"
}
, Cookbook.CookbookEntry::{
, key = "nix-dev-setup"
, title = "Development Environment Setup"
, contentType = Cookbook.ContentType.Configuration
, topics = [ Cookbook.Topic.Deployment ]
, packages = [] : List Text
, language = Schema.Language.Nix
, audience = Schema.DocAudience.User
, location = Schema.DocLocation.LocalFile "docs/dev-setup.md"
}
]
}
Validation rules
The cookbook loader validates entries at load time during mori register and mori cookbook list.
All three rules must pass or the entire catalog is rejected:
-
No duplicate keys — every key must be unique within the catalog.
Error: Duplicate cookbook key: <key>
-
Non-empty topics — every entry must have at least one topic in its topics list.
Error: Cookbook entry '<key>' has no topics
-
Non-empty title — every entry must have a non-empty title.
Error: Cookbook entry '<key>' has an empty title
How to help the user
Creating a cookbook from scratch:
- Check if
mori/cookbook.dhall already exists — if so, read it first
- Ask what resources the user wants to catalog (code examples, guides, patterns, configs)
- For each resource, determine the content type, topics, related packages, and file location
- Write
mori/cookbook.dhall with the correct imports and entries
- Validate:
mori cookbook list (should display entries without errors)
- Optionally register:
mori register to push to the registry for cross-project querying
Editing an existing cookbook:
- Read the current
mori/cookbook.dhall
- Make the requested changes (add entries, update fields, remove entries)
- Validate:
mori cookbook list
- If registered, re-register:
mori register
Common mistakes and fixes:
- Empty topics list — most common error. Always include at least one
Cookbook.Topic.* value.
- Wrong Optional syntax — use
Some "text" (not bare "text") for description, and None Text (not None) to omit.
- Duplicate keys — each entry needs a unique
key. Check existing entries before adding.
- String instead of enum — use
Cookbook.ContentType.SampleCode (not "SampleCode"), Cookbook.Topic.Database (not "Database").
- Empty packages list without type annotation — use
[] : List Text (not bare []) for an empty packages list, since Dhall needs the type annotation.
- Using bare records instead of
:: — write
Cookbook.CookbookEntry::{ key = "…", … } and skip any
defaulted optional field. Writing { key = "…", … } as a
plain record is accepted by Dhall but will break as soon as
the upstream CookbookEntry bundle adds a new defaulted
field.
- Wrong schema namespace —
Schema.ContentType.SampleCode
and Schema.Topic.Database are NOT real. Content types live
in Cookbook.ContentType.X and topics in Cookbook.Topic.X;
Language, DocAudience, and DocLocation live in
Schema.X.
CLI commands for verification
mori cookbook print-schema
mori cookbook list
mori cookbook list --content-type sample-code
mori cookbook list --topic database
mori cookbook list --package hasql
mori cookbook list --language haskell
mori cookbook show event-sourcing-patterns
mori register
mori extension query cookbook
mori extension query cookbook --topic database
mori extension query cookbook --content-type pattern