Hoody Run: Resolve
Section titled “Hoody Run: Resolve”The Hoody Run service is a pure application resolver. It maps a request for an application (by name, source, version, channel, or other selector fields) to an exact shell command that can be run on a terminal. The service never executes anything itself; it returns the resolved command plus, when relevant, a preview handoff that points at the browser display and terminal viewer where the app will appear.
Use these endpoints when you want to look up a program by name and get a deterministic command back. Pair them with the search endpoint to obtain a stable set_id, then resolve a specific candidate from that set race-free.
Resolve an application
Section titled “Resolve an application”GET /api/v1/run/resolve
Section titled “GET /api/v1/run/resolve”Resolve and select an application using query parameters, then return the exact shell command to run. Supports all selector fields plus pick mode and output control.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
app | query | string | Yes | Primary name query |
os | query | string | No | Target OS filter |
source | query | array | No | Source kind filter (repeatable) |
kind | query | string | No | App kind filter |
arch | query | string | No | Target CPU architecture filter |
tags | query | array | No | Free-form tags for filtering and ranking (repeatable) |
profile | query | string | No | Named profile for default preferences |
channel | query | string | No | Release channel hint |
version | query | string | No | Exact version or provider-defined version constraint |
variant | query | string | No | Provider-specific variant hint |
publisher | query | string | No | Publisher hint for curated registries |
repo | query | string | No | Repository hint such as owner/name |
release | query | string | No | Release hint such as a tag name |
asset | query | string | No | Desired asset name or pattern |
pick | query | string | No | Candidate selection mode (ask, first, index, id) |
pick_index | query | integer | No | Candidate index (required when pick=index) |
candidate_id | query | string | No | Specific candidate ID (required when pick=id) |
set_id | query | string | No | Bind pick to a specific candidate set |
terminal_id | query | integer | No | Terminal session ID (default 1) |
display | query | string | No | X11 DISPLAY number |
origin | query | string | No | Origin identifier for observability propagation |
dry_run | query | boolean | No | If true, force command-only response (hoody-run never executes) |
print_curl | query | string | No | Generate curl command (hoody-run) |
format | query | string | No | Output format (json or html) |
limit | query | integer | No | Max candidates (default 25) |
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/resolve?app=firefox&pick=first"await client.run.resolveGet({ app: "firefox", pick: "first" }){ "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", "homepage": "https://www.mozilla.org/firefox/", "tags": ["browser", "web"], "provider": "nix", "source_id": "nixpkgs", "score": 95, "reasons": ["exact name match", "high priority source"], "run_plan": { "command": "nix run nixpkgs#firefox" }, "shell_command": "nix run nixpkgs#firefox" }, "shell_command": "nix run nixpkgs#firefox", "handoff": { "state": "preview", "terminal_id": 1, "display": ":1", "preview_display_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/display/a1b2c3d4e5f6", "preview_terminal_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/terminal/1" }, "warnings": []}{ "error": "missing app", "code": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_APP | Missing app query | No app name was provided in the request | Set app to the desired program name |
INVALID_SELECTOR | Invalid selector parameter | One or more selector parameters could not be parsed | Check enum values and numeric fields, then retry |
UNKNOWN_PROFILE | Unknown profile | The requested profile does not exist | Choose a profile returned by listProfiles or getConfig |
INVALID_PICK | Invalid pick request | The pick mode requirements were not satisfied or the selected candidate was not found | Search first, then supply a valid pick_index or candidate_id |
{ "error": "candidate denied by policy", "code": 403}| Error Code | Title | Description | Resolution |
|---|---|---|---|
POLICY_DENIED | Candidate denied by policy | A pick from an older cached set resolved to a candidate that the current effective policy forbids | Pick a candidate allowed by the active profile, or search again under the current policy |
{ "error": "candidate set expired", "code": 409}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SET_EXPIRED | Candidate set expired | The set_id-bound candidate set has expired; pick=index can no longer be resolved race-safely | Re-run search to obtain a fresh set_id, then retry the pick |
{ "error": "internal error", "code": 500}{ "error": "source resolution failed", "code": 502}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_RESOLUTION_FAILED | Source resolution failed | Candidate resolution could not be completed because upstream source work failed | Retry or inspect provider/source health |
POST /api/v1/run/resolve
Section titled “POST /api/v1/run/resolve”Same behavior as GET /api/v1/run/resolve but accepts the full Selector as a JSON request body. Useful for programmatic clients and complex selectors.
Request Body
Section titled “Request Body”The request body follows the Selector schema. Only app is required.
{ "app": "firefox", "os": "linux", "kind": "gui", "source": ["nix"], "pick": "first"}curl -sS -X POST "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/resolve" \ -H "Content-Type: application/json" \ -d '{"app":"firefox","os":"linux","kind":"gui","pick":"first"}'await client.run.resolve({ app: "firefox", os: "linux", kind: "gui", pick: "first" }){ "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", "homepage": "https://www.mozilla.org/firefox/", "tags": ["browser", "web"], "provider": "nix", "source_id": "nixpkgs", "score": 95, "run_plan": { "command": "nix run nixpkgs#firefox" }, "shell_command": "nix run nixpkgs#firefox" }, "shell_command": "nix run nixpkgs#firefox", "handoff": { "state": "preview", "terminal_id": 1, "display": ":1", "preview_display_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/display/a1b2c3d4e5f6", "preview_terminal_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/terminal/1" }, "warnings": []}{ "error": "missing app", "code": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_APP | Missing app query | No app name was provided in the request body | Set app to the desired program name |
INVALID_SELECTOR | Invalid selector parameter | One or more selector fields could not be parsed | Check enum values and numeric fields, then retry |
UNKNOWN_PROFILE | Unknown profile | The requested profile does not exist | Choose a profile returned by listProfiles or getConfig |
INVALID_PICK | Invalid pick request | The pick mode requirements were not satisfied or the selected candidate was not found | Search first, then supply a valid pick_index or candidate_id |
{ "error": "candidate denied by policy", "code": 403}| Error Code | Title | Description | Resolution |
|---|---|---|---|
POLICY_DENIED | Candidate denied by policy | A pick from an older cached set resolved to a candidate that the current effective policy forbids | Pick a candidate allowed by the active profile, or search again under the current policy |
{ "error": "candidate set expired", "code": 409}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SET_EXPIRED | Candidate set expired | The set_id-bound candidate set has expired; pick=index can no longer be resolved race-safely | Re-run search to obtain a fresh set_id, then retry the pick |
{ "error": "internal error", "code": 500}{ "error": "source resolution failed", "code": 502}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_RESOLUTION_FAILED | Source resolution failed | Candidate resolution could not be completed because upstream source work failed | Retry or inspect provider/source health |
GET /api/v1/run/go/{rest}
Section titled “GET /api/v1/run/go/{rest}”Resolve an application using clean, bookmarkable path-based URLs. Supports both positional and key-value path segments.
Positional forms:
/api/v1/run/go/{app}/api/v1/run/go/{os}/{app}/api/v1/run/go/{os}/{source}/{app}/api/v1/run/go/{os}/{source}/{kind}/{app}
Key-value form: /api/v1/run/go/app/{app}/os/{os}/source/{source}/kind/{kind}/pick/{pick}/...
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
rest | path | string | Yes | Path segments for positional or key-value app specification |
os | query | string | No | Target OS filter when not supplied in the path |
source | query | array | No | Source kind filter (repeatable) |
kind | query | string | No | App kind filter when not supplied in the path |
arch | query | string | No | Target CPU architecture filter |
tags | query | array | No | Free-form tags for filtering and ranking (repeatable) |
profile | query | string | No | Named profile for default preferences |
channel | query | string | No | Release channel hint |
version | query | string | No | Exact version or provider-defined version constraint |
variant | query | string | No | Provider-specific variant hint |
publisher | query | string | No | Publisher hint for curated registries |
repo | query | string | No | Repository hint such as owner/name |
release | query | string | No | Release hint such as a tag name |
asset | query | string | No | Desired asset name or pattern |
pick | query | string | No | Candidate selection mode (ask, first, index, id) |
pick_index | query | integer | No | Candidate index (required when pick=index) |
candidate_id | query | string | No | Specific candidate ID (required when pick=id) |
set_id | query | string | No | Bind pick to a specific candidate set |
terminal_id | query | integer | No | Terminal session ID when not supplied in the path |
display | query | string | No | X11 DISPLAY number |
origin | query | string | No | Origin identifier for observability propagation |
dry_run | query | boolean | No | If true, force command-only response (hoody-run never executes) |
print_curl | query | string | No | Generate curl command (hoody-run) |
format | query | string | No | Output format (json or html) |
limit | query | integer | No | Max candidates (default 25) |
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/go/linux/nix/gui/firefox?pick=first"await client.run.runPathBased("linux/nix/gui/firefox", { pick: "first" }){ "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" }, "shell_command": "nix run nixpkgs#firefox", "handoff": { "state": "preview", "terminal_id": 1, "display": ":1", "preview_display_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/display/a1b2c3d4e5f6", "preview_terminal_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/terminal/1" }, "warnings": []}{ "error": "missing app", "code": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_APP | Missing app query | No app name was provided in the request | Set the app in the path or query string |
INVALID_SELECTOR | Invalid selector parameter | One or more selector parameters could not be parsed | Check enum values and numeric fields, then retry |
UNKNOWN_PROFILE | Unknown profile | The requested profile does not exist | Choose a profile returned by listProfiles or getConfig |
INVALID_PICK | Invalid pick request | The pick mode requirements were not satisfied or the selected candidate was not found | Search first, then supply a valid pick_index or candidate_id |
{ "error": "internal error", "code": 500}{ "error": "source resolution failed", "code": 502}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_RESOLUTION_FAILED | Source resolution failed | Candidate resolution could not be completed because upstream source work failed | Retry or inspect provider/source health |
GET /api/v1/run/t/{terminal_id}/go/{rest}
Section titled “GET /api/v1/run/t/{terminal_id}/go/{rest}”Same as /api/v1/run/go/{rest} but with terminal_id extracted from the path prefix. Allows clean URLs that specify both the target terminal and the application in a single path. Example: /api/v1/run/t/2/go/linux/nix/firefox runs Firefox in terminal 2.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
terminal_id | path | integer | Yes | Terminal session ID (1-65535) |
rest | path | string | Yes | Path segments for app specification |
os | query | string | No | Target OS filter when not supplied in the path |
source | query | array | No | Source kind filter (repeatable) |
kind | query | string | No | App kind filter when not supplied in the path |
arch | query | string | No | Target CPU architecture filter |
tags | query | array | No | Free-form tags for filtering and ranking (repeatable) |
profile | query | string | No | Named profile for default preferences |
channel | query | string | No | Release channel hint |
version | query | string | No | Exact version or provider-defined version constraint |
variant | query | string | No | Provider-specific variant hint |
publisher | query | string | No | Publisher hint for curated registries |
repo | query | string | No | Repository hint such as owner/name |
release | query | string | No | Release hint such as a tag name |
asset | query | string | No | Desired asset name or pattern |
pick | query | string | No | Candidate selection mode (ask, first, index, id) |
pick_index | query | integer | No | Candidate index (required when pick=index) |
candidate_id | query | string | No | Specific candidate ID (required when pick=id) |
set_id | query | string | No | Bind pick to a specific candidate set |
display | query | string | No | X11 DISPLAY number |
origin | query | string | No | Origin identifier for observability propagation |
dry_run | query | boolean | No | If true, force command-only response (hoody-run never executes) |
print_curl | query | string | No | Generate curl command (hoody-run) |
format | query | string | No | Output format (json or html) |
limit | query | integer | No | Max candidates (default 25) |
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/t/2/go/linux/nix/firefox?pick=first"await client.run.runTerminalAnchored(2, "linux/nix/firefox", { pick: "first" }){ "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" }, "shell_command": "nix run nixpkgs#firefox", "handoff": { "state": "preview", "terminal_id": 2, "display": ":2", "preview_display_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/display/a1b2c3d4e5f6", "preview_terminal_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/terminal/2" }, "warnings": []}{ "error": "missing app", "code": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_APP | Missing app query | No app name was provided in the request | Set the app in the path or query string |
INVALID_SELECTOR | Invalid selector parameter | One or more selector parameters could not be parsed | Check enum values and numeric fields, then retry |
UNKNOWN_PROFILE | Unknown profile | The requested profile does not exist | Choose a profile returned by listProfiles or getConfig |
INVALID_PICK | Invalid pick request | The pick mode requirements were not satisfied or the selected candidate was not found | Search first, then supply a valid pick_index or candidate_id |
{ "error": "internal error", "code": 500}{ "error": "source resolution failed", "code": 502}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_RESOLUTION_FAILED | Source resolution failed | Candidate resolution could not be completed because upstream source work failed | Retry or inspect provider/source health |
Search candidates
Section titled “Search candidates”GET /api/v1/run/search
Section titled “GET /api/v1/run/search”Search for runnable application candidates across all configured and enabled package sources. Returns a ranked list of candidates with stable ordering for pick-by-index operations.
The returned set_id can be used with subsequent run requests to ensure race-free candidate selection.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
app | query | string | Yes | Primary name query (aliases q, name) |
os | query | string | No | Target OS filter |
source | query | array | No | Source kind filter (repeatable) |
kind | query | string | No | App kind filter (gui, cli, any) |
arch | query | string | No | Target CPU architecture filter |
tags | query | array | No | Free-form tags for filtering and ranking (repeatable) |
profile | query | string | No | Named profile for default preferences |
channel | query | string | No | Release channel hint (for example stable or beta) |
version | query | string | No | Exact version or provider-defined version constraint |
variant | query | string | No | Provider-specific variant hint (for example portable or headless) |
publisher | query | string | No | Publisher hint for curated registries |
repo | query | string | No | Repository hint such as owner/name |
release | query | string | No | Release hint such as a tag name |
asset | query | string | No | Desired asset name or pattern |
limit | query | integer | No | Max candidates to return (default 25) |
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/search?app=firefox&kind=gui"await client.run.searchCandidates({ app: "firefox", kind: "gui" }){ "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", "homepage": "https://www.mozilla.org/firefox/", "tags": ["browser", "web"], "provider": "nix", "source_id": "nixpkgs", "score": 95, "reasons": ["exact name match", "high priority source"], "run_plan": { "command": "nix run nixpkgs#firefox" }, "shell_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-main", "score": 80, "run_plan": { "command": "pkgx firefox" }, "shell_command": "pkgx firefox" } ]}{ "error": "missing app", "code": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_APP | Missing app query | No app name was provided in the request | Set app, q, or name to the desired program |
INVALID_SELECTOR | Invalid selector parameter | One or more selector parameters could not be parsed | Check enum values and numeric fields, then retry |
UNKNOWN_PROFILE | Unknown profile | The requested profile does not exist | Call listProfiles or getConfig and choose a valid profile name |
{ "error": "source resolution failed", "code": 502}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_RESOLUTION_FAILED | Source resolution failed | Candidate resolution could not be completed because upstream source work failed | Retry or inspect provider/source health |
POST /api/v1/run/search/paged
Section titled “POST /api/v1/run/search/paged”Resolve a full ranked candidate set under a bounded cap, then page through it with an opaque cursor. This is the stable pagination contract for large result sets.
Request Body
Section titled “Request Body”The request body follows the PagedSearchRequest schema. The selector field is required; cursor and page_size are optional for subsequent pages.
{ "selector": { "app": "node", "kind": "cli" }, "page_size": 50}curl -sS -X POST "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/search/paged" \ -H "Content-Type: application/json" \ -d '{"selector":{"app":"node","kind":"cli"},"page_size":50}'await client.run.searchCandidatesPagedIterator({ selector: { app: "node", kind: "cli" }, page_size: 50 }){ "set_id": "a1b2c3d4e5f6", "total_count": 137, "items": [ { "candidate_id": "nix-node-22", "title": "Node.js 22 (nixpkgs)", "description": "Node.js JavaScript runtime via nixpkgs", "kind": "cli", "version": "22.11.0", "provider": "nix", "source_id": "nixpkgs", "score": 90, "run_plan": { "command": "nix run nixpkgs#nodejs" }, "shell_command": "nix run nixpkgs#nodejs" }, { "candidate_id": "pkgx-node-22", "title": "Node.js 22 (pkgx)", "description": "Node.js JavaScript runtime via pkgx", "kind": "cli", "version": "22.11.0", "provider": "pkgx", "source_id": "pkgx-main", "score": 78, "run_plan": { "command": "pkgx node" }, "shell_command": "pkgx node" } ], "next_cursor": "eyJzZXRfaWQiOiJhMWIyYzNkNGU1ZjYiLCJvZmZzZXQiOjUwfQ=="}{ "error": "invalid selector", "code": 400}{ "error": "cursor set expired", "code": 409}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CURSOR_SET_EXPIRED | Cursor set expired | The cached candidate set referenced by the cursor is no longer available | Restart pagination from the first page |
{ "error": "source resolution failed", "code": 502}Preflight and batch
Section titled “Preflight and batch”POST /api/v1/run/preflight
Section titled “POST /api/v1/run/preflight”Resolve, optionally pick, and normalize the execution plan for a selector without scheduling execution. Returns the recommended mode, the selected candidate (if any), the shell command, and any missing requirements or warnings.
Request Body
Section titled “Request Body”The request body follows the Selector schema. Only app is required.
{ "app": "firefox", "kind": "gui", "profile": "default"}curl -sS -X POST "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preflight" \ -H "Content-Type: application/json" \ -d '{"app":"firefox","kind":"gui","profile":"default"}'await client.run.preflightRun({ app: "firefox", kind: "gui", profile: "default" }){ "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" }, "shell_command": "nix run nixpkgs#firefox", "recommended_mode": "dry-run", "handoff": { "state": "preview", "terminal_id": 1, "display": ":1", "preview_display_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/display/a1b2c3d4e5f6", "preview_terminal_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/terminal/1" }, "missing_requirements": [], "warnings": [], "effective_policy": { "require_verified": false, "require_integrity": false, "deny_providers": [], "deny_source_ids": [] }}{ "error": "missing app", "code": 400}{ "error": "candidate denied by policy", "code": 403}| Error Code | Title | Description | Resolution |
|---|---|---|---|
POLICY_DENIED | Candidate denied by policy | A pick from an older cached set resolved to a candidate that the current effective policy forbids | Pick a candidate allowed by the active profile, or search again under the current policy |
{ "error": "candidate set expired", "code": 409}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SET_EXPIRED | Candidate set expired | The set_id-bound candidate set has expired; pick=index can no longer be resolved race-safely | Re-run search to obtain a fresh set_id, then retry the pick |
{ "error": "source resolution failed", "code": 502}POST /api/v1/run/batch
Section titled “POST /api/v1/run/batch”Process multiple search or command-only run items in one request. Each item produces its own success or error payload.
Request Body
Section titled “Request Body”The request body follows the BatchRequest schema. The items array contains individual BatchItemRequest entries, each carrying a request_id, a mode (search or run), and a selector.
{ "items": [ { "request_id": "req-1", "mode": "search", "selector": { "app": "firefox", "kind": "gui" } }, { "request_id": "req-2", "mode": "run", "selector": { "app": "node", "kind": "cli", "pick": "first" } } ]}curl -sS -X POST "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/batch" \ -H "Content-Type: application/json" \ -d '{"items":[{"request_id":"req-1","mode":"search","selector":{"app":"firefox","kind":"gui"}},{"request_id":"req-2","mode":"run","selector":{"app":"node","kind":"cli","pick":"first"}}]}'await client.run.runBatch({ items: [ { request_id: "req-1", mode: "search", selector: { app: "firefox", kind: "gui" } }, { request_id: "req-2", mode: "run", selector: { app: "node", kind: "cli", pick: "first" } } ]}){ "items": [ { "result": "search", "request_id": "req-1", "search": { "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" }, "shell_command": "nix run nixpkgs#firefox" } ] } }, { "result": "run", "request_id": "req-2", "run": { "status": "dry-run", "set_id": "b7c8d9e0f1a2", "selected": { "candidate_id": "nix-node-22", "title": "Node.js 22 (nixpkgs)", "description": "Node.js JavaScript runtime via nixpkgs", "kind": "cli", "version": "22.11.0", "provider": "nix", "source_id": "nixpkgs", "score": 90, "run_plan": { "command": "nix run nixpkgs#nodejs" }, "shell_command": "nix run nixpkgs#nodejs" }, "shell_command": "nix run nixpkgs#nodejs", "handoff": { "state": "preview", "terminal_id": 1, "display": ":1", "preview_display_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/display/b7c8d9e0f1a2", "preview_terminal_url": "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/preview/terminal/1" }, "warnings": [] } } ]}Configuration and health
Section titled “Configuration and health”GET /api/v1/run/config
Section titled “GET /api/v1/run/config”Returns the full persisted runtime configuration including sources, profiles, and the currently selected profile.
This endpoint takes no parameters.
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/config"await client.run.configuration.getConfig(){ "version": 3, "sources": [ { "source_id": "nixpkgs", "enabled": true, "priority": 100, "provider": "nix", "source_type": "nix-pkgs", "config": { "flake": "nixpkgs" } }, { "source_id": "pkgx-main", "enabled": true, "priority": 80, "provider": "pkgx", "source_type": "pkgx" } ], "profiles": [ { "name": "default", "description": "Default profile (inherits global sources)", "defaults": { "os": "linux", "kind": "any", "pick": "ask", "terminal_id": 1, "limit": 25 }, "sources_mode": "inherit", "sources": [] } ], "policy": { "require_verified": false, "require_integrity": false, "deny_providers": [], "deny_source_ids": [] }, "selected_profile": "default", "recipes": [], "webhooks": []}GET /api/v1/run/health
Section titled “GET /api/v1/run/health”Returns the standardized 9-field health response. Unauthenticated. Always returns HTTP 200 with application/json when the service is up.
This endpoint takes no parameters.
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/health"await client.run.healthCheck(){ "status": "ok", "service": "hoody-run", "built": "2026-01-15T08:30:00Z", "started": "2026-01-15T08:31:42Z", "memory": { "rss": 25165824 }, "fds": 12, "pid": 1234, "ip": "127.0.0.1", "userAgent": "hoody-cli/1.0"}API documentation
Section titled “API documentation”GET /api/v1/run/openapi.json
Section titled “GET /api/v1/run/openapi.json”Returns the OpenAPI 3.0.3 specification for this API in JSON format. Converted from the canonical YAML source.
This endpoint takes no parameters.
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/openapi.json"await client.run.documentation.getOpenApiJson(){ "openapi": "3.0.3", "info": { "title": "hoody-run API", "version": "1.0.0" }, "paths": { "/api/v1/run/resolve": { "get": { "summary": "Resolve an application and return exact shell command" } } }}GET /api/v1/run/openapi.yaml
Section titled “GET /api/v1/run/openapi.yaml”Returns the OpenAPI 3.0.3 specification for this API in YAML format.
This endpoint takes no parameters.
curl -sS "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.icu/api/v1/run/openapi.yaml"await client.run.documentation.getOpenApiYaml()openapi: 3.0.3info: title: hoody-run API version: 1.0.0paths: /api/v1/run/resolve: get: summary: Resolve an application and return exact shell command