Run: Recipes
Section titled “Run: Recipes”The Recipes API lets you define, manage, and execute named selector templates that encapsulate how Hoody resolves a candidate set for an application. A recipe pairs a selector template with an allowed_overrides allowlist, and at execution time per-call overrides are merged into the template before resolution. Use these endpoints to list, fetch, create, update, delete, search, and run recipes.
All endpoints are served by the run service on a per-container hostname. A concrete example is 67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com; in production substitute your own {projectId}, {containerId}, and {server} values into the template {projectId}-{containerId}-run-1.{server}.containers.hoody.com.
Read recipes
Section titled “Read recipes”GET /api/v1/run/recipes
Section titled “GET /api/v1/run/recipes”List all saved recipes that can be reused as named selector templates.
This endpoint takes no parameters.
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.listRecipes();[ { "name": "firefox-stable", "description": "Resolve the latest stable Firefox via nixpkgs.", "selector_template": { "app": "firefox", "os": "linux", "kind": "gui", "source": ["nix"], "channel": "stable", "pick": "first" }, "allowed_overrides": ["version", "channel"] }, { "name": "ripgrep", "description": "Resolve the ripgrep CLI tool.", "selector_template": { "app": "ripgrep", "kind": "cli", "pick": "first" }, "allowed_overrides": ["version"] }]GET /api/v1/run/recipes/{name}
Section titled “GET /api/v1/run/recipes/{name}”Retrieve a single saved recipe by name.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | Yes | Recipe name |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes/firefox-stable" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.getRecipe('firefox-stable');{ "name": "firefox-stable", "description": "Resolve the latest stable Firefox via nixpkgs.", "selector_template": { "app": "firefox", "os": "linux", "kind": "gui", "source": ["nix"], "channel": "stable", "pick": "first" }, "allowed_overrides": ["version", "channel"]}{ "error": "recipe not found: missing-recipe", "code": 404}Write recipes
Section titled “Write recipes”POST /api/v1/run/recipes
Section titled “POST /api/v1/run/recipes”Create a named selector template that can later be searched or run with optional overrides.
This endpoint takes no parameters.
Request Body
Section titled “Request Body”The request body is a JSON object that conforms to the Recipe configuration schema.
curl -X POST "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "firefox-stable", "description": "Resolve the latest stable Firefox via nixpkgs.", "selector_template": { "app": "firefox", "os": "linux", "kind": "gui", "source": ["nix"], "channel": "stable", "pick": "first" }, "allowed_overrides": ["version", "channel"] }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.createRecipe({ name: 'firefox-stable', description: 'Resolve the latest stable Firefox via nixpkgs.', selector_template: { app: 'firefox', os: 'linux', kind: 'gui', source: ['nix'], channel: 'stable', pick: 'first' }, allowed_overrides: ['version', 'channel']});[ { "name": "firefox-stable", "description": "Resolve the latest stable Firefox via nixpkgs.", "selector_template": { "app": "firefox", "os": "linux", "kind": "gui", "source": ["nix"], "channel": "stable", "pick": "first" }, "allowed_overrides": ["version", "channel"] }]{ "error": "invalid recipe configuration", "code": 400}{ "error": "recipe already exists: firefox-stable", "code": 409}PATCH /api/v1/run/recipes/{name}
Section titled “PATCH /api/v1/run/recipes/{name}”Partially update an existing recipe.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | Yes | Recipe name |
Request Body
Section titled “Request Body”The request body is a partial update of the recipe configuration.
curl -X PATCH "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes/firefox-stable" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "description": "Resolve the latest stable Firefox via nixpkgs (updated)." }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.updateRecipe('firefox-stable', { description: 'Resolve the latest stable Firefox via nixpkgs (updated).'});{ "name": "firefox-stable", "description": "Resolve the latest stable Firefox via nixpkgs (updated).", "selector_template": { "app": "firefox", "os": "linux", "kind": "gui", "source": ["nix"], "channel": "stable", "pick": "first" }, "allowed_overrides": ["version", "channel"]}{ "error": "recipe not found: missing-recipe", "code": 404}DELETE /api/v1/run/recipes/{name}
Section titled “DELETE /api/v1/run/recipes/{name}”Remove a saved recipe by name.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | Yes | Recipe name |
This endpoint accepts no body.
curl -X DELETE "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes/firefox-stable" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.deleteRecipe('firefox-stable');HTTP/1.1 204 No Content{ "error": "recipe not found: missing-recipe", "code": 404}Execute recipes
Section titled “Execute recipes”POST /api/v1/run/recipes/{name}/run
Section titled “POST /api/v1/run/recipes/{name}/run”Resolve and optionally select a candidate from a saved recipe after applying allowed overrides. Hoody-run never executes the resulting command; the response returns the exact shell command or curl invocation the caller should run.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | Yes | Recipe name |
Request Body
Section titled “Request Body”The request body is a Recipe execution request with optional overrides that are merged into the stored template.
curl -X POST "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes/firefox-stable/run" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "overrides": { "channel": "stable", "version": "128.0.3" } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.runRecipe('firefox-stable', { overrides: { channel: 'stable', version: '128.0.3' }});{ "status": "dry-run", "set_id": "a1b2c3d4e5f6", "selected": { "candidate_id": "nix-firefox-128", "title": "Firefox (nixpkgs)", "description": "Mozilla Firefox web browser via nixpkgs", "kind": "gui", "version": "128.0.3", "provider": "nix", "source_id": "nixpkgs", "score": 95, "run_plan": { "command": "nix run nixpkgs#firefox" } }, "shell_command": "nix run nixpkgs#firefox", "warnings": []}{ "error": "invalid overrides", "code": 400}{ "error": "recipe not found: missing-recipe", "code": 404}POST /api/v1/run/recipes/{name}/search
Section titled “POST /api/v1/run/recipes/{name}/search”Resolve a recipe to a candidate set after applying allowed overrides. The returned set_id can be passed back to the run endpoint with pick: "id" for race-free selection.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | Yes | Recipe name |
Request Body
Section titled “Request Body”The request body is a Recipe execution request with optional overrides that are merged into the stored template.
curl -X POST "https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com/api/v1/run/recipes/firefox-stable/search" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "overrides": { "channel": "stable" } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.recipes.searchRecipe('firefox-stable', { overrides: { channel: 'stable' }});{ "set_id": "a1b2c3d4e5f6", "candidates": [ { "candidate_id": "nix-firefox-128", "title": "Firefox (nixpkgs)", "description": "Mozilla Firefox web browser via nixpkgs", "kind": "gui", "version": "128.0.3", "provider": "nix", "source_id": "nixpkgs", "score": 95, "run_plan": { "command": "nix run nixpkgs#firefox" } }, { "candidate_id": "pkgx-firefox-128", "title": "Firefox (pkgx)", "description": "Mozilla Firefox web browser via pkgx", "kind": "gui", "version": "128.0.3", "provider": "pkgx", "source_id": "pkgx", "score": 80, "run_plan": { "command": "pkgx firefox" } } ]}{ "error": "invalid overrides", "code": 400}{ "error": "recipe not found: missing-recipe", "code": 404}