Runtime
The execution environment that actually runs loops and determines what providers and tools are available.
The runtime is where loops become real work. In Closedloop.ai, the runtime is the combination of:
- a registered compute target (the desktop client on a specific machine)
- that machine's installed tools (
claude,codex,git,python3) - the Claude Code plugins resolved under
~/.claude/plugins/cache/closedloop-ai/ - the process-level sandbox the gateway enforces on every operation
Responsibilities
- Expose provider support — capabilities are reported via the
/healthendpoint and viadesktop.hellowhen the cloud socket connects. - Run execution safely — every path input is filtered through the sandbox allowlist. Certain paths are hard-denied even inside the sandbox.
- Report health and availability — tray state (
starting,ready,degraded,error) plus presence through the cloud socket: the API marks the compute target online when the socket connects and offline when it disconnects. - Return structured output — operation handlers emit NDJSON streams or JSON responses, which the cloud executor forwards as
desktop.command.eventmessages.
Capabilities
The runtime reports a capabilities object shaped like:
ComputeTargetCapabilities {
versions: Partial<Record<CapabilityToolName, string>>
commandSigning: false
}This object advertises protocol support, not tool availability. If a required binary is missing, telemetry emits preflight.binary_not_found.
Binary resolution
Electron on macOS inherits a minimal PATH, so the server spawns the user's login shell ($SHELL -ilc) wrapped in sentinels to extract the real PATH. ~/ is expanded, npm_config_prefix and NPM_CONFIG_PREFIX are sanitized for nvm compatibility, and the result is cached for the session.
Override specific binaries at Settings → Binary paths or via PATCH /api/gateway/settings/binary-paths. The override sources are override, override_invalid, path, or fallback.
Process management
The ProcessManager in src/server/process-manager.ts supports two spawn modes:
spawnDetached— detached with stdio redirected to a log file, unreferenced after spawn. Used for long-running background jobs.exec— wrapsexecFileAsyncfor one-shot calls.
Every spawn calls assertOperationPath(cwd) to enforce the sandbox allowlist before launching.
Plugin resolution
Plugin scripts are resolved under ~/.claude/plugins/cache/closedloop-ai/<plugin-name>/<semver>/scripts/. Registered plugins come from ~/.claude/plugins/installed_plugins.json. The code@closedloop-ai plugin version is reported in desktop.hello.pluginVersion and can be overridden for tests via CL_PLUGIN_VERSION (semver, max 64 chars).
Why the runtime is a first-class concept
A loop that works on one machine and fails on another is a failure of the runtime, not of the plan. Making the runtime explicit — with reported capabilities, sandbox policy, and binary overrides — turns environment issues into diagnosable failures instead of mysterious breakage.