Skip to main content

Launch and Share Recipes

Using a recipe once it exists: launching from the empty-canvas launcher, running one across several worktrees at once, sharing recipes with a team through the repository, and exporting or importing them.

Reviewed

The Empty-Canvas Launcher

When a worktree has no open panels, the canvas is not blank — it is a launcher. Recipes are its first section, not the whole of it. Five sections stack down the column, each arriving 30 ms after the one above it so the surface reads as a sequence rather than a wall:

  1. Recipes — the recipe runner described below, shown once the project's recipes have loaded.
  2. Resume — a single line for the most recent resumable agent session, with a +N more entry into the searchable resume list when there is deeper history. It renders nothing at all when there is nothing to resume, so a genuine first run stays quiet. See Session Management.
  3. Quick actions — a chip per agent you keep on the toolbar, plus New terminal and Browse files, each showing its live keybinding, over a wider Search agents & panels… button that opens the panel palette.
  4. Project Pulse — the activity strip, when it is enabled. See Project Pulse.
  5. Tips — a rotating hint, shown only once you have launched an agent at least once.

Switching projects re-enters nothing, since the sections were already mounted, so Daintree replays the entry animation by hand on a project switch. The whole sequence is suppressed under prefers-reduced-motion, Daintree's own reduce-animations toggle, and performance mode.

Grid Mode and List Mode

With six or fewer recipes, the recipe section uses a grid layout: two columns for one to two recipes, three columns for three to six. Past six recipes, it switches to a compact list mode with a search box that auto-focuses for quick filtering. Every card and row prints its scope label, and a shadowed one is dimmed with its Overridden by Team badge.

In list mode, recipes are grouped into three sections:

  • Pinned: recipes with "Show in Empty State" enabled
  • Recent: the five most recently used recipes, ranked by frequency and recency
  • All: remaining recipes in alphabetical order

Search runs fuzzy matching on recipe names, weighted 70% by name relevance and 30% by usage frequency with a seven-day decay.

Keyboard Shortcuts

KeyAction
/ Navigate between recipes, wrapping through the create button
EnterRun the focused recipe
EscapeClear search
Command-E Control-E Control-E Edit the focused recipe

Where that edit chord is Ctrl+E — Windows and Linux — it is deliberately not captured while the search box has focus, because there it already means "move to end of line".

Status Banners

When you launch a recipe, the runner can show a banner at the top of the grid reporting what happened. There are two.

The spawn-failure banner, an error banner, appears when one or more panels fail to start. It reads like "Started 2 of 3 terminals. 1 failed: Dev server." and offers a Retry failed action. Retry re-runs only the panels that failed. The panels that already started keep running, untouched.

The unresolved-variables banner, a warning banner, appears when a prompt variable couldn't be resolved, for example when no issue is linked. It reads "Missing context for {{issue_number}}" and explains that "These variables stayed empty in the launched commands." The check covers the agent panel's initial prompt.

Stale banners clear themselves on the next run, or when you switch worktrees.

Context Menu

Right-click a recipe card or row for Run, Edit, Duplicate, Pin to Empty State (or Unpin), and Delete.

Before You Have Any Recipes

With no recipes saved, the section falls back to a create prompt — but it uses what it knows about the project first. If Daintree has detected run commands, up to two of them appear as suggestion pills, name on the left and command on the right, filtered to the ones that look like a dev, start, serve, test or build script. Clicking one runs it in a terminal. Only when nothing is detected does the line "Launch agents, dev servers, and terminals together with one click" stand alone. Either way, a Create your first recipe… button sits below.

The cap of two is deliberate: the empty state should be an obvious next click, not a catalog.

Launching Across Worktrees

Terminal spawning is rate limited — six per second, per project — so a burst of new PTYs cannot swamp the host. A recipe fanout would pay that toll once per terminal, which is why a recipe run does not queue as individual spawns.

Instead, every terminal in one recipe run shares a single spawn admission batch: one slot is claimed for the whole burst, and each terminal is admitted against it. Bulk worktree creation extends the same batch across worktrees, so creating worktrees for a list of issues and running the same recipe on each one cold-spawns as one bounded operation rather than one worktree at a time.

