# CookCLI recipe management with a self-hosted web UI

> CookCLI combines Cooklang recipe processing, shopping-list and menu commands, and an embedded web server in one Rust binary. It fits users who want file-backed recipes with optional browser access, while its feature set is broader than a plain terminal recipe viewer.

**cooklang/cookcli** — Recipe Management CLI + embedded web-server in one binary

- Repository: https://github.com/cooklang/cookcli
- Website: https://cooklang.org/cli/
- Stars: 1,417 · Forks: 117
- Language: Rust
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/cooklang-cookcli

## CookCLI's file-backed recipe workflow

CookCLI addresses a specific problem: recipes are often scattered across text editors, shopping applications, and browser bookmarks, while the source files remain awkward to automate. It treats Cooklang files as the central data and provides command-line operations for displaying recipes, constructing shopping lists, planning meals, generating reports, searching recipes, tracking pantry items, and exposing recipes through a web interface.

The intended audience is broad. A home cook can use the commands without learning an application-specific database. A developer can place the `cook` binary in scripts because the recipe collection remains in files. A self-hosting user can run the embedded server instead of assembling a separate frontend and backend.

That design does make syntax matter. CookCLI depends on Cooklang recipe files and `.menu` files, rather than importing arbitrary cooking information automatically. The README documents `cook import` as a website scraping feature, and the default Cargo features include `import`, but it does not describe supported websites, extraction quality, or failure handling for imports. Automation should therefore begin with a small, known collection rather than assume every site can be converted.

## CookCLI command and web-server architecture

The root Rust package produces a binary named `cook`. The workspace also contains `crates/core` and `crates/format`, separating Cooklang processing and formatting from the executable. The web interface is not a separate application that must run beside the CLI. Its Cargo feature pulls in Axum, Tower middleware, file notification support, an asynchronous runtime, and template-related dependencies.

The server and CLI operate on the same recipe folder. Recipe parsing and formatting happen in the Rust library and command layer, while browser-facing HTML, CSS, and JavaScript assets live under `templates/`, `static/`, and `locales/`. The package configuration embeds those directories into the distributed crate. This packaging choice supports the claim that the command-line tool and web UI are delivered together, although the README does not document the complete request-routing structure.

The Cargo features reveal several optional cost and compatibility boundaries. `server` enables the HTTP stack. `sync` includes `server` plus the Cook Cloud sync client and SQLite bindings. `import` enables website importing, `lsp` enables the language server, and `self-update` enables binary updating. Docker builds deliberately use only `server,lsp`, because self-update is not useful inside a container and import would add another dependency. Users compiling a custom binary can therefore avoid unused components, provided they understand the enabled command set.

The web application also includes an editor bridge that spawns `cook lsp`. The repository contains Playwright configuration and npm scripts for Chromium, Firefox, WebKit, mobile browsers, accessibility checks, and browser debugging. These are development and test facilities, not evidence of a separately operated hosted service.

## Installing CookCLI and opening the first recipe

Homebrew provides the shortest documented macOS and Linux installation path. After installation, create a dedicated recipe directory, seed it with the included examples, and open one recipe in CookCLI's human-readable output.

```bash
brew install cookcli
```

Homebrew makes the `cook` executable available on the command line. The README also offers release downloads, RPM packages, Debian packages, and Cargo installation as alternatives, but this tutorial uses Homebrew before introducing the non-Cargo paths.

Create and populate a recipe directory with the sample collection:

```bash
mkdir my-recipes && cd my-recipes
cook seed ./
cook recipe "Neapolitan Pizza.cook"
```

`cook seed ./` writes sample recipes and folders into the current target. The `cook recipe` command then prints the selected recipe's metadata, ingredients, cookware, and numbered steps in a terminal-readable form. In the README example, "Neapolitan Pizza" reports six servings and includes a linked recipe for pizza dough.

For a source installation, the README recommends Cargo with locked dependencies:

```bash
cargo install cookcli --locked
```

The `--locked` option uses the dependency versions recorded in `Cargo.lock`. The README warns that compiling from source takes several gigabytes of memory and disk. That makes a prebuilt package or binary the clearer choice for memory-constrained systems.

## Building shopping lists and weekly menus in CookCLI

CookCLI's practical advantage over a static recipe viewer is the conversion of recipes into planning data. The shopping-list command accepts multiple recipe paths and combines their ingredients. The menu format adds day and meal sections, references recipes with Cooklang links, and permits inline ingredients.

A weekly menu has YAML-like metadata followed by sections such as Saturday and Sunday. Each meal can point at a `.cook` file or declare ingredients inline. That makes the menu useful for both scheduled cooking and aggregation: a shopping list can cover the entire plan rather than requiring recipes to be selected one by one.

The README excerpt does not document the complete shopping-list options. It does not state how duplicate ingredients are normalized, how quantities with incompatible units are merged, whether recipe yields are rescaled, or whether ingredient ordering can be configured. Those are operational details to check before using the output as an authoritative grocery list. The README also does not identify CookCLI as a nutritional calculation engine.

Reports are listed as a capability, but the README gives no command syntax, report schema, or execution model. The repository's presence of tests does not fill that gap. Engineers integrating CookCLI into automation should begin with commands whose complete output and failure behavior are documented, then confirm less visible commands against the linked CookCLI reference.

## Running the CookCLI server locally and with Docker

The local server serves the current recipe directory and can open the browser automatically. The README's example reports the web UI on `http://localhost:9080`.

```bash
cook server --open
```

