Skip to main content

Recipes

Save multi-panel workspace presets as recipes. Launch terminals, AI agents, and dev servers in one click — globally, per-project, or shared with your team via git.

Updated
Reviewed

What Are Recipes?

Recipes are saved workspace presets that launch multiple panels at once. Each recipe defines a combination of terminals, AI agent sessions, and dev server panels, complete with commands, starting prompts, and environment variables. You can spin up your preferred layout in one click, and every panel runs in the active worktree's directory so agents and terminals always start in the right branch.

A single recipe can open up to 10 panels in any combination. You can launch recipes from the RecipeRunner (the empty state when no panels are open), from the new worktree dialog, or broadcast them to multiple worktrees at once via Bulk Operations.

Recipe Scopes

Recipes exist in three tiers that control where they are available and how they are stored.

TierScopeStorageShared via Git
GlobalAll projects, machine-wideApp-level configNo
TeamCurrent project, shared with team.canopy/recipes/{name}.jsonYes
ProjectCurrent project, local onlyMachine-local storeNo

Team recipes are not created directly. Instead, you promote a Global or Project recipe to Team status using Save to Repo in the Recipe Manager. This writes the recipe to .canopy/recipes/ where it can be committed and shared via git.

Team recipes take priority over project-local recipes. If a team recipe and a project recipe share the same name, only the team version is shown. New project recipes default to in-repo storage, so they are ready to be committed and shared from the start.

Note
Scope is locked after creation. You cannot change a recipe from Global to Project or vice versa after saving it.

The Recipe Manager

The Recipe Manager is a dedicated dialog for managing all your recipes across all three tiers. Open it from the action palette (Cmd+Shift+P and search for "Recipe Manager").

The dialog shows three labelled sections: Global Recipes, Team Recipes (visible when .canopy/recipes/ contains recipe files), and Project Recipes. Each section header has a "New" button for creating recipes in that tier.

Per-Recipe Actions

Hover over any recipe row to reveal action buttons:

ActionNotes
EditOpens the recipe editor. Available for all recipe types.
Save to RepoPromotes a global or project recipe to a team recipe. Not shown for recipes already in the repo.
Export to ClipboardCopies the recipe as JSON. Shows a checkmark for two seconds to confirm.
Export to FileOpens a save dialog to write a .json file.
DeleteRemoves the recipe.

Creating Recipes

Click New Global Recipe or New Project Recipe in the relevant section header. You can also right-click any worktree card and select Save Layout as Recipe to capture all currently active panels, including their agent types, commands, and prompts.

Importing Recipes

The Project Recipes section footer has two import buttons: Import from Clipboard (opens a dialog with a text area and scope selector) and Import from File (opens a file picker for .json files). Import validation checks for required fields and drops any invalid panel definitions rather than rejecting the whole recipe. The import only fails if no valid panels remain after validation.

The Recipe Editor

The recipe editor opens when you create or edit a recipe. It has recipe-level settings at the top and panel definitions below.

Recipe-Level Fields

  • Recipe Name — required, auto-focused when the editor opens
  • Scope — Global or Project. On edit, this is read-only since scope cannot change after creation
  • Show in Empty State — pins the recipe to the Pinned section of the RecipeRunner
  • Auto-assign Issue — controls whether the linked GitHub issue is auto-assigned to you when creating a worktree with this recipe. Options: "Always assign to me" (default), "Ask before assigning", "Never assign". See GitHub Integration for issue linking setup

Panel Definitions

Each recipe contains one to ten panels. The available fields depend on the panel type:

Panel TypeFieldsExit Behavior
TerminalTitle (optional), Command (optional)Send to Trash (default), Keep for Review, Remove Completely
Agent (Claude, Gemini, Codex, OpenCode)Title, Initial Prompt (optional, supports variables)Keep for Review (default), Send to Trash, Remove Completely
Dev PreviewTitle, Dev Command (auto-detects from package.json)Send to Trash (default), Keep for Review, Remove Completely

Every panel also supports optional environment variables and a custom title for the tab label. All panels run in the active worktree's directory.

Variables in Prompts

Initial prompts on agent panels support variable replacement using {{double_curly}} syntax. Variables are resolved at run time from the worktree's context and are case-insensitive.

VariableResolves ToExample
{{issue_number}}GitHub issue number linked to the worktree#123
{{pr_number}}Pull request number linked to the branch#456
{{number}}Issue number if set, otherwise PR number#123
{{worktree_path}}Absolute path to the worktree directory/home/user/project
{{branch_name}}Git branch namefeature/issue-42

If a variable's context is missing (no issue linked, for example), it resolves to an empty string. Unknown variable names are left unchanged. When both an issue and PR are linked, {{number}} prefers the issue number.

Note
Variable replacement uses the GitHub context linked to each worktree. See GitHub Integration for how to link issues and PRs to worktrees.

Team Recipes

Team recipes are stored in .canopy/recipes/ inside the repository and committed to git, making them available to everyone working on the project. Each recipe is saved as an individual JSON file, which keeps git diffs clean and minimizes merge conflicts.

Canopy auto-loads any .canopy/recipes/*.json files when a project is opened. New team members get access to shared recipes automatically after pulling. Save to Repo writes directly to .canopy/recipes/ and does not require the "Store settings in repository" toggle to be enabled first.

Saving a Recipe to the Repo

  1. Open the Recipe Manager (Cmd+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. The recipe is written to .canopy/recipes/{recipe-name}.json
  4. Choose Delete Original to remove the local copy, or Keep Both to keep it alongside the team version

Environment Variable Handling

When saving a recipe to the repo, Canopy blanks all environment variable values while preserving the keys. This prevents secrets from being committed to git. The keys remain as a signal to teammates about which environment variables need to be filled in locally.

Committing Team Recipes

Canopy writes the recipe file but does not commit it automatically. You need to stage and commit the file yourself.

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

Export and Import

Exporting Recipes

Recipes can be exported in two ways from the Recipe Manager:

  • Export to Clipboard copies the recipe as JSON (without the internal project ID). A checkmark appears for two seconds to confirm the copy.
  • 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 to choose Global or Project.
  • Import from File opens a file picker for .json files.

During import, Canopy validates the recipe structure, sanitises control characters from commands and prompts, and drops any panels with invalid types. The import only fails if no valid panels remain after validation.

RecipeRunner (Empty State)

When a worktree has no active panels, the content area shows the RecipeRunner. This is the primary surface for discovering and launching recipes.

Grid Mode and List Mode

With six or fewer recipes, the RecipeRunner uses a grid layout (two columns for one to two recipes, three columns for three to six). When you have more than six recipes, it switches to a compact list mode with a search box that auto-focuses for quick filtering.

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 uses 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
EnterRun the focused recipe
EscapeClear search
Cmd+EEdit the focused recipe
Cmd+NOpen the create recipe dialog

Context Menu

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

Zero-Recipe State

When no recipes exist yet, the RecipeRunner shows a brief description of what recipes do and a Create new recipe button to get started.

Example Recipes

Recipe NamePanels
Full Stack DevClaude Code + npm run dev terminal + Dev Preview
Code ReviewClaude Code (prompt: "Review the latest changes") + Gemini CLI (prompt: "Check for security issues")
Test & Watchnpm run test:watch terminal + Dev Preview
Quick FixClaude Code (prompt: "Fix the failing tests")
Tip
Try Save Layout as Recipe after arranging your workspace. Right-click any worktree card to capture all active panels, including agent types, commands, and prompts, as a new recipe.