icaoberg / CookLang: A Markup Language for Recipes

Created Sat, 16 May 2026 00:00:00 +0000 Modified Sat, 16 May 2026 15:39:26 -0400
CookLang: A Markup Language for Recipes

If you have ever managed a recipe collection, you have probably felt the friction: screenshots buried in your camera roll, bookmarked pages that disappear when a site goes down, proprietary apps that lock your data behind an account. CookLang is a different approach. It is a plain-text markup language for writing recipes in a format that is human-readable today and machine-parseable forever.


The Format

A CookLang recipe is just a .cook file. Three special annotations carry all the structure:

Annotation What it marks Example
@ingredient{amount%unit} An ingredient @flour{2%cups}
#cookware{} A piece of cookware #skillet{}
~{duration%unit} A timer ~{20%minutes}

Everything else is plain prose. Here is a minimal example:

Preheat the #oven{} to 180°C.

In a large #bowl{}, combine @flour{2%cups}, @sugar{1%cup}, and @salt{1%tsp}.

Bake for ~{25%minutes} until golden.

That is it. No YAML blocks, no nested JSON, no proprietary schema. The file reads naturally as a recipe and can be parsed by any CookLang-aware tool to automatically extract the ingredient list, generate a shopping list, or run the timers.

The full language specification lives at github.com/cooklang/spec.


cook-cli

The flagship tool is CookCLI — a single Rust binary that handles recipe management, shopping lists, and even serves a web interface for browsing your collection from any device on your network.

Installation

# macOS / Linux via Homebrew
brew install cookcli

# via Cargo (Rust)
cargo install cookcli

Binaries for all platforms are also available on the releases page.

Key Commands

Display a recipe

cook recipe bread.cook

Parses the file and prints a formatted view with the ingredient list separated out.

Scale a recipe

cook recipe --servings 4 bread.cook

All quantities are automatically scaled.

Generate a shopping list

cook shopping-list monday.cook tuesday.cook wednesday.cook

Combines ingredients across multiple recipes, deduplicates, and groups them by store section. Useful for weekly meal prep.

Run a local web server

cook server

Starts a web UI at http://localhost:9080 so you can browse your entire recipe collection from a phone or tablet while cooking — no cloud account required.

Build a static site

cook build --output public/

Generates a self-contained static website from your recipe directory. You can host it anywhere.

Import a recipe from the web

cook import https://example.com/pasta-recipe

Converts a recipe page from hundreds of supported cooking websites into a .cook file, saving it locally.

Search your collection

cook search "chicken"

Full-text search across all .cook files in the current directory.

Why It Follows the Unix Philosophy

cook works well with pipes and standard shell tools. Recipes are files; files live in directories; directories can be version-controlled with git. Your recipe history is a git log. Recovering a deleted recipe is a git checkout. Sharing a recipe is a pull request.


Plugins and Integrations

The CookLang ecosystem has grown significantly. Here are the highlights:

Editor Plugins

VS Code The official VS Code extension adds syntax highlighting and inline validation. A companion theme called Endless Bounty is optimized specifically for .cook files.

Obsidian cooklang-obsidian (330+ stars) renders .cook files as formatted recipe cards inside Obsidian, complete with interactive timers. If you already manage your notes in Obsidian, this is a natural fit.

Neovim / Helix / Zed / Emacs tree-sitter-cooklang provides a Tree-sitter grammar usable across all editors that support the Tree-sitter ecosystem. For Emacs specifically there is also cook-mode.

Language Server cooklang-language-server implements the Language Server Protocol (LSP), giving any LSP-capable editor diagnostics, hover information, and completions.

Static Site Generators

If you want to publish your recipes as a website, there are plugins for the major frameworks:

Plugin Framework
eleventy-plugin-cooklang Eleventy
jekyll-cooklang-converter Jekyll
astro-cooklang Astro
vite-plugin-cooklang Vite
vitepress-plugin-cooklang VitePress
markdown-it-cooklang markdown-it

Mobile Apps

Cook for iOS and Cook for Android are native apps that sync with your local recipe directory via iCloud Drive or the Sync Agent desktop daemon. They support interactive timers and shopping list generation directly from your .cook files.

Home Assistant

homeassistant-cookcli is a custom component that exposes your recipe collection to Home Assistant. Combined with a Raspberry Pi and a touchscreen, you can build a dedicated kitchen display that shows the current recipe step and runs timers through your smart home.

Cookbook Export

  • cooklang-epub — packages your recipe collection as an EPUB ebook
  • cookbook-creator — renders a PDF cookbook from your .cook files
  • cooklang-to-md — converts recipes to plain Markdown for use anywhere

Federation

Federation is a self-hosted recipe discovery system. Run a federation node to make your recipe collection searchable by others running compatible nodes — a distributed, open alternative to recipe platforms.


Getting Started

The quickest path is:

# Install
brew install cookcli

# Write your first recipe
cat > pasta.cook << 'EOF'
Boil @water{1%liter} in a large #pot{}.

Add @pasta{200%g} and cook for ~{10%minutes}.

Drain, then toss with @olive oil{2%tbsp} and @parmesan{50%g}.
EOF

# View it
cook recipe pasta.cook

# Start the web UI
cook server

If you use VS Code, install the CookLang extension and open the file — syntax highlighting kicks in immediately.


Why This Matters

The tools we use to manage recipes are unusually bad given how important cooking is. Most approaches trade data ownership for convenience: your recipes live in someone else’s database, behind a login, in a format you cannot export cleanly. CookLang makes a different bet: plain text, version-controlled, offline-first, with a rich tooling ecosystem built on top of an open spec.

The format is small enough to understand in five minutes and stable enough to build on. That combination is rare.