## Hub activity `hub.status` and `hub.drain` include optional `activity: { busy: boolean, lastActivityAt: number }` when the runtime host supports current execution observations. An absent field means unknown activity. The existing `idle` field retains its RPC and durable-queue meaning. `busy` covers in-process starts and turns, quiet provider and tool waits, runtime-managed prompt and teammate work, and approval waits within live runs across all resident roots. Hub forwards this runtime observation unchanged; its separate `pendingRuns` field reports durable Hub queue entries. Old persisted session status does not establish live work. For resident roots, cancellation remains busy until execution settles. Queued prompts and unconsumed teammate updates held only in memory also keep `busy` true until consumed or cleared. After a provider failure, this pending state can keep an otherwise idle runtime busy indefinitely. The observation adds neither a deadline for paused work nor durable recovery of that state. A tool that ignores cancellation can also remain busy indefinitely: `busy` reports outstanding work, not progress. Tool executors own their deadlines and resource cleanup. Detached and shell-backgrounded processes are not tracked after their tool call returns. `lastActivityAt` is a Unix-millisecond timestamp initialized when the runtime starts. Accepted work, model and tool output, and settlement advance it. Status reads, metadata changes, connections, read-only hydration, and team heartbeats do not. Read-only hydration still reports busy while setup runs. The observation is in memory and does not prevent new work from arriving after a caller reads it. ## Oversized tool result recovery Cached text excludes native image data. Cache admission uses the persisted JSON/string model-preview size for the truncation threshold; YAML size controls only cache capacity. Plain strings stay unchanged; structured cached text is serialized as YAML, preserving multiline payloads as literal blocks without automatic wrapping. Original history and tool events keep their existing format. Recovery uses the existing `read_files` output and per-line limits; disabling that tool does not disable caching or remove recovery notices. Tools created with `createTool` may set `resultPolicy: "cache-oversized"`. Core enables this for MCP and Composio tools. Original output remains in history and events; synchronous model preparation sends a bounded preview with a `cline://cache//.result.txt` URI for cached oversized responses. Use `read_files` with `start_line`/`end_line` to read omitted content. Shell and filesystem search tools do not support these URIs. The stateless agent runtime does not own a cache. Entries expire after five further model iterations without a cache read, across follow-up turns. Explicit reads refresh expiry; model requests do not. A 16 MiB UTF-8 text limit per session evicts least recently read entries; individually larger results have no recovery URI. Shutdown, history reset, and restore clear the cache, and resume does not regenerate entries. Missing reads instruct the agent to refetch with an appropriate read/query tool without repeating side-effecting actions. Evicting cached text does not remove original conversation output or change earlier recovery notices; URI references remain until the cache is cleared. Cache-miss feedback appears only when an agent attempts to read missing content. ## Shared agent review UI `@cline/ui` exports presentation-only components for showing a session's changed files and pull-request status. Configure Tailwind v4 and a token entry point before importing `@cline/ui/components.css`, following the [complete styling setup](./packages/ui/ADOPTION.md#option-2-tailwind-mappings-without-base-styles). Then import the components from the package root: ```tsx import { AgentChangedFile, AgentChangesPanel, AgentPullRequestBar, } from "@cline/ui"; ``` `AgentChangesPanel` owns the Changes header, count, close action, empty state, and scroll region. Compose `AgentChangedFile` children to show collapsible paths, copy feedback, additions/deletions, host-provided actions, and rendered diff content. The host retains change collection, clipboard and editor integration, and conversation focus. `AgentPullRequestBar` accepts normalized `AgentPullRequestData` plus loading and error state. The host owns refresh, polling, navigation, and telemetry, and provides its accessible checks popover through `renderChecks`. Native hosts can intercept links with `onNavigate`; web hosts can omit it to render external anchors. `getAgentPullRequestMergeStatus` and `summarizeAgentPullRequestChecks` expose the same status normalization for other host presentation. ## Fork metadata `createForkSessionMetadata` from `@cline/core` copies metadata, replaces fork ancestry, and removes inherited handoff markers. Callers supply the source ID, timestamp, source, and optional `beforeRunCount`; titles and session creation remain caller-owned. ## Cloud sessions (experimental) `CloudSessionApi` and `CloudSessionController` are exported from `@cline/core/cloud`. The API handles REST requests; the controller handles remote Hub connections, session lifecycle, transcript reconciliation, and approvals. Hosts provide API URLs and a fresh-token callback; feature gating and account selection stay in the host. Importing this subpath does not start a local agent. Use `subscribe` for immutable snapshots and live events, `attach`/`readMessages` to open a session, and `send` for a follow-up. Attaching a provisioning or failed session returns its receipt without connecting. `detach` closes this viewer, not the remote task. Call `dispose` when the host shuts down. Viewers hydrating active runs with `readMessages` reconcile canonical history at completion even when they missed the run-start event and earlier content deltas. `create` accepts `sandboxType: "standard" | "resumable"` (default: `"standard"`). The controller resumes suspended sessions when opened and restores their saved tasks. Hosts replacing controllers during credential refresh can share the `pendingInitialTasks: Map` constructor option. It retains first-task approval/thinking/reasoning preferences, including updates through `restoreCreationOptions`, until the inner task is found or created (or the outer session is deleted). `dispose` preserves an injected map; without one, the controller owns and clears its pending state. Restoring options alone never authorizes recreation of a missing established task. ## Experimental cloud handoff `loadCloudModels` and `CloudSessionController.listModels()` provide eligible cloud models. Handoff requires the selected model; it never substitutes another. Use `create({ handoff, ... })` to provision and seed, or `seedHandoff(id, seed)` for an existing target. Persist target IDs and dispatch markers through the callbacks; use `recoverOnly` after uncertain dispatch to avoid duplicate conversations. Handoff creation requires `onCreating`: durably save intent before returning, and reject a previously unconfirmed intent after restart. Callback errors preserve their original type; they do not prove an earlier POST was rejected or permit clearing its intent. `CloudHandoffSeedRejectedError` means no seed was dispatched; clear only the seed marker before retrying the saved target. `verifyHandoffTranscript` checks the seeded history; `waitUntilReady(id)` waits for provisioning. ## Voice input models `getLocalTranscriptionModels(providerId, config?)` from `@cline/core` returns the voice models supported by a provider's transcription transport. Use it to build voice pickers rather than filtering the bundled chat catalog. Vercel uses its live model list and advertised streaming tags; unavailable or malformed responses fail discovery rather than restoring stale bundled models. Voice selection saves and both batch and streaming execution revalidate through the same service. `isTranscriptionModel` from `@cline/shared` (also exported for browsers) accepts exact audio-only input and text-only output modalities. An explicit transcription label does not override additional input or output modalities. Multimodal live models are classified as `realtime`, which currently has no built-in transport support and is excluded from voice and chat pickers. Dedicated transcription can still use either batch or streaming mode. Classification alone does not prove that a provider implements the required transport. `createStreamingAudioTranscriptionSession` mints short-lived Vercel or single-use ElevenLabs credentials. Its shared response includes `transport` and `sampleRate`; browser clients must capture PCM at that rate (Google live routes require 16 kHz). ElevenLabs exposes batch `scribe_v2` and live `scribe_v2_realtime` separately. ## SSH remote environments `RemoteEnvironmentService` (exported by `@cline/core` and `@cline/sdk`) owns SSH profiles, connection testing, helper installation, authenticated loopback tunnels, remote commands, status changes, and cleanup. It runs in the client's Node host; browser clients expose this API through their host transport. No desktop code is required. OpenSSH config aliases, identity files, and ssh-agent authentication are supported. Connections use batch mode and require an already-trusted host key in OpenSSH known_hosts (or `knownHostsPath`). Before first use, verify the server fingerprint through a trusted channel and enroll it using your SSH client. Unknown or changed keys are rejected before inspection, upload, or execution. ```ts import { ClineCore, RemoteEnvironmentService } from "@cline/core"; const environments = new RemoteEnvironmentService({ helperBinaryDirectory: "/opt/my-client/remote-helpers", onStatusChange: (status) => console.log(status), }); const profile = await environments.upsert({ name: "Build host", host: "builder" }); const connection = await environments.connect(profile.id); const core = await ClineCore.create({ clientName: "my-client", backendMode: "remote", remote: { endpoint: connection.endpoint, authToken: connection.authToken, workspaceRoot: connection.workspaceRoot, }, }); try { // The ordinary session, tools, approvals, and event APIs execute on this host. // Supply provider credentials in the session config, as for other remote hubs. console.log(await core.list()); } finally { await core.dispose(); await environments.dispose(); } ``` The service also exposes `list`, `upsert`, `delete`, `test`, `disconnect`, `run`, `getConnection`, `getActive`, `activateConnection`, and `getStatuses`. `onConnectionLost` lets clients retire runtime bindings after a tunnel fails. Each service instance has a unique remote Hub discovery record, so another client connecting to the same host cannot stop its Hub. Connect/disconnect/profile mutations are serialized; concurrent connects reuse one tunnel. Dispose the `ClineCore` runtime before disconnecting its environment. Do not expose the connection's authentication token to a browser or logs. Profiles default to `~/.cline/data/settings/remote-environments.json`, written atomically with mode 0600. They contain identity-file paths, never private keys. Options include `profilesPath`, `sshPath`, `knownHostsPath`, process timeouts, `helperBinaryPath`, and `helperBinaryDirectory`. The corresponding helper/SSH configuration variables are `CLINE_REMOTE_HELPER_BINARY`, `CLINE_REMOTE_HELPER_DIRECTORY`, `CLINE_SSH_PATH`, and `CLINE_SSH_KNOWN_HOSTS_FILE`. Clients package a matching self-contained helper using the `@cline/core/remote/helper-entry` executable entrypoint, compiled with Bun for the remote OS and architecture. Use `remoteHelperBinaryFilename({ platform, arch })` for the filename (`cline-remote-helper-`). Linux and macOS on x64/arm64 are supported. Helpers must include the same SDK build as the client; missing helpers produce an explicit error, without installing a runtime from the network. The helper implements `--remote-hub-ensure --cwd --discovery-path ` and the core detached-daemon sentinel. Agent tools and persistence run remotely; the host only manages SSH and forwards the authenticated hub connection. ### Provider authentication metadata for host UIs `@cline/shared` (including its browser entry point) exports `ProviderAuthInfo`, `ProviderLocalCli`, `resolveProviderLocalCli(provider)`, and `resolveProviderApiKeyOptional(provider)`. The resolvers accept provider data (`metadata.localCliCommand` with optional `docsUrl`, and `metadata.apiKeyOptional`); they perform no registry lookup. Hosts resolve providers through `@cline/llms` and then pass that data to the shared helpers. `listLocalProviders` includes the resulting facts in each `ProviderListItem.auth` (`localCli`, and `apiKeyOptional` for local inference servers and cloud-credential providers that run without a key), allowing browser clients to render authentication guidance and gate sessions without importing the LLM catalog. `ProviderListItem.modelTools` likewise carries provider-level native tool availability for settings indicators. ## Concurrent subagent tool calls `spawn_agent` and configured `subagent_*` tools declare `executionMode: "parallel"`. Consecutive calls to these tools in one model response run concurrently even when the parent runtime uses its default sequential mode. Each call still returns its child's completed answer, and tool results remain in the model's original call order. A tool's optional `executionMode` overrides the runtime's `toolExecution` setting. Unmarked tools inherit the runtime setting. Sequential calls form ordering boundaries: `read_file → [spawn A, spawn B] → edit_file` executes the read first, then both child runs together, then the edit after both finish. This does not change the execution mode of tools inside the child agents. Preparation remains serial for the whole response, before any tool executes. All before-tool hooks and required approvals therefore complete before the parallel group starts. A before-tool `skip` blocks its own call; a before-tool `stop` prevents the entire response's execution, as before. Pending approvals can delay sibling execution. No background-run handles or new concurrency limit are introduced. ### Configured subagent approvals Configured agents do not expose a tool approval policy setting. The parent’s `subagent_` call follows the parent session’s approval policy; the child executes its available tools without inheriting that policy or approval callback. Its configured `tools` allowlist and disabled-tool filtering still apply. Runtime hooks remain inherited and can block tool execution. ## Saving provider credentials `saveLocalProviderSettings` is asynchronous; callers must await it before reloading provider catalogs or continuing onboarding. When a saved provider has a `modelsSourceUrl`, credential, header, and base URL updates refresh its model list before saving the new settings. `updateLocalProvider` follows the same rule even when the request omits `models` and `modelsSourceUrl`. Endpoint changes relocate same-origin model sources; separate catalog origins remain unchanged. Model refresh in `saveLocalProviderSettings` is best-effort: if it fails during discovery, the new settings are still saved and the last known catalog is retained. Settings and catalog persistence errors still reject the save. Provider-service mutations are serialized per catalog file within the process, including across manager instances and different providers. Discovery prepares the update before the complete settings patch is persisted once. If the catalog write fails, the prior provider settings are restored only while the failed operation still owns the current settings entry; newer saves and removals are preserved. A rollback failure is reported alongside the original error. Explicit `updateLocalProvider` calls still reject failed model fetches and retain the prior settings and catalog. Catalog refreshes replace discovery-owned model IDs while retaining manually added models, their default selection, and overrides on retained model entries. `models.json` records discovery-only IDs in `discoveredModelIds`; IDs also supplied explicitly are user-managed. An explicit `models` update replaces the manual list. An existing model selection in provider settings does not count as a manual addition when initializing a source-backed catalog. Provider capabilities are inherited when registering models, so stored per-model capability overrides continue to take precedence after refreshes. ## Shared UI session rows `@cline/ui` exports `AgentSessionRow`, `AgentSessionRowEditor`, and `AgentSessionOverview`, together with their public props types. These are presentation primitives for session navigation, rename, and metadata content; the host retains session data, routing, menus, permissions, formatting, and interaction policy. Import the shared component stylesheet with the host theme. `AgentSessionRow` owns the row geometry, selected/hover appearance, timestamp placement, and pending/provisioning/running/unread status-dot precedence. Hosts provide the already-formatted `label` and `timestamp`, optional `leading` and `pinnedIndicator` content, and a sibling `action`. Root DOM props and refs pass through to the row wrapper for host-owned context-menu or hover-card triggers. The default control is the desktop native `button`; its `disabled` and `onSelect` props apply only in that mode. URL or router navigation uses the mutually exclusive `renderControl` mode, which receives the shared navigation `className` and row `children` for the host's link or router control. The host control owns its href, accessibility, disabled behavior, and event handling. The control union prevents combining `renderControl` with `disabled` or `onSelect`, and keeps optional actions as siblings so interactive elements are not nested. `AgentSessionRowEditor` supplies the matching edit frame while the host owns the rename input, focus, Enter/Escape/blur handling, and saving state. `AgentSessionOverview` renders a title and `[label, value, fullValue?]` metadata rows; the host owns the hover-card lifecycle, positioning, and metadata formatting. See the [session-row adoption guide](./packages/ui/ADOPTION.md#session-rows) for the import, slot, and trigger/ref examples. ## Shared context usage presentation (`@cline/ui`) `AgentContextUsage` exposes desktop's context ring and token breakdown through its `children` render callback. It adds no wrapper: the host receives `AgentContextUsagePresentation` (`triggerLabel`, `ring`, and `details`) and keeps its own accessible trigger, popover, positioning, focus, and keyboard behavior. `AgentContextUsageProps` accepts `usage: AgentContextUsageData`, optional `costLabel: ReactNode`, and the required render callback. Usage contains `tokensIn`, `tokensOut`, `cacheReadTokens`, and optional `contextWindow`. Supply current-request metrics and the model's authoritative context capacity, not accumulated session token traffic. The component renders nothing when usage is empty or context capacity is unavailable or nonpositive. Cached tokens are part of input usage, not additional context consumption. `costLabel` is a separate host-formatted cost. Numeric zero is displayed; previously hidden falsy values remain omitted. Desktop retains its existing cost formatter and usage source. Import the component and all three public types from `@cline/ui`; see [UI adoption guidance](packages/ui/ADOPTION.md) for theme setup, styling, and composition examples. ## Shared command output and image presentation (`@cline/ui`) `AgentCommandOutput` renders `output` with a running cursor controlled by `isRunning`. Optional `children` let the host retain ANSI rendering or normalize control characters. It follows new output initially, pauses when the user scrolls away, and resumes within 24px of the bottom. Hosts own output collection, limits, and session identity; remount it when switching commands. `tabIndex` and `classNames.viewport` / `classNames.cursor` allow host-specific accessibility styling. `AgentImageLightboxContent` renders an image and two close controls calling `onClose`. The host owns the dialog, positioning, Escape handling, focus management, and image navigation. `backdropTabIndex` can exclude the backdrop from a managed dialog's tab order. Image source validation and resolution remain host-owned; provider-generated URLs must go through an explicit host trust policy before rendering. This presentation primitive does not replace `GeneratedMediaContent` or its inline-byte validation. ## Shell executor errors The executor returned by `createShellExecutor` rejects on execution failure. The following error classes are exported from `@cline/core` so hosts can distinguish process outcomes without parsing messages. They are not an exhaustive list of rejections: cancellation, timeout, and stdin-write failures can reject with other errors. - `CommandExitError` — the shell started and exited non-zero. `exitCode` is the numeric process exit code and `output` contains a completion notice and the captured output (subject to the configured truncation limit). - `CommandTerminationError` — the process terminated without a numeric exit code. `signal` is the terminating signal, or `null` if none was reported; `output` contains a termination notice and the captured output. This error has no `exitCode` field. - `CommandSpawnError` — the shell process could not be started, so there is no exit code. The message keeps the pre-existing `Failed to execute command: …` form. `code` is the operating system error libuv reported (`ENOENT`, `EACCES`, `EFTYPE` for a file that is not a valid executable). Because spawn reports `ENOENT` with the same message when the executable is not found and when the working directory no longer exists, `missing` records which path was absent at failure time: `"executable"` or `"cwd"`. It is `undefined` for every other code. `code` itself is `undefined` if the underlying error has no code. The public `run_commands` tool catches executor failures and resolves with per-command results containing `success: false`, rather than propagating these errors as rejected tool calls. For `CommandExitError` and `CommandTerminationError`, the failed result retains `output` in its `result` field. For `CommandSpawnError`, `result` is empty and `error` includes the spawn failure message. Hosts that need the structured error fields must observe the executor rejection before this conversion. Hosts that record command telemetry should label a `CommandSpawnError` by its `code` (and `missing`) rather than inventing an exit code. The VS Code and standalone adapters do this in the `errorCode` dimension, and use the bounded labels `signal` and `no_exit_code` for `CommandTerminationError`. Only an actual numeric exit is reported as `exitCode`. ## Symlinked instruction files Rules and workflows can be symbolic links to regular files. Source paths and fallback names use the link's name and location, not the target's. Broken, circular, and non-file targets are skipped. `UnifiedConfigFileWatcher` watches only the directory containing the link, not the link's target. Edits to a symlink's target are picked up on the next refresh or new session. ## Unknown model completion recovery The AI SDK adapter maps unified `length` to `max-tokens` and missing or unrecognized reasons (including `other`) to `unknown`. Explicit `stop`, `tool-calls`, `content-filter`, and `error` retain their meanings. The agent also treats a stream without a finish event as unknown. Without tool activity, an unknown response is preserved in history and continued once, with the model-visible user message “Previous turn ended unexpectedly. Continue from where you left off.” The message uses `displayRole: "system"` and `userRunSpan: 0`, matching injected hook context so it stays out of live and replayed chat transcripts. The system prompt is unchanged. A second unknown completion fails the run. Queued user instructions are consumed before the continuation, including in the first iteration. Tool calls receive their results through the normal loop; provider-executed actions are not replayed. ## Host connector transport Pass `connectorsRequest: (path, init) => Promise` to `LocalRuntimeHost` and `createLocalHubScheduleRuntimeHandlers` to supply connector authentication. Paths start with `/api/v1/connectors`; the host supplies the API origin and authentication. Omit it to retain local account authentication and rollout checks.