- Hub-managed Agent Plugins. Packages under
~/.agents/plugins/*on the hub host are discovered and validated from their rootplugin.json; valid skills underskills/are exposed through the skills tool asplugin-name:skill-name, and stdio, Streamable HTTP, and legacy SSE servers frommcp.jsonare started without touchingcline_mcp_settings.json. Workspace.agents/pluginsdirectories are deliberately not scanned, so opening a repo cannot implicitly start repo-controlled MCP servers; extra roots require an explicitagentPluginPaths. Enablement lives in hub settings keyed by manifest name and publishessettings.changed, so clients no longer need their own loader or enablement store. Two bugs fixed along the way:settings.toggle({type: "skills"})wrote adisabledkey into a plugin skill's SKILL.md frontmatter, which the strict Agent Skills parser then rejected so the skill silently vanished until hand-edited; andInMemoryMcpManager.dispose()aborted on the firstdisconnect()rejection, leaking every remaining server's process - A model turn that dies mid-stream with a transient provider error is now retried up to 3 times with exponential backoff instead of failing the whole run — a single forwarded 429 previously aborted the run outright. Retryability is read from the AI SDK's typed signals, and a turn is never retried once it has streamed any text, reasoning, media, or tool call, so nothing is duplicated. Model calls also now allow 5 SDK-level retries for request-start 429/5xx/network failures, up from 2
- Streaming is no longer throttled by hook forwarding. The hub proxied every runtime event to client-contributed
onEventhooks as a capability round trip carrying the full session snapshot, with the agent loop awaiting it — so each streamed token cost a few hundred KB of serialization, a persisted row, and a blocking IPC hop. Per-chunk text, reasoning, and tool-update deltas are no longer forwarded to remoteonEventhooks; every other event still reaches hooks unchanged. The hub event log also moved tosynchronous = NORMAL, dropping one fsync per appended delta - Checkpoints no longer re-hash unchanged untracked files on every turn. Each turn built a throwaway git index, so git re-read every untracked file before each model call — with multi-GB untracked data in the workspace this blocked every message for seconds to minutes. A persistent per-session snapshot index lets git's stat cache skip unchanged files, so from the second turn a snapshot costs about one git process. Snapshot contents are byte-identical to before. A corrupt index now heals with one rebuild-and-retry that also clears a stale
index.lock, where previously a git process killed mid-add degraded that session to HEAD-only checkpoints permanently run_commandsno longer hangs when a command backgrounds a child. The executor settled on the child'scloseevent, which waits for the stdio pipes to drain; a backgrounded process (cmd &,nohup) holds the inherited write-ends open, so a finished command hung until the timeout killed the whole process tree. It now also settles onexitafter a one-second grace period, reporting the exit code and the output collected so farapply_patch"Add File" against a path that already exists is now rejected instead of silently overwriting it. Only UPDATE and DELETE targets were pre-loaded, so the parser's "File already exists" guard never saw ADD targets and the patch destroyed the file's contents with no error and no diff of what was lost- Nested PowerShell invocations are now unwrapped instead of being double-parsed. Command text is fed to PowerShell through a stdin bootstrap that the outer shell parses as PowerShell source, so a command written as
powershell -Command "... $_ ..."had its argument interpolated before the nested shell ran — pipelines using$_emitted one error per enumerated item, an error flood that looked like a hang, while the child still exited 0. Unwrapping is applied only when it is semantics-preserving: same PowerShell edition,-NoProfile, and an entirely quoted-Commandtail; everything else passes through byte-identical - The
run_commandstool description now names the actual PowerShell edition in use —Windows PowerShell (powershell.exe)versusPowerShell (pwsh.exe)orPowerShell (pwsh)— quotes its guidance against the resolved executable, and tells the model to write commands directly rather than wrapping them in another-Commandor/cinvocation. It also no longer claims "in Windows environment" whenpwshis the configured shell on macOS or Linux - No file index is built when the workspace root is the home directory or a filesystem root. Running from
$HOMEand typing an@mention listed every file under home and re-ranked the whole index on each keystroke, driving the process to many GB of RSS until it was OOM-killed. Paths are canonicalized first so symlinked or differently-cased spellings still hit the guard - Credential fields are now stripped of Unicode control and format characters and surrounding whitespace before being saved. A key pasted with an invisible character (BOM, zero-width space, bidi mark) was stored corrupted and the provider returned a 401 indistinguishable from a genuinely wrong key, while masked rendering hid the corruption
- The
editortool's error for a nullold_textnow names the file, says whether the parameter was null or omitted, and spells out the recovery. Models that fill optional parameters with null hit a terse "required" message and re-sent the identical call until the loop detector hard-stopped the run - Provider-native web search is now enabled by default in non-yolo sessions on supported provider/model combinations, instead of requiring
tools.web_search.enabled = true. An explicitfalsestill opts out, and the settings loader fails closed: web search stays disabled when a global settings file exists but cannot be read or parsed
Cline SDK 0.0.83
Released · Cline
Changes skills and plugins, hooks