This is the simplest path for reviewing recipes, menus, shopping lists, and pantry views through a browser. The output also shows the directory from which recipe files are served, which is useful when checking that the command was launched in the intended collection.

A container deployment is defined in `docker-compose.yml`. It uses the published image, maps host port `9080` to container port `9080`, and mounts `./recipes` at `/recipes`:

The repository configuration uses this service definition:

```yaml
services:
 cookcli:
 image: ghcr.io/cooklang/cookcli:latest
 ports:
 - "9080:9080"
 volumes:
 -./recipes:/recipes
 restart: unless-stopped
```

The `latest` tag simplifies startup but does not pin a deployed version. Operators who need reproducible upgrades should account for that distinction when selecting an image reference.

The compose file also documents an important exposure boundary. Opening `http://localhost:9080` needs no origin configuration, but access through a host name or reverse-proxy domain requires that origin to be named. The example environment variable is `COOK_CORS_ORIGIN`, and several origins can be separated by commas. Without sign-in configuration, the web UI should not be treated as access control.

## CookCLI limitations for shared and constrained deployments

CookCLI is not a complete multi-user service according to the repository documentation. Its compose configuration can require sign-in before recipe changes, but users must be added through a container command and the configuration directory must be mounted. The README does not describe roles, concurrent editing conflict handling, audit history, database backup procedures, or a documented recovery process for the server.

Origin restrictions are also easy to overlook. The compose comments state that the server refuses answers when a required host name has not been named. A reverse proxy can therefore produce connection or access failures that appear to be network problems but originate in the server's origin policy.

File ownership is another concrete constraint. The container runs as `1000:1000` by default, and the compose file suggests setting `user` to the host UID and GID to avoid mounted-volume permission problems. Recipe libraries stored on NFS, Windows-mounted paths, or permission-restricted hosts should be checked before relying on the default container identity.

Cook Cloud sync is opt-in rather than part of ordinary local operation. The README associates it with `cook login` and says `cook server` then keeps the recipe folder synchronized through Cook Cloud under Cook Basic. It does not state file-conflict rules, offline behavior, retention, account requirements, or the operational boundary between local files and cloud state. Users who need guaranteed local ownership should first establish which operations require the sync service.

## CookCLI maintenance, upgrades, and alternative architecture

The repository is not archived. Its last push was on 2026-10-15, and the listed `v0.38.1` release was published on 2026-10-09 after releases for `v0.38.0` and `v0.37.0`. This indicates recent development activity, but it does not guarantee compatibility for every deployment.

The default binary includes self-update, sync, server, import, and LSP features. Its `Cargo.lock` supports reproducible Cargo builds when `--locked` is used. Package-based installations have a different upgrade path: Homebrew, RPM, and Debian updates follow their respective package mechanisms. Docker users face a distinct lifecycle because the compose example tracks `latest`, while self-update is excluded from the container build.

The real alternative is not another recipe renderer. It is to treat Cooklang files as source data consumed by separate automation and deploy a separate web application around them. That approach can decouple frontend releases, access control, and application operations from the CLI. Its cost is greater integration work and more components to coordinate. CookCLI's single-binary model avoids that operational separation, but also concentrates recipe processing, HTTP serving, synchronization, editor integration, and optional importing in one project.

For organizations with existing infrastructure, a minimal pipeline can parse or format Cooklang content through existing jobs while CookCLI remains responsible for recipe-oriented commands. CookCLI is the better fit when file portability and a ready-made web interface matter more than independent service scaling.

## Conclusion

CookCLI is suitable for home users and developers who want Cooklang recipes stored as files and accessible through scripts, menus, shopping lists, or a private browser interface. It is a poor fit for teams requiring a separately deployed application with an independently documented service architecture. Before adoption, verify the platform package or Docker bind mount, the authentication requirement, and whether Cook Cloud sync is necessary for the intended workflow.

## FAQ

### How do I install CookCLI on macOS or Linux?

The README documents Homebrew installation with `brew install cookcli`. It also provides release downloads, Debian and RPM packages, and Cargo installation, depending on the preferred packaging method.

### How do I create sample recipes and view one with CookCLI?

Create a directory, run `cook seed ./`, and select a file with `cook recipe "Neapolitan Pizza.cook"`. The recipe command prints metadata, ingredients, cookware, and steps in a human-readable format.

### Can CookCLI serve recipes through a web browser?

Yes. The documented command is `cook server --open`, and the README example serves the interface on `http://localhost:9080`. The compose configuration also publishes port `9080` and mounts `./recipes` at `/recipes`.

### Does CookCLI require Cook Cloud for normal local use?

The README presents local commands and the web server separately from cloud synchronization. After `cook login`, `cook server` can synchronize the recipe folder through Cook Cloud sync, but the README does not make that service a prerequisite for local browsing.

### How do I control access to the Docker-hosted CookCLI server?

The compose comments describe mounting a configuration directory and adding a user with `docker compose run --rm cookcli cook server user add <name>`. They also document `COOK_CONFIG_DIR`, reverse-proxy origins through `COOK_CORS_ORIGIN`, and UID/GID adjustment for mounted recipe files.

## Sources

- [cooklang/cookcli on GitHub](https://github.com/cooklang/cookcli)
- [License: MIT](https://github.com/cooklang/cookcli/blob/main/LICENSE)
- [Project website](https://cooklang.org/cli/)
- [README](https://github.com/cooklang/cookcli/blob/main/README.md)
- [Releases](https://github.com/cooklang/cookcli/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cooklang-cookcli
