Recipes — the leverage switch

Recipes are named hook bundles you engage or disengage on demand. Each recipe bundles a set of Stop/SessionStart hooks and/or cron actions behind one name. The user flips a recipe on or off with the CLI; the system honors the switch everywhere that matters.

Why recipes exist

A harness that runs unconditionally is a framework. A harness you can engage per context is leverage. Recipes split the difference between:

Recipes let you say "engage the PID loop while I'm asleep, disengage it while I'm editing a skill" without touching hook config files.

How it works

Every hook and cron worker consults state/engaged.json at the top of its body via state/bin/sync/is-engaged.sh. If the recipe is not in the engaged list, the hook exits 0 without doing anything. Fresh installs default to disengaged for everything except ambient-sync — safety valve.

state/
  engaged.json           ← the switch (JSON array of recipe names)
  recipes/
    ambient-sync.md      ← default on — Stop pushes, SessionStart pulls
    pid-loop.md          ← default on — auto-regen + aggregate evals
    autopilot.md         ← opt-in    — continuous cron advancing goals
    nightly-digest.md    ← opt-in    — SessionStart "what changed" summary
  bin/sync/
    is-engaged.sh        ← the gate helper (plain grep, no jq)

Installed recipes

ambient-sync — default on

Disengage when: offline, mid-experiment, or debugging sync itself.

pid-loop — default on

Disengage when: you don't want auto-regen clobbering work, or cost-sensitive.

autopilot — opt-in

the goal file + tail of the tick log as context

Engage this when: you want the system to advance goals while you sleep. Disengage when: you want the file tree quiet.

nightly-digest — opt-in

into the system prompt

Engage this when: you want every session to open with cron outcomes, quorum promotions, new frictions.

CLI surface

snappy-os recipes                 # list + engaged state
snappy-os engage <recipe>         # turn on
snappy-os disengage <recipe>      # turn off

Adding a recipe

  1. Write state/recipes/<name>.md with the frontmatter shape:
   name: foo
   title: ...
   engages:
     - hook: Stop
       action: ...
   cron: []
   requires: []
   disengage_side_effects: ...
   leverage: ...
  1. Make the hook script consult state/bin/sync/is-engaged.sh foo and

short-circuit on non-zero exit.

  1. Register it in state/index.md under the Recipes section so check.ts

stays truthful.

That's the whole contract.