Recipes
A recipe is a bash script that Reach can run against the session you are looking at. Unlike a snippet, which is one command you paste, a recipe is a small program: it has a name and a version, takes parameters, declares how risky it is, and is meant to be run more than once on more than one machine.
Recipes live in the Recipes panel in the sidebar. Installed lists what is on this machine; Browse lists what the registry offers.
Running a recipe
Section titled “Running a recipe”- Open the terminal you want to run it on. Recipes only run against an open session.
- In the Recipes panel, click Run on a recipe.
- The dialog names the target session, shows the risk analysis, and asks for any parameters.
- Show the exact command displays what will be written to the terminal, verbatim.
- For anything above mutating, type the recipe’s id to confirm. A button you can hit by reflex is not a confirmation.
- Click Run. The recipe runs in your terminal, where you can watch it.
The recipe file
Section titled “The recipe file”A recipe is an ordinary bash script with its metadata in leading # comments. It runs with bash recipe.sh outside Reach and shellcheck reads it — a format only Reach could execute would be a format nobody could audit, and a recipe is arbitrary code aimed at a server.
#!/usr/bin/env bash# @reach-recipe# id: harden-ssh# name: Harden the SSH daemon# description: Disables root login and password auth, then reloads sshd.# version: 1.0.0# author: you# tags: security, ssh# targets: debian, ubuntu# danger: sensitive# param: SSH_PORT | Port sshd should listen on | 22# param: ADMIN_USER | Account that keeps shell access |# @end
set -euo pipefailecho "Hardening sshd on port ${SSH_PORT} for ${ADMIN_USER}"| Field | Meaning |
|---|---|
id | Lowercase letters, digits and hyphens. Becomes the filename. |
name, description | What people see in the list. |
version | Bump it when the script changes. |
tags | Search terms, comma separated. |
targets | Which systems you wrote it for. Advisory — nothing enforces it. |
danger | benign, mutating, sensitive or destructive. See below. |
param | NAME | label | default. Arrives as an environment variable. A parameter with no default is required. |
Everything after # @end is the script.
How a recipe runs
Section titled “How a recipe runs”Reach sends the whole script to the session as one heredoc:
SSH_PORT='22' ADMIN_USER='alex' bash -s <<'REACH_RECIPE_…'…REACH_RECIPE_…Two consequences worth knowing:
set -euo pipefailworks, and so does the exit status. A failing step stops the recipe rather than carrying on into a half-configured machine.- A recipe cannot prompt.
bash -sowns standard input. Anything you would have asked the user, take as aparaminstead.
Parameter values are single-quoted before they reach the shell. A value cannot become a command.
Risk analysis
Section titled “Risk analysis”Before running, Reach reads the script and classifies every line using the same rules the MCP server applies to an AI’s commands.
| Level | Means |
|---|---|
| Benign | Reads only. No side effects found. |
| Mutating | Changes state, recoverable. |
| Sensitive | Changes system configuration or service availability. Installing a package or restarting a service is sensitive. |
| Destructive | Data loss, or a machine that will not boot. |
The level shown — and the one that decides whether you must type the id to confirm — is the worse of what the author declared and what the scan found. The scan cannot see through a variable: sed -i … "$CONFIG" looks harmless to it even when CONFIG is /etc/ssh/sshd_config. The author can, so an honest danger: sensitive in the header counts even when the scan finds nothing, and the dialog says that is where the rating came from.
The dialog quotes the lines responsible for each finding, and calls out two things separately:
- Lines that download and run code —
curl … | shand the like. Nothing can see what will arrive, so the pattern itself is the warning. - An author who understated the risk. If the header says
benignand the scan saysdestructive, you are told, and the higher level wins. Usually it is a stale header. Sometimes it is not.
Be clear about what this is: pattern matching over shell text. It makes an obvious hazard impossible to miss. It cannot make a subtle one impossible to write. What actually decides whether a registry recipe is safe is the person who reviewed it.
Writing your own
Section titled “Writing your own”Click + in the Recipes panel. The template that opens explains every field in place, so the first recipe is an edit rather than a lookup. The editor parses as you type and shows the same errors the save will, and the status bar shows the parsed id, name, parameter count and risk level.
Recipes are stored as plain .sh files in Reach’s data directory. Edit them there if you prefer; Reach reads them back.
The registry
Section titled “The registry”Browse fetches the community registry. Each entry carries a SHA-256 of the script, and Reach refuses to install one whose bytes do not match — what you install is byte for byte what a maintainer reviewed.
To contribute a recipe, open a pull request against reach-recipes-registry. The merge is the trust boundary; the hash pin is what makes it hold. The repository’s CONTRIBUTING.md covers the format, the validator that CI runs, and the house rules — check before you break, back up what you edit, validate before applying, reload rather than restart, and say on the last line what to do if it went wrong.
Installed recipes are marked From registry and keep working if the registry is later unreachable.