* chore: bump @clinebot/* packages to 0 0.0.38
Upgrade @ai-sdk providers (amazon-bedrock, anthropic, gateway, google) and
@clinebot packages from v0.0.37 to v0.0.38. Adjust the return type of
_createSwitchToActModeTool() to AgentTool and update test imports to use
SdkSessionHost to match the updated core library.
* fix empty workspace
* remove resolveSdkWorkspaceRoot
Instead of aggressively closing idle terminals and warning about busy
ones when the terminal profile changes, we now simply update the setting.
Existing terminals stay open and remain eligible for reuse if the user
switches back. New terminals use the new profile, and getOrCreateTerminal()
skips terminals with a different effective shell during reuse matching.
- Simplified setDefaultTerminalProfile() to void return
- Removed handleTerminalProfileChange() (dead code)
- Removed terminal close/warn notifications from updateSettings.ts
and updateSettingsCli.ts
- Cleaned up unused imports
Previously, terminal matching compared raw shellPath values directly:
- 'default' profile terminals had shellPath=undefined
- 'zsh' profile terminals had shellPath='/bin/zsh'
These never matched, even though on macOS they resolve to the same shell.
Now effectiveShellPath() resolves undefined (default) to the actual
default shell via getShell(), so switching between 'zsh' and 'default'
on macOS won't needlessly close compatible terminals, and terminal reuse
correctly matches terminals running the same effective shell.
When a non-default shell profile is selected (e.g. bash), the terminal
was spawning the correct shell binary via shellPath but inheriting
$SHELL from the parent process (VSCode extension host), which still
pointed to the user's login shell (e.g. /bin/zsh). This caused child
processes that read $SHELL (make, npm scripts, etc.) to see the wrong
shell.
Now VscodeTerminalRegistry.createTerminal() sets SHELL in the terminal's
env to match the shellPath when a specific profile is selected.
When the user changes terminal settings (shell profile, timeout, reuse,
output limit) while terminals are open, the changes now propagate
immediately to the live VscodeTerminalManager instance via
controller.terminalManager (a public getter on SdkController).
Previously, updateSettings.ts and updateSettingsCli.ts tried to access
controller.task.terminalManager which doesn't exist in the SDK controller.
Now they use controller.terminalManager which is the shared instance
created lazily in SdkController.
When the lazy VscodeTerminalManager is first created, applyTerminalSettings()
reads from StateManager and configures:
- defaultTerminalProfile (shell choice: default/zsh/bash/etc.)
- shellIntegrationTimeout
- terminalReuseEnabled
- terminalOutputLineLimit
Also exposes a public terminalManager getter so updateSettings handlers
can apply runtime changes to the existing instance.
Introduces a VSCode-specific run_commands tool that replaces the SDK's
built-in version. This is an IDE-level feature built on top of the SDK,
not integrated into the SDK itself.
The tool supports two execution modes, switchable dynamically:
- Foreground (vscodeTerminal): Uses VscodeTerminalManager for visible
VS Code terminals with shell integration, real-time output streaming,
and 'Proceed While Running' support.
- Background (backgroundExec): Delegates to the SDK's createBashExecutor
for headless child_process.spawn execution with configurable timeout.
Wiring:
- SdkController creates a lazy VscodeTerminalManager
- SdkSessionFactory passes getTerminalManager to VscodeSessionHost
- VscodeSessionHost suppresses SDK's built-in run_commands (bash: undefined)
- createVscodeExtraTools includes the custom run_commands tool
Design doc: sdk-migration/FOREGROUND-TERMINAL-DESIGN.md
Root cause: initial-message-sanitizer only checked the immediately next
user message (i+1) for matching tool results. The SDK persists each
parallel tool result as a separate user message, so for N parallel tool
calls only 1/N was found and (N-1) placeholders were created. The
remaining (N-1) real results were left as separate messages. On merge,
this produced duplicate tool_result blocks causing Anthropic API errors.
Fix:
- Scan ALL consecutive user messages after the assistant to collect tool
results, then consolidate into a single message via splice()
- Add defensive dedup in convertToOpenAiMessages as a safety net
Tests: 12 pass (5 sanitizer + 7 openai-format conversion)
The ask:"completion_result" message was emitted at content_end (when the
attempt_completion tool finished), but a usage event with
say:"api_req_started" always arrived between content_end and done,
becoming the last raw message. The webview uses the last raw message to
determine UI state, so it showed "Thinking..." instead of the completion
UI with the "Start New Task" button.
Fix: defer the ask:"completion_result" emission from content_end to the
done handler, which always runs after the usage event. The done handler
now unconditionally emits ask:"completion_result" (previously it was
conditional on !wasAttemptCompletionSeen). This ensures the ask is
always the final message regardless of whether attempt_completion was
used.
The SDK spawn_agent tool was rendering as a generic tool row in the
webview. This translates its events into the ClineMessage types that
SubagentStatusRow already handles:
- content_start → say:"use_subagents" (prompts list with stable ts)
- content_update → say:"subagent" (running progress, partial=true)
- content_end → say:"subagent" (completed/failed) + say:"subagent_usage"
Also filters sub-agent agent_events by parentAgentId so only the root
agent produces ClineMessages. Without this, every sub-agent tool call,
text output, iteration, and usage event flooded the main chat.
No webview/CLI changes needed — existing SubagentStatusRow and
messageUtils filtering handle all the emitted message types.
Remove the strictPlanModeEnabled feature toggle from the entire codebase.
The setting is not used by the SDK controller path and plan mode behavior
is now handled via system prompt instructions and the switch_to_act_mode
tool in the SDK layer.
Changes:
- Remove state key, ExtensionMessage field, and proto fields (reserved)
- Remove ToolExecutor plan-mode restriction logic (PLAN_MODE_RESTRICTED_TOOLS,
isPlanModeToolRestricted, and the enforcement block)
- Remove from TaskConfig interface, validation, and TASK_CONFIG_KEYS
- Remove settings toggle from webview FeatureSettingsSection and CLI
- Remove from getStateToPostToWebview and updateSettings handlers
- Remove from ExtensionStateContext defaults and test mocks
- Regenerate proto types
Remove the Focus Chain feature toggle from the settings view and
all associated state wiring:
- Settings UI: Remove Focus Chain toggle, reminder interval slider,
and nested-key handling that was only used by focus chain
- ChatView: Remove focus chain checklist state, progress message
memo, and placeholder memo
- TaskSection/TaskHeader: Remove focus chain props and FocusChain
component rendering
- ExtensionStateContext: Remove focus chain settings default and
currentFocusChainChecklist from state provider
- ExtensionMessage: Remove focusChainSettings and
currentFocusChainChecklist from shared ExtensionState type
- getStateToPostToWebview: Stop sending focus chain state to webview
- updateSettings/updateSettingsCli: Remove focus chain settings
update handlers and telemetry toggle tracking
buildSessionConfig() only read subagentsEnabled from taskSettings (per-task
overrides), which is undefined for normal chat flow. This caused
enableSpawnAgent to always be false, making the SDK hide the spawn_agent
tool and causing the model to fall back to the skills tool.
Now reads the global subagentsEnabled setting from StateManager as the
default, with taskSettings still able to override it.
The remote config system (fetch.ts, utils.ts) and other core modules
import AuthService from src/services/auth/AuthService.ts. In the SDK
migration, this was still the classic AuthService class with its own
separate singleton — completely disconnected from the SDK AuthService
that SdkController initializes with actual credentials.
This caused fetchRemoteConfig() to silently fail because:
- AuthService.getInstance().getAuthToken() returned null (no credentials)
- AuthService.getInstance().getActiveOrganizationId() returned null
- ClineAccountService.fetchUserRemoteConfig() failed silently
Fix: Replace src/services/auth/AuthService.ts with a re-export barrel
that points to src/sdk/auth-service.ts, matching the pattern used for
Controller (src/core/controller/index.ts → src/sdk/SdkController.ts).
This ensures all modules that import AuthService get the SDK singleton
which has the actual auth state.
Also stub out AuthServiceMock.ts which extended the classic AuthService
using protected members that no longer exist in the SDK version. The
mock was only used via dynamic require in E2E test mode and is not
referenced by any production code.
The SdkController was missing all remote config support that the classic
Controller provides for enterprise customers (org-level policy enforcement,
MCP server management, provider lockdown, OpenTelemetry, etc.).
Changes:
- Add startRemoteConfigTimer() that fetches immediately then every 1 hour
- Chain timer start after auth restore in constructor
- Call fetchRemoteConfig() on login (handleAuthCallback)
- Fire-and-forget fetchRemoteConfig() at task start (initTask)
- Call clearRemoteConfig() on sign-out (handleSignOut)
- Clear interval timer in dispose() to prevent memory leaks
- Verify refreshRemoteConfig gRPC handler is already wired correctly
The SDK run_commands tool can pass input as a bare string[] (e.g.
["biome check --write src/"]) instead of wrapped { commands: [...] }.
parseToolInput() returns undefined for arrays, so commandText ended up
as "", rendering an empty shell fence in the command approval UI.
Extend both content_start and content_end handlers to detect bare
arrays and bare strings before falling through to parseToolInput(),
mirroring the fix already applied for search_codebase (S6-47).
Adds 6 unit tests covering bare array, multi-element array, bare
string, content_end round-trip, and wrapped-object regression.
- Replace exportTaskWithId stub in SdkController with real implementation
that opens the task directory in the file manager (matching classic behavior)
- Fix openDiskConversationHistory to await openFileIntegration and move
path construction inside the null check
Closes ENG-1828
After consecutive tool failures hitting maxConsecutiveMistakes (default 3),
the UI buttons stayed as Approve/Reject instead of updating to
"Proceed Anyways"/"Start New Task".
Root cause: In the SDK path, trackToolErrors() emitted the
mistake_limit_reached message but the SDK agent continued running,
immediately appending more messages. The mistake_limit_reached message
was never the last message, so the webview never showed correct buttons.
Fix: When the mistake limit is reached, set result.turnComplete = true
and abort the SDK session so the agent stops producing events. The
existing askResponse -> tryResumeSessionFromTask flow handles resumption
when the user clicks "Proceed Anyways".
Closes ENG-1874
The SDK execution path was missing consecutive tool error tracking that
the classic Task class provides via consecutiveMistakeCount. When tools
failed repeatedly, the UI buttons stayed showing "Approve"/"Reject"
instead of updating to "Proceed Anyways"/"Start New Task".
This change:
1. Adds toolError/toolSuccess flags to TranslationResult so the message
translator signals when tool calls succeed or fail (content_end events
with/without event.error)
2. Adds consecutiveToolErrorCount tracking to SdkSessionEventCoordinator
3. When the count reaches maxConsecutiveMistakes (default: 3), emits an
ask="mistake_limit_reached" ClineMessage, which the webview already
handles correctly to show the right buttons
4. Resets the counter on tool success or after emitting the limit message
Fixes ENG-1874
Bridge SDK provider settings with the legacy Codex OAuth manager so ChatGPT Subscription sign-in updates settings state and inference can read the stored token. Clear both stores on sign-out and refresh incomplete SDK-stored credentials.
The webview's onModeToggle handler in ChatTextArea.tsx treats the
returned boolean as 'did I consume your pending input' and calls
setInputValue('') when true. The SDK flow rebuilds the session
without consuming chatContent, so returning true incorrectly wiped
any text the user had typed before toggling.
Match the classic extension's semantic: only return true when the
chatContent was actually consumed as a plan-response message. The
SDK flow never does this, so both success branches now return false
(same-mode no-op already returned false).
ClineMessages and mode indicator continue to update correctly because:
- rebuildSessionForMode keeps this.task and its messageStateHandler
alive across the session rebuild, so clineMessages are preserved
- getStateToPostToWebview() reads mode from stateManager which is
updated before postStateToWebview() is called
- oldUnsubscribe() is called before old session stop/dispose, so no
stale 'ended' events reach the gRPC bridge after rebuild
Adds 7 unit tests in src/sdk/toggle-plan-act-mode.test.ts covering
PLAN/ACT enum decode, chatContent pass-through, boolean round-trip,
invalid enum handling, and error propagation.
rebuildSessionForMode() now logs the resolved provider/model/apiKey from
buildSessionConfig({ cwd, mode: newMode }) so it is visible that the
mode-specific provider and model were picked up (planModeApiProvider /
actModeApiProvider, planModeApiModelId / actModeApiModelId, etc.).
Also adds an auth pre-check mirroring the one in initTask(): if the new
mode resolves to the cline provider without an auth token, emit the
standard auth error message sequence (say:task, say:api_req_started,
ask:api_req_failed) so the webview renders the "Sign in to Cline" button
via ErrorRow instead of crashing on the first SDK API call.
The pre-check runs BEFORE tearing down the old session, so the user
keeps their chat history and can retry after signing in or toggle back
to the original mode.
Replaces the old togglePlanActMode() behavior (which just cancelled the task and left the user to start over) with a full session rebuild that preserves conversation history while swapping in the new mode's system prompt and tools. Mirrors the CLI's onModeChange callback in apps/cli/src/runtime/run-interactive.ts.
Changes in src/sdk/SdkController.ts:
- Add rebuildSessionForMode(newMode): persists mode to global state, reads conversation history from the active session via loadInitialMessages(), tears down the old VscodeSessionHost (unsubscribe + stop + dispose), builds a fresh CoreSessionConfig for the new mode (new system prompt via buildSessionConfig, switch_to_act_mode re-injected for plan), preserves the task/session ID, and starts a new session with initialMessages. Task proxy stays alive so currentTaskItem and clineMessages remain stable across the rebuild.
- Implement applyPendingModeChange(): was a TODO stub; now reads pendingModeChange, clears it, and delegates to rebuildSessionForMode. This is the path the switch_to_act_mode tool uses when the model programmatically transitions plan -> act.
- Rewrite togglePlanActMode(): if activeSession exists, call rebuildSessionForMode; otherwise persist mode and refresh state. No more cancelTask() followed by the user manually restarting.
- Wire applyPendingModeChange into handleSessionEvent: when turnComplete/sessionEnded flips isRunning=false, check pendingModeChange and apply it fire-and-forget. Complements the existing check in fireAndForgetSend so we catch the mode change via either the event stream or the send promise resolution.
Cancel-style teardown on mid-turn toggle (matches classic Cline UX of "switch modes cancels the current task"):
- Reject any pendingToolApprovalResolve with { approved: false, reason: "Mode changed" } so the SDK tool executor unwinds cleanly
- Clear pendingAskResolve (no meaningful answer to give the dying session)
- Cancel the debounced save timer so it does not race with the finalization we write below
- await oldManager.abort(oldSessionId) (same call cancelTask uses) so the AbortSignal propagates through the tool executor: running shell commands get SIGTERM, in-flight LLM streams terminate
- Finalize in-memory messages via finalizeMessagesForSave() to strip partial: true flags and stamp the open api_req_started with cancelReason: "user_cancelled", re-add via messageStateHandler.addMessages() which updates by ts in-place, and persist synchronously via saveClineMessages so on-disk history reflects a cleanly cancelled turn
- Set activeSession.isRunning=false before teardown so late events from the dying session cannot flip state on the new session
Tests: npx tsc --noEmit and npx biome lint both pass clean.
Mirrors the CLI's plan -> act flow (apps/cli/src/runtime/run-interactive.ts)
by adding a programmatic mode-switch tool to SDK sessions started in plan
mode. When the model calls switch_to_act_mode after the user agrees to
the plan, the tool sets a pendingModeChange flag and returns a success
message so the current turn completes normally. After sessionManager.send()
returns, applyPendingModeChange() is invoked as the plumbing entry point
for the full session-rebuild flow (to be implemented in Task 4).
Changes to src/sdk/SdkController.ts:
- Import createTool and Tool type from @clinebot/shared
- Add pendingModeChange: Mode | null field
- Add createSwitchToActModeTool() private method matching the CLI's
tool definition (name, description, success message, timeouts)
- Add injectModeExtraTools() helper and wire it into all four
session-creation code paths: initTask, reinitExistingTaskFromId,
resumeSessionFromTask, and restartSessionForMcpTools
- Add applyPendingModeChange() stub that reads and clears the flag
(Task 4 will fill in the full session rebuild)
- Invoke applyPendingModeChange() from fireAndForgetSend's .then()
after the turn completes (skipped for queue/steer deliveries)
CoreSessionConfig.mode is already set correctly in buildSessionConfig(),
so the SDK's plan preset (which disables editor tools) continues to be
selected -- our injected tool is merged with that preset.
Verification: tsc --noEmit passes with 0 errors; SDK vitest suite
shows 143 passing tests (same as baseline).
Mirrors the CLI plan-mode guardrails (apps/cli/src/runtime/prompt.ts)
so plan mode in VSCode tells the model to explore/analyze/plan and NOT
implement. Previously buildClineSystemPrompt did not emit these
instructions, so plan mode in VSCode had weaker guardrails than the CLI.
Implement the remaining two feasible Cline hooks as SDK AgentExtension
plugins, since AgentHooks lacks the right hook points for these:
- UserPromptSubmit → onInput: fires before the prompt enters the agent
loop, supports cancel and contextModification
- TaskCancel → onSessionShutdown: fires only on user-initiated
cancellation (reason === session_stop), fire-and-forget
Changes:
- hooks-adapter.ts: add buildHookExtensions() returning AgentExtension[]
with one inline extension (cline-lifecycle-hooks) implementing onInput
and onSessionShutdown callbacks
- SdkController.ts: add buildExtensionsWithEmitter() method and wire
config.extensions at all 4 session creation sites (initTask,
reinitExistingTaskFromId, resumeSessionFromTask,
restartSessionForMcpTools)
The existing buildAgentHooks() for the 4 AgentHooks-based hooks
(TaskStart, PreToolUse, PostToolUse, TaskComplete) is untouched.
When using the 'cline' provider without authentication, the SDK throws a
generic 'Missing API key' error that surfaces as a raw red error message
with an infinite 'Thinking...' spinner. The classic extension shows a
friendly login prompt with a 'Sign in to Cline' button instead.
Fix by adding a pre-check in initTask() that detects the cline provider
with no auth token and emits the same message sequence the classic
extension uses (say:task -> say:api_req_started -> ask:api_req_failed
with a serialized ClineError). The webview's ErrorRow already handles
this pattern and renders the sign-in UI.
Also updates catch blocks in fireAndForgetSend(), askResponse(), and
reinitExistingTaskFromId() to detect cline auth errors and emit the
proper auth UI instead of raw say:error messages.
The SDK invokes AgentHooks callbacks inline (not through onEvent), so the
message-translator case "hook" handler never fires for adapter hooks. This
means hooks run silently with no UI feedback.
Fix by emitting hook_status ClineMessages directly from the hooks-adapter
callbacks via a HookMessageEmitter callback provided by SdkController.
Changes to hooks-adapter.ts:
- Add HookMessageEmitter type and buildHookStatusMessage() helper
- Add optional emitHookMessage param to buildAgentHooks()
- In all 4 callbacks, check factory.hasHook() before emitting
- Emit running/completed/cancelled/failed status messages
Changes to SdkController.ts:
- Add buildHooksWithEmitter() that wires emitter to messageStateHandler,
pushMessageToWebview, and debouncedSaveClineMessages
- Override config.hooks at all 4 buildSessionConfig() call sites
Create src/sdk/hooks-adapter.ts that maps 4 Cline hooks to SDK
lifecycle callbacks:
- TaskStart → onSessionStart
- PreToolUse → onToolCallStart
- PostToolUse → onToolCallEnd
- TaskComplete → onRunEnd (gated on finishReason === completed)
Each callback dynamically checks hooksEnabled via StateManager so
toggling mid-session takes effect immediately. All callbacks are
fail-open (errors logged, never block the SDK).
Wire buildAgentHooks() into buildSessionConfig() in
cline-session-factory.ts so every new session gets hook callbacks.
The attempt_completion extra tool defined a command parameter in its schema
but the execute function silently discarded it, wasting tokens.
Re-use the SDK built-in bash executor (via createDefaultExecutors) to run
the command when provided, and append its output to the completion result
returned to the model.
Changes:
- vscode-runtime-builder.ts: createAttemptCompletionTool now accepts cwd,
lazily creates a bash executor, and executes the command parameter
- vscode-session-host.ts: passes input.config.cwd to createVscodeExtraTools
Closes S6-47
When the user sends a follow-up message while the agent is mid-turn,
askResponse() now detects isRunning and passes delivery: "queue" to
the SDK send() call. The SDK enqueues the message and drains it after
the current turn completes, preventing "already in progress" errors.
Changes:
- fireAndForgetSend(): accept optional delivery param, skip isRunning
reset when message was queued (turn didnt complete)
- askResponse(): capture wasAlreadyRunning before setting isRunning,
compute delivery accordingly, skip translator reset for queued msgs
- handleSessionEvent(): log pending_prompts/pending_prompt_submitted
events for visibility
MCP tools were bypassing the approval flow because buildToolPolicies()
only covered built-in SDK tools. MCP tools registered as extra tools
with serverName__toolName names had no policy entries, so the SDK
defaulted them to autoApprove:true.
- Add MCP tool iteration in buildToolPolicies() using McpHub.getServers()
- Gate MCP tool auto-approve on both the global useMcp toggle and each
tool's individual autoApprove flag
- Use serverName__toolName format matching the SDK's default name transform
- Remove unnecessary regex sanitization helper (sdkMcpToolName)
The SDK defaults all tools to autoApprove:true when no toolPolicies
are provided. The user's auto-approval settings (readFiles, editFiles,
executeSafeCommands, etc.) were not being translated into SDK
toolPolicies, so requestToolApproval was never called.
- Add buildToolPolicies() that maps AutoApprovalSettings actions to
SDK tool names with { autoApprove: boolean } policies
- Add toolPolicies option to VscodeSessionHostOptions, pass through
to ClineCore.create()
- Read autoApprovalSettings from StateManager in startNewSession()
and pass the derived toolPolicies to VscodeSessionHost.create()
Implement the requestToolApproval callback so the SDK can request user
approval for non-auto-approved tools (S6-26 Part A).
- Export sdkToolToClineSayTool from message-translator.ts for reuse
- Add handleRequestToolApproval() private method to SdkController that
converts SDK ToolApprovalRequest to ClineSayTool JSON, emits a
ClineMessage with type:ask/ask:tool, and returns a Promise resolved
when the user clicks Approve/Reject in the webview
- Add handleAskQuestion() private method (extracted from inline callback)
- Wire both callbacks into startNewSession() via VscodeSessionHost.create()
- Add pendingToolApprovalResolve field to SdkController, resolved in
askResponse() by reading taskState.askResponse (yesButtonClicked=approve,
noButtonClicked=deny)
- Clean up pendingToolApprovalResolve in cancelTask() and clearTask()
to prevent Promise leaks
- Update PROBLEMS.md to mark Part A as fixed
The SDK built-in ask_question tool was excluded from the agent tool list
because no askQuestion executor was provided. The agent could not ask
clarifying questions when encountering ambiguity.
Changes:
- vscode-session-host.ts: Add askQuestion option, pass defaultToolExecutors
to ClineCore.create() so the SDK includes ask_question in the tool list
- SdkController.ts: Implement askQuestion executor that emits ClineMessage
with ask:"followup" (reusing existing webview UI), stores a pending
Promise resolver, and resolves it when askResponse() is called.
cancelTask()/clearTask() clear pendingAskResolve to prevent leaks.
- message-translator.ts: Update comment to reflect new handling
- PROBLEMS.md: Mark S6-26 Part B as fixed with evidence
The SDK editor tool provides old_text and new_text, but the message
translator stored raw new_text in content. DiffEditRow did not recognize
it as a diff format and fell through to a fallback treating every line
as an addition (all green, no red).
Three fixes:
1. message-translator.ts editor case: when both old_text and new_text
are present, build a SEARCH/REPLACE diff in the format DiffEditRow
expects.
2. message-translator.ts apply_patch case: also check the input field
(SDK format) and populate both content and diff.
3. ChatRow.tsx: prefer tool.diff over tool.content when passing to
DiffEditRow, and check for either in the guard condition.
7 new tests, 1 updated test. All 72 message-translator tests pass.
The SDK search_codebase tool input can be a bare array or string
(per SearchCodebaseUnionInputSchema), but parseToolInput() only
handled objects. This caused empty regex in the UI. Additionally,
the SDK has no path param for search, so the webview showed "/".
Changes:
- message-translator.ts: Handle bare array and string input formats
for search_codebase in sdkToolToClineSayTool()
- ToolGroupRenderer.tsx: Show "codebase" instead of "/" when search
path is empty; fix getActivityText to not require path for search
- RequestStartRow.tsx: Same empty-path fixes for consistency
- 8 new unit tests covering all SDK input formats and content_end
preservation
The SDK migration removed the classic parseMentions() call that resolved
context mentions (@/file, @problems, @git-changes, @https://url, @hash)
into inline content. The SDK's own mention enricher only handles simple
@path mentions and fails with the webview's @/path format.
Add resolveContextMentions() to SdkController that calls parseMentions()
before sending text to the SDK in all three send paths: initTask(),
askResponse(), and resumeSessionFromTask().
Fixes: Context command not returning any response in chat
Three issues fixed in SdkController:
1. Race condition: Late-arriving SDK 'done' events after cancelTask()
produced completion_result messages that replaced the 'Resume Task'
button with 'Start New Task'. Added a filter in handleSessionEvent()
that suppresses these messages when isRunning === false.
2. Dead session: After cancellation, activeSession still existed but the
SDK session was dead (aborted). Clicking 'Resume Task' tried to send()
to the dead session causing 'session not found' error. Changed
askResponse() to also check isRunning, routing cancelled sessions to
resumeSessionFromTask() which creates a fresh SDK session.
3. Idle resume: resumeSessionFromTask() only generated a [TASK RESUMPTION]
prompt when there were no initialMessages. After cancellation there ARE
initialMessages (conversation history), so the prompt was empty and the
session sat idle. Changed to always send a resumption prompt when the
user didn't type anything, matching classic extension behavior.
Main's PR #10196 (Remove foreground terminal, commit 1862f1595) removed
the vscodeTerminalExecutionMode field from ExtensionState. The webview
now unconditionally renders commands as background-exec (ChatRow.tsx
hardcodes isBackgroundExec={true}), so the SDK-adapter override in
getStateToPostToWebview() is both a type error and dead code.
Removes the override and documents why it's no longer needed for any
future archaeology.
S6-39: SDK fetch_web_content uses { requests: [{ url, prompt }] } but
sdkToolToClineSayTool() only checked for a top-level url field. Added
fallback to extract URL from requests[0].url.
S6-40: SDK skills tool uses { skill: "name" } but sdkToolToClineSayTool()
only checked skill_name and name fields. Added skill to the fallback chain.
7 new unit tests covering both SDK and classic input formats.
When the user cancels a running task, AbortController.abort() in the SDK
throws an AbortError that propagated unhandled to the VSCode developer
console. Three fixes:
1. VscodeSessionHost.abort(): wrap inner.abort() in try/catch that
suppresses AbortError (expected) and re-throws others.
2. SdkController.cancelTask(): narrow try/catch to only the abort()
call, suppress AbortError at debug level, and always proceed with
cleanup. Emit ask: "resume_task" instead of say: "info" so the
webview shows the Resume task button (fixes S6-34).
3. SdkController.fireAndForgetSend(): detect AbortError in .catch()
and return early without emitting error events to the UI.
Two bugs combined to cause unbounded stdout accumulation in the SDK
file indexer when starting a new task:
1. SdkController used process.cwd() instead of getCwd() for workspace
resolution. In VSCode extension host, process.cwd() returns the
VSCode installation dir, not the workspace folder, causing rg to
recurse enormous directory trees.
2. SDK file-indexer.ts rg command only excluded .git but not
node_modules/dist/build/etc (which walkDir fallback did exclude).
This is fixed in the linked SDK repo separately.
Fixes:
- Replace all process.cwd() calls in SdkController.ts and
cline-session-factory.ts with getCwd() which resolves the actual
workspace folder via HostProvider.workspace.getWorkspacePaths()
- Document fix in PROBLEMS.md as S6-44
The SDK run_commands tool returns ToolOperationResult[] with structured
output ({query, result, success, error?}). The message translator was
falling through to JSON.stringify() for non-string output, causing raw
JSON like [{"query":"ls","result":"...","success":true}] to appear in
the chat instead of formatted shell output.
Changes:
- Add extractToolOutputText() helper that extracts raw text from
ToolOperationResult[] format, using result.result for success and
result.error for failures
- Update command content_end handler to use extractToolOutputText()
- Override vscodeTerminalExecutionMode to backgroundExec in
SdkController.getStateToPostToWebview() since SDK always uses
background execution
- Add 15 unit tests covering all output extraction cases
Fixes S6-41
The SdkController used process.cwd() in 4 places as the working directory
for SDK sessions. In VSCode, process.cwd() returns the extension host
directory, not the user workspace. This meant Cline could not find project
files without explicit paths.
Added SdkController.getWorkspaceRoot() which resolves the workspace root
via HostProvider.workspace.getWorkspacePaths() (delegates to
vscode.workspace.workspaceFolders[0].uri.fsPath), falling back to
process.cwd() only when no workspace folder is open.
Replaced all 4 process.cwd() calls in initTask(), reinitExistingTaskFromId(),
resumeSessionFromTask(), and restartSessionForMcpTools().
Also added a defensive warning log in buildSessionConfig() for the
process.cwd() fallback path.
Updated PROBLEMS.md: S4-3 marked fixed, S6-38 added.
Renamed isActive to \$isActive in StyledTabButton in ClineRulesToggleModal.tsx.
The dollar-sign prefix tells styled-components to consume the prop for
styling without forwarding it to the underlying DOM element, eliminating
the React warning "React does not recognize the isActive prop on a DOM element."
Updated PROBLEMS.md with S6-45 entry marked as verified fixed.
Keep the active task/session id stable during MCP tool-list restarts so currentTaskItem stays mapped and chat state is not lost after toggling MCP servers.
SessionManager interface changes:
- Add update() and handleHookEvent() to VscodeSessionHost
- Remove readHooks() (no longer in SessionManager interface)
- Import HookEventPayload from @clinebot/core
Auth service fixes:
- Replace InstanceType<typeof UserInfo> with UserInfo type directly
- Fix null assignment to protobuf field (use empty create instead)
In the SDK migration branch, every agent response was showing a green
'Task Completed' rectangle because the done event unconditionally emitted
completion_result messages. In the classic extension, the green rectangle
only appeared when the agent explicitly called the attempt_completion tool.
Changes:
- Register attempt_completion as a custom tool in VscodeRuntimeBuilder
so the SDK agent can call it (the SDK has no built-in equivalent)
- Handle attempt_completion in MessageTranslator: content_start emits
say:'completion_result' (green rectangle), content_end emits
ask:'completion_result' with empty text (enables follow-up input
without a second green rectangle)
- Track attempt_completion calls via MessageTranslatorState so the done
event can skip emitting completion_result when already handled
- When attempt_completion is NOT called, done emits ask:'completion_result'
with empty text (renders as InvisibleSpacer, no green rectangle)
- Update tests: 2 existing tests updated, 1 new test added for the
suppression behavior (35/35 pass)
After restartSessionForMcpTools() completes, the webview was left in
a 'Thinking...' state because no ask:'completion_result' message was
emitted. The webview's handleSendMessage() requires clineAsk to be
set to enable follow-up input.
Fix: Emit ask:'completion_result' after the success info message so
the webview knows the agent is idle and enables the follow-up input.
Tested with debug harness:
1. Sent 'Say hello briefly' → completed
2. Toggled kamibiki MCP server off via UI
3. 'MCP tools changed' + 'reloaded successfully' messages appeared
4. Typed 'Say goodbye' → follow-up inference ran successfully
Three fixes for the SDK migration:
1. Follow-up messages: Changed the 'done' event translation from
say:'completion_result' to ask:'completion_result'. The webview's
handleSendMessage() requires clineAsk to be set to send follow-up
messages. Without the ask message, typing a follow-up and pressing
Enter was silently dropped.
2. Session cleanup: Clear activeSession reference before stop/dispose
to prevent re-entrant calls. Added 3s timeouts to stop()/dispose()
to prevent UI blocking when sessions are in unexpected states.
3. MCP tool change debouncing: When an MCP server connects,
notifyWebviewOfServerChanges() fires multiple times in quick
succession. Added 300ms debounce with fingerprint quick-check
to coalesce these into a single tool list change callback.
Tested with debug harness:
- MCP tools (kb_status, kb_search) work correctly
- Follow-up messages work via both gRPC and DOM (typing + Enter)
- MCP tools work in follow-up turns
- McpHub: Added computeToolFingerprint(), setToolListChangeCallback(),
clearToolListChangeCallback(), and checkToolListChanged() to detect
when the set of available MCP tools changes (servers added/removed/
reconnected). Only fires on actual tool list changes, not mere status
updates.
- SdkController: Added handleMcpToolListChanged() which restarts the
session immediately when idle, or defers via mcpToolRestartPending
flag until the current turn completes. restartSessionForMcpTools()
creates a new VscodeSessionHost with fresh tools, preserves
conversation messages, and emits info messages to the chat.
- SdkController: Fixed MCP settings file path — was reading from
VSCode extension storage (HostProvider.globalStorageFsPath/settings/)
instead of ~/.cline/data/settings/ where the actual MCP settings live.
- task-proxy: Made taskId settable so session restart can update the
proxy's session ID without recreating it.
- Tests: 16 unit tests for tool list change detection covering
fingerprinting, callback firing, and edge cases.
Known issues: S6-28 (reload messages appear twice), S6-29 (new task
button broken after reload). See PROBLEMS.md.
The gRPC handler for showTaskWithId was calling controller.initTask()
which starts a NEW SDK session instead of loading the existing task's
messages from disk. Changed to call controller.showTaskWithId(id)
which correctly: (1) looks up the history item, (2) tears down any
active session, (3) creates a task proxy with loaded messages,
(4) pushes messages through both state updates and partial message
stream, (5) posts state to the webview.
Verified with debug harness: send message → new task → click history
item → conversation restored with all messages.
- S6-24: Preserve tool input from content_start for use at content_end
(MessageTranslatorState stores streamingToolInput/streamingToolName)
- S6-6: Replace readUiMessages (legacy path) with getSavedClineMessages
(uses HostProvider.globalStorageFsPath, matching saveClineMessages)
- Restore postStateToWebview() in handleSessionEvent (needed for streaming)
- Fix TS2352 cast in message-translator.ts (as unknown as Record)
- Add 4 new tests for tool input preservation through streaming lifecycle
- S6-26: Research SDK pending prompts/tool approval/ask_question system
- S6-27: Create focused task for history messages still not rendering
- Update PROBLEMS.md priority section
The partial message handler in ExtensionStateContext only updated
existing messages by matching timestamps — it never appended new ones.
In the classic extension, messages were first added via state updates,
then updated in-place by partial messages. In the SDK migration,
messages arrive via the partial message stream first, so they need
to be appended when no existing message matches.
Also adds debounced ClineMessage persistence in SdkController so
task history can load messages via readUiMessages().
- S6-5: Regressed — inference works but view doesn't switch to chat
- S6-6: Failed verification, merged S6-15 into it
- S6-8: Marked as verified fixed (brown logo)
- S6-19: New — history deletion dialog confirms but doesn't delete
- S6-20: New — MCP tools panel is empty
- Added Priority & Next Steps section recommending S6-5 as top priority
The SDK's DefaultSessionManager passes the systemPrompt from
CoreSessionConfig directly to the Agent — there is no fallback for
empty system prompts. Both the CLI and SDK's VSCode extension call
buildClineSystemPrompt() before passing config to the session manager.
Our buildSessionConfig() was setting systemPrompt: '' (empty string),
which caused the gateway to return empty responses with 0 tokens.
Changes:
- cline-session-factory.ts: Import buildWorkspaceMetadata from
@clinebot/core and buildClineSystemPrompt from @clinebot/shared.
Build the full Cline system prompt in buildSessionConfig() using
workspace metadata, IDE name, mode, provider, and platform.
Falls back to a minimal prompt on error.
- vscode-session-host.ts: Add logging around send() for debugging
inference issues (input/output tokens, response text).
- SdkController.ts: Add logging for session events and agent turn
completion to aid debugging.
Verified: Agent responds correctly with 2776 input tokens (system
prompt) and generates proper output ('Hello, world! 👋').
- Rewrite restoreRefreshTokenAndRetrieveAuthInfo() to read from providers.json
instead of injecting through StateManager secrets
- Add fetchUserInfoFromApi() to get user profile from Cline API at startup
- Delete VscodeOAuthTokenManager (~180 lines) - SDK default handles persistence
- Simplify resolveApiKey() for cline provider to read from providers.json
- Cache getProviderSettings() as singleton to avoid re-reading file
- Net reduction of 94 lines
Documents which directories contain minified/generated code that
produces noisy search results (out/, dist/, src/generated/, etc.),
how to skip them with search_files and grep, and how to search
minified files when necessary (grep -oP, source maps).
Four fixes for making inference work in the VSCode UI:
1. Webview state connection (S6-13): Wire WebviewGrpcBridge to the
controller's getStateToPostToWebview() so state updates include
messages, currentTaskItem, and task history. Added setGetStateFn()
method to the bridge and called it from SdkController constructor.
2. Chat history loading (S6-6): Fix history lookup in showTaskWithId()
and reinitExistingTaskFromId() to check StateManager's taskHistory
first (where updateTaskHistory writes), then fall back to the legacy
file reader. Also clear active session before viewing history.
3. Message translation (S6-12): Add sdkToolToClineSayTool() mapping
function that converts SDK tool names (read_files, editor, etc.) to
classic ClineSayTool format that ChatRow.tsx expects. Add usage event
handling for api_req_started messages. Update tests to match actual
output format.
4. VscodeRuntimeBuilder (S6-14): New custom RuntimeBuilder that bridges
the classic McpHub to the SDK's tool system. Delegates builtin tools
to DefaultRuntimeBuilder but replaces MCP tools with ones loaded from
the classic McpHub, supporting all transport types (stdio, SSE,
streamableHttp). Not yet wired into session creation — needs
VscodeSessionHost wrapper (see S6-9).
All 99 SDK unit tests pass.
- Fix credential resolution: replace broken ProviderSettingsManager and
buildApiHandlerSettings() paths with resolveApiKey()/resolveModelId()
that read directly from StateManager.getApiConfiguration() (includes
secrets). Handles all 30+ providers including cline OAuth token
extraction (idToken from cline:clineAccountId JSON, workos: prefix).
- Fix non-blocking session start: initTask() now calls
core.start({interactive:true}) WITHOUT a prompt (returns immediately),
then fire-and-forgets core.send() for inference. Events stream
in real-time via subscribe(). Same pattern for askResponse().
- Add MCP settings filtering: SDK's StdioMcpClient only supports stdio
transport. ensureFilteredMcpSettings() writes a filtered copy of
cline_mcp_settings.json (stdio-only) and sets CLINE_MCP_SETTINGS_PATH
env var. Future: replace with custom RuntimeBuilder that provides a
clientFactory delegating to classic McpHub for streamableHttp support.
- Fix debug harness gRPC message format for web.post_message.
- Update PROBLEMS.md: S6-5 and S6-11 marked 🟢 Verified Fixed.
Verified: Debug harness sends newTask → session starts, agent runs,
events stream to webview (iteration_start, usage, iteration_end, done).
Protobuf defaults empty strings to ''. The check 'request.clineEnv !== undefined'
was true for empty strings, causing ClineEnv.setEnvironment('') which defaults
to 'production' but also triggers accountLogoutClicked(). This caused the user
to be logged out and the environment to appear to flip when changing models.
Fix: Also check 'request.clineEnv !== ""' before processing.
1. initTask() now saves history item to StateManager immediately
after session starts. Without this, currentTaskItem was undefined
in getStateToPostToWebview(), so the webview never switched to
chat view after sending a message.
2. updateTaskHistory() and deleteTaskFromState() are now real
implementations using StateManager instead of stubs.
3. Exposed window.__clineVsCodeApi in webview for debug harness
access (platform.config.ts).
4. Added detailed logging to initTask() for debugging:
- Session config (provider, model, apiKey presence)
- ClineCore creation
- Session start
- Error details
These fixes address the user-reported issues:
- Send button clears input but doesn't switch to chat view
- Chat history appears empty
TaskProxy improvements for settings handler compatibility:
- api property is now settable (updateSettings replaces it on model switch)
- terminalManager returns a proper stub that safely no-ops
(setDefaultTerminalProfile, setShellIntegrationTimeout, etc.)
- Added TaskProxyTerminalManager interface
SdkController improvements:
- togglePlanActMode() now properly implemented:
- Saves mode to StateManager
- Cancels active task if switching modes mid-task
- Posts state update to webview
- toggleActModeForYoloMode() switches to act mode
These changes ensure the updateSettings gRPC handler works
without modification — it calls controller.task.api and
controller.task.terminalManager which are now properly stubbed.
Following the 'Thunk, Don't Replace' principle, wire the classic
McpHub into SdkController instead of building a custom SDK MCP
manager. The classic McpHub already supports all three transports
(stdio, SSE, streamableHTTP), file watching, and all gRPC handlers.
Changes:
- SdkController.mcpHub: type changed from 'any' to 'McpHub'
- Constructor initializes McpHub with same args as classic Controller
- Existing gRPC handlers (subscribeToMcpServers, restartMcpServer,
deleteMcpServer, toggleMcpServer, etc.) work without modification
- SDK's InMemoryMcpManager will replace it in Step 10 (Cleanup)
Also includes:
- Fix S6-5: buildSessionConfig() falls back to classic StateManager
when SDK ProviderSettingsManager has no provider configured
- Fix S6-6: showTaskWithId() loads messages from disk via
readUiMessages() and adds them to TaskProxy's messageStateHandler
- Updated PROBLEMS.md and README.md with Step 7 progress
S6-5: buildSessionConfig() now falls back to classic StateManager
- Try SDK ProviderSettingsManager first (providers.json)
- If no provider/apiKey found, fall back to StateManager.buildApiHandlerSettings()
- This correctly resolves provider/model/apiKey for the current mode (plan/act)
- Critical because providers.json may not exist yet for existing users
S6-6: showTaskWithId() now loads messages from disk
- Call readUiMessages(taskId) to load ui_messages.json
- Add messages to TaskProxy's messageStateHandler via addMessages()
- This populates the message state so getStateToPostToWebview() returns them
Also: remove unused Settings import from cline-session-factory.ts,
add StateManager import for the fallback path.
- src/sdk/task-proxy.ts: TaskProxy provides classic Task-compatible
interface that delegates to SDK session methods. MessageStateHandler
extends EventEmitter for CLI compatibility (on/off pattern).
TaskProxyState mirrors classic TaskState subset.
- src/sdk/webview-grpc-bridge.ts: Bridges SDK session events to
webview gRPC streams. Translates ClineMessages to proto format
and pushes through sendPartialMessageEvent/sendStateUpdate.
- src/sdk/SdkController.ts: Wired TaskProxy + WebviewGrpcBridge
into session lifecycle. Events flow: SDK → message translator →
gRPC bridge → webview streams. Reuses getStateToPostToWebview()
for state building.
- No 'as' casts in production code — type narrowing used instead.
Stubs throw errors instead of returning undefined as unknown as T.
- 114 unit tests pass across 6 test files.
- 0 new TypeScript errors (3 pre-existing in unrelated files).
- Extension loads, sidebar renders, newTask routes correctly.
- initTask fails at runtime because ClineCore.create() needs SDK
config (Step 6+).
- Add @clinebot/core, @clinebot/llms, @clinebot/shared, @clinebot/agents
as dependencies via file: protocol (linked to ../sdk-wip)
- Create src/sdk/ directory with SdkController stub and barrel export
- Replace src/core/controller/index.ts with re-export from SDK adapter
(classic Controller accessible via origin/main)
- Extract getStateToPostToWebview() to standalone function for reuse
- Add vitest.config.sdk.ts for SDK adapter tests
- Fix implicit any types in handler modules
- Extension compiles and builds successfully (tsc + esbuild pass)
- Single entry point: no CLINE_SDK flag, SDK adapter is the only codepath
Replaces classic src/core/controller/index.ts (see origin/main)
Key changes from feedback:
- Replace 'don't delete what you haven't replaced' with 'delete and document'
- Delete classic code immediately when replaced by SDK equivalent
- Add 'Replaces classic src/core/... (see origin/main)' comments
- Use kb_search/git to reference origin/main for classic implementation
- Single entry point: no CLINE_SDK env variable, no dual codepaths
- Step 1 now modifies src/extension.ts directly
- Rationale: dual entry points caused constant confusion in attempt 2
- Updated ARCHITECTURE.md with key architectural decisions
- Updated .clinerules/sdk-migration.md with new rules
* At-mention picker: show "Searching..." instead of misleading "No results found"
When the @-mention picker fires its initial empty-query searchFiles, slow
workspaces (e.g. network mounts) leave the call in flight for several
seconds. Three small UX bugs combined to make this look broken:
1. The 500ms delayed-loading effect was gated on `searchQuery` being
non-empty, so the spinner never appeared during the initial open —
the user just saw "No results found" forever.
2. While loading, the spinner row stacked above the "No results found"
row, claiming both states at once.
3. The spinner also stacked above the static root-menu items
("Paste URL", "Problems", "Git Commits", "Add File", "Add Folder")
when the picker first opens with empty input, even though those
items are already actionable.
Fixes:
- Drop the `&& searchQuery` guard so the loading effect arms on empty
queries too.
- In `filteredOptions`, strip the lone `NoResults` entry while
`showDelayedLoading` is true — searching is not the same as nothing
matched.
- Render the spinner only when `filteredOptions.length === 0`, so it
never stacks above existing options.
The 500ms delay before the spinner appears is preserved, so fast
searches stay visually quiet.
* fixes
* Drop stale @-mention searchFiles responses to fix "No results" flash
* Track in-flight searches with a monotonic latestSearchTokenRef in
ChatTextArea; resolve/error handlers bail when their captured token
is no longer the latest.
* Send the token as mentionsRequestId; proto already supports it.
* Drop the never-read currentSearchQueryRef scaffold.
* Fixes the cancel-then-re-pick race (Add File → cancel → Add Folder)
reported in CLINE-1814.
Add a checkbox for users to indicate they're on a beta version, and
auto-apply the 'beta' label via the existing auto-label workflow when
the checkbox is checked.
* CLINE-1814 typed RipgrepSpawnError + error_reason proto
* file-search.ts: define RipgrepSpawnError carrying stderr+exitCode; reject
on non-zero ripgrep exit (with empty results) instead of resolving to []
* file-search.ts: re-throw from searchWorkspaceFiles and
searchWorkspaceFilesMultiroot so the controller sees the error and can
attach a structured error_reason to the proto response
* file-search.test.ts: assert spawn-time and exit-time errors both surface
as RipgrepSpawnError
* file.proto/FileSearchResults: add optional error_reason and error_message
fields with the closed enumeration of values documented inline
Phase 1 of the visibility patch. No behaviour change for healthy installs;
broken installs now surface a real error instead of an empty list.
Refs: CLINE-1814
* CLINE-1814 surface error_reason in picker UI
Controller (searchFiles.ts):
* classify thrown errors into a closed enumeration of error_reason values
(workspace_unavailable, ripgrep_spawn_failed, unknown). RipgrepSpawnError
unwraps the first line of stderr into error_message so the picker can
surface ENOENT / EACCES / 'Operation not permitted' verbatim.
* the no-workspace-path branch now returns workspace_unavailable instead
of an empty result list.
* keep using telemetry.captureMentionFailed for aggregate signal but map
ripgrep_spawn_failed -> 'unknown' to stay within the existing closed enum.
Webview (ChatTextArea + ContextMenu):
* ChatTextArea threads errorReason / errorMessage from each searchFiles
RPC response (and from RPC-level rejections) into ContextMenu.
* ContextMenu renders a grey, italic, smaller subtitle beneath the
'No results found' row when an error_reason is present.
* renderErrorSubtitle() carries a short doc-comment for each value so
reviewers can see at a glance how each error_reason maps to UI copy.
Refs: CLINE-1814
* CLINE-1814 trim verbose CLINE-1814 ticket-reference comments
Pure code-quality pass over the Phase 1 changes: condense the long
narrative comments that referenced the ticket into terser explanatory
comments where they still add value, and remove ones that just
repeated what the (now-stable) code already says. No behaviour change.
* CLINE-1814 fix RipgrepSpawnError override of Error.cause
TS error 'This member must have an override modifier because it
overrides a member in the base class Error' - Error gained an optional
'cause' field in ES2022. Drop the explicit field declaration and pass
the cause via the standard ES2022 ErrorOptions in super(). Behaviour
unchanged: instances still expose .cause via the base-class field.
* CLINE-1814 fix Windows race in executeRipgrepForFiles finalisation
CI hit this on Windows:
AssertionError: expected [Promise] to be rejected with a message
matching /ripgrep exited with code 2/, but got 'ripgrep exited with
code null: rg: /bogus: No such file or directory (os error 2)'
The readline 'close' event and the child-process 'exit' event fire in
non-deterministic order on Windows. The previous code keyed off 'close'
alone, which meant the rejection branch could run with exitCode still
null even when the process eventually exited with a real code.
Fix: gate finalisation on both events with a small barrier (rlClosed +
processExited + finalised flags). Idempotent and safe under any
ordering. Test passes on darwin (where the ordering used to be benign)
and the same path now produces the expected exitCode=2 message on
Windows.
No production-behaviour change on the happy path: results still resolve
exactly when the readline finishes parsing stdout.
* CLINE-1814 address Phase 1 code-review feedback
Three small follow-ups from review on the Phase 1 PR:
1) ContextMenu.tsx: drop a stray trailing semicolon on the
selectedType prop declaration so the interface style stays
consistent with the rest of the file (no semicolons on field
declarations). Cosmetic only, no behaviour change.
2) file-search.ts: in executeRipgrepForFiles' rgProcess.on('error')
handler, set finalised = true before reject() so that a subsequent
('close', 'exit') pair can't pass the finalise() guards. The
double-reject was already a no-op (Promises swallow further
reject() calls once settled), but unconditionally maintaining the
barrier invariant makes the lifecycle of this Promise much easier
to reason about and matches the symmetry of the other two
finalise() callers.
3) file-search.test.ts: collapse the awaited-twice rejected-promise
pattern in 'should reject with RipgrepSpawnError when ripgrep
exits non-zero with no results'. The previous form
(await should(p).be.rejectedWith(...); await p.catch(...)) worked
because settled promises replay their value, but it's subtly
misleading. The new form awaits once via .catch() and asserts on
the resulting error directly.
All six File Search unit tests continue to pass.
* CLINE-1814 revert picker error subtitle (UI for impl-detail leak)
Per code-review feedback: surfacing structured error_reason / error_message
from FileSearchResults as a grey-italic subtitle on the 'No results found'
row exposes implementation detail to end-users. The user can't act on
'(ripgrep failed: rg: ENOENT)' or '(internal error: spawn EACCES)' — those
are diagnostic data that belong in logs and aggregate telemetry.
Reverted in this commit:
- ContextMenu.tsx: errorReason / errorMessage props removed,
renderErrorSubtitle helper deleted, NoResults row reverts to a plain
<span>No results found</span>.
- ChatTextArea.tsx: searchErrorReason / searchErrorMessage state and
all setSearchErrorReason / setSearchErrorMessage call-sites removed;
ContextMenu invocation no longer passes the two props.
Kept on purpose:
- The proto field FileSearchResults.error_reason — it's harmless on
the wire and the next commit wires it up to telemetry + structured
logging, which is where this signal actually belongs.
- The classifyError helper and ERROR_REASON_* constants in the
searchFiles controller — same reason, they feed telemetry next.
Six file-search unit tests still pass.
* CLINE-1814 telemetry: surface ripgrep_spawn_failed / workspace_unavailable
Until now the searchFiles controller's catch block collapsed every classified
error_reason — workspace_unavailable, ripgrep_spawn_failed, unknown — onto a
two-value telemetry enum (permission_denied | unknown), throwing away the
diagnostic signal we'd worked hard to extract. The Linear ticket explicitly
asks for the structured signal to feed telemetry; this commit delivers on that.
Changes:
- TelemetryService.captureMentionFailed: extend the errorType enum with
two new categorical values, ripgrep_spawn_failed and workspace_unavailable.
Doc-comment updated to call out that those two are picker-search failures
(vs the existing values which are mention-content retrieval failures).
- searchFiles.ts:
* empty-workspace branch now emits errorType=workspace_unavailable
(previously: not_found).
* catch-block computes errorType from the classified errorReason —
RipgrepSpawnError -> ripgrep_spawn_failed, EACCES -> permission_denied,
otherwise unknown — instead of always permission_denied | unknown.
Net result: ops can now distinguish 'ripgrep is broken on this user's
machine' from 'user is in a one-window-no-folder IntelliJ session' from
genuine code bugs in the search pipeline.
* CLINE-1814 log: include classified errorReason on searchFiles error line
Trivial follow-up to the previous commit. Triagers grepping
~/.cline/cline-core-service.log for searchFiles failures got the raw error
object dumped, but no hint as to which of the structured error_reason
buckets the failure falls into. Now the log line is
[ERROR] Error in searchFiles (errorReason=ripgrep_spawn_failed): <Error...>
so a single grep for 'errorReason=ripgrep_spawn_failed' surfaces every
ripgrep-side failure across the user's session without having to read the
stack trace. Same field value as the gRPC response and the telemetry event,
so the three sources can be cross-referenced in incident triage.
Also moved the classifyError() call above the Logger.error() call (was
below) so the reason is computed once, used twice.
* CLINE-1814 address Phase 1 review feedback (rename, simplify, trim comments)
Five review comments rolled into one commit:
file-search.ts
* Rename RipgrepSpawnError -> RipgrepError. The class covers spawn failures
AND non-zero-exit / stderr-on-empty-stdout paths; the old name only
described half its job.
* Drop the unread 'cause' constructor option. We were never reading
err.cause anywhere downstream, and the only producer was the
spawn-error path which already encodes the underlying message in the
string.
* Replace the rlClosed/processExited/finalised state machine with two
Promise resolvers awaited via Promise.all. Same ordering guarantees on
Windows (both 'close' and 'exit' must fire before we settle), zero
mutable bookkeeping, and the spawn-error path no longer needs to
pre-flip a 'finalised' flag to be safe against a late close+exit pair.
Used new Promise() rather than Promise.withResolvers() because TS lib
is es2022 and withResolvers is es2024; behavior is identical.
searchFiles.ts
* .trim() the stderr before split() so a leading newline doesn't yield
an empty first line on the telemetry / log path.
* Drop the 'this commit' comment (ephemera once 'this commit' is no
longer the most recent one) and the 'Determine mention type based on
the search request' comment, both of which restated the obvious code.
file-search.test.ts
* Update test name and assertion to match the renamed class.
All 6 file-search unit tests pass.
* CLINE-1814 drop unread RipgrepError.exitCode field
Follow-up to the previous review-feedback commit. The 'we're not reading
this anywhere' note was about exitCode, not cause - my mistake. The exit
code is already encoded into the error message string ('ripgrep exited
with code N: <stderr>'), so the dedicated field was carrying no
additional information for any consumer.
Dropped:
* RipgrepError.exitCode field and constructor option
* 'exitCode' from the two new RipgrepError(...) call sites
* 'should(err).have.property(exitCode, 2)' from the unit test
The internal exitCode local in executeRipgrepForFiles stays - it gates
the reject vs resolve decision after both 'close' and 'exit' have fired.
It's just no longer plumbed onto the error.
All 6 file-search unit tests still pass.
* feat(memory-observability): add periodic memory logging to cline-core
Introduces a lightweight memory monitor that logs process.memoryUsage()
snapshots to the existing cline-core log every 5 minutes, plus an
immediate baseline at startup and a final snapshot at graceful shutdown.
Each entry is written as a single `[MEMORY] key=valueMB ...` line so it
is trivially greppable and parseable:
grep '\[MEMORY\]' ~/.cline/cline-core-service.log
The timer is unref()'d so it does not keep the event loop alive on its
own, ensuring the Node process can still exit cleanly.
Also adds an informational log line after process.chdir(__dirname) that
records where V8 will write heap snapshots if --heapsnapshot-near-heap-limit
triggers them, and a best-effort process.on("exit") handler that scans
cwd for .heapsnapshot files on abnormal exit and logs their paths/sizes
so post-mortem investigation starts with the diagnostic data in hand.
This is Part 1 (periodic memory logging) and the Node-side portions of
Part 2 (snapshot directory + exit handler) of the memory observability
implementation plan. The V8 flag itself and the
~/.cline/heapsnapshots/ move-and-cap cleanup live in the Kotlin
CoreProcessManager and are applied separately in the plugin repo.
No business-logic changes; purely additive diagnostics.
* chore(memory-observability): enable --heapsnapshot-near-heap-limit=3 in runclinecore.sh
When cline-core approaches the V8 heap ceiling, V8 will now write up to
3 .heapsnapshot files to the current working directory before giving up
and crashing. These snapshots can be loaded into Chrome DevTools → Memory
tab to identify the objects retaining the most memory.
N=3 is chosen because the last snapshot (written just before the fatal
OOM) shows only live, truly-unreclaimable objects — the earlier ones still
contain garbage the GC hadn't collected yet. Having all three lets us
compare.
This flag is a V8 runtime flag and must be passed on the node command
line; it cannot be enabled from JavaScript at runtime.
Matches the equivalent change on the cline-core launcher in the IntelliJ
plugin repo (CoreProcessManager.kt).
* chore(memory-observability): reduce --heapsnapshot-near-heap-limit from 3 to 1
Reviewer concern: with --max-old-space-size=8192, each heap snapshot
serializes at roughly 4-5x heapUsed on disk, so three snapshots can
burst 24-40 GB to disk in the seconds before an OOM crash — right
when the system is already under memory/CPU pressure. On a laptop
with <40 GB free this can leave partial/corrupted snapshots or
trigger OS pressure on unrelated processes.
The plan doc originally argued 'snapshot 3 of 3 is most valuable
because it contains only live objects'. In practice, by the time V8
triggers the flag it has already run aggressive mark-compact cycles,
so snapshot 1 is nearly-all-live too. Our own Scenario B verification
run confirmed that even the first snapshot contained the retainer
chain — snapshots 2 and 3 added no diagnostic signal.
Trade-off:
- per-OOM disk burst: 24-40 GB -> 8-14 GB (3x reduction)
- time-to-crash (frozen): 30-60 s -> 10-20 s (3x reduction)
- diagnostic signal: essentially unchanged
The persistent-directory cap in CoreProcessManager.kt stays at 3, so
we still retain snapshots from the 3 most recent OOM events for
cross-event comparison.
* chore(memory-observability): shorten runclinecore.sh flag comments
The one-line pointer to CoreProcessManager.kt was more noise than
signal given the flags are visible on the same line as the command.
Rationale for the --heapsnapshot-near-heap-limit value lives in the
Kotlin constant's KDoc and in the commit log.
* Make the nightly publishing script use the stable channel of cline-nightly.
* Address PR review feedback from Greptile and Copilot
- Reject unknown CLI flags with an error message, preventing typos like
--prerelease from silently publishing to the wrong channel (Greptile)
- Rename 'stable' to 'release' throughout docs, help text, and log
messages to match VS Code Marketplace terminology (Copilot)
- Rename workflow step from 'Publish Extension as Pre-release' to
'Publish Nightly Extension' since it now publishes to the release
channel by default (Greptile)
* fix: set --max-old-space-size=8192 for cline-core node process
The cline-core Node.js process was launched without a V8 heap limit,
defaulting to ~2GB. Long conversations with large file reads cause
GC-thrashing and eventual OOM crashes. Set the limit to 8GB to provide
sufficient headroom for extended sessions.
* fix: set --max-old-space-size=8192 for cline-core node process
* docs: add prompt storage schema and OpenTelemetry events reference
- Add comprehensive prompt storage documentation (DEVREL-142)
- Complete enterpriseTelemetry.promptUploading schema
- Setup guides for AWS S3 and Cloudflare R2
- Storage architecture and sync worker behavior
- IAM policies and troubleshooting
- Add OpenTelemetry events catalog (DEVREL-143)
- Document 80+ events across 8 categories
- Example payloads and analytics query patterns
- Integration examples for Datadog, Grafana, New Relic
- Event schema reference and best practices
- Update monitoring documentation
- Add cross-references between related pages
- Update navigation in docs.json
- Integrate new pages into Enterprise > Monitoring section
* fix: update broken link in telemetry.mdx to point to OTel events page
* docs: address PR review comments
- Fix file contents exclusion claim in prompt-storage.mdx
- Remove misleading claim about file contents not being stored
- Add warning that tool inputs (like write_to_file content) are included
- Standardize attribute naming in opentelemetry-events.mdx
- Change model_id to model in event tables for consistency
- Match actual emitted event schema shown in example payloads
- Add SQL syntax note in opentelemetry-events.mdx
- Clarify that attribute access syntax is platform-specific
- Provide examples for BigQuery and ClickHouse
* adjustments
- Update root package.json axios from 1.13.6 to 1.15.0
- Update evals/package.json axios from 1.13.6 to 1.15.0
- Update docs/package.json axios override from 1.13.5 to 1.15.0
- Regenerate all package-lock.json files
* feat: wire up globalSkills consumption from remote config
The remote config schema already includes globalSkills (merged in #10236).
The dashboard can save skills to remote config. This PR wires up the
extension to read and use them.
## Changes
### State storage (Layer 1)
- Add remoteGlobalSkills to REMOTE_CONFIG_EXTRA_FIELDS
- Add remoteSkillsToggles to GLOBAL_STATE_FIELDS
### Remote config transform/apply/clear (Layer 2)
- Map globalSkills → remoteGlobalSkills in transformRemoteConfigToStateShape
- Sync remoteSkillsToggles in applyRemoteConfig using frontmatter.name
as the identity key (not entry.name)
- Clear remoteSkillsToggles in clearRemoteConfig
### Skill discovery (Layer 3)
- discoverSkills accepts optional remoteSkillEntries parameter (pure
utility, no StateManager coupling)
- getSkillContent accepts optional remoteSkillEntries parameter for
remote content loading without disk I/O
- Precedence: remote (enterprise) > disk-global (user) > project
### refreshSkills (Layer 3b)
- Reads remote entries from controller.stateManager, parses frontmatter,
builds SkillInfo entries with alwaysEnabled field
### UseSkillToolHandler (Layer 4)
- Toggle filter checks remoteSkillsToggles for remote: prefixed skills
- Directory note omitted for remote skills
- Passes remoteSkillEntries to both discoverSkills and getSkillContent
### toggleSkill
- Routes remote: prefixed paths to remoteSkillsToggles keyed by name
### Proto + webview
- Added always_enabled field to SkillInfo proto message
- Modal passes isRemote + alwaysEnabled to RuleRow for remote skills
- Uses skill.name as display label for remote skills
## Design decisions
- frontmatter.name is the sole identity for remote skills (entry.name
is ignored). This matches how local skills work.
- remote: path prefix distinguishes remote from disk skills in toggle
stores and content loading.
- skills.ts remains a pure utility module with zero StateManager coupling.
Callers inject remote entries as parameters.
- 42 unit tests covering discovery, precedence, content loading, toggle
sync, and frontmatter parsing.
* fix: enforce alwaysEnabled in toggle sync to prevent stale false overrides
When applyRemoteConfig syncs skill toggles, synchronizeRemoteRuleToggles
preserves existing toggle values — including false. If an admin later
sets alwaysEnabled: true on a skill that a user had previously disabled,
the stale false toggle would survive the sync. The UI would show the
skill as locked-on (via the alwaysEnabled check in refreshSkills), but
UseSkillToolHandler's filter would see false in the toggle store and
exclude it, causing a 'Skill not found' error for a skill the user can
see is active.
Fix: after synchronizeRemoteRuleToggles, force any alwaysEnabled entry
with a false toggle back to true. This makes the toggle store the single
source of truth — both UI and handler now agree.
Adds 4 tests covering the alwaysEnabled enforcement edge cases.
* fix: deduplicate remote skill parsing, add drift validation, and fix architectural gaps
1. Extract shared parseRemoteSkillEntries utility (skills.ts)
- Single validation point for remote skill entries, replacing duplicated
frontmatter parsing in skills.ts, refreshSkills.ts, and remote-config/utils.ts
- Enforces entry.name === frontmatter.name to catch drift between the
dashboard and SKILL.md content (rejects with warning on mismatch)
2. Eliminate redundant frontmatter re-parsing in getSkillContent
- Was re-parsing every entry's frontmatter to find a match by name
- Now uses entry.name for lookup since drift validation guarantees equality
3. Enforce alwaysEnabled in UseSkillToolHandler
- The toggle filter was missing the alwaysEnabled check, so a stale false
toggle could hide an admin-locked skill from the model
- Now matches the logic in refreshSkills.ts
4. Add remote_skills_toggles to SkillsToggles proto
- toggleSkill now returns remoteSkillsToggles in the response, matching
how remote rules/workflows already work
5. Separate Enterprise Skills section in UI
- Remote skills now render under their own "Enterprise Skills" header,
consistent with how rules and workflows display remote entries
6. Update tests for new validation behavior
- Tests now use entry.name matching frontmatter.name (was deliberately
mismatched before); added drift rejection tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: enable viewing remote skills and fix tooltip text in RuleRow
- openRemoteFile now handles remote://skill/{name} URIs (was only
rule and workflow), looking up content from remoteGlobalSkills
- RuleRow's handleEditClick builds the correct URI type for skills
(was falling through to "rule")
- Tooltip text now uses ruleType ("View skill file") instead of
hardcoded "View rule file" for all remote entries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: soften drift validation to warn-not-reject, fix content lookup fallback
The strict entry.name !== frontmatter.name rejection was silently hiding
org-configured skills when the dashboard's entry.name didn't match the
SKILL.md frontmatter name.
- parseRemoteSkillEntries now warns on drift but uses frontmatter.name as
the canonical identity instead of rejecting the entry
- getSkillContent falls back to frontmatter match when entry.name lookup
misses (handles drift for content loading)
- openRemoteFile falls back to frontmatter match for skill view (same
reason)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: include remote skills in system prompt and fix remote config race
The system prompt generation called discoverSkills() without passing
remoteSkillEntries, so the model never learned about remote skills and
never invoked use_skill for them. This was the actual cause of remote
skills being invisible to the model despite showing in the UI.
Also fixes a race condition in applyRemoteConfig where clearRemoteConfig()
wiped the in-memory cache before repopulating it field-by-field. Any
concurrent reader (e.g., UseSkillToolHandler) during that window would
see an empty cache. Replaced with atomic replaceRemoteConfig() that
builds the new cache and swaps it in a single assignment.
- task/index.ts: pass remoteSkillEntries to discoverSkills, add
remoteSkillsToggles + alwaysEnabled filtering (matching handler)
- StateManager: add replaceRemoteConfig() for atomic cache swap
- remote-config/utils.ts: use replaceRemoteConfig instead of
clearRemoteConfig + setRemoteConfigField loop
- Remove debug logging from parseRemoteSkillEntries and handler
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: include remote skills in subagent path
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(models): prepare Claude Opus 4.7 provider support
* remove deprecated params for opus 4.7
- opus 4.7 doesn't accept params like temperature, top_p, top_k anymore.
This commit removes those params only for opus 4.7
* Agent hill climb fixes
* Anthropic adaptive thinking
* Removing 1m context switcher
* Removing 1m models fully
* Restore Anthropic 1M variants and context switchers
* Adding 1m
* remove changeset
* fix Opus 4.5 adaptive thinking detection
---------
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
Replace the old client-side per-org scan for remote config with a single
discovery call to GET /api/v1/users/me/remote-config. Reuse the inline
config value when possible, falling back to the org-level endpoint only
when inline parse fails.
Key changes:
- Single discovery call replaces N org-level requests
- Resolve config before switching org to avoid stranding the user
- Transient errors preserve existing config (log-only, no clearing)
- authenticatedRequest() strict null vs undefined validation
- Auth precheck in fetchUserRemoteConfig() with token pass-through
* fix(prompts): add use_subagents to GLM, Hermes, and XS TOOL_USE_SECTION overrides
These variants use hardcoded TOOL_USE_SECTION templates that bypass the
auto-generated tool descriptions. When use_subagents was added as a new tool,
it was registered in each variant's .tools() config but was never added to the
hardcoded override templates — so models using these variants never saw
use_subagents in their system prompt and could not call it.
This adds the use_subagents description block to the TOOL_USE_SECTION override
templates for glm, hermes, and xs variants, and updates the corresponding
test snapshots.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(prompts): gate use_subagents on subagentsEnabled and isSubagentRun context
The previous commit added use_subagents to the GLM, Hermes, and XS
TOOL_USE_SECTION override templates unconditionally. This was incorrect —
the canonical tool spec gates use_subagents with:
context.subagentsEnabled === true && !context.isSubagentRun
Without this guard, models would advertise use_subagents even when
subagents are disabled by the user, and subagent runs could recursively
spawn further subagents.
This commit:
- Wraps the use_subagents block in all three templates with the same
subagentsEnabled && !isSubagentRun conditional
- Converts HERMES_TOOL_USE_TEMPLATE from a plain string constant to a
function so it can access context (matching the pattern used by GLM
and XS templates)
- Updates snapshots accordingly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(prompts): align use_subagents rendering guard with tool context requirements
---------
Co-authored-by: sunghyun <jjinjukks1227@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(chat): add SpendLimitError UI for SPEND_LIMIT_EXCEEDED (429)
When the Cline backend returns a 429 with code SPEND_LIMIT_EXCEEDED (org
budget cap hit), the chat error flow now shows a dedicated SpendLimitError
component instead of falling through to the generic rate-limit message.
Changes:
- proto/cline/account.proto: add submitLimitIncreaseRequest RPC +
SubmitLimitIncreaseResponse message
- src/services/error/ClineError.ts: add SpendLimit error type; detect
SPEND_LIMIT_EXCEEDED before the generic rate-limit pattern check
- src/services/account/ClineAccountService.ts: add
submitLimitIncreaseRequestRPC() calling POST /api/v1/users/me/budget/request
- src/core/controller/account/submitLimitIncreaseRequest.ts: new gRPC
handler wired automatically by npm run protos
- webview-ui/src/components/chat/SpendLimitError.tsx: new card component
mirroring CreditLimitError; shows spent/limit amounts, resets_at, org
attribution, and a Request Increase button with 5-min localSto
When the Cline backend returns a 429 with code SPEND_LIMIT_EXCEEDED (org
budgetrors to
SpendLbudget cap hit), the chat budget_period,limit_usd,spent_usd,resets_at}
- component instead of falling through to the generic rate-limnd Limit
Reac
Changes:
- proto/cline/account.p
* Update webview-ui/src/components/chat/SpendLimitError.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* chore: shorten spend limit error message verbiage
* fix(storybook): align spend limit story messages with component output
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
The previous copy ("Cline is moving out of the terminal", "old CLI")
gave the impression that the terminal TUI was being deprecated. Updated
to frame Kanban as the new default while making clear the TUI is still
fully available.
* Complete documentation for environment variable-based OpenTelemetry configuration
* Address PR review comments
- Add Values column to OTLP Configuration table for consistency
- Fix New Relic endpoint to include required port 4318
- Add note about Datadog region-specific endpoints
Remove Teams Plan as an option for seat upgrades in the managing-members documentation. This aligns with the product strategy to drive customers toward Enterprise for any multiplayer/team scenarios.
Related: https://github.com/cline/cline-web/pull/256
Surface the actual read_file line window in chat summaries so users can see what context was added, while keeping manual approval and repeated same-file reads rendered accurately.
* feat(cli): unify update flow for cline and kanban
* fix(cli): only install kanban when update is available
* fix(cli): include cline and kanban versions in no-update message
- Add linux-aarch64 to TARGET_PLATFORMS in package-standalone.mjs so
better-sqlite3 prebuilt binaries are downloaded for this platform.
- Rename linux-arm64 to linux-aarch64 in download-ripgrep.mjs for
consistency with the JetBrains plugin naming convention (which uses
Java's os.arch value 'aarch64').
* fix(read_file): add stable line labels in act/plan
* prompt: clarify read_file line labels for replace_in_file
* Update prompt snapshots
* feat(read_file): add chunked reading with start_line/end_line parameters
Add optional start_line and end_line parameters to read_file so models
can read files in chunks instead of loading entire files into context.
Default limit is 1000 lines per read, with a continuation hint guiding
the model to paginate when needed.
Made-with: Cursor
* feat: align read_file line format with SDK while keeping superior chunking
- Change line format from 'L1:' to '1 |' to match SDK format
- Add proper NaN validation for start_line/end_line parameters
- Keep 1000-line chunking with continuation hints (superior to SDK)
- Update tool description and tests to reflect new format
- Add directory usage guardrail back to tool description
- Update replace_in_file prompt to reference new line format
This aligns the PR with the newer SDK design patterns while
preserving the superior chunking behavior that prevents context
overflow issues.
* fix: resolve duplicate step numbering in replace_in_file instructions
Fixes the duplicate step 5 issue when NOTEBOOK_INSTRUCTIONS is
concatenated with BASE_DIFF_INSTRUCTIONS for .ipynb files.
Changes notebook instructions to step 6 to avoid ambiguity.
* test: update unit test snapshots
* test: fix gemini3 tools snapshot
* test: regenerate gemini3 tools snapshot
* fix: preserve line ranges on cached file reads
* test: refresh gemini3 tools snapshot
* test: strengthen chunked read assertions
* fix: normalize inverted read file ranges
VSCode's webview doesn't reliably play VP9/WebM, while JetBrains'
JCEF lacks H.264 decoding. Restore the original H.264/MP4 video and
use HTML5 <source> elements with explicit MIME types so each platform
picks the format it supports:
<source src=... type="video/mp4" /> <!-- VSCode -->
<source src=... type="video/webm" /> <!-- JetBrains -->
Also:
- Restore .mp4 Git LFS tracking in .gitattributes
- Update CI LFS verification to check both files
- Add webm to JetBrains MIME type map (BrowserRequestHandler)
JetBrains IDEs use JCEF (Chromium Embedded Framework) for webviews,
which often does not include H.264 decoding due to licensing
restrictions. This causes the kanban demo video to fail to play.
Transcode the video from H.264/MP4 to VP9/WebM, which is a royalty-free
codec universally supported in Chromium derivatives. This also reduces
the file size from 3.6MB to ~900KB.
Updated all references:
- Source component import (ClineKanbanLaunchModal.tsx)
- Git LFS tracking (.gitattributes)
- CI workflow LFS checks (publish.yml, publish-nightly.yml)
The migration announcement didn't explain what Kanban is. Swap the
"run cline --tui" line for a one-liner describing the product so users
know what they're opting into. The --tui escape hatch is still
discoverable via the Exit menu item.
* refactor: replace hand-rolled YAML parser in refreshSkills with shared helper
The refreshSkills controller had its own line-by-line YAML parser that
only handled simple key: value pairs. Replace it with the shared
parseYamlFrontmatter helper already used by the skills discovery path.
Same output for name and description fields. The shared parser handles
edge cases (arrays, nested values, quoted colons) more robustly.
* refactor: inline parseYamlFrontmatter, remove redundant wrapper
Remove the parseFrontmatter wrapper since only `data` is used by
the caller. Inline the call directly at the use site.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: John Choi <johnchoi@MacBook-Pro.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: upgrade MiniMax default model to M2.7
- Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to model list
- Set MiniMax-M2.7 as default model
- Keep all previous models as alternatives
- Update provider documentation
* fix: correct M2.7 cache pricing and update prompt caching docs
- Updated cacheReadsPrice from 0.015 to 0.03 for both MiniMax-M2.7 and
MiniMax-M2.7-highspeed to match M2.5 pricing (same cache read rate
across M2.x models)
- Updated prompt caching tip to explicitly mention highspeed variants
* fix: correct MiniMax model pricing to match official rates
- M2.7-highspeed/M2.5-highspeed/M2.1-lightning: $0.60/$2.40 (not $0.30/$1.20)
- M2.7 cache: reads $0.06/M (not $0.03), writes $0.375/M (not $0.0375)
- All models: cache writes $0.375/M (not $0.0375)
Ref: https://platform.minimax.io/docs/llms.txt
---------
Co-authored-by: PR Bot <pr-bot@minimaxi.com>
The Kanban launch-by-default feature (beb54a4) redirects bare `cline`
invocations to Kanban, which blocks all TUI tests that launch without
`--tui`. Adding the flag ensures tests reach the legacy TUI as expected.
* feat(cli): refresh welcome banner and kanban launcher
* feat(cli): launch kanban by default with migration view
* feat(cli): add kanban process lifecycle management
Detach the kanban child process on Unix so it gets its own process
group, forward signals to the group for graceful shutdown, and fall
back to SIGKILL after a 10s timeout. Resolves exit codes from signals
correctly (130 for SIGINT, 143 for SIGTERM).
* feat: add repeated tool call loop detection
Detect when the LLM calls the same tool with identical arguments
repeatedly, which wastes tokens without making progress. This is
the #1 active complaint in the Cline issue tracker (13+ open issues
including #9923, #9916, #9846, #9816).
Two-stage escalation:
- Stage 1 (3 identical calls): inject a warning nudging the LLM
to try a different approach
- Stage 2 (5 identical calls): trigger the existing
consecutiveMistakeCount escalation (asks user or fails in YOLO)
Detection uses JSON.stringify with a sorted key replacer for
deterministic comparison. Metadata params like task_progress
(which change every call even when actual tool arguments are
identical) are stripped from the comparison.
Complementary to fileReadCache, which deduplicates file content but
still allows the tool call to succeed and consume a turn. Loop
detection catches the repeated call pattern itself.
Changes:
- loop-detection.ts: shared helper (toolCallSignature, checkRepeatedToolCall)
- TaskState.ts: add lastToolParams, consecutiveIdenticalToolCount
- ToolExecutor.ts: call checkRepeatedToolCall in handleCompleteBlock
- responses.ts: add formatResponse.repeatedToolCall
- loop-detection.test.ts: 5 tests
Manually verified: CLI test confirms soft warning at call 3,
YOLO mode failure at call 5.
Refs: #9923, #9916, #9846, #9816
* fix: address review feedback on loop detection
- Change hardEscalation threshold from >= to === so it fires exactly
once at count 5, matching softWarning behavior
- Widen toolCallSignature param type to Partial<Record<string, string>>
to match actual block.params type from ToolExecutor
- Add negative boundary assertions to verify no false positives at
calls 0, 1, 3, 4
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: reset loop detection state when user continues after mistake_limit_reached
When hard escalation fired at count === 5 and the user clicked
"continue", consecutiveIdenticalToolCount was never reset. The count
would exceed 5 but === 5 never matched again, silently disabling
loop detection for the rest of the task.
Reset consecutiveIdenticalToolCount, lastToolName, and lastToolParams
alongside the existing consecutiveMistakeCount reset so the detector
fully re-arms after the user continues.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: John Choi <johnchoi@MacBook-Pro.local>
* fix: prevent OOM crash from globby's eager .gitignore scanning in listFiles
Replace globby's gitignore:true (which reads ALL .gitignore files in the
entire tree upfront, including inside gitignored directories) with
incremental .gitignore reading during BFS traversal.
In projects with large gitignored vendored dependencies containing many
nested repos, globby collects thousands of patterns, builds a massive
regex, and V8 runs out of memory during regex compilation (~488MB).
The fix reads .gitignore files only from directories the BFS actually
enters. Gitignored directories are never entered, so their .gitignore
files are never parsed and the pattern count stays small.
- Set gitignore:false, handle .gitignore ourselves
- Read root .gitignore in buildIgnorePatterns() to seed initial patterns
- Read subdirectory .gitignore lazily during globbyLevelByLevel BFS
- Accumulate patterns in currentIgnore so deeper levels respect them
- Add 4 tests: root patterns, file patterns, subdirectory .gitignore,
and OOM-prevention (no reading inside gitignored dirs)
* Code review followup
* Potential fix for code scanning alert no. 147: Incomplete string escaping or encoding
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Replace generic "missing parameter" errors with targeted guidance for
the two tools observed failing most in SWE-bench (6% of failures).
The new messages include the expected format (SEARCH/REPLACE blocks,
XML example) without the 30-line boilerplate reminder.
Made-with: Cursor
* fix: read cache_write_tokens from OpenRouter API instead of hardcoding 0
- Read prompt_tokens_details.cache_write_tokens from OpenRouter stream usage
chunks instead of hardcoding cacheWriteTokens to 0
- Read native_tokens_cache_write from generation endpoint fallback
- Replace fragile hardcoded model ID switch statement for cache_control blocks
with prefix-based matching (anthropic/, minimax/) so new models automatically
get prompt caching enabled
- Add unit test verifying cache_write_tokens are correctly extracted
Co-authored-by: Ara <arafat.da.khan@gmail.com>
* fix: read cache_write_tokens from OpenRouter API instead of hardcoding 0
- Read prompt_tokens_details.cache_write_tokens from OpenRouter stream usage
chunks instead of hardcoding cacheWriteTokens to 0
- Read native_tokens_cache_write from generation endpoint fallback
- Replace fragile hardcoded model ID switch statement for cache_control blocks
with prefix-based matching (anthropic/, minimax/) so new models automatically
get prompt caching enabled
- Add unit test verifying cache_write_tokens are correctly extracted
Co-authored-by: Ara <arafat.da.khan@gmail.com>
* Release v3.74.0 Notes
* Release v3.74.0 Notes
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: alex-lum <alex@cline.bot>
The presentation scheduler introduced in ff05ec3bb awaits in-flight
flushes during dispose(), but ask() blocks indefinitely on pWaitFor
waiting for user input. When abortTask() sets abort=true and then
awaits scheduler.dispose(), the in-flight flush (blocked on
ask("completion_result")) never resolves, deadlocking the UI.
Add abort flag check to ask()'s pWaitFor condition so blocked asks
unblock immediately when the task is aborted.
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: fix SDK documentation accuracy and completeness
- Fix setPermissionHandler API Reference to use correct async/return signature
(was showing old callback pattern with (request, resolve) => void)
- Remove non-existent PermissionResolver type from Exported Types table
- Fix PermissionHandler type description to match actual signature
- Add missing hooksDir option to ClineAgentOptions documentation
- Fix newSession() example to use real model IDs
- Replace developer personal path in Full Example with generic path
- Use placeholder for version in initialize() example to avoid staleness
- Expand Stop Reasons table and add note about current implementation
- Add missing key exported types: AcpSessionStatus, AcpSessionState,
RequestPermissionRequest/Response, PermissionOption, SessionUpdatePayload,
SessionModelState, ModelInfo, TextContent/ImageContent/AudioContent,
SetSessionMode/Model request/response types, TranslatedMessage
* docs: improve SDK visibility and disambiguate from API code examples
- Move SDK page higher in Cline CLI nav (after Installation, before Interactive Mode)
- Add sidebarTitle 'SDK (Programmatic Use)' for clearer nav label
- Rename api/sdk-examples to 'Code Examples' to avoid naming confusion with the Cline SDK
- Update API overview card title to match
* Apply suggestions from code review
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* docs: add ClientCapabilities, Error Handling, and BYO API key docs to SDK
- Document clientCapabilities object and its effect on agent behavior
- Add Error Handling section with all throwable errors per method
- Expand BYO API key setup with concrete CLI auth examples
* docs: fix duplicated Stop Reasons table rows from code review
* docs: fix 3 accuracy issues found in source code audit
- Fix protocolVersion: was '0.9.0' (fabricated), actually 1 (number) from @agentclientprotocol/sdk
- Fix clientCapabilities: was claiming they change SDK behavior, but ClineAgent always uses standalone providers (capabilities only matter via AcpAgent stdio wrapper)
- Fix permission options: remove reject_always (never sent by agent, only allow_once/allow_always/reject_once are used)
* docs: clarify custom clineDir usage with CLI --config flag
Address PR review feedback: the BYO auth section mentioned custom
clineDir without showing how to target it from the CLI. Remove the
vague reference and add explicit --config flag documentation with
side-by-side SDK and CLI examples.
* docs: remove misleading 'by default' qualifier from SDK BYO auth section
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix(cli): use kanban@latest to always fetch newest version
npx -y kanban may use a cached version. Using @latest ensures
users always get the most recent kanban release.
* chore(cli): bump version to 2.8.2 and update changelog
* Implement minimal change set for latency improvements
Cline's code review improvements
Further code review improvements
* fix: address code review issues for presentation scheduler
- Add reset() method to TaskPresentationScheduler to prevent stale
timer leaks between API request retries within the same task
- Call presentationScheduler.reset() in streaming state reset section
- Fix hadVisibleAssistantContent to track reasoning content, not just
text, preventing every reasoning chunk from getting immediate priority
- Remove unused 'low' priority from PresentationPriority type and
associated cadence configuration (YAGNI)
- Trim TaskLatencyTrigger to only values actually used: text/reasoning/tool
- Add JSDoc to isRemoteWorkspaceEnvironment documenting the heuristic
fallback and its false-positive risk
- Add Logger.warn for invalid cadence env-var overrides
- Add comment at scheduler construction explaining detection promise
dependency on remoteWorkspaceDetectionPromise
- Add comments to CLI host bridge about intentional remoteName omission
- Expand test coverage: reset(), coalescing, priority upgrade tests
* fix: address code review issues in latency/presentation scheduler
- Fix #1/#3: Set didPresentAnyContent=true for text and tool_calls chunks
so coalescing actually activates for text-only and tool streams (was
only set for reasoning chunks, defeating the 40/90ms cadence goal)
- Fix#2: Re-check flushInProgress after awaiting in-flight flush in
runFlushCycle to prevent two concurrent callers from both proceeding
past the guard and starting concurrent flushes
- Fix#4: Document flushNow() disposed no-op contract so callers
understand the finalization guarantee
- Fix#5: Add disposed guard to reset() to prevent post-dispose state
mutation
- Fix#6: Remove platform/version heuristic from isRemoteWorkspaceEnvironment
— only use remoteName. The substring match on 'remote' produced false
positives for version strings like '1.0.0-remote-fix'. Non-VSCode hosts
should populate remoteName explicitly to opt in to the higher cadence.
- Fix#7: Add remoteWorkspaceDetectionSettled flag and warn if getDelayMs
is called before detection resolves, making the timing dependency
explicit and detectable in production logs
- Fix#8: Upgrade disabled-scheduler bypass error from Logger.debug to
Logger.warn so silent flush failures are visible
- Update latency.test.ts: replace heuristic test with false-positive
regression tests and add null/empty-field coverage
* fix: address code review issues in latency/presentation scheduler
- Fix flushNow race condition: wait for all in-flight flushes to drain
before setting pendingPriority so the post-flush continuation cannot
steal it, guaranteeing at least one flush runs after flushNow() returns
- Add regression test for the flushNow race condition
- Fix disabled-path (CLINE_DISABLE_PRESENTATION_SCHEDULER): use
presentationScheduler.flushNow() instead of a fire-and-forget void
call so the presentAssistantMessage lock/pending-updates mechanism
is respected when the scheduler is bypassed
- Rename didPresentAnyContent -> didScheduleAnyContent to accurately
reflect that content has been scheduled, not necessarily flushed
- Update stale comment in streaming loop to match new variable semantics
- Upgrade remote workspace detection failure log level from debug to warn
- Document reset() interaction with in-flight flush on already-reset state
- Document empty-string remoteName edge case in getHostVersion.ts
* refactor: polish presentation scheduler for production readiness
- Extract PresentationPriority type to shared presentation-types.ts,
breaking the latency.ts → TaskPresentationScheduler.ts type coupling
- Remove redundant pendingWhileFlushing flag from TaskPresentationScheduler;
pendingPriority alone is sufficient for the post-flush continuation check
- Cache env var reads in latency.ts at module load (hot path optimization)
- Inline flushAssistantPresentation() one-liner into the scheduler constructor
- Make processNativeToolCalls protected to enable type-safe test access
- Remove as any cast in Task.processNativeToolCalls.test.ts
* Fixes as per Greptile review feedback
* Further fixes as per Greptile feedback
* Further fixes as per Greptile feedback
Replace hardcoded free models list with runtime resolution from
recommended models. The handler now dynamically fetches free model
IDs using refreshClineRecommendedModels with fallback to static
defaults, and normalizes model IDs for consistent comparison.
* feat: add file read deduplication cache to prevent repeated reads
- Add fileReadCache to TaskState for tracking read files per task
- ReadFileToolHandler checks cache before reading, returns cached content on repeat reads
- Warns model after 3+ reads of same file to stop re-reading
- WriteToFileToolHandler and ApplyPatchHandler invalidate cache on file changes
- Reduces wasted API tokens from models reading same files repeatedly
* fix: address file read cache gaps - image blocks, execute_command, redundant invalidation
* Update src/core/task/tools/handlers/ExecuteCommandToolHandler.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* PR changes
- __`TaskState.ts`__ — Simplified cache type from `{ content: string; readCount: number; imageBlock? }` to `{ readCount: number; mtime: number; imageBlock? }`. Dropped `content` to save memory; added `mtime` for external change detection.
- __`ReadFileToolHandler.ts`__ — Four improvements:
- __Removed redundant `.set()` call__ — reviewer was correct that objects are modified by reference in Map
- __Added mtime-based cache validation__ — on cache hit, `stat()` the file and compare mtime. If the file was modified externally (user edited in their editor), the cache entry is evicted and a fresh read occurs
- __Dropped content from cache__ — cache now only stores metadata (readCount, mtime, imageBlock). On cache hits, the file is re-read from disk, addressing memory concerns
- __Softened readCount >= 3 warning__ — removed the aggressive "Do NOT read this file again" language; now says "Please use the information you already have and proceed with your task"
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat: add feature tips tooltip during thinking state
Show rotating feature tips below the Thinking indicator to keep users engaged and educate them on features like Double-Check Completion, .clinerules, Plan Mode, MCP Servers, checkpoints, and more.
- New FeatureTip component with 12 curated tips
- 2s delayed appearance, 8s cycling with fade transitions
- Visible throughout entire thinking/reasoning phase
- Proper timer cleanup on unmount
* Update webview-ui/src/components/chat/FeatureTip.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Update webview-ui/src/components/chat/FeatureTip.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Update webview-ui/src/components/chat/ChatRow.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: remove unused useMemo import from FeatureTip
* fix: increase test delays in QuitCommand.test.tsx for Windows CI reliability
* Update webview-ui/src/components/chat/FeatureTip.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: add smooth fade-in for first tooltip appearance
The first tooltip was appearing abruptly because the element went from
not-in-DOM (return null) to opacity-100 instantly. Added hasFadedIn state
with requestAnimationFrame to ensure the CSS transition applies on initial
render, giving the first tip a smooth 300ms fade-in.
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
llama.cpp's STB image library doesn't support WebP format. Users running
GLM 4.6V, GLM 4.5, and Devstral models via llama.cpp server (openai-compatible
endpoint) were hitting a 400 error when using the browser tool because Cline
sends screenshots as WebP by default.
modelDoesntSupportWebp() only checked for Grok models. Extend it to also
cover GLM and Devstral model families using the existing family detection
functions. Also update isGLMModelFamily() to handle space-separated model IDs
like 'GLM 4.6V' (the format llama.cpp server reports for this model).
Fixes#8203
* fix: Claude Code provider failing with 4.6 models and newer CLI versions
- Update --disallowedTools list to match current Claude Code CLI tools
(12 new tools were unblocked, causing models to use native tool_use
instead of Cline's XML tools)
- Fix rate_limit_event handling for new CLI format (top-level type
instead of system subtype)
- Handle unknown content block types and new message types gracefully
- Fix assistantHasContent check to account for tool calls accumulated
via toolUseHandler even when useNativeToolCalls is false
* resolved .include mismatch to .containEql
* Update src/integrations/claude-code/types.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Removed `LegacyRateLimitEvent` type and its union reference from `types.ts`
* Fixed loop with async tool calls in new claude code.
* PR review feedback fixes
__Fix #2 (claude-code.ts):__ Cleaned up the error field check — replaced verbose `"error" in message` guard + ternary chain with a simpler `message.error` check using optional chaining and nullish coalescing (`message.content?.[0]` + `?? fallback`).
__Fix #3 (claude-code.ts):__ Replaced `message.content.length > 0 ? message.content[0] : undefined` with `message.content?.[0]` using optional chaining for the `stop_reason` block.
__Fix #4 (claude-code.ts):__ Replaced repeated `(content as any)` casts in the `default` switch case with a single typed cast: `const unknownBlock = content as { type: string; text?: string }`, making the code cleaner and safer.
__Fix #5 (ApplyPatchHandler.ts):__ Replaced both `await import("node:path")` and `require("node:path")` dynamic imports with a static `import { resolve as resolvePath } from "node:path"` at the top of the file.
* Remove file read deduplication feature (moved to separate PR)
* Remove ReadFileToolHandler file-not-found test (moved to separate PR)
* Add LegacyRateLimitEvent type for older CLI format
* Restore ReadFileToolHandler.ts and test from upstream/main (fix stale local main revert)
* Revert ReadFileToolHandler.ts to match fork main (no try/catch, no test file)
* manually reverting back
* Update src/core/api/providers/claude-code.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Restore ReadFileToolHandler.ts and test to match cline/cline upstream main
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Fix issue with Windows notification
Fix Windows proto tooling
Fix Windows unit test path normalization
Revert "Fix Windows unit test path normalization"
This reverts commit 73400a3ca6f0300d009f7c8238a016d769186f3a.
Remove package-lock.json changes
* Remove unnecessary changes
* Use command approval string for notifications
* Address PR feedback on Windows notifications
* Fix Windows protoc path for CI
* Polish notification safety and test coverage
* Fix unfound tests in CI
* Harden Windows notifications and protoc execution
* Fix Windows path normalization in glob test
* Fix as per Greptile feedback
* feat(wandb): add W&B Inference by CoreWeave provider
Adds support for W&B Inference as an API provider using a W&B API key.
Implements a provider handler with OpenAI-compatible streaming and a static
model catalog, and wires the provider through the API layer, configuration
schema, storage, CLI model picker, and settings UI.
* Updated input/output price of NVIDIA-Nemotron
* Updated helpText
* handle reasoning tokens in streaming respons
* Added clarifying comment on how W&B token usage is reported and why cached tokens
* fix: restore proto field numbers changed by generation script
* Update src/core/api/providers/wandb.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: catch errors in path-based tool handlers instead of crashing
ListCodeDefinitionNamesToolHandler, ListFilesToolHandler, and
SearchFilesToolHandler let exceptions from their core operations
propagate through ToolExecutor's re-throw path, crashing the CLI
process. This is the same class of bug fixed for ReadFileToolHandler
in #9730.
Changes per handler:
- Wrap the core operation in try/catch, returning formatResponse.toolError()
on failure so the model can see the error and recover gracefully.
- Move consecutiveMistakeCount reset to after a successful operation so
repeated failures accumulate toward the yolo-mode mistake limit.
- Increment consecutiveMistakeCount on caught errors.
Add end-to-end tests exercising each handler with a mock TaskConfig,
covering: non-existent paths, missing parameters, failure accumulation,
and success-based counter reset.
* address review: expand try/catch scope, add stub-based tests
- Include resolveWorkspacePath inside try/catch in
ListCodeDefinitionNamesToolHandler and ListFilesToolHandler (matching
SearchFilesToolHandler's pattern) so path resolution failures are
also caught gracefully.
- Fix trivially-true assertion in file-not-a-directory test.
- Add 6 new stub-based tests that force core operations to throw:
parseSourceCodeForDefinitionsTopLevel, listFiles, and
determineSearchPaths — verifying the catch paths return
formatResponse.toolError() and increment consecutiveMistakeCount.
- Total: 19 passing tests (up from 13).
* address review: move clineignore check before IO in ListFilesToolHandler
Move the .clineignore access validation before resolveWorkspacePath and
listFiles so blocked paths are rejected without incurring IO cost.
Also ensures consecutiveMistakeCount is only reset after all
validations and the core operation succeed.
* address review: increment counter on clineignore denial
Clineignore denial in ListFilesToolHandler now increments
consecutiveMistakeCount so repeated attempts at blocked paths
accumulate toward the yolo-mode mistake limit. Added 2 tests
verifying single and repeated clineignore denials.
Total: 21 passing tests.
* fix: increment consecutiveMistakeCount when SearchFilesToolHandler searches fail
Previously, SearchFilesToolHandler's executeSearch() caught regexSearchFiles
errors and returned {success: false}, but the handler unconditionally reset
consecutiveMistakeCount to 0 even when ALL searches failed. This contradicted
the PR's goal of accumulating failures toward the yolo-mode mistake limit.
Now we check if any search succeeded before resetting the counter:
- If at least one search succeeded: reset to 0 (existing behavior for successes)
- If all searches failed: increment the counter (new fix)
Also added comprehensive test coverage for this scenario, including tests for:
- regexSearchFiles throwing errors
- Repeated search failures accumulating
- Successful search resetting the counter after failures
* fix: detect error strings in ListCodeDefinitionNamesToolHandler
parseSourceCodeForDefinitionsTopLevel returns error strings instead of
throwing exceptions for file paths and non-existent directories. The
handler now detects these error conditions and increments
consecutiveMistakeCount so repeated failures accumulate correctly.
This addresses Greptile's feedback that the counter was unconditionally
resetting to 0 for all real-world failure modes of this handler.
* fix: catch extractFileContent errors in ReadFileToolHandler
When extractFileContent throws (e.g. file not found), the exception
propagated through ToolExecutor which re-threw it, crashing the CLI
process with exit code 1.
Now file read errors are caught and returned as formatResponse.toolError()
so the model can see the error and recover gracefully (e.g. try a
different file path) instead of terminating the entire task.
Also increments consecutiveMistakeCount so the yolo-mode mistake limit
still functions correctly.
* add tui UI tests
using microsoft/tui-test library, can run many headless versions of
cline and execute ui tests (requires Node <= 20)
improve brittle sleep calls
* add cli-tui-tests github action
---------
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
The Oracle Code Assist URL moved from /artificial-intelligence/code-assist/
to /application-development/code-assist/. The old URL returns a 404.
Fixes#9776
Co-authored-by: gatof81 <gatof81@users.noreply.github.com>
- calling telemetry service before initializeCli call causes a
"hostprovider not initialized error", which invokes errorservice, which
causes another "hostprovider not initialized error", which was breaking
this cline use case: echo "say hello" | cline
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
* Add an UsafeImage handler that asks for consent before loading specific images
* Fix div as child of p
* Render self-contained images without consent
* Render alt conditionally and store approved src
* use a block span
* feat(telemetry): restore cache token and cost metrics in captureTokenUsage
Add optional `options` parameter to `captureTokenUsage()` to record
cache write/read token counters and cost histograms that were
previously missing from telemetry.
- Extend `captureTokenUsage` with `cacheWriteTokens`, `cacheReadTokens`,
and `totalCost` fields via an options object
- Record `cline.tokens.cache_write`, `cline.tokens.cache_read` counters/
histograms and `cline.tokens.cost` histogram when provided
- Forward cache/cost data from both streaming `onUsageChunk` and
`getApiStreamUsage` fallback call sites in the task loop
- Add 3 test cases covering options forwarding, undefined skipping,
and event property inclusion
* refactor(telemetry): extract shared TokenUsage type and add value assertions
Address PR review feedback:
- Extract shared TokenUsage interface used by both captureTokenUsage and
captureConversationTurnEvent, preventing future drift
- Add numeric value assertions for cache/cost counters and histograms
so regressions recording wrong values are caught
- cli was storing fields to persistent state when it shouldn't be. The
value of these flags should only live for the duration of the CLI
session
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
Exposes the existing useAutoCondense setting as a CLI flag, following
the same pattern as --double-check-completion. This allows enabling
auto-condense in eval runs (e.g. SWE-bench via Harbor) to reduce
context exhaustion failures.
Made-with: Cursor
The Gemini converter was the only provider that didn't include
parameter-level descriptions in native tool call schemas. Anthropic
and OpenAI converters both resolve param.instruction into each
parameter's description field. This was missing for Google/Gemini,
meaning the model only saw parameter names and types with no
explanation of what each parameter expects.
Made-with: Cursor
listFiles() passed unvalidated paths as globby's `cwd`, crashing with
"The cwd option must be a path to a directory" when the model provided a
file path instead of a directory. This affected ~22% of SWE-bench tasks.
- Add isDirectory guard in listFiles() before calling globby
- Fix listFiles() to use resolved absolutePath for cwd instead of raw dirPath
- Return actionable error in parseSourceCodeForDefinitionsTopLevel when
path is a file, guiding the model to use read_file instead
- Clarify list_code_definition_names parameter description to
distinguish directory input from file input
Made-with: Cursor
- S1: Don't modify test assertions to match buggy code
- S2: Run project's existing test suite to verify fixes
- CLI_RULES: Remove Node.js-specific examples (npm/tsc)
Made-with: Cursor
* Add implementation plan doc
* feat(hooks): reintroduce runtime hooks feature toggle
* fix: thread effective hooks toggle through hook execution
* test: cover hooks feature toggle visibility and settings wiring
* Remove implementation plan doc
* Move Hooks toggle to Advanced section in Feature Settings
* Fixes as per PR feedback
* Clarifying hooksEnabled
* Make hooksEnabled true by default
* Further fixes as per Greptile feedback
* Further fixes as per Greptile feedback
* Fix failing tests
Fixes#9269 - Thinking blocks missing in Bedrock Opus 4.6
Changes:
- Add explicit handling for 'thinking' and 'redacted_thinking' content types
in formatMessagesForConverseAPI() so they are silently skipped instead of
triggering 'Unsupported content type: thinking' warnings
- Capture signature from additionalModelResponseFields thinking responses
- Add signature_delta handling in contentBlockDelta for streaming
- Add redacted_thinking block handling in contentBlockStart for streaming
- Extend ContentBlockStart/Delta interfaces with signature and data fields
- Add 'redacted_thinking' and 'document' to SupportedContentType union
- Add tests for thinking/redacted_thinking block filtering in message conversion
* feat(cli): add --hooks-dir flag for runtime hook injection
Adds a --hooks-dir <path> CLI flag that allows passing an additional
hooks directory at spawn time. This enables orchestration tools (like
Kanbanana) to inject per-session lifecycle hooks without mutating
the user's global or workspace hooks directories.
The runtime hooks directory is included alongside existing global
(~/Documents/Cline/Hooks/) and workspace (.clinerules/hooks/)
directories during hook discovery. All hooks from all directories
are merged and run in parallel, so runtime hooks are purely additive.
* fix(cli): initialize runtime hooks before interactive startup
Add --no-verify to the initial checkpoint commit in
CheckpointGitOperations.ts. This was already used for subsequent
commits in CheckpointTracker.ts but was missing from the initial
empty commit, causing Cline to fail to initialize when users have
global pre-commit hooks (e.g., conventional commits enforcement).
Fixes#9672
* feat: add telemetry for AI output accepted/rejected across tool handlers
Add line-level diff stats and file operation tracking to telemetry
events when users accept or reject tool outputs. Introduces a shared
`computeLineDiffStats` utility and `captureAiOutputAccepted`/
`captureAiOutputRejected` methods on the telemetry service, wired
into ApplyPatch, WriteToFile, ExecuteCommand, InsertContent, and
SearchAndReplace handlers.
* feat(telemetry): add source tracking for agent vs human edits
Add telemetry differentiation between agent-generated changes and
human modifications to capture more granular edit metrics:
- Add 'source' field to captureAiOutputAccepted telemetry events
- Track human edits by computing diff stats between agent's proposed
content and final saved content
- Apply source tracking to ApplyPatchHandler and WriteToFileToolHandler
- Enable separate analytics for agent vs human contributions
This allows measuring how often and to what extent users modify
AI-generated code, providing insights into AI output quality and
user trust patterns.
* refactor(telemetry): centralize ai output attribution across file edit handlers
- add shared `AiOutputTelemetry` utility for accepted/rejected events
- refactor `WriteToFileToolHandler` and `ApplyPatchHandler` to use shared helpers
- preserve existing telemetry behavior (`source: "agent" | "human"`) while reducing duplication
- keep line diff/file-op attribution semantics unchanged
* fix(telemetry): use pre-save content for human edit line diff stats
The source:"human" telemetry was diffing agent content against
finalContent (post-save), which includes auto-formatting changes
from the editor. This inflated linesChanged/linesDeleted counts
when the formatter modified lines alongside the user's actual edits.
Use diff.applyPatch() to reconstruct the user's pre-save content
from the existing userEdits patch, excluding formatter noise from
the line diff stats.
* fixing syntax error
* refactor(telemetry): make next-hunk bounds check explicit
* remove comment
Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>
---------
Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>
Add author_association check so only MEMBER, OWNER, and COLLABORATOR
users can trigger the JetBrains test workflow via issue comments.
Previously any GitHub user could trigger it, allowing unauthorized
use of the GitHub App token and Actions minutes.
Fixes GHSA-5fq9-fh5x-w83r (SEC-29)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add provider/model context to all hook payloads
* Fixes as per Greptile feedback
* Further fixes as per Greptile feedback
* Further fixes as per Greptile feedback
* further fixes as per Greptile feedback
* Fix flapping hooks tests on Windows
* fix: stop infinite getLatestMcpServers RPC loop when opening MCP servers panel
The ServersToggleModal useEffect had setMcpServers in its dependency array,
but the context provided an unstable inline wrapper around the useState setter,
creating a new function reference on every render. This caused the effect to
re-fire on every context re-render while the modal was visible, producing 14+
RPC calls in ~15ms.
- Remove setMcpServers from useEffect deps in ServersToggleModal (the effect
should only fire when visibility changes)
- Replace inline arrow wrappers in ExtensionStateContext with direct references
to the stable useState setters (setMcpServers, setRequestyModels,
setHuggingFaceModels, setMcpMarketplaceCatalog)
* address review feedback: add setMcpServers back to deps, use property shorthand
- Add setMcpServers back to useEffect deps in ServersToggleModal now that the
context passes the stable useState setter directly (per Copilot review)
- Remove eslint-disable comment since it's no longer needed
- Use property shorthand for setGroqModels and setBasetenModels in context value
* initial doc changes
* rm general api endpoint
* Add API documentation section with endpoint reference pages
- Add new API docs: overview, getting-started, authentication, models,
chat-completions, errors, and SDK examples
- Update api/reference.mdx with expanded endpoint documentation
- Update enterprise-solutions/api-reference.mdx with improvements
- Update docs.json with new API section navigation entries
---------
Co-authored-by: Juan Pablo <juan@cline.bot>
Co-authored-by: Tony Loehr <turingxo@gmail.com>
* fix: prevent Chinese filename escaping in diff view
Use Uri.parse() instead of Uri.from() for the diff view URI to prevent
non-ASCII characters (e.g. Chinese) in filenames from being
percent-encoded. This is consistent with how other diff URIs are created
in openMultiFileDiff.ts and VscodeCommentReviewController.ts.
Uri.from() encodes the path component, turning Chinese characters into
percent-encoded sequences like %E7%A0%94..., which causes the diff view
to display escaped filenames and fail to open properly.
* fix: encode URI-reserved delimiters in filename before Uri.parse
Encode %, #, and ? in the filename before passing to Uri.parse() to
prevent them from being interpreted as URI delimiters. This handles
edge cases where filenames contain these characters (valid on macOS/Linux)
while preserving non-ASCII characters like Chinese.
* feat(hooks): add Windows hook execution via PowerShell
* chore(changeset): add release note for Windows hooks
* Get hooks working on Windows
Remove changeset file (we no longer use changeset files)
feat(hooks): support Windows PowerShell hook resolution and management
feat(hooks): complete windows powershell hook support and tests
Detect linux-style hooks only on macOS and linux and detect PowerShell-style hooks only on Windows
Fixes for failing unit tests on Windows in CI
Fix failing unit tests on Windows in CI
Fix unit tests for hooks on Windows
Be clear about .ps1 file extension for hooks in PowerShell vs. bash/binary for linux-style hooks
Remove separate test suite step
Reapply hooks-specific test suite
Fix failing hooks tests
* Harden Windows hook PowerShell runtime and test coverage
* test: centralize hook test env and platform overrides
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
When OCA token refresh fails with 400 invalid_grant or 401, legacy secrets
ocaAccessToken and ocaTokenSet (from older Cline versions) were left in VS
Code's secret storage. clearAuth() only cleared ocaApiKey and ocaRefreshToken,
causing every subsequent re-auth attempt to fail in a loop requiring manual
SQLite deletion to recover.
Fix:
- Add ocaAccessToken and ocaTokenSet to SecretKeys in state-keys.ts
- Update OcaAuthProvider.clearAuth() to clear all 4 OCA secrets
Fixes#9567
* fix: resolve 'Could not find the file context' error in Explain Changes
Both handleCommentReply() in explainChangesShared.ts and the onCommentStart
callback in explainChanges.ts were using a strict absolutePath-only match
when looking up files in changedFiles. If the VS Code comment controller
returns a path in a different format (relative vs absolute, different
separators on Windows), the lookup would silently fail and show
'Error: Could not find the file context'.
Add relativePath as a fallback in both lookup sites, making them
consistent with the already-correct logic in streamAIExplanationComments.
Fixes#9382
* Refactor to use parseInt instead of Number.parseInt
* Adding 1m
* fix: wire cline model proto fields for api config
* fix: wire cline picker to shared recommended model logic
* fix: address Cline model picker parity and startup model-info sync
* remove OpenRouter preset model ID support
* rename Cline endpoint feature flag
* Fixing stuff
* Fixing stuff
* Fixing stuff
* refactor: gate cline models endpoint behind feature flag
- Update refreshClineModels to use the EXTENSION_CLINE_MODELS_ENDPOINT feature flag instead of a hardcoded boolean, allowing controlled rollouts of the endpoint source.
- Remove recommended/free models fallback logic, featured model cards, and the initialTab property from OpenRouterModelPicker to simplify the UI component.
* fix: use JSON_SCHEMA for yaml.load to prevent unsafe deserialization
Add { schema: yaml.JSON_SCHEMA } to both yaml.load() calls to reject
custom YAML tags (e.g. !!js/function) that could enable code execution
from untrusted .clinerules or skills files.
Add security tests verifying custom tags are rejected.
* add changeset
The CLI's applyProviderConfig() was reading model info from a disk
cache (controller.readOpenRouterModels) instead of fetching from
the provider API. In headless/Docker environments (e.g., terminal-bench)
the cache doesn't exist, so model info was never set. Both handlers
then fell back to openRouterDefaultModelInfo with maxTokens: 8192,
causing write_to_file truncation on large outputs.
Changes:
- Replace controller.readOpenRouterModels() (disk cache) with
refreshOpenRouterModels() (fetches from API, with cache fallback)
- Add vercel-ai-gateway to the model info fetch path using
refreshVercelAiGatewayModels()
Relates to #7998
Co-authored-by: Cursor <cursoragent@cursor.com>
The "Generate Commit Message" feature was using all changes instead of
only staged changes. Now prioritizes staged changes via getGitDiffStagedFirst(),
falling back to all changes only when nothing is staged.
Closes#5749
Co-authored-by: Raushan Singh <raushrak@Raushans-MacBook-Air.local>
* fix: update stale maxTokens values for Claude 3.7+ models
Every Claude model from 3.7 Sonnet onward had maxTokens set to 8192
in the static model definitions. These values were correct for Claude
3.5 and earlier, but Anthropic has significantly increased output
limits for newer models:
- Claude Opus 4.6: 128K (was 8192, 15.6x too low)
- Claude 3.7 Sonnet: 128K (was 8192, 15.6x too low)
- Claude Sonnet 4.6/4.5/4, Haiku 4.5, Opus 4.5: 64K (was 8192)
- Claude Opus 4, Opus 4.1: 32K (was 8192)
These static definitions are the source of truth for Anthropic direct,
Bedrock, Vertex, and SAP AI Core providers. With the old values, any
write_to_file call exceeding 8192 output tokens would be silently
truncated, producing a missing 'content' parameter error.
Values verified against Anthropic docs, AWS Bedrock docs, Google
Vertex AI docs, and the Vercel AI Gateway API.
Relates to #7998
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: update openRouterDefaultModelInfo.maxTokens to 64K
This fallback ModelInfo (representing claude-sonnet-4.5) is used
when dynamic model info isn't available — notably by the Cline and
Vercel providers in the CLI when the model cache is empty (e.g.,
fresh Docker containers in terminal-bench).
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
The OpenRouter stream transform had a 30-line switch statement that
hardcoded max_tokens=8192 for every Claude model. This was written when
8192 was the actual max output for Claude, but modern Claude models
support much higher limits (e.g. 128K for Sonnet 4.6, 64K for others).
OpenRouter's API already reports the correct max_completion_tokens per
model, and model.info.maxTokens reflects this (128000 for Sonnet 4.6).
The hardcoded switch was silently overriding the dynamic value.
This caused write_to_file failures on OpenRouter (and the Cline
provider, which shares this code path) whenever the tool call content
exceeded 8192 output tokens. The response was truncated
(finish_reason: "length"), producing incomplete JSON that lost the
content parameter.
Runtime evidence:
- Before: max_tokens=8192 sent, completion_tokens=8192 (ceiling),
finish_reason="length", write_to_file content missing
- After: max_tokens=128000 sent, completion_tokens=9824 (needed more
than 8192), finish_reason="tool_calls", write_to_file succeeded
Fixes#7998
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: add MiniMax M2.5 model to MiniMax provider
- Add MiniMax-M2.5 to minimaxModels with 192K context, 128K max tokens,
prompt caching, and reasoning/thinking support
- Update minimaxDefaultModelId to MiniMax-M2.5
- Add minimax/minimax-m2.5 to OpenRouter prompt caching switch
Closes#9391
* fix: add temperature: 1 to MiniMax M2.5 for reasoning support
* docs: update MiniMax provider docs with M2.5 model
* feat: wire up thinking/reasoning support for MiniMax M2.5
- Pass thinkingBudgetTokens from factory to MinimaxHandler
- Use thinking param in API call when reasoning is enabled
- Disable temperature and forced tool_choice when thinking is on
- Add ThinkingBudgetSlider to MiniMaxProvider UI for M2.5
* Add MiniMax-M2.5-highspeed
* Add thinking for highspeed
* Refactor thinking logic
---------
Co-authored-by: BarreiroT <tomasmbarreiroi@gmail.com>
Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>
- Update model ID and name from gpt-5.2-codex to gpt-5.3-codex
- Change tag from "HOT" to "NEW" for the updated model
- Add What's New banner entry promoting Codex 5.3 availability
This commit ensures that internal placeholder tools, specifically `focus_chain`, are filtered out from the final list of native tools exposed to the LLM.
- Added a test case in `PromptRegistry.test.ts` to verify `focus_chain` is excluded from native tools output.
- Updated snapshot files for various models (OpenAI GPT-5, Vertex Gemini 3, etc.) to reflect the removal of the `focus_chain` tool definition.
Fixes false positives in getReadablePath() when directories share a prefix
(e.g., /home/user/project matching /home/user/project-backup). The existing
isLocatedInPath() function correctly handles path boundaries using path.relative().
Closes#8761
Co-authored-by: Raushan Singh <raushrak@Raushans-MacBook-Air.local>
* sdk lib
* improve cline sdk api surface
- better api design and messages
* fix some types, fix session id retrieval, improve wording
* hide controller from sdk surface completely
---------
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
* chore: replace baseUrl with explicit relative paths in tsconfig files
Remove `baseUrl: "."` from tsconfig configurations and update all path aliases to use explicit relative paths (e.g., `./src/*` instead of `src/*`). This makes path resolution more explicit and avoids potential ambiguity in module resolution across the main project and webview-ui configurations.
* update package-lock.json
* Release V3.67.0
Bump version from 3.66.0 to 3.67.0 in package.json and
package-lock.json. Add changelog entry for v3.67.0 covering new
features (subagent skills, AgentConfigLoader, Responses API, websocket
preconnect, CLI /q command), bug fixes (reasoning delta crash, OpenAI
tool ID, auth checks, Gemini 3.1 Pro), and other changes. Update
WhatsNewItems fallback banners to reflect current promotions.
* Fixing stuff
* refactor: consolidate subagent request usage tracking into state object
Replace scattered per-request token tracking variables with a structured
`SubagentUsageState` interface containing `currentRequest` and
`lastRequest` states. This improves code organization by grouping related
token metrics (input, output, cache write/read, total tokens, cost) into
a cohesive `SubagentRequestUsageState` object, reducing variable sprawl
and making the usage lifecycle (current → last) more explicit.
* feat(subagent): add support for skills and optional modelId in agent config
- Update `AgentBaseConfigSchema` and `AgentConfigFrontmatterSchema` to include an optional `skills` field and make `modelId` optional.
- Implement `parseSkills` and `normalizeSkillName` in `AgentConfigLoader` to handle skill parsing from YAML frontmatter.
- Update `SubagentBuilder` to provide access to configured skills.
- Modify `SubagentRunner` to filter available skills based on the agent's configuration, falling back to all available skills if none are specified.
- Update host retrieval to use `HostRegistryInfo` instead of `HostProvider`.
This allows subagents to be restricted to specific skills and provides more flexibility in model configuration.
* update unit test
* feat(cli): fetch featured models from backend with local fallback
- Add async getFeaturedModelsForCline() to fetch models via controller
- Load featured models dynamically in AuthView with useEffect
- Update FeaturedModelPicker to accept featuredModels as optional prop
- Refactor helper functions to accept models parameter for flexibility
- Keep local hardcoded models as fallback when backend fetch fails
* Fixing stuff
* Fixing stuff
* Fixing stuff
description: Create a GitHub pull request following project conventions. Use when the user asks to create a PR, submit changes for review, or open a pull request. Handles commit analysis, branch management, and PR creation using the gh CLI tool.
description: Create a GitHub pull request following project conventions. Use when the user asks to create a PR, submit changes for review, or open a pull request. Handles commit analysis, branch management, PR template usage, and PR creation using the gh CLI tool.
Fix a streaming crash when a chunk has usage data but no `delta` by guarding reasoning field checks in provider handlers. Add regression tests for OpenRouter, Cline, Vercel AI Gateway, and Fireworks handlers to cover usage-only chunks.
The CLI lives in `cli/` and uses React Ink for terminal UI.
- If needed, look at `cli/src/constants/colors.ts` for re-used terminal colors, e.g. `COLORS.primaryBlue` highlight color (selections, spinners, success states).
- Never use `dimColor` with gray (e.g. `<Text color="gray" dimColor>`) - it's too hard to read. Use `color="gray"` for secondary text and normal foreground (no color) for primary text.
- When thinking about how to handle state or messages from core, look at webview for how it communicates with the vs code extension.
- When updating the webview, consider and suggest to the user to update the CLI TUI since we want to provide a similar experience to our terminal users as we do our vs code extension users.
## Adding New API Providers
When adding a new API provider to the extension, you must also update the CLI:
1.**Update `cli/src/components/ModelPicker.tsx`**: Add the provider to the `providerModels` map so `getDefaultModelId()` returns the correct default model. Import the models and default ID from `@shared/api`:
```typescript
import { newProviderDefaultModelId, newProviderModels } from "@/shared/api"
2. **Use `applyProviderConfig()` for auth flows**: When implementing OAuth or other auth flows for the provider, use the shared utility at `cli/src/utils/provider-config.ts`:
```typescript
import { applyProviderConfig } from "../utils/provider-config"
This handles setting provider, default model, API key mapping, state persistence, and rebuilding the API handler.
3. **Provider-specific auth**: If the provider uses OAuth (like `openai-codex`), add handling in `SettingsPanelContent.tsx`'s `handleProviderSelect` callback. See the existing Codex OAuth flow as a reference.
All via `POST localhost:19229/api` with `{"method":"...", "params":{...}}`:
- **`launch`** / **`shutdown`** — lifecycle
- **`ui.screenshot`** — screenshot to `/tmp/cline-debug/`; returns `{path}` — **use `read_file` on the path to examine, do NOT `open` the file** (Preview.app covers the VSCode window)
- **`web.evaluate`** `{expression}` — eval in webview
- **`web.post_message`** `{message}` — send postMessage to extension host via exposed vsCodeApi
- **`wait_for_pause`** `{timeout?}` — block until breakpoint hit
- **`ui.locator`** `{role?, testId?, text?, frame?}` — Playwright locator (auto-retries on stale sidebar frame)
- **`ui.react_input`** `{text, selector?, clear?, submit?}` — set React textarea value via `execCommand('insertText')`; works reliably across multiple tasks
- **⚠️ Dismiss promotional overlays FIRST**: On fresh launches, full-screen promo overlays block the sidebar. **Dismiss immediately after `ui.open_sidebar`**, before any other interaction or screenshot. May need to run twice:
- **Screenshots — don't open the file**: `ui.screenshot` and `ui.sidebar_screenshot` save PNGs to `/tmp/cline-debug/` and return the `{path}`. Use `read_file` on that path to examine screenshots. Running `open <path>` launches Preview.app on macOS which covers the VSCode window.
- **Scripts count = 0 after launch**: CDP connects after extension host starts, so scripts parsed during startup aren't tracked. Breakpoints still work via sourcemap resolution.
- **Port 9230**: Extension host inspector. If another VSCode instance uses this port, the harness will fail to connect. Kill other debug instances first.
- **macOS only** for now (Playwright Electron launch behavior).
- **Webview CDP**: `connect_webview` may fail depending on Electron version. `web.evaluate` still works via Playwright's `frame.evaluate()` fallback.
- **Sourcemap paths**: esbuild outputs relative paths like `../src/extension.ts` in the sourcemap. The resolver handles this, but if a file isn't found, use `ext.source_files` to see exact paths.
- **OAuth with fake codes**: Browser capture intercepts the URL but doesn't provide a valid auth code. For real OAuth testing, open the captured URL in a browser. For unit testing, mock the token exchange.
See `src/dev/debug-harness/README.md` for full API reference.
@@ -14,10 +14,53 @@ This file is the secret sauce for working effectively in this codebase. It captu
## Miscellaneous
- This is a VS Code extension—check `package.json` for available scripts before trying to verify builds (e.g., `npm run compile`, not `npm run build`).
- When creating PRs, if the change is user-facing and significant enough to warrant a changelogentry, run `npm run changeset` and create a patch changeset. Never create minor or major version bumps. Skip changesets for trivial fixes, internal refactors, or minor UI tweaks that users wouldn't notice.
- When creating PRs, contributors should not create changelog-entry files. Maintainers handle release versioning and changelog curation during the release process.
- When adding new feature flags, see this PR as a reference https://github.com/cline/cline/pull/7566
- Additional instructions about making requests: @.clinerules/network.md
## Searching the Codebase — Avoiding Build Output
Several directories contain build output or generated code that produces
noisy or unusable results with `search_files` / `grep`:
| Directory | What it is | Why it's a problem |
|-----------|-----------|-------------------|
| `out/` | esbuild bundle output | Mirrors `src/` structure as minified JS — every search gets duplicate hits on single-line files |
| `dist/` | Packaged extension | Entire extension bundled into one minified `extension.js` (~1 long line) |
When adding a new provider (e.g., "openai-codex"), you must update the proto conversion layer in THREE places or the provider will silently reset to Anthropic:
1.`proto/cline/models.proto` - Add to the `ApiProvider` enum (e.g., `OPENAI_CODEX = 40;`)
2.`convertApiProviderToProto()` in `src/shared/proto-conversions/models/api-configuration-conversion.ts` - Add case mapping string to proto enum
3.`convertProtoToApiProvider()` in the same file - Add case mapping proto enum back to string
**Why this matters:** Without these, the provider string hits the `default` case and returns `ANTHROPIC`. The webview, provider list, and handler all work fine, but the state silently resets when it round-trips through proto serialization. No error is thrown.
**Other files to update when adding a provider:**
-`src/shared/api.ts` - Add to `ApiProvider` union type, define models
-`src/shared/providers/providers.json` - Add to provider list for dropdown
-`src/core/api/index.ts` - Register handler in `createHandlerForProvider()`
-`webview-ui/src/components/settings/utils/providerUtils.ts` - Add cases in `getModelsForProvider()` and `normalizeApiConfiguration()`
-`webview-ui/src/utils/validate.ts` - Add validation case
## Responses API Providers (OpenAI Codex, OpenAI Native)
Providers using OpenAI's Responses API require native tool calling. XML tools don't work with the Responses API.
**Symptoms of broken native tool calling:**
- Tools get called multiple times (e.g., `ask_followup_question` asks the same question twice)
- Tool arguments get duplicated or malformed
- The model responds but tools aren't recognized
**Root causes to check:**
1.**Provider missing from `isNextGenModelProvider()`** in `src/utils/model-utils.ts`. The native variant matchers (e.g., `native-gpt-5/config.ts`) call this function. If your provider isn't in the list, the matcher returns false and falls back to XML tools.
2.**Model missing `apiFormat: ApiFormat.OPENAI_RESPONSES`** in its model info (`src/shared/api.ts`). This property signals that the model requires native tool calling. The task runner in `src/core/task/index.ts` checks this and forces `enableNativeToolCalls: true` regardless of user settings.
**When adding a new Responses API provider:**
1. Add provider to `isNextGenModelProvider()` list in `src/utils/model-utils.ts`
2. Set `apiFormat: ApiFormat.OPENAI_RESPONSES` on all models that use the Responses API
3. The variant matcher and task runner will handle the rest automatically
## Adding Tools to System Prompt
This is tricky—multiple prompt variants and configs. **Always search for existing similar tools first and follow their pattern.** Look at the full chain from prompt definition → variant configs → handler → UI before implementing.
1.**Add to `ClineDefaultTool` enum** in `src/shared/tools.ts`
2.**Tool definition** in `src/core/prompts/system-prompt/tools/` (create file like `generate_explanation.ts`)
- Define variants for each `ModelFamily` (generic, next-gen, xs, etc.)
- **Fallback behavior**: If a variant isn't defined for a model family, `ClineToolSet.getToolByNameWithFallback()` automatically falls back to GENERIC. So you only need to export `[GENERIC]` unless the tool needs model-specific behavior.
3.**Register in `src/core/prompts/system-prompt/tools/init.ts`** - Import and spread into `allToolVariants`
4.**Add to variant configs** - Each model family has its own config in `src/core/prompts/system-prompt/variants/*/config.ts`. Add your tool's enum to the `.tools()` list:
**How overrides work:** Variants can override components via `componentOverrides` in their `config.ts`, or provide a custom template in `template.ts` (e.g., `next-gen/template.ts` exports `rules_template`). If no override, the shared component from `components/` is used.
**Example: Adding a rule to RULES section**
1. Check if variant overrides rules: look for `rules_template` in `variants/*/template.ts` or `componentOverrides.RULES` in `config.ts`
2. If shared: modify `components/rules.ts`
3. If overridden: modify that variant's template
4. XS variant is special—has heavily condensed inline content in `template.ts`
**After any changes, regenerate snapshots:**
```bash
UPDATE_SNAPSHOTS=true npm run test:unit
```
Snapshots live in `__tests__/__snapshots__/`. Tests validate across model families and context variations (browser, MCP, focus chain).
To ensure Cline works correctly in all environments (VSCode, JetBrains, CLI) and with various network configurations (especially corporate proxies), strictly follow these guidelines for all network activity.
In extension code, do NOT use the global `fetch` or a default `axios` instance. (Note, `shared/net.ts` is exempt from these rules because it sets up the fetch wrappers.) In Webview code, you SHOULD use global `fetch`.
Global `fetch` and default `axios` do not automatically pick up proxy configurations in all environments (specifically JetBrains and CLI). You MUST use the provided utilities in `@/shared/net` which handle proxy agent configuration. In the webview, the browser/embedder handles proxies.
## Guidelines
### 1. Using `fetch`
Instead of `fetch(...)`, import the proxy-aware wrapper:
@@ -19,7 +19,7 @@ Review and address all comments on the current branch's PR.
- Inline comments: `gh api repos/{owner}/{repo}/pulls/{pr_number}/comments`
- General comments: `gh pr view {pr_number} --json comments,reviews`
4. Present a summary of all comments with your recommendation for each (apply, skip, or respond). Ignore bot noise (changeset-bot, CI status, etc.).
4. Present a summary of all comments with your recommendation for each (apply, skip, or respond). Ignore bot noise (release automation, CI status, etc.).
The goal of this workflow is to take a changeset for a release of Cline, an autonomous coding agent extension that plugs right into your IDE, and write the updated announcement component, and the updated changelog.
For reference, here are some examples of how we converted previous changesets to announcement components / changelogs.
- 3.14
<changeset>
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
claude-dev@3.14.0
Minor Changes
77c9863: create clinerules folder if its currently a file and creating new rule
0ffb7dd: disabling shift hint for now & improving tooltip behavior
79b76fd: Add support for custom model ID in AWS Bedrock provider, enabling use of Application Inference Profile.
eb6e481: Full support for LaTeX rendering
df37f29: Add support for custom API request timeout. Previously, timeouts were hardcoded to 30 seconds for providers like Ollama or 15 seconds for OpenRouter and Cline. Now users can set a custom timeout value in milliseconds through the settings interface.
e4d26be: allow cursorrules and windsurfrules
c5de50f: Fix Handle @withRetry() SyntaxError when running extension locally issue
61d2f42: enabled pricing calculation for gemini and vertex + more robust caching & cache tracking for gemini & vertex
aed152b: add truncation notice when truncating manually
2fe2405: Migrate Cline Tools Section to new docs
19cc8bc: Add a timeout setting for the terminal connection, allowing users to adjust this if they are having timeout issues
03d4410: Added copy button to code blocks.
c78fe23: addressed race condition in terminal command usage
91e222f: add checkpoints after more messages
14230e7: add newrule slash command
1c7d33a: Add remote config with posthog allowing for disabling new features until they're reading, making for a better developer experience.
4196c14: add cache ui for open router and cline provider
d97424f: showing expanded task by default
5294e78: Refactor to not pass a message for showing the MCP View from the servers modal
70cc437: Fix Windows path issue: Correct handling of import.meta.url to avoid leading slash in pathname
4b697d8: Migrate the addRemoteServer to protobus
Patch Changes
c63d9a1: updated drag and drop text to say "drop" instead of "drag"
459adf0: Add markdown copy to chat
74ec823: Minor UX improvement to drag and drop ux
b0961f4: Remove linear pull request action
e9ce384: searchCommits protobus migration
5802b68: createRuleFile protobus migration
df7f9fc: Add dependsOn to more blocks in the tasks.json
41ae732: Fix for git commit mentions in repos with no git commits
7e78445: Adding args to allow Cursor to open workspaces (for checkpoint testing/development)
bdfda6f: feat(bedrock): Introduce Amazon Nova Premier
65243ad: Introduce UI library for future UI development
4565e06: checkIsImageURL migrated to protobus
5a8e9d8: protobus migration for openImage
deeda6e: Lowering Gemini cache TTL time
db0b022: Adding UI to show openrouter balance next to provider
4650ffa: deleteRuleFile protobus migration
d4bd755: fix cost calculation
</changeset>
<changelog>
## [3.14.0]
- Add UI to show openrouter balance next to provider
- Add support for custom model ID in AWS Bedrock provider, enabling use of Application Inference Profile (Thanks @clicube!)
- Add more robust caching & cache tracking for gemini & vertex providers
- Add support for LaTeX rendering
- Add support for custom API request timeout. Timeouts were 15-30s, but can now be configured via settings for OpenRouter/Cline & Ollama (Thanks @WingsDrafterwork!)
- Add truncation notice when truncating manually
- Add a timeout setting for the terminal connection, allowing users to set a time to wait for terminal startup
- Add copy button to code blocks
- Add copy button to markdown blocks (Thanks @weshoke!)
- Add checkpoints to more messages
- Add slash command to create a new rules file (/newrule)
- Add cache ui for open router and cline provider
- Add Amazon Nova Premier model to Bedrock (Thanks @watany!)
- Add support for cursorrules and windsurfrules
- Add support for batch history deletion (Thanks @danix800!)
- Improve Drag & Drop experience
- Create clinerules folder creating new rule if it's needed
- Enable pricing calculation for gemini and vertex providers
- Refactor message handling to not show the MCP View of the server modal
- Migrate the addRemoteServer to protobus (Thanks @DaveFres!)
- Update task header to be expanded by default
- Update Gemini cache TTL time to 15 minutes
- Fix race condition in terminal command usage
- Fix to correctly handle `import.meta.url`, avoiding leading slash in pathname for Windows (Thanks @DaveFres!)
2964388: Added copy button to MermaidBlock component
75143a7: Add the ability to fetch from global cline rules files
Patch Changes
a0252e7: convert inline style to tailwind css of file SettingsView.tsx
ab59bd9: Add stream options back to xai provider
7276f50: Icons to indicate an action is occuring outside of the users workspace
0b19ba6: update to NEW model
</changeset>
<changelog>
## [3.13.0]
- Add Cline rules popover under the chat field, allowing you to easily add, enable & disable workspace level or global rule files
- Add new slash command menu letting you type “/“ to do quick actions like creating new tasks
- Add ability to edit past messages, with options to restore your workspace back to that point
- Allow sending a message when selecting an option provided by the question or plan tool
- Add command to jump to Cline's chat input
- Add support for OpenAI o3 & 4o-mini (Thanks @PeterDaveHello and @arafatkatze!)
- Add baseURL option for Google Gemini provider (Thanks @owengo and @olivierhub!)
- Add support for Azure's DeepSeek model. (Thanks @yt3trees!)
- Add ability for models that support it to receive image responses from MCP servers (Thanks @rikaaa0928!)
- Improve search and replace diff editing by making it more flexible with models that fail to follow structured output instructions. (Thanks @chi-cat!)
- Add detection of Ctrl+C termination in terminal, improving output reading issues
- Fix issue where some commands with large output would cause UI to freeze
We have a changeset PR that automatically generated as new unreleased PRs are merged into main, the PR is always called "Changeset version bump" and the author is github-actions.
The Changeset PR description looks something like this:
<changeset-pr-description>
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
# Releases
## claude-dev@3.16.0
### Minor Changes
- c6e8b04: Recent task list is now collapsible, allowing users to hide their recent tasks (e.g. when sharing their screen).
- aabe4ae: Add detection for new users to display special components
- 6c18d51: adds global endpoint for vertex ai users
- 080ed7c: Add Tailwind CSS IntelliSense to the the recommended extensions list
- 5147e28: new workflow feature
### Patch Changes
- c0b3c69: fix eternal loading states when the last message is a checkpoint
- 570ece3: selectImages protos migration
- 8d8452e: askResponse protobus migration
- cd1ff2a: Finishing the migration of Vscode Advanced settings to Settings Webview
</changeset-pr-description>
The changeset pr is ALWAYS on the following branch: `changeset-release/main`.
I have the `gh` command line tool set up and authenticated, so you have everything you need.
The first step is to get the full diff from the changeset PR to look at the changes that were automatically made to the `CHANGELOG.md` file. By default it will automatically add a new section to the changelog.md file with the new version. The problem with the automatically generated section is that it just takes the text that the developers threw into their changeset files for each corresponding PR, and they can be pretty vague and bad. Additionally there's some stuff that is totally irrelevant for the end user, like minor refactoring changes. So I manually typically go in and update this section to be a proper changelog that will show up in our patchnotes. You can look at how the rest of the file is done because those are all good examples of us updating this to use good language for the end user. We usually put new features up top (and the most exciting flagship features at the very top), and then bug fixes/improvements at the bottom. Having some basic organization to the ordering of the bullet points by content is nice. But use common sense.
To handle this process effectively, do the following:
For each of the automatically generated bullet points in the Changelog.md, you should
1. Take the commit hash at the start of the bullet point, and use the `gh` command line tool find the PR that it was associated with.
2. Use the `gh` command to get the PR title/description/discussion to understand the context surrounding the PR.
3. Use the `gh` command line tool to get the full PR diff to fully understand the changes made in the code.
4. Synthesize that knowledge to determine (a) whether or not this change is relevant to end users and (b) what the text & ordering of the line should be.
5. Update the `CHANGELOG.md` accordingly
Do this for every single item in the list from the autogenerated bullet points. We want to be diligent and have a full understanding of every feature so we can make the best changelog ever!
Here are some principles for good changelogs from keepchangelog.com, a handy guide:
<keepachangelog-pinciples-for-good-changelogs>
### Guiding Principles
- Changelogs are for humans, not machines.
- There should be an entry for every single version.
- The same types of changes should be grouped.
- The latest version comes first.
### Bullet points in the changelog should follow these principles:
- Types of changes
- Added for new features.
- Changed for changes in existing functionality.
- Deprecated for soon-to-be removed features.
- Removed for now removed features.
- Fixed for any bug fixes.
- Security in case of vulnerabilities.
</keepachangelog-pinciples-for-good-changelogs>
Lastly, when developers make a PR, they typically make a changeset. And they have 3 options when making the changeset:
1. Patch
2. Minor
3. Major
Sometimes they label something as minor when really it should just be a patch. Or vice versa. Because of this, the automatic version bump may be incorrect. So when starting out this workflow, you should use the <ask_followup_question> tool to confirm with me whether or not this should be a patch bump (show the old version number and what the proposed new version number would be) or a minor bump. Part of the release process is making sure the version in package.json that is automatically changed actually corresponds with what we decided the bump should actually be based on the features. ALL these modifications happen in the `changeset-release/main` branch btw.
<important_note>
Before doing any of this, make sure you check out the `changeset-release/main` and pull the most recent up to date changes. Then perform all this work in that branch.
New announcement banners should ONLY be made for minor version bumps or higher. That's another reason why double checking if the changelog warrants the bump is important.
Also, SUPER important: For any external contributors that aren't part of the cline github organization, we always want to add a (Thanks @username!) at the end of the changelog to attribute them properly. We're an open source project and it's ethical to do this.
</important_note>
Once the changelog looks good, and the version number looks good, we gotta double check that the version number in the changelog has the brackets around it. And as a final step, double check the package.json version number matches the latest number in the changelog. And as the ultimate final step we run `npm run install:all` to make sure the package version number permiates through the lock file.
<detailed_sequence_of_steps>
# Cline Release Process - Detailed Sequence of Steps
## Before Starting
1. First, examine the changeset PR without checking it out:
```bash
gh pr view changeset-release/main
```
2. View the PR diff to see the auto-generated CHANGELOG.md changes:
# Check if user is a member of the Cline organization
# this command is a bit finnicky, but it 100% works.
# if you see a `Error executing command: The command ran successfully, but we couldn't capture its output. Please proceed accordingly.` error, just retry it until you actually get the output
# don't make any assumptions, just retry the command to actually get the output and determine if they're external or not.
# no output means they are an external contributor, otherwise if there is output they are an internal contributor (part of our github org)
gh api "orgs/cline/members" --jq "map(.login)" | grep -i "pashpashpash"
```
d. View the full PR diff to understand code changes:
```bash
gh pr diff <PR-number> > pr-diff-<PR-number>.txt
cat pr-diff-<PR-number>.txt
```
## Updating the Changelog
5. Based on PR analysis, update the CHANGELOG.md with user-friendly descriptions:
- Use the `<replace_in_file>` tool to edit the CHANGELOG.md file
- Group by feature type (Added, Changed, Fixed)
- Put most exciting features at the top
- Move bug fixes and small improvements to the bottom
- Use clear, end-user focused language
- For external contributors, add attribution at the end of the relevant entry: `(Thanks @username!)`
## Version Number Verification
6. Confirm the version bump is appropriate:
- Check package.json to verify the auto-generated version number:
```bash
cat package.json | grep "\"version\""
```
- If the feature set doesn't warrant a minor bump, use the `<replace_in_file>` tool to modify package.json
7. Ensure the version in CHANGELOG.md has brackets around it:
```
## [3.16.0]
```
## Creating the Announcement (for minor/major versions only)
8. If this is a minor version bump, create/update the announcement component:
- Use the `<replace_in_file>` tool to edit the src/views/components/announcement.tsx file
- Update the highlights based on key features
- Move previous version highlights to the "Previous Updates" section
- Use the previous announcement components as reference for structure
## Finalizing the Release
9. Update dependencies with the new version number:
@@ -89,16 +89,9 @@ On the main branch, create a commit that updates:
2. **package.json** - Update the version field to the new version
3. **Delete changesets** for the commits being included in the hotfix. This prevents the changeset bot from including duplicate entries in the next regular release.
3. No changelog-entry file cleanup is needed. Contributors do not create changelog-entry files in this repo.
Find and delete the changeset files associated with the selected commits:
```bash
ls .changeset/
```
Each changeset file in `.changeset/` corresponds to a PR. Read them to identify which ones belong to the commits you're hotfixing, then delete those files.
**Skip running `npm run install:all`** - the automation handles outdated lockfiles.
**Skip running `npm run install:all`** - release automation handles lockfile consistency as needed.
Commit with message format: `v{VERSION} Release Notes (hotfix)`
@@ -107,7 +100,7 @@ In the commit body, mention:
- List the cherry-picked commits that will be included
So until the settings page is update, and this is added to settings in a way that's clean and doesn't confuse new users, I don't think we can merge this. Please bear with us.
</request_changes_comment>
<request_changes_comment>
Also, don't forget to add a changeset since this fixes a user-facing bug.
The architectural change is solid - moving the focus logic to the command handlers makes sense. Just don't want to introduce subtle timing issues by removing those timeouts.
- Adding enums (e.g. `ClineSay`) → also update `src/shared/proto-conversions/cline-message.ts`.
## Adding API Providers (silent failure risk)
Three proto conversion updates are **required** or the provider silently resets to Anthropic:
1.`proto/cline/models.proto` — add to `ApiProvider` enum.
2.`convertApiProviderToProto()` in `src/shared/proto-conversions/models/api-configuration-conversion.ts`.
3.`convertProtoToApiProvider()` in the same file.
Also update: `src/shared/api.ts`, `src/shared/providers/providers.json`, `src/core/api/index.ts`, `webview-ui/.../providerUtils.ts`, `webview-ui/.../validate.ts`, `webview-ui/.../ApiOptions.tsx`, and `cli/src/components/ModelPicker.tsx`.
For Responses API providers: add to `isNextGenModelProvider()` in `src/utils/model-utils.ts` and set `apiFormat: ApiFormat.OPENAI_RESPONSES` on models.
## Adding Tools to System Prompt (5+ file chain)
1. Add enum to `ClineDefaultTool` in `src/shared/tools.ts`.
2. Create definition in `src/core/prompts/system-prompt/tools/` (export `[GENERIC]` minimum).
3. Register in `src/core/prompts/system-prompt/tools/init.ts`.
4. Whitelist in `src/core/prompts/system-prompt/variants/*/config.ts` for each model family.
5. Handler in `src/core/task/tools/handlers/`, wire in `ToolExecutor.ts`.
6. If tool has UI: add `ClineSay` enum in proto → `ExtensionMessage.ts` → `cline-message.ts` → `ChatRow.tsx`.
7. Regenerate snapshots: `UPDATE_SNAPSHOTS=true npm run test:unit`.
## Modifying System Prompt
Modular: `components/` (shared) + `variants/` (model-specific) + `templates/` (`{{PLACEHOLDER}}`). Variants override components via `componentOverrides` in `config.ts` or custom `template.ts`. XS variant is heavily condensed inline. Always regenerate snapshots after changes.
## Global State Keys (silent failure risk)
Adding a key requires: type in `src/shared/storage/state-keys.ts`, read via `context.globalState.get()` in `src/core/storage/utils/state-helpers.ts``readGlobalStateFromDisk()`, and add to return object. Missing the `.get()` call compiles fine but value is always `undefined`.
echo "(no test output captured — process may have been killed before output was flushed)" >> $GITHUB_STEP_SUMMARY
fi
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Debugging" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **TUI traces** are attached as artifacts below — download and inspect them to see terminal state at the point of failure." >> $GITHUB_STEP_SUMMARY
echo "- **To view a trace replay/Run a TUI Trace: ** run \`npx tui-test show-trace path/to/trace/file\` in your terminal" >> $GITHUB_STEP_SUMMARY
echo "- **Full test log** is also attached as an artifact." >> $GITHUB_STEP_SUMMARY
echo "- Tests run with \`retries: 2\` so any failure shown is a consistent failure, not a flake." >> $GITHUB_STEP_SUMMARY
# Ignore all webview-ui files except the build directory (https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/hello-world-react-cra/.vscodeignore)
- Restore VS Code foreground terminal support and settings.
- Add latest OpenAI, SAP AI Core, and Z AI models.
### Fixed
- Fix hook template JSON escaping.
- Improve ripgrep file search error handling.
### Changed
- Remove hardcoded model lists from docs.
## [3.81.0]
### Added
- Add GPT-5.5 model support for OpenAI Codex subscription users.
### Fixed
- Remove hardcoded "What’s New" fallback items in webview; only remote-configured welcome banners are shown.
### Changed
- Improve cline-core memory diagnostics used by the extension runtime:
- enable near-heap-limit heap snapshots
- add periodic memory usage logging
- log discovered heap snapshots on abnormal exits for easier OOM debugging
## [3.80.0]
### Added
- Wire up remote `globalSkills` from enterprise remote config with full UI, toggle support, and system prompt integration — enterprise-managed skills now appear under a dedicated "Enterprise Skills" section and support `alwaysEnabled` enforcement
- Onboarding flow now uses dynamically fetched recommended models instead of a hardcoded list, with a fallback to the welcome view on failure
- Add dedicated "Quota Exceeded" error message in the chat error UI when Cline account spend caps are hit
### Fixed
- Fix OOM crashes during long conversations by setting `--max-old-space-size=8192` for the cline-core Node.js process (was defaulting to ~2 GB)
- Show detailed error information in the chat error row instead of a generic caught error message
- Update `axios` to 1.15.0 across all packages
### Changed
- Remove foreground terminal mode — all task command execution now defaults to background mode, removing the VS Code integrated terminal dependency and related settings UI
- Remove old hardcoded announcement banners
## [3.79.0]
### Added
- Add Claude Opus 4.7 model support
- Add Azure Blob Storage as a storage provider
- Add `globalSkills` to remote config
- Inline value reuse in user-level remote-config discovery
### Fixed
- Fix cache reflection for Cline and Vercel API handlers
- Fix stuck `command_output` ask when terminal command ends unexpectedly
- Add `use_subagents` to system prompt for GLM, Hermes, and XS models
- Fix action injection security risk
### Changed
- Remove deprecated evals tool
## [3.78.0]
### Added
- Add a dedicated "Spend Limit Reached" error UI when spend caps are hit
- Docs updates
### Fixed
- Show actual `read_file` line ranges in chat UI
## [3.77.0]
### Added
- Add "Lazy Teammate Mode" experimental toggle
-`read_file` tool now supports chunked reading for targeted file access
### Fixed
- Exclude `new_task` tool from system prompt in yolo/headless mode
- Fix Kanban demo video formatting
### Changed
- Polish `Notification` hook functionality
## [3.76.0]
### Added
- Add Cline Kanban launch modal in webview; CLI now launches Kanban by default with a migration view
@@ -8,9 +8,7 @@ We actively patch only the most recent minor release of Cline. Older versions re
We appreciate your efforts to responsibly disclose your findings and will make every effort to acknowledge your contributions.
To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/cline/cline/security/advisories/new) tab.
The team will send a response indicating the next steps in handling your report. After the initial reply, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
To report a security issue, please submit your report through our [Bugcrowd Vulnerability Disclosure Program](https://bugcrowd.com/engagements/clinebot-vdp-ess). Bugcrowd will manage communication and triage on our behalf.
When reporting, please include:
@@ -18,10 +16,10 @@ When reporting, please include:
- Steps to reproduce or a proof of concept
- Any logs, stack traces, or screenshots that might help us understand the problem
We acknowledge reports within 48 hours and aim to release a fix or mitigation within 30 days. While we work on a resolution, please keep the details private.
Please keep the details private until a resolution has been reached.
## Escalation
If you do not receive an acknowledgement of your report within 5 business days, you may send an email to security@cline.bot.
If you are unable to submit through Bugcrowd, you may send an email to security@cline.bot.
- Restore foreground terminal support and settings.
- Add latest OpenAI, SAP AI Core, and Z AI models.
### Fixed
- Fix hook template JSON escaping.
- Improve ripgrep file search error handling.
### Changed
- Remove hardcoded model lists from docs.
## [2.17.0]
### Added
- Add GPT-5.5 model support for OpenAI Codex subscription users.
### Changed
- Improve `cline-core` runtime memory diagnostics used by CLI:
- enable near-heap-limit heap snapshots
- add periodic memory usage logging
- log discovered heap snapshots on abnormal exits for easier OOM debugging
## [2.16.0]
### Added
- Wire up remote `globalSkills` from enterprise remote config with full toggle support and system prompt integration — enterprise-managed skills now support `alwaysEnabled` enforcement
- Add dedicated "Quota Exceeded" error message when Cline account spend caps are hit
### Fixed
- Fix OOM crashes during long conversations by setting `--max-old-space-size=8192` for the cline-core Node.js process (was defaulting to ~2 GB)
- Show detailed error information instead of a generic caught error message
- Update `axios` to 1.15.0 across all packages
### Changed
- Remove dead ACP terminal setter stubs as part of foreground terminal mode removal
## [2.15.0]
### Added
- Add Claude Opus 4.7 model support
- Inline value reuse in user-level remote-config discovery
- Add `globalSkills` to remote config
### Fixed
- Stabilize Windows CI test path handling
## [2.14.0]
### Added
- Simplify unified `cline update` flow for `cline` and `kanban`
- Docs updates
### Fixed
- Update Kanban migration view copy
## [2.12.0]
### Added
-`read_file` tool now supports chunked reading for targeted file access
### Fixed
- Exclude `new_task` tool from system prompt in yolo/headless mode
### Changed
- Polish `Notification` hook functionality
## [2.9.0]
### Added
- Latency improvements for remote workspaces
## [2.8.2]
### Fixed
- Use `kanban@latest` in `cline kanban` to always fetch the newest version
## [2.8.1]
### Added
- Implement dynamic free model detection for Cline API
- Add file read deduplication cache to prevent repeated reads
- Add feature tips tooltip during thinking state
### Fixed
- Fix flaky CLI Enter-key handling across Windows/test environments
- Replace error message when not logged in to Cline
- Align ClineRulesToggleModal padding with ServersToggleModal
- Skip WebP for GLM and Devstral models running through llama.cpp
- Respect user-configured context window in LiteLLM getModel()
- Honor explicit model IDs outside static catalog in W&B provider
- Add missing Fireworks serverless models and pricing
## [2.8.0]
### Added
- Added W&B Inference by CoreWeave as a new API provider with 17 models including DeepSeek-V3.1, Llama 4, and Qwen3-Coder
- Added CLI TUI end-to-end test suite
### Fixed
- Claude Code: handle rate limit events, empty content arrays, error results, and unknown content types without crashing
- CLI: `/q` and `/exit` slash commands now execute immediately on Enter without requiring the slash menu to be visible
- CLI: slash command filtering now prioritizes exact and prefix matches over fuzzy matches
## [2.7.0]
### Added
- Added MCP add shortcuts for stdio and HTTP servers
- Added `--continue` for the current directory
- Added `--auto-condense` flag for AI-powered context compaction
- Added `--hooks-dir` flag for runtime hook injection
- Enabled error autocapture
- Prompt rules now include test verification guidance and make `CLI_RULES` language-agnostic
### Fixed
- Fixed remount behavior so TUI remounts only on width resize
- Fixed startup prompt replay on resize remount
- Fixed task flags so they are applied before the welcome TUI mounts
### Changed
- Hooks: reintroduced feature toggle
## [2.6.1]
### Added
- Added GPT-5.4 models for ChatGPT subscription users
- Hooks: Added a `Notification` hook for attention and completion boundaries
- Added `--hooks-dir` CLI flag for runtime hook injection
- Added `--auto-approve-all` CLI flag for interactive mode
### Fixed
- Handle streamable HTTP MCP reconnects more reliably
## [2.6.0]
### Added
- Hook payloads now include `model.provider` and `model.slug`
- Token/cost updates now happen immediately as usage chunks arrive, not after tool execution
### Fixed
- Improve subagent context compaction logic
- Subagent stream retry delay increased to reduce noise from transient failures
- State serialization errors are now caught and logged instead of crashing
- Removed incorrect `max_tokens` from OpenRouter requests
## [2.5.2]
### Added
- Added Windows PowerShell support for hooks (execution, resolution, and management), improving hook behavior on Windows for CLI and shared core workflows.
### Fixed
- Restored GPT-OSS native file editing for OpenAI-compatible models used through shared core tooling.
- Improved OpenRouter context overflow error handling so auto-compaction triggers correctly for wrapped 400 errors.
- Hardened checkpoint recovery by retrying nested git restore and preventing silent `.git_disabled` leftovers.
- Added a User-Agent header for requests to the Cline back-end to improve request handling consistency.
## [2.5.1]
### Added
- Expanded CLI markdown rendering support (headings, lists, blockquotes, fenced code blocks, links, and nested lists).
### Fixed
- Fixed CLI headless auth provider model metadata loading for Cline and Vercel AI Gateway by fetching model info from API with cache fallback.
- Increased flaky CLI import test timeout on Windows CI to reduce intermittent test failures.
## [2.5.0]
### Added
- Added Cline SDK API interface for programmatic access to Cline features and tools, enabling integration into custom applications.
- Added Codex 5.3 model support
### Fixed
- Fix OpenAI Codex by setting `store` to `false`
- Use `isLocatedInPath()` instead of string matching for path containment checks
## [2.4.3]
### Added
- Add /q command to quit CLI
- Fetch featured models from backend with local fallback
### Fixed
- Fix auth check for ACP mode
- Fix Cline auth with ACP flag
- Fix yolo mode to not persist yolo setting to disk
it("renders basic markdown elements correctly with appropriate styling",()=>{
constmessage: ClineMessage={
ts: Date.now(),
type:"say",
say:"text",
text:"# Heading 1\n\nThis is a **bold** and *italic* text with `inline code`.\n\n- List item 1\n- List item 2\n\n> Blockquote\n\n```javascript\nconst x = 1;\n```",
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.