The batch is bounded, not unlimited. A batch admits at most 30 PTYs, and bulk creation chunks the work into as many batches as it needs rather than raising that ceiling. Each batch expires after 30 seconds, so a run that dies partway through cannot hold an admission slot open. Dev preview panels don't count against it — they aren't PTYs.

Two other caps apply to a single run. A recipe can define at most 10 panels, and a run dispatched by an agent through the MCP surface is capped at three terminals, so one approved tool call can't open a full ten-panel workspace. Anything past a cap comes back as a reported failure, not a silent drop. To drive the agents once they are running, see Fleet.

Team Recipes

Team recipes live in .daintree/recipes/ inside the repository and are committed to git, so everyone working on the project has them. Each recipe is saved as its own JSON file. That keeps git diffs clean and minimizes merge conflicts.

Daintree auto-loads any .daintree/recipes/*.json files when a project opens. New team members get the shared recipes after pulling, with no extra step. Save to repo writes straight to .daintree/recipes/ and does not need the "Store settings in repository" toggle enabled first.

Saving a Recipe to the Repo

  1. Open the Recipe Manager (Shift-Command-P Control-Shift-P Control-Shift-P and search for "Recipe Manager")
  2. Hover over a Global or Project recipe and click Save to repo
  3. Confirm in the dialog. Daintree writes the recipe to .daintree/recipes/{recipe-name}.json
  4. Choose Delete original to drop the local copy, or Keep both to keep it alongside the team version

Environment Variable Handling

When you save a recipe to the repo, Daintree blanks every environment variable value and keeps the keys. That keeps secrets out of git. The keys stay behind as a signal to teammates about which environment variables they need to fill in locally.

Your local values are not lost. Daintree keeps a machine-local mirror of each in-repo recipe holding the values you filled in, and reconciles the two whenever the repository copy changes, so a pull that rewrites the shared file does not blank your environment or reset the recipe's usage history.

Committing Team Recipes

Daintree writes the recipe file. It does not commit it. You stage and commit the file yourself.

Tip
After saving a recipe to the repo, run git add .daintree/recipes/ && git commit to share it with your team. Daintree auto-loads any .daintree/recipes/*.json files when a project is opened.

How recipe files are written

Every recipe write — a create, an edit, a delete, and the reconciliation pass that folds the repository's files back into your local store — goes through a single queue per project, one turn at a time. Each turn reads the state the previous turn left on disk. That closes the window where a reconcile and an edit could read the same snapshot and one of them silently win.

Reconciliation also refuses to guess. If .daintree/recipes/ is missing entirely — you checked out a commit that predates it — or if the directory could only be read in part, Daintree cannot tell a recipe a teammate deleted from one that simply doesn't exist on this branch. In that case it makes no filesystem changes at all and defers until the directory is readable again, so your local-only environment values and usage metadata survive a branch switch.

When a teammate edits the same recipe

If an in-repo recipe's file changed on disk between the moment Daintree loaded it and the moment you save — a git pull, a branch switch, a stash pop — the write is refused rather than applied. Your edit is rolled back in the UI and a dialog titled Recipe '<name>' changed on disk asks how to reconcile:

  • Reload from disk discards your in-flight edit and refreshes to match the file. This is the safer choice and the one the dialog leads with.
  • Overwrite recipe re-applies your edit on top, replacing the newer file content.
  • Dismissing the dialog leaves the rolled-back state in place, so you can look at the file and retry.

A related case is a filename collision: two recipes whose names reduce to the same file name. Only one can own the file. The other stays project-local rather than being dropped, and the collision is reported so you can rename one, instead of being logged where nobody would see it.

Export and Import

Exporting Recipes

The Recipe Manager exports recipes two ways:

  • Export to clipboard copies the recipe as JSON, without the internal project id or the shadowing marker. The button reads "Exported" for two seconds to confirm.
  • Export to file opens a save dialog to write a .json file to disk.

Importing Recipes

The Project Recipes section of the Recipe Manager has two import options:

  • Import from clipboard opens a dialog with a text area for pasting JSON and a scope selector for Global or Project.
  • Import from file opens a file picker for .json files.

On import, Daintree validates the recipe structure, rejects control characters in commands, arguments, dev commands and environment values, and drops any panel with an unknown type. The import only fails if no valid panels remain after validation.