Compare commits

..
Author SHA1 Message Date
candieduniverse a9c7c65ded Get the build working 2026-04-07 16:25:07 -07:00
candieduniverse 9f7b52c351 Remove reportbug compatibility plumbing 2026-04-07 14:53:35 -07:00
candieduniverse 14e7b26d1c Retire unused legacy prompt families 2026-04-07 14:33:58 -07:00
candieduniverse 40344dbd8a Downgrade Focus Chain setting writes to compatibility mode 2026-04-07 14:31:17 -07:00
candieduniverse 09faca946d Hide legacy Focus Chain setting from settings UI 2026-04-07 14:28:16 -07:00
candieduniverse feec5d6543 Decouple task progress checklist from Focus Chain 2026-04-07 14:24:46 -07:00
candieduniverse f0a2b3c899 Expand feature removal migration backlog 2026-04-07 13:55:47 -07:00
candieduniverse 656f6ef6a5 Clean up task progress tool spec docs 2026-04-07 13:08:27 -07:00
candieduniverse d46b78001e Rename prompt task progress constants 2026-04-07 13:00:02 -07:00
candieduniverse 1edf1827fd Remove openFocusChainFile compatibility RPC 2026-04-07 12:55:17 -07:00
candieduniverse 1a665dacce Remove dead focus chain telemetry hooks 2026-04-07 12:46:43 -07:00
candieduniverse d1fd4b849a Hide dead focus chain file affordance 2026-04-07 12:38:19 -07:00
candieduniverse ced77606a3 Keep feedback prompts independent of focus chain 2026-04-07 12:33:40 -07:00
candieduniverse 318c37a831 Decouple task progress prompts from focus chain 2026-04-07 12:28:01 -07:00
candieduniverse 37e62ef56b Sync cleanup plan with completed doc slices 2026-04-07 12:14:09 -07:00
candieduniverse 05898a1bdc Clean up remaining workflow product copy 2026-04-07 12:12:47 -07:00
candieduniverse 1b5a1b8c15 Reframe terminal settings as fallback controls 2026-04-07 12:08:59 -07:00
candieduniverse cd5155e4f6 Clarify checkpoints as current migration-era behavior 2026-04-07 12:05:35 -07:00
candieduniverse d474268b55 Relabel focus chain settings as legacy 2026-04-07 12:01:52 -07:00
candieduniverse 6d4ca3c0b1 Demote focus chain to legacy docs surface 2026-04-07 11:58:53 -07:00
candieduniverse 4960152251 Demote memory bank to legacy docs surface 2026-04-07 11:55:48 -07:00
candieduniverse 24f8ae66a7 Update feature removal cleanup ledger progress 2026-04-07 11:52:19 -07:00
candieduniverse 8798b38ee1 Relabel workflow config UI as legacy 2026-04-07 11:50:54 -07:00
candieduniverse a9ab4abbf9 Reframe workflows as legacy compatibility docs 2026-04-07 11:47:58 -07:00
candieduniverse 8adbf2af1a Remove deep-planning and hide reportbug product surfaces 2026-04-07 11:42:16 -07:00
candieduniverse a28c40d581 Create implementation plan doc 2026-04-07 11:15:20 -07:00
Dominic Cooney 8913eedeb2 Uncommitted agent scree. 2026-04-07 23:42:44 +09:00
Dominic Cooney 6d2701623e docs: update CAVEATS.md — mark all fixed issues, reorganize sections
All 24 issues now in Fixed section with condensed descriptions.
Only #15 (MCP tools not visible to agent) remains as Open Issue.
2026-04-07 21:59:05 +09:00
Dominic Cooney f6db6977db fix: implement Cline model discovery and update recommended model text
- Implement handleRefreshClineModels handler in grpc-handler.ts that
  reads from disk cache first, then fetches from Cline API directly
  using globalThis.fetch (avoids ClineEnv initialization requirement)
- Convert API response to ModelInfo records with proper protobuf format
- Remove refreshClineModelsRpc from stub list
- Update ClineModelPicker.tsx fallback text from claude-sonnet-4.5 to
  claude-sonnet-4.6 to match current recommended model

Fixes #20 (model type-ahead search empty) and #21 (outdated model recommendation)
2026-04-07 21:56:00 +09:00
Dominic Cooney 4971611493 fix(#14): omit placeholder size from delete task button tooltip
DeleteTaskButton tooltip now shows 'Delete Task' when taskSize is
unavailable, instead of 'Delete Task (size: --)'. When size data is
available, it shows 'Delete Task (12.4 KB)'.
2026-04-07 21:39:57 +09:00
Dominic Cooney c7f5a65c2e fix(#5): suppress token usage bar when token counts are zero
ContextWindow.tsx now returns null when tokenData.used === 0, preventing
a brief flash of '0 / 200.0k' in the token usage bar when api_req_started
fires with zeroed counts before real data arrives.
2026-04-07 21:38:13 +09:00
Dominic Cooney 987b32ca51 fix(#4): clear chat input immediately on send, before async gRPC calls
Previously setInputValue('') was called after await TaskServiceClient
newTask/askResponse completed, causing a visible delay where the typed
text lingered in the input field during the network round-trip.

Now the input, active quote, images, and files are cleared synchronously
before any async operations, giving immediate visual feedback.
2026-04-07 21:35:13 +09:00
Dominic Cooney 269c0391a2 fix(#19): remove Terminal Execution Mode dropdown from settings
The Terminal Execution Mode dropdown (VS Code Terminal / Background Exec)
is legacy — only background terminal execution is supported. Removed the
dropdown, its handler (handleExecutionModeChange), and unused imports
(PlatformType, usePlatform) from TerminalSettingsSection.tsx.

Verified via debug harness: Terminal settings now shows Default Terminal
Profile, Shell integration timeout, Enable aggressive terminal reuse,
and Terminal output limit.
2026-04-07 21:29:54 +09:00
Dominic Cooney be16c82dd2 fix(#16): remove Workflows tab from Cline Rules modal
Workflows are no longer a feature. Remove the Workflows tab button,
description text, content section (remote/global/local workflow toggle
lists), and remote workflows banner condition from ClineRulesToggleModal.

The currentView state type is narrowed from 4 options to 3:
'rules' | 'hooks' | 'skills'. Workflow-related state/functions are kept
since they're still used by slash command components.

Verified via debug harness: modal now shows only Rules and Skills tabs.
2026-04-07 21:26:10 +09:00
Dominic Cooney 639329de22 docs: document #15 MCP tools investigation — ClineCore MCP wiring gap
Issue #15 (MCP tools missing) is caused by ClineCoreSession in
cline-session-factory.ts not passing MCP configuration through coreConfig
when calling host.start(). @clinebot/core has full MCP support
(InMemoryMcpManager, registerMcpServersFromSettingsFile) but the SDK
session factory never wires MCP servers into sessions.

Documented the investigation findings and three possible fix paths in
CAVEATS.md for future work.
2026-04-07 21:21:48 +09:00
Dominic Cooney db85573182 fix(account): show logged-in state by handling subscribeToAuthStatusUpdate streaming
Three fixes:
1. webview-grpc-bridge.ts: Added explicit case for subscribeToAuthStatusUpdate
   in handleStreamingRequest(). Previously fell into the default no-op case,
   so the webview never received the auth state and always showed AccountWelcomeView
   ('Sign up with Cline') even when credentials existed on disk.

2. grpc-handler.ts: Added 'roles' field to getUserOrganizations response.
   Missing roles caused isAdminOrOwner() to crash on .findIndex().

3. helpers.ts: Added null safety (activeOrg.roles ?? []) in isAdminOrOwner()
   as defense against undefined roles field.
2026-04-07 21:19:02 +09:00
Dominic Cooney 1e8d997d6c fix(mcp): add null safety for marketplace catalog items in getMcpServerDisplayName
The getMcpServerDisplayName function crashed with 'Cannot read properties of
undefined (reading find)' when mcpMarketplaceCatalog.items was undefined.

This happened because the refreshMcpMarketplace gRPC stub returns an empty
object {}, which replaces the default { items: [] } state. When the Configure
tab renders ServerRow components that call getMcpServerDisplayName(), the
.items.find() call crashes and takes down the entire React app.

Fix: Add optional chaining (?.items?.find) to handle undefined catalog/items.
2026-04-07 21:10:08 +09:00
Dominic Cooney 2c4fa3a1f8 docs: update CAVEATS.md - mark #22, #24, #25 as fixed 2026-04-07 20:58:03 +09:00
Dominic Cooney ab9333d3b7 fix(sdk): history view empty - getTaskHistory returned wrong key name
The grpc-handler's handleGetTaskHistory returned { data: { history } }
but the webview's HistoryView component reads response.tasks (matching
the proto TaskHistoryArray.tasks field). Changed the return to
{ data: { tasks, totalCount } }.

Also added proper support for the GetTaskHistoryRequest filter params:
- favoritesOnly: filter to favorited tasks only
- searchQuery: case-insensitive text search on task descriptions
- sortBy: newest/oldest/mostExpensive/mostTokens sorting
- currentWorkspaceOnly: filter by workspace cwd

Maps HistoryItem fields to TaskItem proto shape (id, task, ts,
isFavorited, totalCost, tokensIn, tokensOut, cacheWrites, cacheReads).

Also fixes pre-existing lint issues in the file:
- isNaN → Number.isNaN
- console.warn → Logger.log
- Added cwd to GrpcHandlerDelegate interface

Fixes CAVEATS.md issue #24.
2026-04-07 20:57:11 +09:00
Dominic Cooney 3142d198c9 fix: persist planActSeparateModelsSetting and autoApprovalSettings to globalState.json
updateSettings() and updateAutoApprovalSettings() in SdkController were routing
all writes through saveApiConfiguration(), which only writes keys in
ApiHandlerSettingsKeys or SecretKeys. User settings like planActSeparateModelsSetting
and autoApprovalSettings are USER_SETTINGS_FIELDS, so they were silently dropped.

Fix: updateSettings() now also writes each key directly to globalState.json via
writeGlobalStateKey(), and updateAutoApprovalSettings() bypasses saveApiConfiguration()
entirely, writing directly to globalState.json.

Also fixes pre-existing lint issues: unused isTaskRunning field, unused response
parameter, and console.error → Logger.error.

Fixes CAVEATS #22 and #25.
2026-04-07 20:41:48 +09:00
Dominic Cooney a74f37a518 Some fixes, mo problems. 2026-04-07 20:17:53 +09:00
Dominic Cooney 759b189c8f docs: document terminal settings radical simplification
The SDK uses background terminal execution, making most of the
TerminalSettingsSection obsolete. Added detailed table of what to
remove vs keep, list of related files to delete, and added to
Phase 2 checklist.
2026-04-07 13:28:45 +09:00
Dominic Cooney 766675d381 docs: update CAVEATS #13 with real root cause and verification 2026-04-07 00:06:25 +09:00
Dominic Cooney 85c594c381 fix: implement getAvailableTerminalProfiles gRPC handler
The stub returned {data:{}}, so response.profiles was undefined. The
webview called setAvailableTerminalProfiles(undefined) which overwrote
the default [], then profilesToShow.map() crashed React — blank webview.

Now calls getAvailableTerminalProfiles() from utils/shell.ts which
returns platform-specific profiles (Default, zsh, bash on macOS).

Verified via debug harness:
- Handler returns {data:{profiles:[...]}} with 3 profiles
- Navigated to Settings > Terminal tab
- 'Default Terminal Profile' dropdown renders with Default/zsh/bash
- 'Shell integration timeout', 'terminal reuse' all visible
- React did not crash (rootEmpty: false)
2026-04-07 00:05:57 +09:00
Dominic Cooney 45112d953f docs: add Caveats section to DEBUG-HARNESS.md
- Document 'Introducing Cline Kanban' promo overlay that obscures the
  sidebar on fresh launches, with dismissal commands
- Document CDP disconnect after window reload requiring full harness restart
2026-04-06 23:57:14 +09:00
Dominic Cooney 2a13e85bad fix: terminal settings crash, workflows text, CAVEATS update
- Fix #13: Add missing availableTerminalProfiles: [] to state-builder.ts
  preventing React crash when TerminalSettingsSection calls .map() on undefined
- Fix #12: Update ClineRulesToggleModal tooltip from 'Manage Cline Rules &
  Workflows' to 'Manage Cline Rules', fix aria-label similarly
- Update CAVEATS.md: move issues #8-13 to Fixed section, only #4 and #5
  (minor UX issues) remain open
2026-04-06 23:46:23 +09:00
Dominic Cooney da6cf70e87 fix: resolve broken gRPC handlers for SDK bridge
- Fix #8: Plus button now clears task via SDK bridge (clearSdkTask)
  and sends typed navigate('chat') message
- Fix #9: Implement searchFiles handler with real filesystem walk
  for @ mentions / autocomplete
- Fix #10: selectFiles returns { images: dataURL[], files: path[] }
  matching proto StringArrays (values1/values2) webview expects
- Fix #11: Plan/Act mode toggle converts proto enum values
  (0=PLAN, 1=ACT) to app string format
- Fix #12: Simplify chat placeholder text (remove 'workflows')
- Fix #13: scrollToSettings fires navigate callback via typed message

Top bar buttons (settings, history, chat, account, MCP, worktrees)
now send typed navigate messages alongside classic gRPC subscription
events, enabling navigation in SDK mode.
2026-04-06 23:42:37 +09:00
Dominic Cooney ccc454cb5a More notes about missing grpcs. 2026-04-06 23:02:04 +09:00
Dominic Cooney b7ed460ad8 Agent doc updates. 2026-04-06 22:18:08 +09:00
Dominic Cooney 766ef22017 Agentic debugging tool improvements. 2026-04-06 18:59:21 +09:00
Dominic Cooney 4402b0d277 Agent documented bugs/caveats. 2026-04-06 18:51:55 +09:00
Dominic Cooney 9563ef4057 Cline/Anthropic inference works. 2026-04-06 13:36:45 +09:00
Dominic Cooney 402aaeb311 Start new task button appears on task completion; works. 2026-04-04 07:57:41 +09:00
Dominic Cooney 91e6353093 Settings persist across restarts, Ollama output not garbled. 2026-04-04 07:42:30 +09:00
Dominic Cooney fa7128fc84 Local inference with ollama works, output is garbled (might be phi4-mini tho...) 2026-04-04 07:28:08 +09:00
Dominic Cooney a90a2ca30c cwd and workspaceRoot; suspicious string munging with Cline API keys. 2026-04-04 00:17:50 +09:00
Dominic Cooney 7825571267 Picks up saved model settings. 2026-04-04 00:03:48 +09:00
Dominic Cooney d74a82b202 Wire ClineCoreSession but keys apparently missing. 2026-04-03 23:46:51 +09:00
Dominic Cooney 205bee34e3 More agent work (some prevaricating.) 2026-04-03 23:37:03 +09:00
Dominic Cooney 535e8f960d Model displays and submitting a chat switches to thinking. 2026-04-03 21:38:43 +09:00
Dominic Cooney 3f467c3eb3 More agent work. 2026-04-03 21:20:09 +09:00
Dominic Cooney cf78c0e65e Phase 1, Unit 9 2026-04-03 20:41:15 +09:00
Dominic Cooney 08eb7c326c Phase 1 units 4-8. 2026-04-03 20:09:51 +09:00
Dominic Cooney e581f4cc9a Phase 1 to unit 3 2026-04-03 19:42:58 +09:00
Dominic Cooney 3c883d2955 phase 1 unit 1: SDK foundation — deps, test infra, vitest config
- Add @clinebot/core, agents, llms, shared v0.0.28 as dependencies
- Add vitest as dev dependency for SDK adapter tests
- Create src/sdk/ directory structure with index.ts and test fixtures
- Add vitest.config.sdk.ts with Vite plugin to fix SDK package
  browser/development export condition issues
- Add npm scripts: test:sdk, test:sdk:watch
- Exclude src/sdk/ from mocha (.mocharc.json ignore)
- Regenerate prompt snapshots from phase 0 cleanup
- All 1349 existing unit tests pass, 5 new SDK foundation tests pass
- Classic extension build verified green
2026-04-03 18:44:11 +09:00
Dominic Cooney 2154425f40 phase 0: remove browser automation, shadow git checkpoints, focus chain, deep planning, /reportbug
Removed implementations and replaced with no-op stubs:
- Browser automation (BrowserSession, BrowserDiscovery, BrowserToolHandler)
- Shadow git checkpoints (CheckpointTracker, factory, initializer, etc.)
- Focus chain (FocusChainManager, tool variants)
- Deep planning (/deep-planning slash command)
- /reportbug slash command
- Go CLI artifacts (go.work.sum)

~15,500 lines deleted across 88 files. Build and type-check pass.
Debug harness is unaffected.
2026-04-03 11:02:44 +09:00
Dominic Cooney 68194f379a Add debug harness. 2026-04-03 10:38:03 +09:00
Dominic Cooney 19e88302ac Cherry pick visibility, migration from last attempt. 2026-04-03 10:14:54 +09:00
Saoud Rizwan 7a91a9be2e Bump version from 2.12.0 to 2.13.0 2026-04-01 20:09:42 -07:00
Saoud Rizwan 93a494d009 feat(cli): simplify unified update flow for cline and kanban (#10099)
* 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
2026-04-01 20:08:19 -07:00
CandiedUniverse 2bd21f8a45 Update changelog and release version (#10085) 2026-04-01 10:02:58 -07:00
John Simone 2f33f71ebd Add lazy teammate mode (#10081) 2026-04-01 08:55:43 -07:00
TheRealSpencer dec10aaec3 pin axios version due to current package integrity (#10060)
* pin axios version due to current package integrity

* update axios versions
2026-03-31 11:02:20 -07:00
Dominic Cooney c09705a45f Add Linux ARM64 (aarch64) support for JetBrains plugin (#10062)
- 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').
2026-03-30 23:57:12 -07:00
Saoud Rizwan 73058c871a ci: post release changelogs to #releases Slack channel (#10057) 2026-03-30 19:43:00 -07:00
03211f1364 feat(sdk): add fetchFeaturebaseToken method [ENG-1673] (#10005)
* feat(sdk): add fetchFeaturebaseToken method

- Add fetchFeaturebaseToken() to ClineAccountService
- Add FeaturebaseTokenResponse type and endpoint constant
- Add E2E mock server handler and unit tests

Ref: ENG-1673

* fix: address review feedback - narrow test glob and add JSDoc

- Fix P2: scope mocharc glob to **/*.test.ts to avoid matching non-test files
- Fix P2: add JSDoc comment to fetchFeaturebaseToken for consistency

---------

Co-authored-by: John Choi <john.choi@cline.bot>
Co-authored-by: John Choi <johnwschoi@users.noreply.github.com>
2026-03-30 14:48:53 -07:00
CandiedUniverse 65e9727c65 Add is_remote_workspace metric (#10019)
* Create implementation plan doc

* feat(telemetry): track remote workspace metadata

* test(workspace): assert telemetry emission during setup

* Remove implementation plan doc

* Improvements pre- code review

* Fix as per Greptile feedback
2026-03-27 19:04:07 -07:00
Robin Newhouse 884fbfb21e feat(read_file): add chunked reading with start_line/end_line parameters (#9711)
* 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
2026-03-27 12:24:57 -07:00
Dominic Cooney 0c880c7bb1 fix: Serve H.264/MP4 for VSCode and VP9/WebM for JetBrains (#10012)
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)
2026-03-27 03:35:20 -07:00
Dominic Cooney a915122c6d fix: Transcode kanban demo video from H.264/MP4 to VP9/WebM (#9997)
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)
2026-03-27 07:39:05 +09:00
Robin Newhouse 835ed94736 fix: exclude new_task tool from system prompt in yolo/headless mode (#9958) 2026-03-26 12:10:47 -07:00
Robin Newhouse 00ca3d13fa test(oca): add messages api routing and stream helper tests (#9494) 2026-03-26 12:02:13 -07:00
3f3a87aed9 Hooks: Notification hook polish (#9909)
* Create implementation plan doc

* Implement notification hook helper

* Remove generated proto artifacts from branch

* Remove implementation plan doc

* Update src/core/hooks/__tests__/notification-hook.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update src/core/hooks/notification-hook.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>
Co-authored-by: Tony Loehr <turingxo@gmail.com>
2026-03-26 10:10:15 -07:00
John SimoneandRenee Huang 7a0f11837e Add Kanban docs (#9988)
* add kanban docs

* fix rendering error in overview, drop kanban flags from commands

* fix stray link

---------

Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com>
2026-03-26 08:12:09 -07:00
Max 03d2d01eed chore: bump version to 3.76.0 (#9986) 2026-03-26 07:52:28 -07:00
Dominic Cooney db1b1c45bd chore: update dependencies flagged by npm audit (#9980) 2026-03-26 21:03:35 +09:00
Saoud Rizwan a4131e57d8 fix(cli): replace --tui hint with kanban description in migration view
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.
2026-03-25 22:52:22 -07:00
Saoud Rizwan 683dd9a741 chore(cli): bump version to 2.11.0 2026-03-25 19:24:48 -07:00
Saoud Rizwan 0d437f71b0 fix(cli): remove noisy install message when launching kanban 2026-03-25 19:24:20 -07:00
Saoud Rizwan fc77c0faea chore(cli): bump version to 2.10.0 2026-03-25 18:38:24 -07:00
Saoud Rizwan 12c85c4233 Update tips about kanban 2026-03-25 18:26:06 -07:00
Saoud Rizwan d6b7a1ab41 fix(cli): launch kanban directly with package manager fallback 2026-03-25 18:26:06 -07:00
CandiedUniverse 3926e7b404 Stabilize auth e2e onboarding tests and clean up mock server URL parsing (#9974)
* Fix tests that fail when kanban modal is visible

* Fix deprecation warning

* Improve isVisible() as per Greptile suggestion
2026-03-25 16:35:09 -07:00
Tony Loehr 5ba4314b9a feat: add toggle to disable feature tips in chat (#9973) 2026-03-25 15:28:09 -07:00
9ccad7f764 refactor: replace hand-rolled YAML parser in refreshSkills with shared helper (#9956)
* 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>
2026-03-25 09:06:15 -07:00
Saoud Rizwan 3562f54dbf fix(cli): enable shell mode for kanban spawn on Windows
npx.cmd requires shell: true on Windows to resolve correctly.
2026-03-25 07:35:53 -07:00
OctopusandPR Bot d427d5d76a feat: upgrade MiniMax default model to M2.7 (#9886)
* 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>
2026-03-25 05:17:13 -07:00
Saoud Rizwan 072e2887b0 fix(cli): add --tui flag to TUI e2e tests to bypass Kanban redirect
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.
2026-03-25 04:36:12 -07:00
Saoud Rizwan 9c71a6f021 feat(webview): add Cline Kanban launch modal and queue announcements (#9963)
* feat(webview): add dedicated Cline Kanban launch modal

* fix(ci): fetch LFS media assets in publish workflows
2026-03-25 04:32:09 -07:00
Saoud Rizwan 7627a382aa feat(cli): launch kanban by default with migration view (#9914)
* 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).
2026-03-25 02:01:56 -07:00
Tomás Barreiro 978c633c90 Add KanBan to remote config [PF-632] (#9959)
* Add KanBan to remote config

* Update tests
2026-03-25 02:33:52 +01:00
Tony Loehrandgreptile-apps[bot] e807b520e0 feat(cli): add rotating feature tips during thinking/acting phases (#9874)
* feat(cli): add rotating feature tips during thinking/acting phases

Port the FeatureTip component from the VSCode extension (PR #9799) to the
CLI. Shows rotating educational tips below the ThinkingIndicator while Cline
is processing, appearing after a 2-second delay and cycling every 8 seconds.

Includes 17 tips covering:
- Core features: .clinerules, Plan/Act mode, checkpoints, MCP servers
- CLI-specific: /settings, /skills, /history, /compact, /reportbug
- Workflows: kanban, auto-approve toggle, history navigation, @ mentions
- Images via --images flag, browser testing, double-check completion

* Update FeatureTip.tsx

* Apply suggestions from code review

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: resolve FeatureTip.tsx syntax errors (duplicate export, missing tipIndex state)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-24 17:57:35 -07:00
f3a3f30db5 feat: add repeated tool call loop detection (#9933)
* 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>
2026-03-24 13:40:31 -07:00
Igor TceglevskiiandCopilot Autofix powered by AI f1c7934064 fix: prevent OOM crash from globby's eager .gitignore scanning in lis… (#9917)
* 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>
2026-03-22 15:20:57 -07:00
Robin Newhouse 1d42da5248 Add tool-specific error messages for replace_in_file and execute_command (#9710)
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
2026-03-21 11:57:00 -07:00
7f3974a827 fix: read cache_write_tokens from OpenRouter API instead of hardcoding 0 (#9871)
* 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>
2026-03-20 15:46:29 -07:00
CandiedUniverse d40ab56aff Changelog and version bump for release (#9910) 2026-03-20 15:29:45 -07:00
CandiedUniverse bbdf445db7 fix: prevent resume asks from unblocking on abort (#9908)
* fix: prevent resume asks from unblocking on abort

* Add test case for resume_completed_task

* Prevent flaky tests
2026-03-20 10:51:16 -07:00
CandiedUniverse d992a3bf21 Stabilize hooks fixture tests with per-scenario isolation (fix flaking tests) (#9868)
* Refactor flaking hooks tests

Fix flaking hooks tests

Strengthen hooks fixture test isolation

* Address Greptile hooks test review

* Harden Windows hook timing tests

* Loosen hook cancellation timing margins

* Fixing more flaking tests
2026-03-20 09:50:14 -07:00
ace95988f8 fix: resolve deadlock when clicking New Task/Exit after task completion (#9905)
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>
2026-03-20 08:53:21 -07:00
Tony Loehrandgreptile-apps[bot] 54726f1677 docs: fix SDK documentation accuracy and completeness (#9856)
* 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>
2026-03-19 21:01:24 -07:00
Saoud Rizwan 6308fef0a9 fix(cli): use kanban@latest to always fetch newest version (#9898)
* 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
2026-03-19 19:37:53 -07:00
CandiedUniverse b3fc79b8ce Remove example hooks (#9896) 2026-03-19 18:42:55 -07:00
CandiedUniverse ff05ec3bbe Latency improvements for remote workspaces (#9858)
* 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
2026-03-19 17:05:49 -07:00
Ara bde7049c01 Release v3.74.0 Notes (#9879) 2026-03-18 19:08:50 -07:00
Ara 7cd06744ad feat: implement dynamic free model detection for Cline API (#9878)
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.
2026-03-18 18:55:06 -07:00
shey-cline c88d3238cf Replace Error Message When Not Logged In to Cline (#9632) 2026-03-18 16:01:06 -07:00
jessy-clineandSaoud Rizwan 852ca2348f fix(ui): align ClineRulesToggleModal padding with ServersToggleModal (#9870)
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-03-18 14:13:39 -07:00
CandiedUniverse 7091ccf2c7 Fix flaky CLI Enter-key handling across Windows/test environments (#9867)
* fix(cli): normalize enter key handling in ink inputs

* fix(cli): pass input through auth select enter handling
2026-03-18 12:20:25 -07:00
Mathisandgreptile-apps[bot] ad6c33ac5b feat: add file read deduplication cache to prevent repeated reads (#9836)
* 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>
2026-03-18 10:38:23 -07:00
Tony Loehrandgreptile-apps[bot] 71e312e92a feat: add feature tips tooltip during thinking state (#9799)
* 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>
2026-03-17 13:51:37 -07:00
5903840f79 Added Fields to Responses API for the Oracle Code Assist (OCA) Provider (#9852)
* added fields to responses api

* fix temp problem

* cleaning up

* clean modelId

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: Charlotte Stinson <charlottestinson@Charlottes-MacBook-Pro.local>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-17 13:41:39 -07:00
ClineXDiego 0c677b63db fix(browser): skip WebP for GLM and Devstral models running through llama.cpp (#9837)
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
2026-03-17 14:57:40 -03:00
ClineXDiego b741135f85 fix(litellm): respect user-configured context window in getModel() (#9834) 2026-03-17 05:36:44 -07:00
Ara 2eab216815 fix(wandb): honor explicit model IDs outside static catalog (#9839) 2026-03-16 16:40:28 -07:00
Ara e57174eec8 fix(fireworks): add missing serverless models and pricing (#9810)
* feat: refresh Fireworks serverless model defaults

* fix(fireworks): handle cached token usage and write pricing

* fixing maxtokens for gemini family

* feat(fireworks): add missing serverless models and pricing
2026-03-16 14:28:23 -07:00
Max ad4631c682 bump cline version (#9833) 2026-03-16 13:36:41 -07:00
Mathisandgreptile-apps[bot] aae23e8685 fix: Claude Code provider failing with 4.6 models and newer CLI versions (#9783)
* 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>
2026-03-16 13:01:55 -07:00
dependabot[bot] 0ff27591d5 chore(deps-dev): bump lodash (#8803)
Bumps the npm_and_yarn group with 1 update in the /testing-platform directory: [lodash](https://github.com/lodash/lodash).


Updates `lodash` from 4.17.21 to 4.17.23
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.17.23
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 12:25:46 -07:00
dependabot[bot] 23127f22de chore(deps): bump qs from 6.14.1 to 6.15.0 (#9343)
Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.15.0.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.14.1...v6.15.0)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.15.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 12:00:02 -07:00
CandiedUniverse 57ed14d1b1 Fix issue with Windows notification (#9743)
* 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
2026-03-16 09:44:20 -07:00
aikido-autofix[bot]andMax a769585406 fix(security): update dependencies (#9812)
Co-authored-by: aikido-autofix[bot] <119856028+aikido-autofix[bot]@users.noreply.github.com>
Co-authored-by: Max <maxpaulus43@gmail.com>
2026-03-16 09:15:40 -07:00
CandiedUniverse c44b29b002 Fix Windows CLI tests related to /q and /exit (#9747)
* Fix flaky Windows CLI quit slash tests

* Refine CLI slash command handling and test stability

* Address Greptile cleanup feedback
2026-03-16 07:59:26 -07:00
dependabot[bot] bb4e397a51 chore(deps): bump undici from 7.20.0 to 7.24.3 (#9825)
Bumps [undici](https://github.com/nodejs/undici) from 7.20.0 to 7.24.3.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.20.0...v7.24.3)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 7.24.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 07:52:50 -07:00
Saoud Rizwan 9824d8d476 Bump CLI version from 2.7.0 to 2.7.1 2026-03-15 20:36:02 -07:00
Saoud Rizwan a46c5288ca Fix Notification hook getting called by command output asks 2026-03-15 20:08:06 -07:00
Mohammad Bakirandgreptile-apps[bot] 91b947de69 feat: Add W&B Inference by Coreweave as provider (#9800)
* 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>
2026-03-13 16:06:35 -07:00
Saoud Rizwan 7b25a21b26 fix(cli): add -y flag to npx kanban to auto-confirm install 2026-03-13 15:47:18 -07:00
Ara 1d1071dcf5 fix: consolidate Parallel tool-calling fixes (#9738)
* fix: consolidate parallel tool-calling fixes

* test(snapshot): fix vertex gemini3 snapshot newline

* fix gemini toolcall id collision (#9768)

* test(snapshot): fix vertex gemini3 snapshot newline

* fix(gemini): prevent native tool-call ID collisions

* fixing maxtokens for gemini family

* test(gemini): assert fallback tool call ids
2026-03-13 09:20:23 -07:00
Dominic Cooney 8d07b7d6cb fix: catch errors in path-based tool handlers instead of crashing (#9732)
* 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.
2026-03-12 20:58:06 -07:00
Dominic Cooney aacc69a558 fix: catch file-not-found in ReadFileToolHandler instead of crashing CLI (#9730)
* 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.
2026-03-13 10:52:32 +09:00
MaxandMax Paulus 🥪 a27bedffb6 max/cli tui e2e tests (#9753)
* 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>
2026-03-12 16:06:25 -07:00
Diego Ferreyraandgatof81 bbeecefe84 docs: fix broken Oracle Code Assist website link (#9782)
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>
2026-03-12 11:56:34 -03:00
alex-lum 50b57f472f feat(telemetry): add provider to task.tokens event (#9762) 2026-03-11 17:30:03 -07:00
CandiedUniverse 0e7e0099cd Changelog and version bump for release (#9775) 2026-03-11 17:21:04 -07:00
AJ JuaireandSaoud Rizwan 44cbfe9d9c Update Jupyter Notebook gifs (#9772)
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-03-11 16:25:46 -07:00
Saoud Rizwan 4ecccf5105 feat(cli): add mcp add shortcuts for stdio and http servers (#9773) 2026-03-11 16:17:43 -07:00
Ara 6d29bc6551 fix(prompt): resolve native tool placeholder interpolation (#9764)
* fix(prompt): resolve CWD and MULTI_ROOT_HINT in native tool schemas

* refactor(prompt): share multi-root hint constant
2026-03-11 08:10:58 -07:00
Saoud Rizwan 820057308a feat(cli): add kanban alias command (#9763) 2026-03-10 21:57:16 -07:00
Ara 7355f7e3b9 fix(gemini): cap flash output tokens to 8192 across providers (#9749) 2026-03-10 14:10:14 -07:00
MaxandMax Paulus 🥪 156f18f7b2 call telemetry service after initializeCli (#9752)
- 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>
2026-03-10 11:50:34 -07:00
Tomás Barreiro 6129caa423 Get user consent before loading images in Markdown (#9745)
* 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
2026-03-09 21:06:57 -07:00
alex-lum ffa4785f43 fix(telemetry): restore cache token and cost metrics in captureTokenUsage (#9741)
* 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
2026-03-09 15:55:23 -07:00
CandiedUniverse 92ec126dca Fix Windows unit test path normalization (#9742) 2026-03-09 13:23:47 -07:00
Ara c4c8b16afb chore: remove changesets bot artifacts (#9739) 2026-03-09 12:26:48 -07:00
MaxandMax Paulus 🥪 2eed79dcd7 use setSessionOverride instead of setGlobalState (#9707)
- 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>
2026-03-09 11:20:57 -07:00
shey-cline d39a53feed Add Padding to Retry Message (#9635) 2026-03-09 09:29:27 -07:00
Dominic Cooney cae9bff416 test: rebaseline vertex_gemini3.tools.snap (#9731)
Commit 55569efb7 changed the list_code_definition_names path parameter
description but did not update the snapshot baseline.
2026-03-09 07:57:05 -07:00
Saoud Rizwan 36618fb327 fix(cli): remount TUI only on width resize (#9736) 2026-03-09 04:03:59 -07:00
Saoud Rizwan a335b5cb3e fix(cli): prevent startup prompt replay on resize remount (#9735) 2026-03-09 03:30:01 -07:00
Saoud Rizwan bce71b4448 feat(cli): add --continue for current directory (#9726)
* feat: add cli continue flag for current directory

* docs(cli): clarify continue command examples
2026-03-08 19:54:44 -07:00
Robin Newhouse f6d2b4d9ac Add --auto-condense CLI flag to enable AI-powered context compaction (#9705)
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
2026-03-08 16:28:48 -07:00
Robin Newhouse 911fcfda47 gemini-hc: add parameter descriptions to Gemini tool schemas (#9681)
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
2026-03-08 16:27:50 -07:00
Robin Newhouse 55569efb74 fix(tools): prevent crash when list_files/list_code_definition_names receives a file path (#9680)
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
2026-03-08 16:07:03 -07:00
Robin Newhouse 18561ed59d prompt: add test verification rules and make CLI_RULES language-agnostic (#9679)
- 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
2026-03-08 15:58:13 -07:00
Saoud Rizwan fa7265fa33 feat: add Anthropic Opus 4.6 fast mode variants (#9725)
* feat: add Anthropic Opus 4.6 fast mode variants

* refactor: localize Anthropic fast mode beta constant

* fix: correct Anthropic 1M fast mode pricing
2026-03-08 15:31:37 -07:00
M.Yoshida(Jyuko Co.,Ltd) bf96223639 docs: add .github/copilot-instructions.md for AI coding agents (#9606)
* docs: add .github/copilot-instructions.md for AI coding agents

* docs: update copilot-instructions with provider, state, and CLI guidance
2026-03-08 14:51:55 -07:00
Saoud Rizwan c489f79508 fix(cli): apply task flags before welcome TUI mount (#9721) 2026-03-07 11:20:53 -08:00
CandiedUniverse 6ccd662a1f Hooks: Add feature toggle (toggled off by default) (#9671)
* 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
2026-03-06 13:49:03 -08:00
Tomás Barreiro a2fa4d3b92 [ENG-1571] Enable CLI Error autocapture (#9686)
* Introduce the enableErrorAutocapture option

* Enable capturing CLI extension

* Capture exception immediately

* Handled uncaptured exceptions

* refactor

* Add tests

* Capture unhandledExceptions

* Add an error boundary to the ink app

* Wrap the App in the ErrorBoundary

* Check for consent before capturing error

* Add context to the error capturing

* Fix tests

* refactor

* Remove `unref`
2026-03-06 20:39:44 +01:00
CandiedUniverseandgreptile-apps[bot] c8f81374a3 Fix flaky hooks tests on Windows (#9690)
* test(hooks): reduce Windows hook-runner launch overhead

test(hooks): make Windows hook tests deterministic

refactor(hooks): use platform-agnostic launcher cache naming

Improvements as per Cline code review feedback

test(hooks): remove direct-node acceleration path and stabilize windows timings

* test(hooks): add deterministic launcher cache concurrency coverage

* Improvements as per Cline code review feedback

* Update src/core/hooks/__tests__/hookprocess.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Improvements as per Greptile feedback

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-06 10:46:34 -08:00
ClineXDiego eb25634bd4 fix(bedrock): handle thinking and redacted_thinking blocks in message conversion and streaming (#9424)
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
2026-03-06 10:41:43 -08:00
MaxandMax Paulus 🥪 1753d9dc15 release changelog and version bump (#9706)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-03-06 09:45:20 -08:00
Saoud Rizwan a562868cb9 feat(cli): add --auto-approve-all flag for interactive mode (#9698) 2026-03-06 02:08:59 -08:00
Saoud Rizwan bf5265758f feat(hooks): add Notification hook for attention boundaries (#9699)
* feat(hooks): add Notification hook for attention and completion

* chore(hooks): use default Notification template

* Revert "chore(hooks): use default Notification template"

This reverts commit 85f4e942fc.

* fix(hooks): escape JSON quotes in bash templates

* Revert "fix(hooks): escape JSON quotes in bash templates"

This reverts commit 29dfb9e01e.

* chore(hooks): preserve single-backslash template escaping

* fix(hooks): keep single-backslash JSON escaping in templates

* Revert "fix(hooks): keep single-backslash JSON escaping in templates"

This reverts commit b4c829489f.

* fix(hooks): keep escaped JSON echo template pattern
2026-03-06 02:07:25 -08:00
Saoud Rizwan 469752a201 feat(cli): add --hooks-dir flag for runtime hook injection (#9658)
* 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
2026-03-05 23:33:41 -08:00
Araandgreptile-apps[bot] 8fb2e8a3aa Adding gpt 5.4 models to chatgpt subscripiton (#9692)
* Adding gpt-5.4 to chatgpt subscription

* Fixing stuff

* Apply suggestion from @greptile-apps[bot]

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>
2026-03-05 18:06:17 -08:00
ClineXDiego aef32f52f9 fix: bypass git hooks on checkpoint initial commit (#9688)
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
2026-03-05 19:02:00 -03:00
Dominic Cooney 2baf966db7 fix: handle streamableHttp reconnects and preserve OAuth redirect URIs across sessions (#9642)
- Make redirect URIs with dynamic ports valid, or reregister.
- Handle reconnects for streaming HTTP MCP servers.
2026-03-05 09:00:20 +09:00
alex-lumandTomás Barreiro 152ba674da feat: add OTel tracking for AI output line/file metrics (lines added/deleted/changed, files created/deleted/moved) (#9562)
* 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>
2026-03-04 14:45:57 -08:00
MaxandMax Paulus 🥪 12f5dc2e9e update changelog and bump version numbers (#9664)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-03-04 13:39:15 -08:00
Saoud Rizwan 28d806a4e4 fix(openrouter): stop sending max_tokens in stream requests (#9634) 2026-03-04 18:48:59 +01:00
AraandClaude Opus 4.6 e92c7de8c0 Restrict /test-jetbrains workflow trigger to authorized users (#9657)
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>
2026-03-04 09:13:41 -08:00
CandiedUniverse 718e5b53f6 Add model identifier to the JSON payload that hooks receive (#9646)
* 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
2026-03-03 19:08:41 -08:00
Saoud Rizwan e484534bcb fix(task): process usage chunks independently from non-usage stream flow (#9576) 2026-03-03 12:27:20 -08:00
Dominic Cooney 2822723495 fix: stop infinite getLatestMcpServers RPC loop when opening MCP servers panel (#9643)
* 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
2026-03-03 09:08:34 -08:00
Saoud Rizwan b5c0cc18d8 fix(subagent): fix subagents erroring out by handling context-window limit errors (#9637)
* fix(subagent): align error handling with main loop behavior

* fix(subagent): persist context truncation state across retries
2026-03-02 22:13:32 -08:00
Dominic Cooney fb04a9bd15 Log RPC size histogram. (#9626) 2026-03-03 14:53:30 +09:00
6def83a5d9 [doc] api doc changes (#9581)
* 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>
2026-03-02 16:22:39 -08:00
CandiedUniverse fc3d986d05 Release: version bump and changelog updates (#9640)
* Update changelog for release

* Version bump the package*.json files for release
2026-03-02 15:53:06 -08:00
Saoud Rizwanandcline-test 520ddb83bb fix(checkpoints): retry nested git restore and prevent silent .git_disabled leftovers (#9620)
* fix(checkpoints): harden nested git repo restore cleanup

* Fix checkpoint initialization to take less time

---------

Co-authored-by: cline-test <132302818+candieduniverse@users.noreply.github.com>
2026-03-02 12:22:01 -08:00
Ara d96c5d4b40 workflow: add default auto-tag flow for Publish Release (#9584)
* workflow: add auto-tag mode to publish release

* workflow: pin auto-tag release to tested commit sha

* workflow: clarify publish release input semantics

* workflow: constrain publish tag input to refs/tags
2026-03-02 11:38:48 -08:00
Br1an e6cbae0edc fix: prevent Chinese filename escaping in diff view (#9612)
* 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.
2026-03-02 10:35:48 -08:00
Saoud Rizwan 76bd0926e6 fix: trigger auto-compaction on OpenRouter context overflow errors (#9633)
* fix(context): detect wrapped OpenRouter 400 context errors

* fix(openrouter): preserve status for context overflow detection

* docs(context): clarify OpenRouter error-shape handling

* Revert "docs(context): clarify OpenRouter error-shape handling"

This reverts commit 9458d4472b.

* Revert "fix(openrouter): preserve status for context overflow detection"

This reverts commit a2c76d1693.

* Revert "fix(context): detect wrapped OpenRouter 400 context errors"

This reverts commit 3e8fb10b9e.

* Reapply "fix(context): detect wrapped OpenRouter 400 context errors"

This reverts commit 6df27d6853.

* Reapply "docs(context): clarify OpenRouter error-shape handling"

This reverts commit beb52e1429.

* fix(context): narrow OpenRouter status parsing fallback

* fix(context): align OpenRouter status parsing with agreed shape
2026-03-02 10:34:27 -08:00
Renee Huang 819f9ce00d show sdk docs in cline page (#9597) 2026-03-02 10:14:41 -08:00
Max fd8cecddd5 update cline sdk docs (#9532) 2026-02-27 11:28:48 -08:00
CandiedUniverseandSaoud Rizwan a502bd8653 WIP: Make hooks work on Windows PowerShell (#9552)
* 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>
2026-02-27 10:51:46 -08:00
Robin Newhouse d48d5ee74d fix: restore gpt-oss native file editing on OpenAI-compatible models (#9434)
* fix(core): enable gpt-oss native file editing

* test(evals): add gpt-oss openai-compat smoke coverage
2026-02-27 10:18:25 -08:00
Tomás Barreiro cd320ea01f Add User-Agent to requests to the Cline back-end (#9583) 2026-02-26 18:52:31 -08:00
CandiedUniverse 60485277c4 Version bump and changelog for release (#9577) 2026-02-26 15:57:14 -08:00
ClineXDiego 0a8f1ef248 fix: clear all OCA secrets on auth refresh failure to prevent re-auth loop (#9569)
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
2026-02-26 20:12:48 -03:00
ClineXDiego 4b2619daf7 fix: resolve "Could not find the file context" error in Explain Changes (#9449)
* 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
2026-02-26 20:12:37 -03:00
Ara 913cf4b74d feat: add dynamic Cline provider model fetching from Cline endpoint (#9102)
* 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.
2026-02-26 14:58:45 -08:00
Robin Newhouse 8e5be3f648 fix: use JSON_SCHEMA for yaml.load to prevent unsafe deserialization (#9500)
* 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
2026-02-26 14:48:58 -08:00
CandiedUniverse 6c519ff6e5 Increase timeout of flaky test; this is not the long term solution but it will be quick and easy today (#9568) 2026-02-26 12:45:18 -08:00
Robin NewhouseandCursor c61f9a9394 fix: fetch model info from API in CLI headless auth for Cline and Vercel providers (#9547)
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>
2026-02-26 12:42:34 -08:00
Raushan SinghandRaushan Singh fa53f301a4 fix: generate commit message from staged changes only when staging exists (#9529)
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>
2026-02-26 18:53:33 +01:00
Robin NewhouseandCursor c36e375af5 fix: update stale maxTokens values for Claude 3.7+ models across Anthropic, Bedrock, Vertex, and SAP AI Core (#9545)
* 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>
2026-02-26 09:44:25 -08:00
Robin NewhouseandCursor 94b02bf052 fix: use model.info.maxTokens for OpenRouter instead of hardcoded 8192 (#9544)
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>
2026-02-25 21:57:30 -08:00
shey-cline f10b6f39be Add Additional Markdown Formatting in CLI (#9392) 2026-02-24 14:43:53 -08:00
shey-cline 42e6a24d0f Add Focus Indicator on Action Buttons in Extension (#9487) 2026-02-24 14:43:16 -08:00
CandiedUniverseandMax Paulus 🥪 452733c3fd Release changeset PR (#9528)
* Update package.json and package-lock.json version numbers for patch release

* Patch fix changeset PR

* update cli package.json

* fixup! Patch fix changeset PR

---------

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-24 14:10:39 -08:00
7fadcfaa3f feat: add thinking to MiniMax M2.5 and add the M2.5-highspeed model to MiniMax provider (#9394)
* 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>
2026-02-24 22:24:41 +01:00
Tomás Barreiro 9989225b69 Parse CLINE_OTEL_EXPORTER_OTLP_HEADERS headers and force the build constant ones (#9534) 2026-02-24 22:07:55 +01:00
Ara 8a73f63189 feat: update recommended model from GPT-5.2 Codex to GPT-5.3 Codex (#9533)
- 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
2026-02-24 12:49:20 -08:00
Ara 31e8c85f0a Remove voice mode UI and disable dictation (#9511)
* remove voice mode UI and disable dictation flags

* remove legacy dictation settings path and dead voice recorder

* remove dictation feature stack and state/proto hooks
2026-02-24 12:26:15 -08:00
Bee 5b9916866d fix: remove placeholder tools from final native tool list (#9499)
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.
2026-02-24 12:07:55 -08:00
Tomás Barreiro f001e735f8 Add isLocatedInPath tests (#9526)
* Add isLocatedInPath tests

* Add another test case
2026-02-24 19:22:55 +01:00
Tomás Barreiro 32893ee343 Fix OpenAI Codex by setting Store to false (#9523) 2026-02-24 18:28:32 +01:00
Raushan SinghandRaushan Singh 0d4e47e5c3 fix: use isLocatedInPath() instead of string.includes() for path containment check (#9519)
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>
2026-02-24 18:23:29 +01:00
MaxandMax Paulus 🥪 c1a43482e7 sdk lib (#9259)
* 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>
2026-02-23 22:30:54 -08:00
Bee ea65383e16 chore: replace baseUrl with explicit relative paths in tsconfig files (#9508)
* 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
2026-02-23 18:00:09 -08:00
Ara b97d1487a7 Release V3.67.0 (#9509)
* 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
2026-02-23 17:25:30 -08:00
Robin Newhouse 091cf945e4 Move PR skill to .agents/skills (#9505)
* Move PR skill to .agents/skills and add changeset guidance

* Remove changeset guidance from PR skill
2026-02-23 16:31:32 -08:00
Bee df4f551ba7 feat: add support for skills and optional modelId in subagent config (ENG-1564) (#9502)
* 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
2026-02-23 16:23:36 -08:00
Ara 88da4ddf89 feat: fetch featured models from backend with local fallback (#9495)
* 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
2026-02-23 16:13:51 -08:00
CandiedUniverse 93eb607e6d Remove all traces of changeset-converter.yml GitHub Action and npm run changeset (#9506) 2026-02-23 15:53:56 -08:00
Tony LoehrandJuan Pablo Flores 810b5b78f5 added mcp enterprise configuration details (#9501)
Co-authored-by: Juan Pablo Flores <juan@cline.bot>
2026-02-23 15:51:05 -08:00
Tony Loehr 38ea422f6a Sso video (#9496)
* docs: add CVE scan sample to navigation, fix accordion labels, clarify --yolo flag

* added sso video

* Remove CVE scanner changes from SSO video PR
2026-02-23 15:29:48 -08:00
Robin Newhouse a7a35c0138 ci: add automatic retries for smoke test jobs (#9503) 2026-02-23 14:55:38 -08:00
Bee 01547ba1f4 feat: add AgentConfigLoader for file-based agent configs (ENG-1547) (#9245)
* refactor: centralize tool handler registration and filter by allowed tools

- Create centralized toolHandlersMap for all tool handler instantiation
- Add registerToolHandlers method to register only allowed tools from config
- Filter subagent tools to only include allowed tools from allowedTools config
- Remove scattered tool handler registration logic in favor of single source of truth
- Improve maintainability by consolidating tool handler creation in one place

This refactoring ensures subagents only have access to explicitly allowed tools
and makes the tool registration process more maintainable and consistent.

It also improves separation of concerns by having the coordinator manage all tool handler registration, while the executor focuses on orchestration. The allowedTools parameter enables runtime filtering of available tools for different contexts.

Also update PromptRegistry to load synchronous and simplify variant lookup

- Convert async load() to synchronous, called in constructor as both loadVariants and loadComponents are not async functions
- Remove health check logic and loaded state tracking
- Extract getVariant() method with proper generic fallback
- Add getComponents() accessor and simplify component loading
- Convert variant/component loaders from async to synchronous
- Remove unnecessary await calls throughout the codebase
- Add PromptRegistry tests for variant resolution and components

* fix test

* feat: add AgentConfigLoader for file-based agent configs

Add AgentConfigLoader singleton to manage agent configurations loaded from
YAML files in the agents directory. Supports hot-reloading via file watcher,
validates config schema with Zod, and integrates with extension lifecycle
(StateManager initialization and tearDown disposal).

* add tests

* add missing export

* update tests

* feat(tools): implement dynamic tool registration for subagents

Updates the tool system to support dynamically registered subagents as individual tools.

- Modifies `ClineToolSet` to generate specific tool definitions for configured subagents via `AgentConfigLoader`.
- Updates `parseAssistantMessageV2` to use `getToolUseNames()` instead of a static list, enabling the parser to recognize dynamic tool tags.
- Replaces the generic `USE_SUBAGENTS` tool with specific subagent instances when available in the system prompt context.

* update config path and refine tool descriptions

- Relocate the subagent configuration directory from `~/.cline/data/agents` to `~/Documents/Cline/Agents` to improve user accessibility.
- Update subagent tool descriptions and parameter instructions in the system prompt to be more descriptive and helpful for the model.

* revert unrelated changes

* revert unrelated changes

* update unit test

* fix: await AgentConfigLoader initialization before StateManager completes

Ensure agent configs are fully loaded during StateManager initialization
by awaiting the `ready()` promise. Previously, `AgentConfigLoader` was
instantiated without waiting for the initial load to complete, causing
potential race conditions where configs might not be available when
needed.

- Add `initialLoadPromise` field to track the async initial load
- Expose a `ready()` method to allow callers to await initialization
- Await `AgentConfigLoader.getInstance().ready()` in StateManager

* set previousRequestTotalTokens
2026-02-23 13:26:41 -08:00
Robin Newhouse 7f1632f09f fix: prevent reasoning delta crash on usage-only stream chunks (#9432)
* fix: guard missing delta in reasoning streams

* test: isolate litellm prompt cache call-count assertions
2026-02-23 12:29:34 -08:00
Han Wang 1b0ab3d01b sambanova provider: update models list (#9479)
* Add changeset

* Allow temperature config

* update issues summary

* Update SambaNova docs

* Update list of sambanova models

* Update minimax m2.5

* remove 2 models

* Remove residual
2026-02-23 11:27:36 -08:00
Chaitanya Eranki dce0902596 Oca Messages API implementation for new Claude Models (#9447)
* Made messages api changes

* Made changes

* Added changes

* Made maxTokens point to the right thing

* Removed deprecated max_tokens field

* Reverted the change

* Making an additional change to not cause any issues with chat completions

* reverting changes so we can make them in the backend

* Added changeset

* Fixed changes based on AI comments
2026-02-23 11:20:05 -08:00
Bee 9e7a30bd34 feat: preconnect websocket to reduce response latency (#9458)
Warm up the OpenAI WebSocket connection early in WebSocket mode to avoid handshake latency on the first response.create call. This introduces a responsesWsReadyPromise to track the connection state and prevent duplicate connection attempts while the initial connection is in flight.
2026-02-23 11:17:03 -08:00
Bee 2b1b1d1cf2 fix: restrict OpenAI tool ID transformation to native provider (#9459)
* fix: restrict OpenAI tool ID transformation to native provider

Update `convertToOpenAiMessages` and `transformToolCallId` to only apply tool ID transformations when the provider is explicitly set to `openai-native`. This prevents unintended ID modifications for other providers (like OpenRouter or local LLMs) that use the OpenAI format but may have different tool ID requirements or already provide compatible IDs.

* update tests

* transformToolCallIdForNativeApi
2026-02-23 11:16:55 -08:00
MaxandMax Paulus 🥪 fcf3792f63 fix auth check for acp mode (#9491)
- acp code wasn't using the proper 'isAuthConfigured' method for
checking auth status

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-23 09:41:56 -08:00
shey-clineandgreptile-apps[bot] 0e833ade82 Add /q command to quit CLI (#9400)
* init

* changeset

* Apply suggestion from @greptile-apps[bot]

oops

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* add tests

* add /q info to help panel

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-23 07:37:34 -08:00
Ara 4455db5198 Pull Cline's recommended from internal endpoint (#9376)
* feat(cline): fetch recommended models from API endpoint

* Adding 1m

* Adding 1m

* Adding 1m

* fix: harden model tag label handling and tab init

* fix(models): add retry-safe fetch, id canonicalization, and shared filtering

* chore: trigger PR head refresh

* refactor(models): remove canonical alias map for OpenRouter IDs

* refactor(webview): remove redundant cline fetch on mount

* Adding 1m
2026-02-22 22:28:55 -08:00
Bee 03ab2968a6 feat: responses api for openai native provider (#9411)
* fix: openai native provider token usage mapping

- Add `store` parameter support to OpenAI native provider options to allow persisting completions.
- Fix incorrect mapping of `cached_tokens` and `reasoning_tokens` in usage statistics.
- Include `thoughtsTokenCount` in the final usage report to track reasoning model performance and costs.

* feat: add websocket support for OpenAI Responses API

This commit introduces WebSocket support for the OpenAI Native provider's Responses API, providing an alternative to the standard HTTP streaming.

- Implement `createResponseStreamWebsocket` in `OpenAiNativeHandler` with a fallback to HTTP on failure.
- Refactor `OpenAiNativeHandler` to modularize tool mapping and parameter construction for the Responses API.
- Update `OcaHandler` to explicitly disable `previousResponseId` when using the Responses API and add validation for model information.
- Integrate `undici` WebSocket for better compatibility in the extension environment.

* disablePreviousResponseId

* feat: add timestamp to conversation messages for response chaining

Add `ts` field to `ClineStorageMessage` to track when messages were
created. Use this timestamp to enforce a 23-hour validity window when
chaining OpenAI responses via `previousResponseId`, since the API only
retains responses for 24 hours. Also fix non-null assertion operators
in tests to use optional chaining for safer access.

* add OpenAI Responses Websocket Mode ApiFormat support

- Add `OPENAI_RESPONSES_WEBSOCKET_MODE` to the `ApiFormat` enum in proto definitions.
- Update `OpenAiNativeHandler` to use the new API format for determining when to use websocket mode, replacing previous environment-based logic.
- Refactor tool mapping for OpenAI Responses to support strict mode and correctly handle null parameters.
- Ensure the `store` option is disabled when `previous_response_id` is present in websocket mode.
- Bump version to 2.4.1 and update package dependencies.

* use abortController

* add support for websocket mode to openai-codex

* set behind feature flag
2026-02-20 17:17:54 -08:00
MaxandMax Paulus 🥪 a0d52d4d59 cli yolo mode should not persist yolo setting to disk ever (#9370)
- added a method to StateManager, setSessionOverride, which overrides
state settings while the statemanager lives in memory

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-20 11:16:29 -08:00
MaxandMax Paulus 🥪 75fbeb4aad fix cline auth with acp flag (#9405)
- was missing a check for "cline:clineAccountId" in the isAuthed method
of acp agent

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-20 11:15:45 -08:00
Bee 70db6bde34 fix: inline focus-chain slider within its feature row (#9444)
* fix: inline focus-chain slider within its feature row

Moves the focus-chain reminder interval `SettingsSlider` from a
standalone element rendered after all experimental feature rows to
being rendered directly beneath the focus-chain `FeatureRow`. The
slider now renders conditionally when `feature.id === "focus-chain"`
and the feature is enabled, improving UI cohesion and making the
relationship between the toggle and its configuration more explicit.

Additionally:
- Relocates focus-chain from `experimentalFeatures` to `agentFeatures`
- Removes the `isExperimental` prop and "Experimental:" label badge
  from `FeatureRow` and related feature toggle definitions
- Simplifies `SettingsSlider` markup by removing the wrapper card
  styling, making it suitable for inline embedding
  - Removes unused line from common.ts

* nestedKey
2026-02-20 10:58:46 -08:00
Saoud Rizwan 02c2601e0e fix(gemini): add 3.1 pro while keeping 3.0 compatibility (#9438) 2026-02-20 09:18:40 -08:00
Juan Pablo Flores 94692b5091 docs: add MCP support documentation for Cline CLI (#9390) 2026-02-20 09:39:02 -06:00
Robin Newhouse a2794c680f fix(evals): restore missing smoke eval npm scripts (#9429) 2026-02-19 14:49:27 -08:00
CandiedUniverse 6d3f8e1d5d fix(release-eng): Pin VSCode nightly build to node version 22 (#9423)
* fix(release-eng): Pin VSCode nightlybuild to node version 22

* fix(release-eng): Pin publish.yml GitHub workflow to node version 22
2026-02-19 12:04:14 -08:00
cryptoque 3e5847890b feat: add dynamic flag to adjust banner cache duration (#9421) 2026-02-19 11:03:50 -08:00
CandiedUniverse 0eab54ab12 fix(release-eng): Fix nightly extension publish failure caused by workspace self-link mismatch (#9420) 2026-02-19 10:40:45 -08:00
7fa0a4924b Changeset version bump (#9413)
* changeset version bump

* Updating CHANGELOG.md format

* Adding 1m

* Adding 1m

* Adding 1m

* Adding 1m

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
2026-02-19 10:36:21 -08:00
Junjie Tang 8680218e0e Update sap-ai-sdk version (#9417) 2026-02-19 06:46:09 -08:00
Dominic Cooney 8787ab35b9 Update package-lock.json. (#9414) 2026-02-18 22:56:49 -08:00
Dominic Cooney 6ed3944f04 Export global, workspace and secrets from VSCode to share with CLI (#9227)
Caveat: Task history, tasks, etc. are not written to the same place by all clients yet. This is just about globalState, workspaceState and secrets.
2026-02-19 15:46:23 +09:00
Bee 1dd8e763d1 fix(chat): make Cmd/Ctrl+A select-all deterministic (#9408)
Handle plain Cmd/Ctrl+A directly in `ChatTextArea` keydown to force
textarea-wide selection via `setSelectionRange`, while preventing default
and propagation. This avoids intermittent failures caused by global shortcut
listener races, and keeps Cmd/Ctrl+Shift+A behavior unchanged.fix(chat): make Cmd/Ctrl+A select-all deterministic

Handle plain Cmd/Ctrl+A directly in `ChatTextArea` keydown to force
textarea-wide selection via `setSelectionRange`, while preventing default
and propagation. This avoids intermittent failures caused by global shortcut
listener races, and keeps Cmd/Ctrl+Shift+A behavior unchanged.
2026-02-18 20:55:57 -08:00
Bee 28e6297769 fix: flaky Cancel behavior by preventing duplicate cancel actions (CLINE-1380) (#9409)
* fix: flaky Cancel behavior by preventing duplicate cancel actions

This PR fixes chat cancel behavior where users sometimes had to click Cancel multiple times, and repeated clicks could accidentally transition into Resume/restart behavior.

* move to finally
2026-02-18 20:55:41 -08:00
Bee 5a2a5d1c0a refactor: replace non-null assertions with checks in PatchParser (#9402)
* refactor: replace non-null assertions with safe null checks in PatchParser

Replace all forbidden non-null assertions (`!`) in PatchParser.ts with
safe alternatives using optional chaining (`?.`) and nullish coalescing
(`?? ""`/`?? 0`). Also refactor the Levenshtein distance matrix from a
2D array to a flat array to eliminate index-based non-null assertions,
improving type safety and code robustness.

No feature behavior changes.

* simplify Levenshtein matrix indexing

Initialize the distance matrix with zeroes and add `at`/`set` helpers for flat-array access in `levenshteinDistance`.

This removes repeated index math and nullish fallbacks, making the algorithm easier to read while keeping bounds-safe access and identical behavior.refactor(patch-parser): simplify Levenshtein matrix indexing

Initialize the distance matrix with zeroes and add `at`/`set` helpers for flat-array access in `levenshteinDistance`.

This removes repeated index math and nullish fallbacks, making the algorithm easier to read while keeping bounds-safe access and identical behavior.
2026-02-18 19:35:48 -08:00
Max 113039a259 CLI 2.0: allow custom inference profile arn for bedrock provider (#9271) 2026-02-18 19:16:32 -08:00
Max 4023c18257 remove default timeout (#9401) 2026-02-18 17:28:50 -08:00
cryptoque 7c95b53892 Add support for DB backed Welcome Banner (#9315)
* feat: add welcome banner support from backend

* make DB banner format conform with existing banners

* add support for welcome banner actions

* remove debugging helper that bypass dismissal, dismissal should work again

* undo changes to make welcome banner always appear during debugging

* remove console logs for debugging

* clean up bannerservice

* clean up welcomesection.tsx

* add new tests for ide type filtering

* add welcome banner own feature flag and conditionally display between hard coded welcome banner and DB backed ones

* turn on welcome banner flag locally by default

* close welcome banners when clicking on actions

* apply bot review suggestion, fix memory leak

* address feedback: use p without span

* split welcome banners into a seperate component to keep whatsnewmodal clean

* get action through api schema instead of extractin it from rules_json

* use only bannerWaitTimeoutRef, remove waitingForBannersRef

* resolve new merge conflict

* linter

* cerebra
2026-02-18 14:52:02 -08:00
Bee 9fd2b99be4 chore: remove autoCondenseThreshold setting and related code (#9396)
- Remove `auto_condense_threshold` from `Settings` and `UpdateSettingsRequest` in `state.proto`.
- Remove `autoCondenseThreshold` from `ApiProviderInfo` interface.
- Update `generate-state-proto.mjs` to remove double field handling and improve integer parsing.
- Add error handling to `ContextManager` when parsing previous request JSON to prevent crashes on malformed data.
2026-02-18 12:43:30 -08:00
7c782abaf4 Changeset version bump (#9364)
* changeset version bump

* Updating CHANGELOG.md format

* update package versions

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-18 12:22:53 -08:00
Ara 3a14a88f4f fix: include root workspace for changesets release (#9393) 2026-02-18 11:40:02 -08:00
Saoud Rizwan 28d60a83a4 fix(models): keep Sonnet 4.5 as default for now (#9389)
* fix(models): keep Sonnet 4.5 as default

* chore(changeset): add release note for Sonnet 4.5 default

* fix(models): remove Sonnet 4.6 from curated model lists

* fix(models): restore Sonnet 4.6 in web recommended list
2026-02-18 10:53:07 -08:00
Saoud Rizwan ae6468b161 fix(models): reinstate minimax m2.5 free promo surfaces (#9387) 2026-02-18 10:28:54 -08:00
Saoud Rizwan af93e31862 feat(models): make sonnet 4.6 default and remove free promo positioning (#9377) 2026-02-18 10:07:20 -08:00
Tomás Barreiro ca154eb8f5 Add MiniMax M2.5 to the MiniMax provider (#9381)
* Add MiniMax M2.5 to the MiniMax provider

* Add changeset

* Update default model
2026-02-18 09:16:23 -08:00
Tomás Barreiro 1d8497c6bf Prevent error messages when displaying featured models in the CLI (#9379)
* Fix the featured models key

* Add changeset
2026-02-18 16:51:29 +01:00
Seb Duerr 5871fd02b1 feat(cerebras): remove deprecated llama-3.3-70b and qwen-3-32b models (#9345)
* feat(cerebras): remove deprecated llama-3.3-70b and qwen-3-32b models

These models have been deprecated from the Cerebras inference platform.

- Remove llama-3.3-70b and qwen-3-32b from cerebrasModels in api.ts
- Update supported models documentation in cerebras.mdx
- Add changeset for the deprecation

* fix: remove stale llama-3.3-70b and qwen-3-32b references from rate limits

Remove dead switch cases in getRateLimits() that referenced deprecated models
no longer present in cerebrasModels.
2026-02-17 23:39:38 -08:00
alex-lum 2d81c310d2 Alex/inf 413 bug no telemetry for versions greater than 20 (#9372) 2026-02-17 18:55:07 -08:00
Robin NewhouseandCursor 0c691f72d2 feat(cli): add /skills slash command (#9089)
* feat(cli): add /skills slash command for managing skills

- Add /skills to CLI_ONLY_COMMANDS in slashCommands.ts
- Create SkillsPanelContent component with:
  - Display global and workspace skills with toggle indicators
  - Enter to use skill (inserts @path into input)
  - Space to toggle skill enabled/disabled
  - Selectable marketplace link to skills.sh
  - Keyboard navigation with arrow keys and vim keys
- Wire up panel in ChatView.tsx
- Add comprehensive tests for keyboard interactions

* refactor(cli): use static skill controller imports

* fix(cli): add React import to skills panel test

* fix(cli): suppress required React import lint in skills test

* fix(cli): harden /skills panel interactions

Revert optimistic skill toggle state when persistence fails, and surface a fallback URL when opening the marketplace fails. Also tighten and extend tests to verify exact marketplace URL handling and rollback behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 17:13:51 -08:00
Robin NewhouseandCursor a8409137b3 fix: disable click-to-set auto-condense threshold and hardcode default (#9348)
* fix: disable click-to-set auto-condense threshold and hardcode default

Clicking anywhere on the context window progress bar silently set
autoCondenseThreshold to a value based on click position (e.g. 0.05),
persisting in globalState. This caused compaction to fire at ~10K tokens
instead of the intended ~150K, resulting in ~20 context resets per task.

- Comment out click and keyboard handlers on progress bar (keep components
  for future release with proper UX)
- Hardcode threshold to 0.75 default, ignoring corrupted stored values

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: add shouldCompactContextWindow unit tests

Cover threshold math including the accidental low-threshold bug case,
undefined/zero fallbacks, cache token inclusion, and maxAllowedSize cap.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: hardcode autoCondenseThreshold in all remaining callsites

Address Greptile review: SubagentRunner.ts, task/index.ts display
logic, and controller/index.ts webview state all still read the
corrupted value from globalState. Hardcode 0.75 everywhere.

Co-authored-by: Cursor <cursoragent@cursor.com>

* style: remove unnecessary union type on hardcoded threshold

Drop `number | undefined` annotation from the hardcoded 0.75 literal
in SubagentRunner.ts per Greptile review feedback.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: use SETTINGS_DEFAULTS constant, remove commented-out code, clarify test

- Replace hardcoded 0.75 with SETTINGS_DEFAULTS.autoCondenseThreshold
  across all 4 callsites for a single source of truth
- Delete commented-out click/keyboard handlers in ContextWindow.tsx,
  replace with TODO referencing PR #9348
- Make bug-case test self-documenting by deriving token values from
  the threshold calculation

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 16:32:13 -08:00
Saoud Rizwan 34a21b8e26 docs: add security policy (#9365) 2026-02-17 16:00:01 -08:00
eb9f53edf4 fix: smarter retry for write_to_file missing content parameter (#9276)
* fix: smarter retry for write_to_file missing content parameter (#7998)

Replace generic 'missing parameter' error with progressive guidance when
write_to_file fails due to empty content parameter. This breaks the
infinite retry loop where the model repeatedly attempts the same
write_to_file call that exceeds output token limits.

Changes:
- Add writeToFileMissingContentError() to formatResponse with 3 tiers:
  1st failure: suggestions (use skeleton + replace_in_file)
  2nd failure: strong directive (stop retrying write_to_file)
  3rd+ failure: CRITICAL stop, forces alternative strategies
- Add context window awareness: warns model when >50% context used
- Add getContextUsagePercent() helper to WriteToFileToolHandler
- Add 22 unit tests covering progressive escalation and context awareness

Fixes #7998

* add changeset for write_to_file retry fix

* refactor: simplify write_to_file error handling per review

- Simplify writeToFileMissingContentError to single-tier error following
  existing diffError pattern (no progressive escalation)
- Use shared getLastApiReqTotalTokens() for context window awareness
- Remove private getContextUsagePercent() method from handler
- Add proactive skeleton + replace_in_file guidance to write_to_file
  tool description for all variants
- Simplify tests to match new API (11 tests)

* test: update system prompt snapshots

* chore: revert write_to_file prompt guidance

* feat: restore progressive 3-tier guidance for write_to_file missing content

Restore the progressive escalation that was removed in dd3c12d4e:
- Tier 1 (1st failure): Gentle suggestions (skeleton + replace_in_file)
- Tier 2 (2nd failure): Strong directive, 'Do NOT attempt full write again'
- Tier 3 (3rd+ failure): CRITICAL stop, forces alternative strategies
- Context window warning when >50% full
- Dynamic UI message: 'Retrying...' vs 'multiple times — different approach'
- 21 tests covering all tiers and context awareness

* nit: extract context window warning threshold to named constant

Also replace emoji with plain text in warning message for consistency.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Robin Newhouse <robin@cline.bot>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 19:08:42 -03:00
github-actions[bot]andArafatkatze c60f18d907 Adding 1m (#9346)
Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
2026-02-17 11:11:54 -08:00
Saoud Rizwan 36c68a6ab9 fix: remove expired MiniMax free promo surfaces (#9361)
* fix: remove expired MiniMax free promo surfaces

* fix: remove MiniMax M2.5 from recommended models

* chore: update GLM 5 whats-new promo wording
2026-02-17 10:57:19 -08:00
Saoud Rizwan 80dfce0f60 docs: remove stale Claude 5 mention from Auto Compact docs (#9360)
* docs: remove stale Claude 5 wording from auto compact docs

* Remove stale Claude 5 mention from docs
2026-02-17 10:48:23 -08:00
Saoud Rizwan 955ae2f62f feat: add Claude Sonnet 4.6 support and surface it as free (#9356)
* feat: add Sonnet 5 support and make it default across surfaces

* feat: surface Sonnet 5 as free while keeping Sonnet 4.5 defaults

* fix: rename Sonnet 5 support to Sonnet 4.6 across providers and UI

* fix: allow duplicate onboarding model ids across free and frontier

* chore: update Sonnet 4.6 banner to limited-time free messaging

* fix: align Bedrock Sonnet 4.6 model ids with AWS format

* feat: update whats new promo to Sonnet 4.6 free offer

* chore: update Sonnet 4.6 promo copy and timing
2026-02-17 10:43:24 -08:00
Dominic Cooney 8cb0c6d236 Fix e2e tests. (#9350) 2026-02-17 15:06:40 +09:00
github-actions[bot] bb05b2f7b0 changeset version bump (#9316)
Updating CHANGELOG.md format

update changelog

update banner and bump version

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-16 12:46:01 -08:00
alex-lumandTomás Barreiro 1a911f4232 fix(telemetry): refresh OTEL org attributes on identify (#9318)
* fix(telemetry): refresh OTEL user/org attributes on every identify

* fix(telemetry): refresh OTEL user/org attributes on every identify

* test(telemetry): cover OTEL identifyUser org refresh scenarios

* refactor(telemetry): rename member_roles to member_role (singular)

* Apply suggestion from @BarreiroT

simpler commenting

Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>

* removing verbose comments

/**
 * Helper to build a ClineAccountUserInfo with an active organization.
 */

* removing verbose comments

* removing unnecessary logger

* assert -> chai expect

---------

Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>
2026-02-16 12:45:31 -08:00
Ara 1cfd560921 feat(cline): add z-ai/glm-5 to free model recommendations (#9341)
* feat: add z-ai/glm-5 to free models list

Include Z.AI's GLM 5 in the free model whitelist for zero-cost usage
and update the model picker UI to display the free label.

* Adding thinking

* Adding thinking

* Adding thinking
2026-02-16 11:59:09 -08:00
Juan Pablo Flores 203ff8f549 docs: enrich Quick Start guide with more context for new users (#9338)
* docs: enrich Quick Start guide with more context for new users

* docs: add Antigravity to full installation guide
2026-02-16 09:00:50 -08:00
Saoud Rizwan e920f1de02 fix(chat): keep reasoning visible before low-stakes tool groups (#9335)
* fix(chat): keep reasoning visible before low-stakes tool groups

* chore(changeset): add patch note for tool-group reasoning visibility

* fix(chat): keep thinking loader visibility aligned with waiting states

* fix(chat): avoid clipping descenders in thinking label
2026-02-15 17:14:41 -08:00
Saoud Rizwan b266475d0a fix(chat): prevent partial row churn during native tool arg streaming (#9334)
* fix(chat): prevent partial text flicker during native tool streaming

* fix(chat): revert act mode partial dedupe change
2026-02-15 15:40:54 -08:00
Saoud Rizwan 402361c482 fix(chat): restore reasoning traces and polish thinking UX (#9330)
* fix(chat): restore reasoning traces and polish thinking UX

* chore(changeset): add patch note for reasoning trace UX fixes
2026-02-15 01:19:59 -08:00
Renee HuangandJuan Pablo Flores e884699d24 New Cline Docs (#9280)
* only doc changes

* merge

* fix installtion page redirects

* fix redirect, remove unused parts

* rm irrelevant info

* clean up terminal guides

* docs: add home page and reorganize navigation

* chore: remove 71 unused docs files not referenced in navigation

Remove .mdx files that are no longer referenced in docs.json navigation
and only existed as stale content from previous documentation restructuring.
These files were either completely orphaned or only served as redirect
source pages (Mintlify handles redirects at the routing level without
needing the source file to exist).

Updated docs.json redirects that previously pointed to archive/ pages
to point to current equivalents instead:
  - /archive/understanding-context-management → /model-config/context-windows
  - /archive/prompt-engineering-guide → /customization/cline-rules
  - /archive/telemetry → /enterprise-solutions/monitoring/telemetry

Deleted files by category:

Archive (entire directory removed):
  - archive/prompt-engineering-guide.mdx
  - archive/telemetry.mdx
  - archive/understanding-context-management.mdx

Cline CLI:
  - cline-cli/cli-reference-deprecated.mdx

Enterprise Solutions (16 files):
  - enterprise-solutions/bundled-endpoints.mdx
  - enterprise-solutions/configuration/overview.mdx
  - enterprise-solutions/configuration/choosing-your-deployment.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/overview.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/rules.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/workflows.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/control-other-cline-features/overview.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/mcp/overview.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/mcp/mcp-marketplace.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/mcp/remote-mcp-servers.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/providers/overview.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/providers/custom.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/providers/aws-bedrock/overview.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/providers/google-vertex/overview.mdx
  - enterprise-solutions/configuration/infrastructure-configuration/providers/litellm/overview.mdx
  - enterprise-solutions/monitoring/opentelemetry_override.mdx

Exploring Cline's Tools (entire directory removed):
  - exploring-clines-tools/cline-tools-guide.mdx
  - exploring-clines-tools/new-task-tool.mdx
  - exploring-clines-tools/remote-browser-support.mdx

Features — old pages consolidated into core-workflows/ and customization/ (37 files):
  - features/checkpoints.mdx
  - features/drag-and-drop.mdx
  - features/editing-messages.mdx
  - features/explain-changes.mdx
  - features/skills.mdx
  - features/yolo-mode.mdx
  - features/at-mentions/ (7 files — all consolidated into core-workflows/working-with-files)
  - features/cline-rules/ (2 files — consolidated into customization/cline-rules)
  - features/commands-and-shortcuts/ (5 files — consolidated into core-workflows/using-commands)
  - features/customization/ (2 files)
  - features/hooks/ (3 files — consolidated into customization/hooks)
  - features/slash-commands/ (7 files)
  - features/slash-commands/workflows/ (3 files — consolidated into customization/workflows)
  - features/tasks/ (2 files — consolidated into core-workflows/task-management)

Introduction (entire directory removed):
  - introduction/overview.mdx
  - introduction/welcome.mdx

MCP:
  - mcp/adding-mcp-servers-from-github.mdx
  - mcp/configuring-mcp-servers.mdx

More Info (entire directory removed):
  - more-info/telemetry.mdx

Prompting (entire directory removed):
  - prompting/cline-memory-bank.mdx
  - prompting/prompt-engineering-guide.mdx
  - prompting/understanding-context-management.mdx

Provider Config:
  - provider-config/fireworks-ai.mdx
  - provider-config/ollama.mdx

Getting Started:
  - getting-started/selecting-your-model.mdx

Total: 71 files deleted, 12,344 lines removed.

* docs: update and add documentation pages

* revert unintended formatting changes to src files

* new first project docs

---------

Co-authored-by: Juan Pablo Flores <juan@cline.bot>
2026-02-14 22:02:22 -08:00
Saoud Rizwan f59d950ac6 fix: open Cline sidebar for task deeplinks (#9320)
* fix: open Cline sidebar for task deeplinks

* refactor: share task URI path constant
2026-02-14 01:15:13 -08:00
Ara d2e4f1c7b9 feat(zai): add glm-5 pricing and make it default (#9253) 2026-02-13 20:42:49 -08:00
AraandCopilot 49975fd0a3 feat(cli): support Moonshot provider across CLI flows (#9314)
* feat(cli): add moonshot provider support across CLI flows

* Update cli/man/cline.1

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 16:10:10 -08:00
shey-cline c0020e10b1 Allow Custom AWS Regions in Bedrock (CLI) (#9103)
* init

* changeset

* prevent regoinIndex = -1 when navigating with arrow keys while filteredRegions.length = 0

* refactor

* content fix
2026-02-13 15:46:36 -08:00
Ara 8dc5e15ee0 chore: bump version to 3.62.0 (#9313) 2026-02-13 15:13:36 -08:00
github-actions[bot]andgithub-actions 276cb4c3a4 Changeset version bump (#9312)
* changeset version bump

* v3.62.0 Release Notes

- Banners now display immediately when opening the extension instead of requiring user interaction first
- Resolved 17 security vulnerabilities including high-severity DoS issues in dependencies (body-parser, axios, qs, tar, and others)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-02-13 14:24:54 -08:00
Saoud Rizwan 8169abbc74 fix(e2e): stabilize banner and code action assertions (#9311) 2026-02-13 14:11:55 -08:00
Ara a47ad46824 fix: rename package from "claude-dev" to "cline" in changesets (#9309)
Update changeset metadata files to use the correct package name
"cline" instead of the legacy "claude-dev" identifier.
2026-02-13 14:08:57 -08:00
Saoud Rizwan 7896e6d896 feat: promote MiniMax M2.5 in top banner and route CTA to free tab (#9307)
* feat: add minimax promo banner and free-tab model routing

* Add changeset for promoting MiniMax M2.5
2026-02-13 13:20:22 -08:00
aikido-autofix[bot] 166ec38d26 fix(security): update dependencies (#9234)
Co-authored-by: aikido-autofix[bot] <119856028+aikido-autofix[bot]@users.noreply.github.com>
2026-02-13 12:42:06 -08:00
Tomás Barreiro e44ea9d772 Post state to webview after fetching the banners (#9306)
* Post state to webview after fetching

* Test post state to webview is called

* refactors
2026-02-13 21:18:32 +01:00
Ara fcca1d4fe3 v3.61.0 Release Notes (#9305) 2026-02-13 10:35:16 -08:00
github-actions[bot] 34f0795217 v3.60.0 Release Notes (#9274)
- Fixes for Minimax model family
- Fixes for Response chaining for OpenAI's Responses API

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-13 09:02:46 -08:00
Bee 0648ed42b2 feat: make response ID chaining configurable (#9285)
Add an optional `usePreviousResponseId` flag to
`convertToOpenAIResponsesInput` and gate previous assistant-response
lookup behind it.

This makes response chaining opt-in instead of always-on, so providers
can control whether to continue from the latest stored OpenAI response
ID.feat(openai): make response ID chaining configurable

Add an optional `usePreviousResponseId` flag to
`convertToOpenAIResponsesInput` and gate previous assistant-response
lookup behind it.

This makes response chaining opt-in instead of always-on, so providers
can control whether to continue from the latest stored OpenAI response
ID.
2026-02-13 08:40:02 -08:00
Saoud Rizwan f32dde2c16 chore: update codex environment config 2026-02-13 04:17:07 -08:00
Saoud Rizwan 605c497eaf chore: update codex environment config 2026-02-13 04:14:22 -08:00
Saoud Rizwan a8322eec44 fix(task): avoid duplicate partial text from reentrant presentation (#9302) 2026-02-13 03:47:56 -08:00
Saoud Rizwan 974a7a748a fix(webview): add spacing before ask followup options 2026-02-13 02:31:14 -08:00
Saoud Rizwan fb2d092301 fix(hooks): preserve streaming tool rows in combineHookSequences (#9301) 2026-02-13 02:10:27 -08:00
Saoud Rizwan 45b3eb4833 fix(chat): stabilize tool-group text and thinking footer behavior (#9300)
* fix(chat): ignore streamed text after tool group starts

* fix(chat): suppress thinking during ask and completion handoff

* fix(chat): prevent thinking footer shimmer remount flicker
2026-02-13 02:03:32 -08:00
Bee a5048189e5 fix: remove focused BannerService test to run full suite (#9299)
The unit test suite currenlt is running the BannerService tests only when it should run the full suite.
Also update package-lock.json that wentout of sync.
2026-02-13 01:08:30 -08:00
Saoud Rizwan 897e842eb4 fix(task): ignore interleaved reasoning UI after text starts (#9298) 2026-02-13 00:25:08 -08:00
Saoud Rizwan 0389d4de07 Revert "fix(task): prevent duplicate streamed text rows after completion (#9235)" (#9297)
This reverts commit b514f18e4f.
2026-02-13 00:20:33 -08:00
Saoud Rizwan d99eec15d8 fix(minimax): emit single reasoning chunk on thinking start (#9290) 2026-02-12 23:46:53 -08:00
Ara 98ed009e69 fix: add missing name fields to free featured models and improve type safety (#9291)
- Add `name` property to minimax, kat-coder-pro, and trinity-large-preview
  models that were previously missing it
- Move type annotation from `as FeaturedModel[]` casts to the variable
  declaration for proper type checking at assignment time
- Add test to verify all featured models include a display name
2026-02-12 23:18:51 -08:00
Saoud Rizwan 8fb7b94297 Revert "Jose/thinking and flicker fix (#9148)" (#9292)
This reverts commit d8397c71b2.
2026-02-12 22:54:07 -08:00
Jose R. Perezandcline-test d8397c71b2 Jose/thinking and flicker fix (#9148)
* feat: persistant thinking loader at bottom of stream during any cline activity with no visual feedback

* feat: thinking and flicker fix

* refactor: remove multi-layer throttling, use single canonical throttle point

Collapse 4 independent throttle layers (up to ~500ms added latency) into
a single 50ms debounce in subscribeToPartialMessage. Replace index-based
partial message tracking with stable ts-based tracking. Remove webview
queue/timer/flush system in favor of cheap equality dedup.

* fix: Add production-grade improvements to flicker fix

- Fix global mutable state bug in subscribeToPartialMessage.ts
- Add comprehensive test coverage (51 tests passing)
- Rename ThrottledApiHandler → SanitizedApiHandler
- Remove incomplete OpenAI reasoning effort code

* Fix test failures

* PR changes as per Greptile feedback

* Fixes as per feedback during PR review

---------

Co-authored-by: cline-test <132302818+candieduniverse@users.noreply.github.com>
2026-02-12 22:28:46 -08:00
3899469d76 feat(evals): comprehensive LLM evaluation framework with CI (#8909)
* chore(evals): reorganize eval structure with purpose-based naming

- Move evals/diff-edits/ → evals/benchmarks/tool-precision/replace-in-file/
- Move evals/cli/ → evals/legacy/cli/ (preserve for reference)
- Create evals/benchmarks/real-world/ directory
- Create evals/benchmarks/coding-exercises/cases/ directory
- Create evals/analysis/ directory structure

Note: No repositories/exercism/ directory found to move.
Skipping pre-commit hook as this is a reorganization of legacy code.

* chore(evals): remove legacy evaluation code

Remove abandoned evaluation infrastructure:
- evals/benchmarks/tool-precision/ - Dashboard, database, diff implementations
- evals/legacy/cli/ - Old HTTP-based eval harness

This functionality is superseded by the new testing pyramid:
- Tool precision is now covered by contract tests in src/core/
- E2E testing uses the cline-bench framework

* feat(evals): add analysis framework for benchmark results

Add shared infrastructure for analyzing evaluation results:
- TypeScript schemas for Harbor and analysis output formats
- Parsers for Harbor, tool-precision, and exercise results
- Failure classifier with pattern matching (cline-failures.yaml)
- Metrics calculator (pass@k, consistency, latency)
- JSON and Markdown reporters
- CLI with analyze and compare commands
- Unit tests for classifier and metrics

This framework is used by both smoke tests and E2E evaluations
to provide consistent metrics and failure categorization.

* feat(evals): add contract tests for API transforms

Add tests to verify API response transformations preserve data correctly:
- thinking-traces.test.ts: Tests thinking block extraction and formatting
- tool-parsing.test.ts: Tests tool call parsing across providers

These contract tests catch regressions when modifying transform logic,
ensuring API responses are correctly processed regardless of provider.
Run with: npm run test:unit

* feat(evals): add provider smoke tests with pass@k metrics

Add lightweight smoke tests that validate provider integrations work
correctly with real LLM calls:

Scenarios (5 curated tests):
- 01-create-file: Tests write_to_file tool
- 02-edit-file: Tests replace_in_file tool
- 03-read-summarize: Tests read_file tool
- 04-multi-file: Tests multi-file edits
- 05-typescript-function: Tests code generation

Features:
- CLI-based runner using the cline CLI
- Multiple trials per scenario for reliability testing
- pass@k metrics (solution finding) and pass^k (consistency)
- Results storage with logs and latest symlink
- Adaptive metric display based on trial count

Run locally: npm run eval:smoke

* feat(evals): add E2E runner with cline-bench

Add end-to-end testing infrastructure using real-world production bugs:

- cline-bench submodule: 12 curated tasks from actual Cline sessions
  - Complex multi-file refactors
  - Bug fixes requiring deep context understanding
  - Cross-language/framework tasks

- E2E runner (evals/e2e/run-cline-bench.ts):
  - Integrates with Harbor for containerized execution
  - Supports single task or full suite runs
  - Pass/fail metrics with detailed logging

Run: npm run eval:e2e -- --task discord-trivia

Note: E2E tests require Docker and are intended for weekly/release
testing, not per-commit CI (each task takes 20-30 minutes).

* feat(evals): add CI workflow and documentation

CI Workflow (.github/workflows/cline-evals-regression.yml):
- Triggers on push/PR to main (src/core, src/shared, proto, evals paths)
- Builds CLI from source with Go 1.24
- Runs 5 smoke test scenarios in parallel
- Uses Anthropic API with claude-sonnet-4
- Uploads results as artifacts with summary

npm scripts:
- eval:smoke - Run smoke tests locally (builds CLI first)
- eval:smoke:run - Run smoke tests (assumes CLI is built)
- eval:e2e - Run cline-bench E2E tests

Documentation:
- ARCHITECTURE.md: Testing pyramid overview with ASCII diagrams
- EVALS_OVERVIEW.md: High-level introduction for mixed audience
- Updated README.md with current structure and usage

* chore(evals): restore tool-precision as deprecated legacy

Restore the diff edit evaluation framework for @ara's use case.
Marked as DEPRECATED - target removal Q2 2026 when cline-bench
is fully operational for model comparison.

Note: Skipping linter as this is legacy code being preserved as-is.

* feat(evals): add per-scenario model support and apply_patch test

Also honor --model overrides and prune stubs.

* chore(evals): update smoke tests for CLI 2.0

- Remove Go setup from workflow (CLI 2.0 is TypeScript)
- Build CLI via `npm run build` in cli/ directory
- Install CLI via `npm link` to test built code from PR
- Update CLI flags: -y -m model --json (remove -o and -s)
- Provider configured via `cline auth` before tests run

* chore(evals): add auth check and CLI 2.0 flags

- Add configureAuth() that runs cline auth non-interactively
- Require CLINE_API_KEY env var or use existing ~/.cline auth
- Add --config flag to use shared config directory
- Add -t timeout flag to CLI args
- Reduce scenario timeout to 30s for faster iteration
- Remove --json flag (CLI doesn't output errors in json mode)

* feat(evals): add parallel execution and move workspaces to results

- Add --parallel flag to run scenarios concurrently (default limit: 4)
- Move trial workspaces from scenarios/ to results/ directory
- Workspaces now cleaned up with `npm run eval:smoke:clean`
- Keeps scenarios/ clean and version-controllable

* ci: add smoke tests workflow with parallel execution

- Single job runs all 7 scenarios in parallel using test runner's --parallel flag
- Builds CLI in-job (no artifact passing needed)
- Outputs summary.md to GitHub step summary
- Syncs package-lock.json for tiktoken/commander deps

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(evals): increase 01-create-file timeout to 120s

The 30s timeout was too short for reliable execution.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: restore changesets deleted during rebase

These changesets belong to the already-merged CLI fix (#9073)
and should not be deleted by this branch.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(evals): remove unused dependencies from package.json

Drop execa, node-fetch, ora, sqlite, uuid, yargs and their types.
These were leftovers from the old CLI-based eval runner. The smoke
tests use Node builtins and the tool-precision benchmark only needs
axios, better-sqlite3, chalk, commander, dotenv, tiktoken.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add TypeScript build info files to .gitignore

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-02-12 22:23:35 -06:00
Robin Newhouse e85332319e feat: add .agents/skills directory support for skill discovery (#9074)
* feat: add .agents/skills directory support for skill discovery

Add compatibility for the standardized .agents/skills directory pattern,
both globally (~/.agents/skills) and locally (.agents/skills in workspace).

* feat: make .agents/skills the default for new skills

New skills are now created in .agents/skills (local) and ~/.agents/skills
(global) by default. These directories also have highest priority in
skill discovery, overriding skills with the same name from other locations.

* docs: update skills documentation for .agents/skills directories

* refactor skills directory helpers
2026-02-12 22:08:30 -06:00
1a29d428ae refactor: BannerService initialization and cache management (#8969)
* increases banner cache duration to 24 hours so we make one api calls per day per user; implements a circuit breaker that stops retrying after 3 consecutive failures

* add new tests

* Clear banner cache when auth status changes

* revert 5898bc6e0e

* Fixing circuit breaker

* fix: reset circuitBreakerOpenedAt on failed half-open recovery

Previously, circuitBreakerOpenedAt was only set when consecutiveFailures
reached exactly MAX_CONSECUTIVE_FAILURES. This meant that after a failed
half-open recovery attempt, the timestamp wasn't updated, causing the
circuit breaker to immediately enter half-open state again on the next call.

Now circuitBreakerOpenedAt is updated on every failure once the circuit
breaker is tripped, ensuring proper timeout between recovery attempts.

* refactor: BannerService initialization and cache management

- Move BannerService initialization from common.ts to AuthService (which is initialized in controller)
- Re-initialize BannerService after auth state updates to ensure user context
- Add HostRegistryInfo to centralize host/platform information collection
- Improve rate limiting with exponential backoff (5min → 15min → 30min)
- Refactor error handling to better distinguish between rate limits and server errors
- Remove temporary disabled banner fetching comments

This change ensures banners are only fetched when user authentication is
available and implements more robust rate limiting to prevent API hammering.
The banner service now properly tracks user context and respects server
rate limits with progressive backoff delays.

* refactor(banner): simplify banner service initialization and usage

- Remove `getBanners()` wrapper method from Controller class
- Call `BannerService.get().getActiveBanners()` directly in Controller
- Change `BannerService.initialize()` to synchronous, returns instance immediately
- Make banner fetching non-blocking by moving to background
- Remove unused `BannerCardData` import from Controller
- Update tests to handle asynchronous background fetching with timeouts
- Clean up AuthService banner service initialization comment

This change simplifies the banner service API by removing unnecessary abstraction layers and making initialization non-blocking. The service now fetches banners in the background rather than blocking on initialization, improving application startup performance.

* clean up

* apply feedback

* un-skip unit test

* mock

* mock env

* clean up and add debounce fetch

* log fetch time

* revert

* feature flag: remote-banners

* fix loop in authService on auth update

Co-authored-by: Tomás Barreiro <BarreiroT@users.noreply.github.com>

* Fix tests

* small fixes

* use .? for banner

* moves initializeDistinctId to StateManager

* initializeDistinctId

* use v2 endpoint

---------

Co-authored-by: Zhongying Qiao <cryptoque@users.noreply.github.com>
Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
Co-authored-by: Tomás Barreiro <BarreiroT@users.noreply.github.com>
Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>
Co-authored-by: BarreiroT <tomasmbarreiroi@gmail.com>
2026-02-12 18:28:12 -08:00
Saoud Rizwan 92cf03e42c feat(subagents): simplify research output guidance and command workflow (#9284) 2026-02-12 16:00:02 -08:00
Beeandgreptile-apps[bot] 3ea393a5e9 fix: openai native provider token usage mapping (#9272)
* fix: openai native provider token usage mapping

- Add `store` parameter support to OpenAI native provider options to allow persisting completions.
- Fix incorrect mapping of `cached_tokens` and `reasoning_tokens` in usage statistics.
- Include `thoughtsTokenCount` in the final usage report to track reasoning model performance and costs.

* Update src/core/api/providers/openai-native.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>
2026-02-12 14:26:35 -08:00
9829e7d49e restore yolo mode to what it was before cline cli started (#9205)
Apply suggestions from code review

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-12 11:10:24 -08:00
MaxandMax Paulus 🥪 56de96e5ff fix oca auth (#9145)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-12 10:20:28 -08:00
github-actions[bot] ecde79cf08 v3.59.0 Release Notes (#9263)
- Added Minimax 2.5 Free Promo
- Fixed Response chaining for OpenAI's Responses API

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-12 10:20:19 -08:00
Bee ff36cbcb87 feat: implement response chaining for Responses API (#9270)
* feat: implement response chaining for Responses API

Implement response chaining by tracking and passing previous_response_id
to continue conversations from the last assistant message. This enables
the Responses API to maintain context across multiple turns.

Key changes:
- Search backwards through messages to find last assistant message with ID
- Only send new messages after the chained response
- Track function call metadata (call_id, name, id) across chunks
- Include call_id in tool_call events for proper correlation
- Clean up debug logging and remove commented code
- Remove redundant "Ran out of tokens" log message

This improves conversation continuity and ensures function calls are
properly tracked with their associated IDs throughout the streaming
response lifecycle.

* clean up

* update oca

* codex
2026-02-12 10:01:34 -08:00
shey-cline 5a75f08118 Prevent Parent Container Scrolling In Dropdowns (#9146)
* init

* missed some dropdowns & make scroll behavior work for scrolling nested elements

* add changeset

* add combobox roles
2026-02-12 10:00:40 -08:00
shey-cline 120754c2fe Allow Custom AWS Regions in Bedrock (Extension) (#9104)
* init

* changeset

* addressed comments – add onBlur, aria attributes and redundant useMemo
2026-02-12 09:57:04 -08:00
Saoud Rizwan 5d048d09f8 fix(subagents): retry initial stream bootstrap failures (#9264)
* fix(subagents): retry initial stream bootstrap failures

* fix(subagents): align initial retry classification with main loop

* fix(subagents): compact context on window limit during startup

* fix(subagents): proactively compact context at token thresholds

* feat(subagents): optimize file reads before context truncation
2026-02-12 06:34:43 -08:00
Saoud Rizwan 36580ce086 chore(codex): update environment to use launch script and simplify reinstall
Point the VS Code action at the new run-extension-host.sh script and
drop the git checkout of lock files from the reinstall action.
2026-02-12 05:53:25 -08:00
Saoud Rizwan c584bf4185 feat(dev): add tmux-based extension host launch script
Replaces the inline VS Code launch command with a proper dev script that:
- Builds protos and webview upfront
- Runs esbuild, tsc, and webview watchers in parallel tmux panes
- Waits for dist/extension.js before launching the extension host
- Cleans up all processes and closes the dev window on Ctrl+C
2026-02-12 05:53:18 -08:00
Saoud Rizwan 8133babf41 fix(chat): keep focus chain placeholder visible to prevent layout jump (#9266)
* fix(webview): stabilize focus chain header space and placeholder

* fix(chat): add follow-up bottom scroll to avoid short scroll

* style(chat): refine markdown spacing and tool group summary tone

* fix(chat): retry auto-scroll at 40ms and 70ms

* fix(chat): keep focus chain placeholder visible until checklist exists
2026-02-12 03:50:01 -08:00
Saoud Rizwan 741f524da7 chore(deps): upgrade openai sdk to 6.21.0 for xhigh reasoning (#9267) 2026-02-12 03:48:13 -08:00
Robin Newhouse d3918dd7df fix(task): canonicalize attempt_completion result parameter (#9262) 2026-02-12 00:37:27 -06:00
alex-lum 024bb65443 Add organization attributes to telemetry metrics (#9242) 2026-02-11 16:51:24 -08:00
58ebbdbf80 Changeset version bump (#9252)
* changeset version bump

* Updating CHANGELOG.md format

* changeset version bump

* Updating CHANGELOG.md format

* Eve manually updating the banner and the release version

* Manually update the changelog

* Fix GLM 5 model ID in banner

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: cline-test <132302818+candieduniverse@users.noreply.github.com>
2026-02-11 16:30:14 -08:00
Juan Pablo Flores cee74d2f3a docs: add subagents feature documentation (#9258)
* docs: add subagents feature documentation

Add new documentation page covering the Subagents feature, including
how it works, enabling/configuring, auto-approve behavior, available
tools, and usage guidance. Register the page in docs.json sidebar nav.

* docs: remove hardcoded subagent limit from subagents page

Remove references to 'up to five' subagents, as the limit is no longer
fixed. Updates both the intro paragraph and the How It Works section.
2026-02-11 15:54:57 -08:00
Ara a6f3b9f856 Revert "fix MCP OAuth: add missing scope parameter (#9117)" (#9256)
This reverts commit 401358374f.
2026-02-11 15:07:34 -08:00
Ara 0e524ffc3a feat(zai): add glm-5 pricing and make it default (#9254)
* feat(zai): add glm-5 pricing and make it default

* fix(zai,qwen): fallback model id when apiModelId is invalid
2026-02-11 14:05:50 -08:00
Ara 95ca14fa2a Fixing changeset files (#9251) 2026-02-11 12:38:31 -08:00
MaxandMax Paulus 🥪 a6c57a4ce5 print task id in headless modes (#9229)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-11 12:21:02 -08:00
Tomás Barreiro 9470cf19cd Add headers to the Remotely Configured MCP server schema (#9238) 2026-02-11 18:53:44 +01:00
Saoud Rizwan acf34860bb chore: fix codex desktop app configuration 2026-02-11 02:34:33 -08:00
Saoud Rizwan 49cad88aca chore: fix codex desktop app configuration 2026-02-11 02:25:59 -08:00
Saoud Rizwan 3c65cbc7f2 chore: add codex desktop app configuration 2026-02-11 02:22:29 -08:00
Saoud Rizwan 12603d4be1 feat: replace legacy CLI subagents with native use_subagents tool (#9208)
* feat: checkpoint subagent tool workflow and approval UX

* feat: support subagent tool execution without native tool calls

* fix: expose use_subagents when native tool calling is disabled

* fix: stabilize subagent command UX and suppress nested command rows

* chore: tune subagent prompt guidance for context-heavy exploration

* fix: align subagent row spacing with chat row conventions

* fix: keep cancelled subagent state during immediate resume

* feat: implement subagent message rendering for approval prompts and progress updates

* feat: enhance SubagentRunner with tool use ID resolution and fallback handling

* fix: stabilize subagent cline requests with ulid and initial workspace metadata

* refactor: unify subagent chat row rendering

* feat: surface subagent costs in task metrics and status rows

* fix: refine cli subagent tree alignment and wrapping

* fix: refine subagent streaming rows in cli and webview

* fix: ensure unique act mode hint keys in CLI chat

* feat: add subagents settings toggle wiring across webview and cli

* fix(webview): stream subagent stats per prompt while constructing prompts

* fix: remove duplicate subagentsEnabled declaration after rebase

* chore: restore package lockfiles to main

* fix: harden task history usage parsing and clean prompt separators

* chore: refine subagent response formatting guidance

* feat: collapse subagent prompts with show more

* feat: show latest subagent tool call in status rows

* fix: fall back to non-native mode for subagents when native tools are unavailable

* fix: retry empty subagent responses before failing

* fix(subagents): require attempt_completion and dedupe tool result formatting

* feat(subagents): polish prompt guidance and webview status row
2026-02-11 02:17:45 -08:00
Robin NewhouseandCursor b514f18e4f fix(task): prevent duplicate streamed text rows after completion (#9235)
* fix(task): prevent duplicate partial text rows after completion

Avoid adding a new partial text message when the latest text row is already completed with the same content. This stops a presenter race from rendering duplicate streamed text lines for MiniMax-style timing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(task): cover duplicate partial text dedupe behavior

Add a Task.say unit test that reproduces the duplicate-partial-after-complete scenario and verifies we skip creating a second text row with identical content.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 23:44:01 -08:00
Saoud Rizwan ce85d7d414 fix(cli): preserve OAuth callback paths in auth redirects (#9237) 2026-02-10 19:28:28 -08:00
Saoud Rizwan 739d75afe3 fix(claude-code): add opus 4.6 1m model option (#9231)
* fix(claude-code): add opus 4.6 1m model option

* fix(claude-code): support opus[1m] alias and align opus alias

* fix(claude-code): add sonnet[1m] model support
2026-02-11 04:19:44 +01:00
fc1be2baac add more shortcuts to help output (#9204)
* add more shortcuts to help output

* Apply suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-10 16:14:11 -08:00
Saoud Rizwan 5dcaa8c8cc fix(vertex): add opus 4.6 1m model support on Vertex (#9230)
* fix(vertex): add opus 4.6 1m and global endpoint support

* fix(vertex): enable thinking for opus 4.6 1m in webview
2026-02-10 15:30:12 -08:00
CandiedUniverse 79cf77db0a Finish adding Amazon Bedrock to isNexGenModelProvider() list [CLINE-1291] (#9216)
* Add Bedrock to the list in isNextGenModelProvider()

* feat(bedrock): Remove testing script used to develop isNextGenModelProvider() change against

* refactor: extract shared isParallelToolCallingEnabled into model-utils

Consolidate duplicated parallel tool calling logic from ToolExecutor.ts
and task/index.ts into a single exported function in model-utils.ts.

Both callers now delegate to the shared function, eliminating the need
to maintain identical checks in two places.
2026-02-10 14:39:48 -08:00
Robin Newhouse 4b61799df5 docs: improve PR creation skill to use --body-file flag (#8789)
Replaces inline --body with --body-file approach in the PR creation skill documentation. This avoids shell escaping issues, newline problems, and command-line flakiness when creating PRs with complex markdown content.

Related to #8785
2026-02-10 15:52:05 -06:00
cryptoque 806708e802 feat: enable sync-ed deletion for remote mcp servers from remote config to extension (#9210)
* feat: enable sync-ed deletion for remote mcp servers from remote config to extension

* chore: add tests for syncing remote mcp server adding and removal

* address comments
2026-02-10 10:24:19 -08:00
MaxandMax Paulus 🥪 642ea849e3 fix publish-cli-trusted workflow (#9220)
- parent workflow needs to request permissions for children workflows

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-09 21:53:40 -08:00
MaxandMax Paulus 🥪 dff8193de5 make trusted npm publish workflow (#9219)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-09 21:40:04 -08:00
MaxandMax Paulus 🥪 a05c1c5e53 store input text on remount (#9124)
- my input was getting cleared when i resized the screen. this fixes
that

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-09 21:06:59 -08:00
MaxandMax Paulus 🥪 9a11976d27 improve cline config command (#9212)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-09 18:15:05 -08:00
Tomás Barreiro b54647ab17 [PF-389] Render remote config options and add test buttons (#9051)
* WIP - Render a Remote Config secttion and add an option to refresh

* Add the different remote config sections and test them

* fixes

* refactor

* Add proper wrapping

* Stack more values

* Properly report errors when prompt uploading fails

* Add a better error message for the otel test button

* clean

* Fix option rendering

* Render less options if they aren't configured
2026-02-10 02:46:40 +01:00
ClineXDiego 6e253dfa9a Fix/vscode web oauth callback (#9173)
* fix: use vscode.env.asExternalUri for web OAuth callbacks

In VS Code Web (Codespaces, code serve-web), OAuth callbacks using
http://127.0.0.1:PORT break because the extension host runs remotely.

Changes:
- getCallbackUrl now accepts a path parameter
- Desktop: uses vscode://extension-id/path directly
- Web (UIKind.Web): uses vscode.env.asExternalUri() for web-reachable URL
- Updated all callers (/auth, /openrouter, /hicap, /requesty, MCP) to
  pass path and use URL+searchParams for proper encoding
- Added regression test asserting web callback URL is not 127.0.0.1
- AuthHandler (localhost HTTP) now only used by CLI/standalone mode

* fix: use URL.searchParams for proper callback URL encoding

Callers were using template literal interpolation to embed callback URLs
into query strings, which breaks when the URL contains special characters
(e.g. from asExternalUri with query params). Use URL+searchParams.set()
which automatically encodes values.

* chore: revert unrelated whitespace change in account.proto

* revert: remove non-essential URL encoding changes in auth callers

Keep only the core fix (getCallbackUrl path parameter + asExternalUri for web).
Revert the URL+searchParams encoding improvement to minimize diff.

* fix: URL-encode callback_url in auth callers, add encoding test

In VS Code Web, callback URLs from asExternalUri can contain their own
query params (?tkn=...&extra=...). String-interpolating them into
callback_url= causes everything after the first & to be parsed as
top-level params, truncating the callback URL.

Use URL + searchParams.set() in openrouter, hicap, and requesty callers.
Replace tautology test with deterministic round-trip encoding assertions.
2026-02-09 16:43:24 -08:00
Ara 7236d02ebb feat(tools): add auto-approval support for attempt_completion commands (#8926)
* feat(tools): add auto-approval support for attempt_completion commands

- Add auto-approval logic for bash commands in AttemptCompletionHandler
- Show commands as 'say' instead of 'ask' when auto-approved
- Display notification prompting user approval when manual approval needed
- Add 30-second timeout notification for long-running auto-approved commands
- Fix Logger import path from @/shared to @shared

* Send to cline provider
2026-02-09 15:57:29 -08:00
Saoud Rizwan 84fef6fe1f chore(ci): remove ai review workflows and publish caching (#9211) 2026-02-09 15:42:44 -08:00
CandiedUniverse 7bdbf0a9a7 feat(bedrock): Support parallel tool calling in Amazon Bedrock [CLINE-1291] (#9150)
* feat(bedrock): Create agent implementation plan for supporting parallel tool calling.

* Add Bedrock tool calling support

* Improve Bedrock tool calling test guidance

* Add Bedrock CLI parallel tool calling test script

* fix: add ALLOW_AWS_DEFAULT_CHAIN support to live integration test script

* chore: add changeset for Bedrock parallel tool calling

* feat(bedrock): enable native parallel tool calling for Bedrock provider

- Add 'bedrock' to isNextGenModelProvider() so native tool calling is enabled
- Add 'bedrock' to getNativeConverter() to use Anthropic-format tool specs (input_schema)
- Fix empty tool description validation error in mapClineToolsToBedrockToolConfig
  (Bedrock requires description length >= 1)
- Update CLI test to use Sonnet 4.5 (Haiku too small for native tool calling)
- Add <invoke> XML detection to CLI test to catch XML fallback

Verified: conversation history shows 3 native tool_use blocks in a single
assistant response with 3 matching tool_result blocks — true parallel
tool calling via Bedrock Converse API.

* docs: mark all phases complete in bedrock parallel tool calling implementation plan

* chore: switch test scripts default model to Haiku 4.5 (cheaper for testing)

* feat: enhance CLI verification suite with 3 test cases (single, parallel, round-trip)

* Remove bedrock parallel tool calling implementation plan doc.

* refactor: simplify to single CLI verification script for bedrock parallel tool calling

Remove the handler-level test script (test-bedrock-tool-calling.ts) and consolidate
into a single focused CLI test that proves parallel tool calling works end-to-end:
- Spawns Cline CLI with Bedrock config
- Asks it to read 3 files
- Verifies ≥2 parallel native tool calls (not XML fallback)
- Task completion proves tool result round-trip works

* refactor(bedrock): improve type safety and code quality for parallel tool calling

- Add typed interfaces (ToolUseStart, ToolUseDelta) for Bedrock stream
  events instead of relying on `as any` casts
- Extend ContentBlockStart and ContentBlockDelta interfaces with toolUse
  fields so stream parsing uses typed property access
- Remove dead `inputBuffer` field from activeToolCalls Map (was tracked
  but never read — tool input deltas are yielded immediately)
- Add JSDoc to mapClineToolsToBedrockToolConfig explaining its purpose
  and return semantics
- Document why createDeepseekMessage intentionally ignores the tools
  parameter (DeepSeek R1 uses InvokeModel, not Converse API)

* refactor(scripts): improve test script readability and resource cleanup

- Add try/finally with cleanupDirs() to remove temp workspace and config
  dirs after each run (previously accumulated in $TMPDIR)
- Extract named constants for CLI_TIMEOUT_SECONDS and HEARTBEAT_INTERVAL_MS
- Add CliResult interface for the runCli return type
- Rename cryptic variables: hb → heartbeatInterval, c → chunk, p/d → filePath/data
- Add JSDoc to parseReadFilePaths and hasXmlFallback
- Add explanatory comments to empty catch blocks
- Log stderr on non-zero exit code for easier debugging
- Extract createTestWorkspace() to separate workspace setup from main flow
- Add section separator comments for visual structure

* test(bedrock): add missing edge-case tests and remove dead describe block

- Add tests for mapClineToolsToBedrockToolConfig edge cases:
  undefined/empty input returns undefined, tools without input_schema
  are silently dropped
- Add test for formatMessagesForConverseAPI with array tool_result
  content (multi-block text responses)
- Add test for tool_result is_error → status:'error' mapping
- Remove empty 'reasoning content handling (deprecated)' describe block

35 tests passing (was 31).

* test(bedrock): add integration-level tests covering E2E script gaps

Add 'native tool calling integration' test suite that validates the
concerns previously only covered by the live E2E CLI script:

- Bedrock + Claude 4 is recognized as native tool calling eligible
  (catches silent regression if Bedrock is removed from
  isNextGenModelProvider or Claude 4 from isNextGenModelFamily)
- Bedrock + Claude 3.x correctly does NOT qualify (pre-4.0 guard)
- Native tool calling disabled when user setting is off
- createAnthropicMessage passes toolConfig to ConverseStreamCommand
  (catches the tool spec not reaching the API)
- Full multi-turn tool call round-trip formatting (tool_use in
  assistant → tool_result in user → reformatted for next API call)

40 tests passing (was 35).

* Remove functional verification script before code review
2026-02-09 15:23:56 -08:00
MaxandMax Paulus 🥪 bab336f172 use cline provider for cline pr review workflow. use npx instead of npm install (#9202)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-09 10:21:32 -08:00
MaxandMax Paulus 🥪 967342999f if yolo mode is on, don't ask permission to use mcp tools (#9100)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-09 10:12:30 -08:00
Jose R. Perez d19a8779e7 feat: consolidate ViewHeader and styling (#8989)
* feat: consolidate ViewHeader and styling

* feat: changeset

* fix: added back environment variables for color differentiation

* fix: co-pilot fixes

* feat: github copilot fix
2026-02-09 10:02:16 -08:00
Saoud Rizwan 5c04fa3aa3 fix(cli): flush telemetry on shutdown and include activation metadata (#9195) 2026-02-08 22:00:45 -08:00
Saoud Rizwan 7c31c1d02a fix: restore reasoning behavior parity after #9168 (#9188)
* fix: restore reasoning parity after #9168

* fix: restore webview reasoning support compatibility checks

fix: simplify reasoning support model matching
2026-02-08 19:43:23 -08:00
Saoud Rizwan 740f99400b feat(cli): add max-consecutive-mistakes task flag (#9194) 2026-02-08 18:52:45 -08:00
Igor Tceglevskii 195294f389 feat: bundled endpoints.json (#9113) 2026-02-08 18:31:01 -08:00
Saoud Rizwan 2cc070eee2 fix(api): preserve vercel model id when metadata is missing (#9192) 2026-02-08 18:00:13 -08:00
Saoud Rizwan 627838243e fix(e2e): increase test timeout for Windows CI runners (#9185)
The diff editor e2e test flakes consistently on Windows CI because the
40s test timeout is too tight. The test does signin, message send,
history verification, then a second message send before the diff
assertion -- on slow Windows runners this setup alone can eat most of
the budget. Bumping to 60s gives enough headroom.
2026-02-08 11:27:48 -08:00
Saoud Rizwan f8a1f75664 feat: add output precision and threshold rules to double-check prompt (#9184)
Add Terminal-Bench-proven rules as items 5 and 6 in the double-check
re-verification checklist, so they're enforced at completion
verification time rather than in the system prompt.
2026-02-08 11:09:27 -08:00
Saoud Rizwan 54aeba1fee feat: add double-check completion experimental feature (#9180)
* feat: add double-check completion experimental feature

When enabled, the first attempt_completion call in a task is rejected
with a tool error that instructs the model to re-verify its work
against the original task requirements. The rejection includes the
initial task text for context. The second call proceeds normally.

This is opt-in (default off) and available via:
- Settings > Features > Experimental > Double-Check Completion
- CLI flag: --double-check-completion
- CLI TUI settings panel toggle

Adds completionAttemptCount to TaskState, plumbs the setting through
TaskConfig/ToolExecutor following existing patterns, and includes
9 unit tests.

* chore: add cli:run script for quick CLI testing

* fix: increase task preview to 8000 chars, revert unintended regex change

* fix: preserve existing proto field numbers

The auto-generator renumbered open_ai_headers (175->177) and
openai_codex_oauth_credentials (46->48), and dropped the reserved 146
comment. Restore original field numbers to avoid breaking wire-format
compatibility.

* fix: remove partial completion_result message on double-check rejection

During streaming, handlePartialBlock shows the completion_result in
the chat view. When we reject the first attempt, we need to clean up
that partial message so the user doesn't see a stale completion that
was actually rejected.

* refactor: switch from counter to boolean toggle for double-check

Use a boolean pending flag instead of a counter so that every
attempt_completion gets double-checked, not just the first one in
a task. The flag toggles: reject (set pending), accept (clear pending),
so if the model does more work and tries to complete again later, it
gets double-checked again.
2026-02-08 10:56:10 -08:00
Robin Newhouse a03642ba4a fix(prompt): add output precision and threshold iteration rules (#9178)
* fix(prompt): add output precision and threshold iteration rules

Two concise rules proven effective via Terminal-Bench testing:

1. Output precision: produce exactly what's specified, no extra columns/fields/debug output
2. Threshold iteration: verify results meet numerical criteria before completing

Tested on 6 targeted Terminal-Bench tasks (job 2026-02-07__16-15-00):
- log-summary-date-ranges: FAIL→PASS (output precision rule eliminated extra columns)
- dna-insert: FAIL→PASS (iterate rule helped agent meet Tm threshold)

A third rule (no-cleanup) was tested and deliberately excluded: it failed to
prevent self-sabotage on configure-git-webserver despite STRICTLY FORBIDDEN
language, and caused a side-effect on polyglot-c-py by preventing legitimate
build artifact cleanup. The cleanup behavior is too deeply trained to override
via prompt rules alone.

* test: update prompt snapshots for new rules
2026-02-08 09:37:04 -08:00
Saoud Rizwan b65435fc55 fix(cli): route PostHog networking through shared fetch (#9149)
* fix(cli): route PostHog networking through shared fetch

* remove unnecessary `as RequestInit` casts from PostHog fetch wrappers

PostHogFetchOptions is a structural subset of RequestInit, so the cast
is unnecessary. Also removes a stale comment about shared client support
in PostHogErrorProvider.
2026-02-07 18:26:23 -08:00
Saoud Rizwan 88694d39fa feat(cli): allow --thinking flag to accept custom token budget (#9177)
The --thinking flag now accepts an optional number argument to set a
custom thinking budget instead of always using the 1024 default.

  cline "prompt" --thinking         # 1024 tokens (default)
  cline "prompt" --thinking 8000    # 8000 tokens

Invalid values get a warning and fall back to 1024.
2026-02-07 17:06:33 -08:00
Saoud Rizwan 6c53daa88e feat: move reasoning effort to model config and settings UX (#9168)
* feat: move reasoning effort to model config and update model selection UX

* refactor: dedupe reasoning effort handling and drop lockfile churn

* refactor: default reasoning effort to low

* refactor(cli): sync mode-scoped thinking and reasoning writes

* fix: centralize reasoning effort normalization and avoid implicit openai effort

* fix: restore proto field number for codex credentials and reserve removed fields

- Keep openai_codex_oauth_credentials at field 46 (was incorrectly
  changed to 47)
- Add reserved 146 in Settings for removed openai_reasoning_effort
- Add reserved 15 in UpdateSettingsRequest for removed openai_reasoning_effort
- Remove stale openai_reasoning_effort field from UpdateSettingsRequest

* fix: map medium reasoning effort to LOW for Gemini models

Gemini API only accepts LOW and HIGH thinking levels. MEDIUM exists in
the SDK enum but is rejected at the API level. Map medium to LOW and
update the default fallback accordingly.
2026-02-07 16:58:10 -08:00
Ara 1f3c00c613 feat(task): add support for writing prompt metadata artifacts (#9158)
Introduces a mechanism to save system prompts and task metadata to disk for debugging and analysis purposes.

- Added `writePromptMetadataArtifacts` to the `Task` class.
- Feature is enabled via the `CLINE_WRITE_PROMPT_ARTIFACTS` environment variable.
- Artifacts are saved to `.cline-prompt-artifacts` or a custom path defined by `CLINE_PROMPT_ARTIFACT_DIR`.
- Writes both a JSON manifest (containing task ID, model info, and timestamp) and the raw system prompt for every API request.
2026-02-07 15:21:41 -08:00
Saoud RizwanandAra 4d455ea015 fix(terminal): tune execute_command timeout strategy for long-running tasks (#9159)
* fix(terminal): tune managed timeout policy for long-running commands

* Reduce default command timeout from 120 to 30 seconds

* Update ExecuteCommandToolHandler.timeout.test.ts

---------

Co-authored-by: Ara <arafat.da.khan@gmail.com>
2026-02-07 14:47:26 -08:00
Saoud Rizwan 3daf24662e fix(prompt): add guidance to use -- for leading-dash positional args (#9161) 2026-02-07 14:18:55 -08:00
Saoud Rizwan 942fcf5762 fix(terminal): surface command exit codes in results (#9156) 2026-02-07 13:31:22 -08:00
ClineXDiego 70a99047ed fix: use vscode.env.asExternalUri for auth callback URLs in VS Code Web (#9144)
* fix: use vscode.env.asExternalUri for auth callback URLs in VS Code Web

The OAuth callback redirect was broken in VS Code Web (code serve-web)
environments because the callback URL used a raw vscode:// URI scheme,
which the OS would route to the local desktop VS Code app instead of
the web instance.

This change wraps both getCallbackUrl() and getIdeRedirectUri() with
vscode.env.asExternalUri() which properly transforms URIs based on the
environment:
- Desktop VS Code: unchanged (vscode://...)
- VS Code Remote SSH: adds remote authority for proper routing
- VS Code Web: transforms to HTTPS URL that routes through the web server

Fixes #5109 (remaining callback redirect issue)
Related: #2152

* fix: use HTTP-based auth callback for VS Code Web mode

In VS Code Web (code serve-web), vscode:// URIs redirect to the desktop
app instead of staying in the browser. This change uses AuthHandler
(local HTTP server) for the auth callback in web mode, matching how
CLI/standalone already handles auth.

- getCallbackUrl: use AuthHandler when UIKind.Web
- getIdeRedirectUri: return empty in web mode to avoid vscode:// redirect

* fix: add fallback for openExternal RPC for JetBrains compatibility

The openExternal host bridge RPC is not implemented in the JetBrains
plugin, causing sign-in to fail silently. This adds a fallback to the
'open' npm package when the host RPC fails with UNIMPLEMENTED.

Fixes #9164, #9137, #9138
2026-02-07 10:25:14 -08:00
Robin Newhouse 844038084c feat: add CLI build workflow for testing from any commit (#9131) 2026-02-07 05:23:22 -08:00
Robin Newhouse 0c6f77ea46 Remove accidentally committed implementation_plan.md (#9160) 2026-02-07 00:11:02 -06:00
Saoud Rizwan 9b70f94174 fix(prompt): require verification before completion (#9154)
* fix(prompt): require verification before completion

* fix(prompt): align gemini verification-first completion guidance
2026-02-06 19:22:40 -08:00
Saoud Rizwan 0a4f939ecb chore(ci): tag bot PR reviews with workflow footer (#9152) 2026-02-06 15:08:38 -08:00
Tomás Barreiro 095ee24288 Limit the CLI provider list to what's remotely configured (#9135)
* Limit the CLI provider list to what's remotely configured

* Refactor

* fix react
2026-02-06 09:14:29 -08:00
Saoud Rizwan 523dd9ef7d fix(ui): add loading indicator and fix api_req_started rendering (#9133)
The chat streaming UI refactor removed the loading indicator that
previously showed when an API request was in progress. This left users
staring at a frozen UI during the latency between sending a message
and receiving the first streamed content.

Changes:
- Add "Thinking..." shimmer in the Virtuoso Footer as the sole loading
  indicator, covering both pre-api_req_started (backend processing) and
  post-api_req_started (waiting for model response) states
- Filter out api_req_started messages that have no visible content
  (no error/cancel). These rows rendered as invisible padding since
  the PR removed the old API request accordion UI. Reasoning messages
  already render as their own standalone ChatRows.
- Thread footerActive flag to MessageRenderer so the last message skips
  pb-2.5 when the Footer is showing, keeping spacing consistent with
  the pt-2.5 on every ChatRow
2026-02-05 16:38:21 -08:00
Robin Newhouse 6d8fb8507b fix(cli): handle stdin redirection in CI environments (#9121)
- Add stdinIsTTY check to shouldUsePlainTextMode() - Ink requires raw mode on stdin
- Only error on empty stdin when no prompt is provided (allows: cline 'prompt' < /dev/null)
- Fixes crash in GitHub Actions and other CI environments
2026-02-05 13:32:52 -08:00
MaxandMax Paulus 🥪 edc93f35f1 update changelog for 3.57.1 (#9130)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-05 13:12:54 -08:00
ckrauseandCopilot 401358374f fix MCP OAuth: add missing scope parameter (#9117)
* fix MCP OAuth: add missing scope parameter

* Update src/services/mcp/McpOAuthManager.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-05 13:06:01 -08:00
MaxandMax Paulus 🥪 f8bcad16a5 update package-lock.json (#9127)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-05 12:44:46 -08:00
AJ Juaire 26391c94e9 Correct Bedrock Opus 4.6 model id (#9126) 2026-02-05 12:21:37 -08:00
Ara 462438ece5 Update changelog wording (#9125) 2026-02-05 11:53:48 -08:00
github-actions[bot]andArafatkatze 92521ed279 Release Notes for v3.57.0 (#8980)
- Cline CLI 2.0 now available. Install with `npm install -g cline`
- Anthopic Opus 4.6
- Minimax-2.1 and Kimi-k2.5 now available for free for a limited time promo
- Codex-5.3 through OpenAI Codex provider

- Fix read file tool to support reading large files
- Fix decimal input crash in OpenAI Compatible price fields (#8129)
- Fix build complete handlers when updating the api config
- Fixed missing provider from list
- Fixed Favorite Icon / Star from getting clipped in the task history view

- Make skills always enabled and remove feature toggle setting

Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
2026-02-05 11:35:58 -08:00
MaxandMax Paulus 🥪 08aa81f798 add taskId flag to CLI (#9095)
- allows you to resume a session headlessly or interactively with a
taskId

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-05 11:32:54 -08:00
Tomás Barreiro e025995177 Revert LiteLLM model name change and use the rawModel name (#9123)
* Revert LiteLLM model name change and use the rawModel name

* Add both to the list
2026-02-05 11:15:17 -08:00
Saoud Rizwan ee361ef3ae feat: add GPT-5.3 Codex model for ChatGPT subscription users (#9122)
* feat: add GPT-5.3 Codex model for ChatGPT subscription users

OpenAI released GPT-5.3 Codex today. Adding it to the OpenAI Codex
provider (ChatGPT Plus/Pro subscription) model list and setting it
as the new default.

Changes:
- Add gpt-5.3-codex to openAiCodexModels with same specs as 5.2
- Update default model to gpt-5.3-codex
- Update featured models in CLI and webview OpenRouter picker

* revert: remove gpt-5.3-codex from OpenRouter featured models

GPT-5.3 Codex is only available via ChatGPT subscription, not through
the OpenAI API or OpenRouter. Reverting featured model changes.
2026-02-05 11:05:00 -08:00
MaxandMax Paulus 🥪 c8ef342c19 cli multi label support. new featured model (#9118)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-05 10:51:54 -08:00
Saoud RizwanandRobin Newhouse 7c8701799d feat: add Claude Opus 4.6 model support (#9119)
* feat: add Claude Opus 4.6 model support with 1M context window

Adds support for Claude Opus 4.6, Anthropic's latest model with:
- 200K base context window with optional 1M context variant
- Tiered pricing for >200K context (2x input/output pricing)
- Extended thinking/reasoning support
- Prompt caching support

Changes:
- Added model definitions for Anthropic, Bedrock, and Vertex providers
- Added OpenRouter 1M variant support
- Updated thinking models lists across all provider UIs
- Added context window switcher for Opus 4.6
- Updated JP cross-region inference models list

* feat: update featured model to Opus 4.6 in model picker

* chore: add changeset for Claude Opus 4.6

* fix: correct Opus 4.6 model IDs (no date suffix)

---------

Co-authored-by: Robin Newhouse <robin@cline.bot>
2026-02-05 10:38:54 -08:00
Ara fbcf63ad71 fixing large model (#9110) 2026-02-05 09:16:25 -08:00
Saoud Rizwan fffe626b3a Bump CLI version from 2.0.3 to 2.0.4 2026-02-05 02:07:38 -08:00
Saoud Rizwan 2dccd6f6f6 fix(cli): use value import for React instead of type-only import
JSX requires React as a value when using jsx: react in tsconfig.
2026-02-05 02:04:22 -08:00
Saoud Rizwan 39971128cb fix(cli): use value import for React instead of type-only import 2026-02-05 02:00:43 -08:00
Saoud Rizwan b725490582 fix(cli): fix cursor position after pasting text
Use refs instead of state values in useInput callback to avoid stale
closures. Also manually update textInputRef before calling setCursorPos
so the bounds check uses the correct new text length.
2026-02-05 01:51:25 -08:00
Saoud Rizwan 8f78645154 fix(cli): show default model name when no model configured
ChatView was returning empty string when the model ID key didn't exist
in state, causing first-time CLI users to see a blank model name. Added
fallback to getProviderDefaultModelId() to match WelcomeView's behavior.
2026-02-05 01:33:24 -08:00
Saoud Rizwan 0ef1c0bf47 fix(cli): make robot animation static on click or drag
Previously the animated robot only became static when the user scrolled.
Now it also becomes static when clicking or dragging, giving users more
ways to dismiss the animation. Renamed onScroll to onInteraction to
reflect the broader scope.
2026-02-05 01:23:02 -08:00
Bee 4c07df370b chore: update biome configuration and linting rules (#9109)
* chore: update biome configuration and linting rules

Update @biomejs/biome package to latest version: 2.3.14

- Change $schema to point to local node_modules for better IDE performance and stability.
- Enable and promote several linting rules from "off" to "info" or "warn" across correctness, style, suspicious, and complexity categories.
- Update file inclusion/exclusion patterns to use more explicit formatting and set ignoreUnknown to true.
- Improve code quality enforcement by surfacing potential issues such as non-null assertions, useless constructors, and implicit any types.

* package-lock udpate

* includes tailwind

* useIterableCallbackReturn
2026-02-04 19:40:38 -08:00
ClineXDiego f440f3a5dd fix: use vscode.env.openExternal for auth in remote environments (#9111)
* fix: use vscode.env.openExternal for auth in remote environments

Fixes #5109

The OAuth authentication flow was broken in VS Code Server and remote
environments because the code used the npm 'open' package directly, which
tries to launch a browser on the server itself (which has no display).

This change routes browser URL opening through VS Code's native
vscode.env.openExternal() API via the HostBridge pattern, which properly
forwards URLs to the user's local machine in remote environments.

Changes:
- Added openExternal RPC to proto/host/env.proto
- Created VS Code handler using vscode.env.openExternal()
- Updated src/utils/env.ts to use HostProvider.env.openExternal()
- Added openExternal to CLI CliEnvServiceClient (uses npm 'open')
- Added openExternal to CLI ACPEnvServiceClient (uses npm 'open')

Related issues: #5394, #2152, #7971

* chore: add changeset for vscode server auth fix

* refactor: extract shared openUrlInBrowser utility for CLI
2026-02-04 19:31:20 -08:00
Tomás Barreiro 3ce1ad3504 Parse remotely configured R2 options (#9090)
* Parse remotely configured R2 options

* Fix R2 options
2026-02-05 03:53:44 +01:00
Tomás Barreiro 00bc38d4e0 Add Workspace Configuration to commit generation (#9107) 2026-02-05 02:25:17 +01:00
Tomás Barreiro a1f2601fe0 Replace the LiteLLM model selector with autocomplete (#9075)
* Replace the LiteLLM model selector with autocomplete

* Add changeset

* refactor
2026-02-04 12:42:08 -08:00
MaxandMax Paulus 🥪 8e3689a5d6 tag released cli versions (#9071)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-04 12:10:02 -08:00
Tomás Barreiro a64f46a5f4 Lock remotely configured Anthropic options (#9087)
* Add Anthropic to the remote config provider settings

* Lock the Anthropic Base URL when it's remotely configured
2026-02-04 19:42:02 +01:00
Tomás Barreiro 507483b2c3 Add Anthropic to the remote config provider settings (#9084) 2026-02-04 19:34:18 +01:00
Marco Alejandro Chavez Santos 42ce100143 Add Authentication Button on HICAP provider to get API KEY (#9098)
* add auth option to get API-KEY for hicap from hicap dashboard website

* remove default hicap model selection

* change url hicap get api keys, add useEffect when update hicapApiKey

* add changeset
2026-02-04 10:29:03 -08:00
CandiedUniverse 7be4e6c6d3 Remove isExperimental flag from Parallel Tool Calls feature setting. (#9097) 2026-02-04 09:47:41 -08:00
Ara 09b91a1ea5 chore: update CODEOWNERS assignments (#9096)
- Remove /docs/ from code ownership
- Update /.github/ owners to @arafatkatze, @maxpaulus43, @candieduniverse
- Update /README.md owner to @juanpflores
- Remove former owners @garoth, @sjf, @nickbaumann98
2026-02-04 09:29:15 -08:00
Tomás Barreiro 7127a2ffa7 Clean old API keys that are stored in secrets (#9091) 2026-02-04 12:02:17 -03:00
Bee d6987d4578 chore: update package-lock.json (#9079) 2026-02-03 21:09:56 -08:00
Tomás Barreiro 7b59cbcb5c Add r2 Blob storage options (#9052) 2026-02-04 03:49:10 +01:00
Ara 0e26ba46d0 fix(ci): always run npm ci regardless of cache hit status (#9078)
Remove conditional checks that skipped dependency installation when
cache was hit. The npm cache speeds up npm ci but does not replace
the need to run it - node_modules still needs to be populated.
2026-02-03 16:34:57 -08:00
MaxandMax Paulus 🥪 3b313ae41f remove prepublish script (#9077)
- this was breaking the publish npm workflow when we try to run npm
publish from the dist-standalone folder (dist-standalone doesn't have
the esbuilt.ts file)
- we don't need this script anyway because we use the npm-main.yaml
workflow to publish the cli

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-03 15:54:37 -08:00
CandiedUniverse 7e74f35f23 feat(hooks): Call combineHookSequences() properly from the CLI. (#9066) 2026-02-03 14:19:56 -08:00
Saoud Rizwan 59c05f4b84 Update copyright year to 2026 2026-02-03 13:51:23 -08:00
Saoud Rizwan 5d6424682f Update README.md 2026-02-03 13:50:49 -08:00
Robin Newhouse b1a8db252a fix(cli): prevent hang when spawned without TTY (#9073)
* fix(cli): prevent hang when spawned without TTY

When the CLI is spawned as a child process without a TTY (e.g., from
spawn() in smoke tests or CI), process.stdin.isTTY is false even when
nothing is piped to stdin. This caused readStdinIfPiped() to wait up
to 5 minutes for input that would never arrive.

Fix by using fs.fstatSync(0) to check if stdin is actually a FIFO
(pipe) or file before waiting. This correctly handles:
- Spawned processes without TTY → returns immediately
- Actual piped input (echo "x" | cline) → waits and reads
- stdin from /dev/null → returns immediately

* chore: add changeset

* test(cli): add tests for stdin type detection
2026-02-03 13:45:56 -08:00
Tony LoehrandRenee Huang 5ae47fb90b Update docs for CLI 2.0 and fix workflow (#9068)
* Add ACP editor integrations documentation with JetBrains and Neovim video demos

* Add Model Orchestration documentation with --config and --thinking flags

- Document --config and --thinking flags in CLI reference
- Create new model-orchestration.mdx sample page
- Add patterns for CI/CD review, task phase optimization, and multi-model consensus
- Link to production GitHub Actions workflow
- Update samples overview with new card
- Update docs navigation

* Add Worktree Workflows documentation with --cwd flag

- Document --cwd flag in CLI reference
- Create comprehensive worktree-workflows.mdx sample page
- Add patterns for parallel execution and cross-worktree piping
- Include real-world examples and best practices
- Add CLI section to features/worktrees.mdx for discoverability
- Update samples overview and navigation
- Cross-link between CLI and VS Code worktree docs

* Remove broken image references from worktrees documentation

- Remove worktrees-overview.png Frame (image not available)
- Remove worktrees-merge.png Frame (image not available)
- Documentation remains fully functional with comprehensive text explanations

* Remove accidentally committed local test file

- Delete src/test/verify-platformio-mcp.ts which was causing CI failures
- File contained TypeScript errors and hardcoded local paths
- Was meant for local testing only, should not have been committed

* Add native JetBrains plugin recommendation to ACP docs

- Add prominent Note recommending native JetBrains plugin
- Link directly to JetBrains installation section
- Position ACP setup as an alternative approach
- Keep all existing ACP content and video

* docs: refine CLI reference formatting and ACP title

Improve CLI reference readability with clearer headings and descriptions, and clarify the ACP editor integration page title for better discovery.docs: refine CLI reference formatting and ACP title

Improve CLI reference readability with clearer headings and descriptions, and clarify the ACP editor integration page title for better discovery.

* Fix CLI 2.0 syntax in model-orchestration.mdx

- Updated issue analysis pipeline to use shell variables for passing context
- Added explanatory note about why direct piping doesn't work
- Corrected example to complete each phase before starting the next
- All examples now use proper CLI 2.0 syntax

* Completely rewrite cli-reference.mdx with accurate CLI 2.0 information

- Removed all outdated CLI 1.0 content (instance management, Cline Core architecture, gRPC references)
- Added accurate CLI 2.0 commands: task, history, config, auth, update, version, dev
- Corrected all command flags and options based on actual man page
- Added proper examples for all commands
- Included environment variables documentation (CLINE_DIR, CLINE_COMMAND_PERMISSIONS)
- Added shell completion instructions
- Removed incorrect three-layer architecture description
- All content now matches cli/man/cline.1.md source of truth

Fixes outdated documentation issue mentioned in PR#9036

* Fix MDX syntax error in cli-reference.mdx

- Replace angle bracket URLs with proper markdown links
- MDX parser was interpreting <https://...> as invalid HTML tags
- Now uses [url](url) format which is proper MDX syntax

Fixes deployment validation error

* docs: Add GitHub PR Review sample and modernize Actions integration

* fix: Add cline installation step to PR review workflow

- Fix CI/CD failure by actually installing cline before running it
- Update docs model ID to match workflow (claude-opus-4-5-20251101)
- Change from 'npx cline version' to 'npm install -g cline' + 'cline version'

---------

Co-authored-by: Renee Huang <renee@cline.bot>
2026-02-03 13:31:35 -08:00
Tomás Barreiro 28c2697ae1 Refresh LiteLLM models (#9070)
* Refresh LiteLLM models

* return promise

* Disable button while loading

* Loading

* Await the fetch
2026-02-03 21:57:06 +01:00
Saoud Rizwan cf01317885 fix(cli): await applyProviderConfig in handleProviderSelect
applyProviderConfig is async and for Cline/OpenRouter providers it
awaits fetching model data before setting state. When switching to
an already-configured provider (Cline, OCA), the call wasn't awaited,
so refreshModelIds() ran before the model ID was set in state,
causing the model to not update to the default.
2026-02-03 12:56:32 -08:00
Saoud Rizwan 7d5eebe192 Bump CLI version from 2.0.2 to 2.0.3 2026-02-03 12:52:21 -08:00
Saoud Rizwan 91a3636356 refactor(cli): add applyBedrockConfig utility, simplify saveConfiguration
- Added applyBedrockConfig to provider-config.ts for AWS Bedrock setup
- AuthView saveConfiguration now uses applyProviderConfig/applyBedrockConfig
- SettingsPanelContent handleBedrockComplete now uses applyBedrockConfig
- Removed duplicate Bedrock config building code from both components
- Cleaned up unused imports

# Conflicts:
#	cli/src/components/SettingsPanelContent.tsx
2026-02-03 12:39:41 -08:00
Saoud Rizwan 5d02eea9cd refactor(cli): use applyProviderConfig in ImportView, remove legacy apiProvider
- ImportView now uses applyProviderConfig instead of manual config building
- Removed legacy apiProvider field from AuthView, ImportView, SettingsPanelContent
  (it's unused - runtime reads actModeApiProvider/planModeApiProvider instead)
2026-02-03 12:39:41 -08:00
Saoud Rizwan 45b2786dbf fix(cli): ensure welcomeViewCompleted is flushed after applyProviderConfig
applyProviderConfig calls flushPendingState internally, so any state
set after it needs its own flush. Added explicit flush after setting
welcomeViewCompleted in OCA and OpenAI Codex auth success handlers.
2026-02-03 12:39:41 -08:00
Saoud Rizwan 4924192b64 refactor(cli): use applyProviderConfig for auth success handlers
Simplifies OCA, Cline, and OpenAI Codex auth success handlers in
AuthView to use the shared applyProviderConfig utility instead of
manually constructing provider config objects.

This removes duplicated logic around mode-specific provider keys
and model ID keys that applyProviderConfig already handles.
2026-02-03 12:39:41 -08:00
MaxandMax Paulus 🥪 28c548b3ee simplify package-npm script (#9067)
cli/package.json is already formatted correctly for publishing

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-03 12:36:47 -08:00
BeeandSaoud Rizwan 9b9035ea4a feat: add authentication support to oca provider in CLI (#9059)
* feat: add authentication support to oca provider in CLI

This change integrates the OcaAuthService into the AuthView component. It adds a new 'oca_auth' step to the authentication flow, allowing users to select 'oca' as a provider and initiate the authentication request via OcaAuthService.

* fix(cli): add subscription to OCA auth status updates

The OCA auth flow was missing the subscription mechanism to know when
browser auth completes. Without this, the CLI would spin indefinitely
after opening the browser.

Added a useEffect that subscribes to OcaAuthService.subscribeToAuthStatusUpdate
when in oca_auth step. When auth succeeds (user.uid present), saves the
provider config and transitions to success.

* fix(cli): add OCA auth support to SettingsPanelContent

AuthView only handles onboarding. Users also need to be able to switch
to OCA provider from the settings panel after initial setup.

Added:
- handleOcaLogin callback to start OAuth flow
- useEffect subscription to OCA auth status updates
- Case in handleProviderSelect for "oca" provider
- Escape key handling to cancel OCA auth
- UI for "Waiting for OCA sign-in..." state
- isWaitingForOcaAuth to input disabled check

* refactor(cli): extract OCA auth logic into useOcaAuth hook

Reduces code duplication between AuthView and SettingsPanelContent by
extracting the OCA auth subscription and state management into a
reusable hook.

The hook handles:
- Starting the OAuth flow (initialize + createAuthRequest)
- Subscribing to auth status updates
- Tracking waiting state
- Calling onSuccess callback when auth completes
- Exposing isAuthenticated for checking existing sessions

Both components now use the hook with their own onSuccess handlers
for component-specific state updates.

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-02-03 12:28:26 -08:00
BeeandArafatkatze e4b39aeb22 fix: apply models cache retrieval across model refresh functions (#8976)
* fix: apply models cache retrieval across model refresh functions

This change introduces a unified caching mechanism for model information retrieved from various API providers (Groq, OpenRouter, Vercel). Each service now first checks if the data is available in the shared StateManager's cache before making an API request. This improves performance by leveraging cached results and reduces redundant network calls when refreshing models multiple times. The cache is stored in memory for quick access during subsequent calls within a single execution context.

Changes made:
1. Added import of `StateManager` to each relevant model refresh file.
2. Implemented initial cache check logic at the beginning of each function.
3. Updated error handling and logging consistency across services.
4. Added storage back into StateManager's cache after successful API retrieval for Groq, Vercel AI Gateway only (OpenRouter update already handled).

* promises

* add vercelModels

* feat: add 1-hour TTL to model cache

Adds a time-to-live mechanism to the model info cache so that:
- Duplicate fetches are still prevented within a reasonable window
- Users can get new models after 1 hour without restarting VS Code

Changes:
- Add MODEL_CACHE_TTL_MS constant (1 hour)
- Update cache structure to include timestamp alongside data
- Update setModelsCache to store timestamp with data
- Update getModelsCache to check TTL and invalidate expired cache
- Update getModelInfo to also respect TTL

---------

Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
2026-02-03 12:18:21 -08:00
MaxandMax Paulus 🥪 f7c54e964f cli version bump (#9064)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-03 11:42:46 -08:00
d116ac5dcf feat: render markdown table in UI (#9056)
* feat: display markdown table in UI

Simplify the handlePartialBlock method in AttemptCompletionHandler by:
- Removing conditional logic for command vs no-command cases
- Always displaying partial result if present
- Deferring command handling to the final execution step
This fixes an issue where attempt completion response doesn't get streamed to the UI during partial result.

Also replaced react-remark with react-markdown and remark-gfm dependencies to MarkdownBlock in UI for enhanced markdown rendering support with GitHub Flavored Markdown features, including displaying table.

* add changeset

* Update src/core/task/tools/handlers/AttemptCompletionHandler.ts

handlePartialBlock hard-codes the partial flag to true when calling uiHelpers.say(...). For consistency with other tool handlers and to avoid incorrect behavior if this method is ever invoked with a non-partial block, pass block.partial through instead.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Robin Newhouse <robin@cline.bot>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 11:41:25 -08:00
BeeandSaoud Rizwan ac22d5d81a chore: add CLI type checking and caching to ci workflow (#9049)
* chore: add CLI type checking and caching to ci workflow

- Added a new cache step for CLI dependencies in the GitHub Actions test workflow to improve build performance.
- Included a step to install CLI dependencies using `npm ci`.
- Updated the `ci:check-all` script in `package.json` to include CLI type checking.
- Added a `cli:typecheck` script to handle type checking within the CLI directory.

* Fix type and import issues for cli

* Includes CI tests in test workflow

* use npx npm-run-all

* update ci:check-all

* ci: skip npm ci steps on cache hit in test workflow

Update the test workflow to conditionally run npm installation steps only when a cache hit is not found. This optimization reduces CI execution time by avoiding redundant dependency installations when the node_modules are already restored from cache.

* ci: update cache keys and add dependency verification in test workflow

Updated the cache keys for root, webview-ui, cli, and testing-platform dependencies by adding a version prefix (v1). This ensures a clean cache state and helps avoid potential corruption or mismatch issues.

Additionally, added a verification step in the test job to log cache hit status and check for the presence of key dependencies like biome and globby. This helps diagnose issues where the cache might be restored but dependencies are not correctly available for subsequent steps.

* update Verify and fix root dependencies

* fix type check script

* add isSettingsKey check

* update settingskey set

* apply feedback

* npx

* feat: flashing dot for streaming chat messages in CI (#9054)

Introduce an ink-spinner to the DotRow component to provide visual feedback when messages are being streamed. This improves the CLI user experience by clearly indicating that a tool call or message is currently in progress.

- Add `flashing` prop to `DotRow` component
- Replace static dot with `toggle8` spinner when `flashing` is true
- Update `ChatMessage` to pass `flashing` state based on `isStreaming` and `partial` message properties

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>

* ci: simplify dependency caching using built-in npm cache

Replace manual actions/cache steps with setup-node's built-in npm caching feature across all workflow jobs. This change:

- Removes redundant cache action steps for root, webview-ui, cli, and testing-platform dependencies
- Uses setup-node's native `cache: 'npm'` option with `cache-dependency-path` to handle multiple package-lock.json files
- Eliminates conditional installation steps based on cache hits
- Reduces workflow complexity and maintenance overhead while maintaining caching functionality

The built-in caching provides the same performance benefits with less configuration and better integration with the Node.js setup action.

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-02-04 03:34:14 +08:00
b57aefb5a1 Cli 2.0 docs (#9060)
* docs: restructure CLI reference to web-friendly format

Replace embedded man page format with structured markdown sections
for better readability. Simplify description, reorganize commands and
options into clear categories, and update Next Steps navigation cards.

* Add ACP editor integrations documentation (#9036)

* Add ACP editor integrations documentation with JetBrains and Neovim video demos

* Add Model Orchestration documentation with --config and --thinking flags

- Document --config and --thinking flags in CLI reference
- Create new model-orchestration.mdx sample page
- Add patterns for CI/CD review, task phase optimization, and multi-model consensus
- Link to production GitHub Actions workflow
- Update samples overview with new card
- Update docs navigation

* Add Worktree Workflows documentation with --cwd flag

- Document --cwd flag in CLI reference
- Create comprehensive worktree-workflows.mdx sample page
- Add patterns for parallel execution and cross-worktree piping
- Include real-world examples and best practices
- Add CLI section to features/worktrees.mdx for discoverability
- Update samples overview and navigation
- Cross-link between CLI and VS Code worktree docs

* Remove broken image references from worktrees documentation

- Remove worktrees-overview.png Frame (image not available)
- Remove worktrees-merge.png Frame (image not available)
- Documentation remains fully functional with comprehensive text explanations

* Remove accidentally committed local test file

- Delete src/test/verify-platformio-mcp.ts which was causing CI failures
- File contained TypeScript errors and hardcoded local paths
- Was meant for local testing only, should not have been committed

* Add native JetBrains plugin recommendation to ACP docs

- Add prominent Note recommending native JetBrains plugin
- Link directly to JetBrains installation section
- Position ACP setup as an alternative approach
- Keep all existing ACP content and video

* docs: refine CLI reference formatting and ACP title

Improve CLI reference readability with clearer headings and descriptions, and clarify the ACP editor integration page title for better discovery.docs: refine CLI reference formatting and ACP title

Improve CLI reference readability with clearer headings and descriptions, and clarify the ACP editor integration page title for better discovery.

* Fix CLI 2.0 syntax in model-orchestration.mdx

- Updated issue analysis pipeline to use shell variables for passing context
- Added explanatory note about why direct piping doesn't work
- Corrected example to complete each phase before starting the next
- All examples now use proper CLI 2.0 syntax

* Completely rewrite cli-reference.mdx with accurate CLI 2.0 information

- Removed all outdated CLI 1.0 content (instance management, Cline Core architecture, gRPC references)
- Added accurate CLI 2.0 commands: task, history, config, auth, update, version, dev
- Corrected all command flags and options based on actual man page
- Added proper examples for all commands
- Included environment variables documentation (CLINE_DIR, CLINE_COMMAND_PERMISSIONS)
- Added shell completion instructions
- Removed incorrect three-layer architecture description
- All content now matches cli/man/cline.1.md source of truth

Fixes outdated documentation issue mentioned in PR#9036

* Fix MDX syntax error in cli-reference.mdx

- Replace angle bracket URLs with proper markdown links
- MDX parser was interpreting <https://...> as invalid HTML tags
- Now uses [url](url) format which is proper MDX syntax

Fixes deployment validation error

---------

Co-authored-by: Renee Huang <renee@cline.bot>

* docs: enhance interactive mode documentation with structured settings overview

* docs: restructure and improve CLI reference documentation

- Reorganize command structure with clearer global options section
- Add mode behavior table explaining interactive vs plain text modes
- Improve option descriptions with consistent formatting
- Add horizontal rules between sections for better readability
- Document timeout option and environment variables more clearly
- Add Tips & Tricks section for common usage patterns
- Update frontmatter description to reflect content changes

* docs: improve ACP editor integrations page with editor descriptions

- Update page title to be more concise ("ACP: Editor Integrations")
- Remove redundant H1 header that duplicated the title
- Add introductory descriptions for JetBrains, Neovim, and Zed sections
- Rename "Zed Editor" section to just "Zed" for consistency

* docs: expand CLI reference with modes of operation and agent behavior

* Update docs/cline-cli/cli-reference-deprecated.mdx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Tony Loehr <turingxo@gmail.com>
Co-authored-by: Renee Huang <renee@cline.bot>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 11:29:15 -08:00
MaxandMax Paulus 🥪 11da3ee89e add windows to cli publish package json (#9063)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-03 11:24:07 -08:00
BeeandSaoud Rizwan e4e63912dd feat: add API key support for Cline provider (#9057)
* feat: add API key support for Cline provider

Add support for authenticating with Cline provider using an API key as an alternative to account-based authentication. This change allows users to configure Cline with either a direct API key or through the existing account authentication flow.

Changes:
- Add `clineApiKey` option to ClineHandler and pass through API configuration
- Update authentication check to accept either API key or account ID
- Modify provider configuration detection to check both auth methods
- Remove automatic Cline auth flow trigger on provider selection
- Add `clineApiKey` to provider-to-API-key mapping for proper key management

This provides more flexibility in authentication methods while maintaining backward compatibility with existing account-based authentication.

* promise all

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-02-03 10:56:04 -08:00
Tomás Barreiro f17d523b2e Fix OTEL endpoints (#9050)
* Fix OTEL endpoints

* refactor
2026-02-03 19:24:01 +01:00
MaxandMax Paulus 🥪 edbba8b7f6 return empty mcp config if cline_mcp_settings.json doesn't exist or is empty file (#9061)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-03 10:12:52 -08:00
Max 7b09999fdf add man page to cli/package.json (#9044) 2026-02-02 21:45:00 -08:00
Tomás Barreiro 01240744a2 Remove reliance on the extensionEnabled flag and verify the source of truth (#9046)
* Remove reliance on the extensionEnabled flag and verify the source of truth

* Fix tests

* Add try block

* Fix telemetrySetting checks
2026-02-03 06:40:17 +01:00
Saoud Rizwan 2944416758 feat(cli): show contextual hints when in settings subpages
When navigating to subpages within the Settings panel (model picker,
provider picker, language picker, etc.), the Panel header now shows
"Esc to go back" instead of "Esc to close" and hides the arrow key
navigation hint since tabs cannot be switched while in a subpage.
2026-02-02 21:08:36 -08:00
alex-lum b5b503dd50 adding in org and member tracking (#9037) 2026-02-02 18:54:58 -08:00
Saoud Rizwan a24ab0c6b8 fix(telemetry): capture event when user opts out of telemetry (#9041)
* fix(telemetry): capture event when user opts out of telemetry

Previously, when a user disabled telemetry, we immediately called
optOut() on providers without first capturing an event to record
this decision. This meant we had no visibility into opt-out rates.

This change captures a "user.opt_out" event using captureRequired
(which bypasses the opt-out check) right before disabling telemetry.

* also track when users opt back in to telemetry

This allows seeing each user's final telemetry state:
- user.opt_out = they disabled telemetry
- user.telemetry_enabled = they re-enabled after opting out
- neither = telemetry on by default, never changed

* refactor: only capture telemetry events on explicit user action

Move event capture from updateTelemetryState() to the controller's
updateTelemetrySetting() method. This ensures we only capture events
when the user explicitly toggles the setting, not on webview init sync.

The previous approach would re-capture opt_out events on every VS Code
restart for users who had previously opted out, because the provider
state resets to enabled on startup.

Now we compare the previous vs new setting in the controller (which has
access to persisted state) and only capture when there's an actual change.

* use distinct event name for explicit user opt-in

The constructor already fires user.telemetry_enabled on startup.
Add user.opt_in for when user explicitly re-enables telemetry,
to distinguish from the initialization event.
2026-02-02 18:19:34 -08:00
Saoud Rizwan 3bc6cc6a92 Bump CLI package version 2026-02-02 16:35:15 -08:00
MaxandMax Paulus 🥪 bd7f2a29d6 error cline if someone piped in empty text (#9038)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-02 16:27:54 -08:00
MaxandMax Paulus 🥪 b1c5f0b811 cli/fix - quick auth should exit process with no interactive ui (#9035)
- this will support ci/cd use case

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-02 16:14:04 -08:00
Bee ac30e49e0b chore(deps): update package-lock.json peer dependency flags (#9040)
Update peer dependency markers in package-lock.json to correctly reflect the dependency relationships. This change moves the `peer: true` flag to packages that are actual peer dependencies (like react, vite, typescript, @opentelemetry/api, @modelcontextprotocol/sdk) and removes it from optional dependencies and platform-specific packages (like @rollup/* platform binaries, @csstools/* packages, and tldts-related packages).

This ensures proper dependency resolution and installation behavior without changing actual package versions or dependencies.
2026-02-03 08:10:48 +08:00
Saoud Rizwan d86f5ed4c9 fix(cli): fetch fresh org data from server when switching organizations
The CLI was reading organization data from authService.getUserOrganizations()
which returns cached data. This caused org switches to not persist across
CLI restarts.

Now uses accountService.fetchUserOrganizationsRPC() to fetch fresh data
from /api/v1/users/me, matching how the webview's getUserOrganizations
RPC works.
2026-02-02 15:12:54 -08:00
Saoud Rizwan 336d31f95f docs(cli): simplify README title to just 'Cline' 2026-02-02 15:08:17 -08:00
Saoud Rizwan fc9c413058 fix(cli): add Home/End key support (fn+left/right on macOS)
Ink's useInput hook parses Home/End keys but doesn't expose them
(sets input='' and doesn't add key.home/key.end to the key object).

Changes:
- Add useHomeEndKeys hook to intercept Home/End from raw stdin
- Create shared keyboard.ts constants for escape sequences
- Remove dead Home/End code from useTextInput (was never firing)
- Add numbered priority documentation to ChatView's useInput handler
2026-02-02 12:47:35 -08:00
Saoud Rizwan e0282826fc fix(cli): match 'Act mode' without 'to' prefix for (Tab) hint
The markdown parser splits 'toggle to **Act mode**' into separate chunks,
so the previous regex requiring 'to Act Mode' as a complete phrase would
fail to match when Act mode was inside bold/italic formatting.
2026-02-02 12:41:55 -08:00
Saoud Rizwan bf83b816e2 fix(cli): support auto-updates for nightly versions (#9034)
* fix(cli): support auto-updates for nightly versions

Previously, the auto-update logic only checked npm's "latest" tag,
so users on nightly builds (2.0.0-nightly.X) would never receive
nightly updates. The update commands also hardcoded @latest.

Changes:
- Detect nightly versions by checking for "-nightly." in version string
- Query npm "nightly" tag when current version is a nightly build
- Use @nightly in update commands for nightly users
- Fix compareVersions() to properly parse and compare nightly timestamps
  (previously it would produce NaN when parsing "2.0.0-nightly.X")

* fix: tighten nightly version regex to require valid semver format
2026-02-02 11:59:07 -08:00
Saoud Rizwan 24033613cd fix(cli): correct provider model ID key generation for anthropic and separate providers (#9033)
Two bugs fixed:

1. getProviderModelIdKey() returned invalid key for Anthropic because
   ProviderKeyMap used "apiModelId" (lowercase "a"), producing
   "actModeapiModelId" instead of "actModeApiModelId". Removed anthropic
   from the map so it falls through to the generic key as intended.

2. Settings panel derived both act/plan model keys from actModeApiProvider.
   If plan and act providers differ, plan model reads/writes targeted wrong
   keys. Now uses planModeApiProvider for plan model key lookups.
2026-02-02 11:36:12 -08:00
MaxandMax Paulus 🥪 f76cfbce48 remove cache hit check for npm publish workflows (#9032)
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-02 10:37:13 -08:00
2a63545224 fix npm-nightly github workflow (#9031)
- use scripts/package-npm.mjs script and remove other unnecessary steps
in the cli build process

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-02-02 10:14:08 -08:00
Jose CastelliandSaoud Rizwan 5308dedc81 fix: updating script documentation and removing unnecessary continue on error (#8769)
* updating script documentation and removing unnecessary continue on error

* test update

* removing comment

* removing unnecessary line

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-02-02 10:11:37 -08:00
Bee 4c699da00b fix(ci): always run npm ci to prevent stale cache issues (#9030)
* fix(ci): always run npm ci to prevent stale cache issues

## Summary

- Remove conditional `npm ci` execution that skipped install on cache hit
- Fixes CI failures when cached `node_modules` becomes stale or incomplete (e.g., missing `npm-run-all`)

## Test plan

- [ ] Verify CI passes on this PR
- [ ] Re-run workflow to confirm it works with fresh and cached states

* Add a step to install vsce globally in the e2e workflow,

* Add `GITHUB_TOKEN` env var to `npm ci` steps to prevent rate limiting when `@vscode/ripgrep` downloads binaries from GitHub

* removed the conditional checks on the npm ci steps

* add GITHUB_TOKEN to the npm ci step.
2026-02-02 10:05:55 -08:00
6cff60b53b feat(cli): add TypeScript CLI (#9021)
* json mode support and model ID fix

* revert non cli-ts changes

* Support Image render

* support plain text

* implement logger

* Fix error not showing in Chat and use unified chat view

* feat(cli): add CLI-specific system prompt adjustments

- Add isCliEnvironment boolean to SystemPromptContext, computed from
  platform check in task/index.ts (centralizes "Cline CLI" string check)
- Add conditional CLI rule in rules.ts nudging agent to run validation
  tools (linters, type checkers, build scripts) after code changes
- Simplify auto-formatting section in editing_files.ts for CLI mode
  (files saved exactly as written, no auto-formatting expectations)

* update cli host info

* store to system keychain

* check

* set storage backup

* revert to file-base

* Replace TaskView with ChatView

* remove old task view components

* Update build step and fix BannerService init

* Set up telemetry for CLI

* Capture Telemetry Events

* feat(cli): add onboarding auth flow with model selection and config import

Auth Flow:
- Auto-redirect first-time users to auth flow when no provider configured
- Support Cline account sign-in with browser-based OAuth
- Support BYO API key configuration for all providers
- Add escape key navigation to go back between steps
- Show provider display names from providers.json (single source of truth)

Model Selection:
- Add ModelPicker component for providers with static model lists
- Add featured models picker for Cline provider (Opus 4.5, GPT 5.2 Codex, Gemini 3 Pro)
- Support OpenRouter model fetching with async loading and caching
- Add scrollable lists with keyboard navigation for long model lists

Config Import:
- Detect and import API keys from Codex CLI (~/.codex/auth.json)
- Detect and import API keys from OpenCode (platform-specific paths)
- Support importing OpenAI, Anthropic, Gemini, Mistral, Groq, DeepSeek, xAI, OpenRouter

Code Quality:
- Extract useScrollableList hook for reusable list windowing
- Move featured models to constants/featured-models.ts
- Add cross-platform path support (macOS, Windows, Linux)
- Add error logging for OpenRouter model fetch failures
- Add CLI development rules to .clinerules/cli.md (blueBright highlight color)

* feat(cli): TUI improvements and new UI components

New Components:
- ActionButtons: Tool approval buttons with mode-based colors (1/2 shortcuts)
- DiffView: Pretty diff view for file edits with +/- highlighting
- TaskView: Alternative verbose task display mode
- MessageList/MessageImage: Supporting components

Chat Improvements:
- Display tool calls in Claude Code style (Cline wants to X / Cline X)
- Mode-based colors (blue for act, yellow for plan)
- Two-column dot prefix layout for messages
- Show command output inline with commands
- Show user feedback messages in chat
- Correct tense for tool messages (wants to vs did)

Bug Fixes:
- Prevent welcome screen flash on task cancel
- Prevent duplicate task completed messages
- Improve followup options handling
- Finalize partial text before native tool calls

Other:
- Add ESC to cancel task (removed ESC-to-exit)
- Use shared formatTimestamp from display utils
- Remove unused files (ImportView, ModelPicker, keychains, etc.)

* feat(cli): add onboarding auth flow with model selection and config import

Auth Flow:
- Auto-redirect first-time users to auth flow when no provider configured
- Support Cline account sign-in with browser-based OAuth
- Support BYO API key configuration for all providers
- Add escape key navigation to go back between steps
- Show provider display names from providers.json (single source of truth)

Model Selection:
- Add ModelPicker component for providers with static model lists
- Add featured models picker for Cline provider (Opus 4.5, GPT 5.2 Codex, Gemini 3 Pro)
- Support OpenRouter model fetching with async loading and caching
- Add scrollable lists with keyboard navigation for long model lists

Config Import:
- Detect and import API keys from Codex CLI (~/.codex/auth.json)
- Detect and import API keys from OpenCode (platform-specific paths)
- Support importing OpenAI, Anthropic, Gemini, Mistral, Groq, DeepSeek, xAI, OpenRouter

Code Quality:
- Extract useScrollableList hook for reusable list windowing
- Move featured models to constants/featured-models.ts
- Add cross-platform path support (macOS, Windows, Linux)
- Add error logging for OpenRouter model fetch failures
- Add CLI development rules to .clinerules/cli.md (blueBright highlight color)

* refactor(cli): consolidate tool utilities and reduce code duplication

- Create utils/tools.ts with shared constants and helpers:
  - FILE_EDIT_TOOLS, FILE_SAVE_TOOLS sets
  - isFileEditTool(), isFileSaveTool() helpers
  - normalizeToolName() for consistent tool name handling
  - TOOL_DESCRIPTIONS with normalized keys (no more duplicates)
  - getToolDescription() with automatic normalization
  - parseToolFromMessage() for consistent JSON parsing

- Update components to use shared utilities:
  - ChatMessage.tsx: Remove 60+ line TOOL_DESCRIPTIONS duplicate, use shared
  - ChatView.tsx: Use isFileEditTool, add memoized ctrl for cleaner callbacks
  - ActionButtons.tsx: Use isFileSaveTool and parseToolFromMessage
  - MessageRow.tsx: Use isFileEditTool

- Simplify ChatView.tsx controller pattern:
  - Memoize ctrl = controller || taskController
  - Remove redundant local ctrl definitions in callbacks
  - Cleaner dependency arrays

* feat(cli): add slash command autocomplete menu

- Add SlashCommandMenu component with keyboard navigation
- Add slash-commands.ts utilities for query extraction and filtering
- Integrate into ChatView with proper state management
- Workflows shown first, then default commands
- Max 5 visible items with arrow key cycling
- Bright blue highlight for selected item
- Footer hidden when menu is shown

* refactor(cli): unify menu styles and fix navigation

- Update FileMentionMenu to match SlashCommandMenu style
- Max 5 visible items, bright blue text selection, no hints
- Hide footer when file menu is shown
- Stop at boundaries instead of wrapping on arrow keys

* feat(cli): highlight @mentions and /commands in input field

- Add HighlightedInput component to parse and style text
- Gray background for @mentions and /commands
- Only first /command is highlighted (matches processing behavior)
- Use shared mentionRegexGlobal for proper mention detection
- Prefix file paths with / when inserting mentions (@/path/to/file)

* refactor(cli): extract shared menu utilities

- Add getVisibleWindow() for scrollable list windowing
- Add sortCommandsWorkflowsFirst() for command ordering
- Remove duplicated windowing logic from SlashCommandMenu and FileMentionMenu

* feat(cli): integrate slash commands with settings panel

- Add /settings as CLI-only slash command
- Open settings panel when /settings selected from menu
- Add Shift+Tab shortcut for auto-approve all toggle
- Hide input and footer when settings panel is open

* feat(cli): improve thinking budget display and add settings control

- Change footer display from '| thinking: 10,000' to '(thinking)' after model ID
- Add thinking budget fields to API settings tab
- Support editing thinking budget for both Act and Plan modes
- Parse numbers with comma separators, treat 'disabled'/empty as 0

* fix(cli): add missing taskId prop to ChatView

Was missing from merge conflict resolution - the useEffect that loads
tasks by ID needs the taskId prop to be defined.

* fix(cli): restore auto-approve indicator in footer

* fix(cli): only highlight valid slash commands

- Add availableCommands prop to HighlightedInput
- Only highlight slash commands that exist in the available commands list
- Prevents highlighting partial commands like /hel while typing /help

* feat(cli): restore movable cursor in input field

- Add cursorPos state and tracking
- Integrate cursor into HighlightedInput component
- Arrow keys move cursor left/right and up/down in multi-line
- Insert and delete at cursor position
- Visual cursor with inverse styling

* fix(cli): remove redundant Esc to exit from chat footer

ThinkingIndicator already shows 'esc to interrupt' during acting/planning,
making the footer's 'Esc to exit' confusing and misleading. Removed the
double-esc-to-exit logic and UI from ChatView.

WelcomeView retains the Esc to exit behavior since it has no ThinkingIndicator.

* fix(cli): disable incrementalRendering to prevent resize artifacts

Ink's incremental rendering tries to erase N lines based on previous
output height, but when the terminal shrinks rapidly, this leaves
UI artifacts (duplicate input boxes). Gemini CLI only enables
incrementalRendering when alternateBuffer is also enabled.

* refactor(cli): consolidate tool ask/say rendering in ChatMessage

Merge duplicate code paths for tool ask and tool say into a single
block. Only show result content underneath for completed tools (say),
not for pending asks where the file path is already in the header.

* feat(cli): show git diff stats in footer

Display files changed, additions, and deletions next to repo/branch:
  cline (saoudrizwan/cli) | 2 files +50 -3

Stats refresh when messages change to reflect file edits.

* fix(cli): show full model ID in footer without truncation

* feat(cli): show chevron indicator when menu has more items below

* fix(cli): update /settings command description

* feat(cli): add searchable model picker to settings API tab

Brings the same searchable model picker experience from the onboarding
auth flow to the settings panel. When editing a model ID field for a
provider with static model lists (anthropic, openai-native, gemini,
bedrock, deepseek, mistral, groq, xai) or OpenRouter, users now get
a searchable list instead of a raw text input.

Changes:
- Import hasModelPicker and ModelPicker in SettingsPanelContent
- Add isPickingModel and pickingModelKey state for picker mode
- Show ModelPicker when editing model ID for supported providers
- Handle escape key to close picker
- Fall back to text input for providers without model lists

* fix(cli): refresh model ID and thinking budget when settings panel closes

The modelId and thinkingBudget useMemo hooks only had [mode] as a
dependency, so they didn't recalculate when the model was changed in
settings. Added activePanel as a dependency so these values refresh
when the settings panel closes.

* feat(cli): replace thinking budget with simple toggle in settings

Changed the API settings tab to show a checkbox toggle for extended
thinking instead of an editable budget field. When enabled, sets the
budget to 1024 tokens (matching webview behavior). When disabled,
sets budget to 0.

* refactor(cli): reorganize API settings with section headers

Reorganized the API tab with section headers for better visual
structure:
- Provider and 'Use separate models' toggle at top
- 'Act Mode' or 'Model' section header with Model ID and Enable thinking
- 'Plan Mode' section (when separate models enabled) with its options

Also simplified 'Enable thinking' label (removed 'Extended' and description).

* fix(cli): move separate models toggle to bottom, remove separators

* fix(cli): remove Model header when not using separate models

* fix(cli): add spacing before separate models toggle when enabled

* fix(cli): add spacer after provider when separate models enabled

* feat(cli): add searchable provider picker to settings API tab

Adds a searchable provider picker to the settings panel, matching the
onboarding auth flow experience. When selecting a new provider, prompts
for the API key before switching.

Changes:
- Create ProviderPicker component with search and keyboard navigation
- Export getProviderLabel and POPULAR_PROVIDERS for reuse
- Create ApiKeyInput component shared between settings and auth flow
- Update model ID to new provider's default when changing providers
- Prompt for API key when selecting a provider that needs one

* fix(cli): fix API key submission in settings provider picker

ApiKeyInput's onSubmit callback was capturing stale state due to
React's closure behavior with useInput. Fixed by:

1. Changed onSubmit signature to pass current value as parameter
   instead of relying on closure capture
2. Fixed settings to use stateManager.setApiConfiguration() instead
   of non-existent secretStorage.set() method
3. Disabled parent useInput when in API key entry mode to prevent
   handler conflicts

* fix(cli): remove thinking indicator from model ID line

* fix(cli): use inverse cursor style in all input fields

Replace legacy gray bar cursor (▌) with inverse block cursor to match
the chat field style across all input components.

* fix(cli): filter mouse escape sequences from text input handlers

Added isMouseEscapeSequence() helper in utils/input.ts to detect and
filter terminal mouse tracking sequences (e.g. [<35;46;17M) from the
AsciiMotionCli mouse tracker. Applied to all components with text input:
- ApiKeyInput
- AskPrompt
- AuthView (TextInput)
- ChatView
- ModelPicker
- ProviderPicker
- SettingsPanelContent
- WelcomeView

* fix(cli): rebuild API handler when provider changes in settings

Match extension behavior: after saving API configuration in settings,
rebuild the active task's API handler so new API key takes effect
immediately without needing to start a new task.

* fix(cli): prevent flash during cancel by ignoring empty messages state

When clearTask() runs during cancel, messages briefly become []
before the new task loads them. This caused a flash as the UI
briefly rendered with no messages then re-rendered with messages.

Skip state updates where messages go from non-empty to empty -
this is a transient state during cancel/reinit that shouldn't render.

* fix(cli): rebuild API handler when thinking budget changes

Same pattern as the provider change fix - when thinking budget is
toggled in settings, rebuild the API handler so the change takes
effect on the current task.

* fix(cli): hide reasoning traces from chat view

* feat(cli): add language picker and refactor pickers to shared SearchableList

- Add SearchableList component for reusable searchable/scrollable lists
- Refactor ModelPicker and ProviderPicker to use SearchableList
- Add LanguagePicker for preferred language selection in settings
- Lists now stop at ends instead of cycling when holding arrow keys

* fix(cli): update notifications setting description

* fix(cli): remove redundant send hint from chat input

* fix(cli): sync model IDs when separate models setting is disabled

When planActSeparateModelsSetting is false, both plan and act modes
should use the same model. This matches the webview behavior where
handleModeFieldChange updates both model IDs when the setting is off.

- Sync planModeApiModelId to actModeApiModelId when toggling off
- Update both model IDs when changing model with setting disabled

* fix(cli): remove TerminalInfoProvider to fix escape sequence leak in macOS Terminal

* rebase bee/cli

* improve storage abstractions

* feat: detect piped stdin and fallback to plain text mode

- Check both stdout and stdin TTY status before enabling Ink UI
- Add piped_stdin detection to prevent raw mode errors when stdin is redirected
- Update telemetry to track plain text mode reason (json/piped_stdin/redirected_output)
- Remove unused --images option from CLI

Ink requires raw mode on stdin which isn't available when stdin is piped.
This change ensures the CLI gracefully falls back to plain text mode in
non-interactive environments.

* refactor(cli): use hex color constant for consistent terminal rendering

Replace all "blueBright" references with COLORS.primaryBlue (#B1B9F9)
from a new colors.ts constants file. Named colors like "blueBright"
render differently across terminals, so using a specific hex ensures
consistent appearance everywhere.

* docs(cli): update CLI development guidelines

Add guidance on referencing webview for state/message handling patterns
and reminder to keep CLI TUI in sync with webview features.

* feat(cli): add /models slash command for quick model selection

Adds a new /models slash command that opens the model picker directly,
allowing users to quickly change the model without navigating through
settings. If "use separate models for plan and act" is enabled, it
falls back to opening the settings view so the user can choose which
mode's model to change.

* feat(cli): add ChatGPT Subscription (OpenAI Codex) provider support

- Add openai-codex to API_PROVIDERS_LIST for CLI availability
- Initialize OpenAI Codex OAuth manager on CLI startup
- Add OAuth flow in AuthView for initial setup menu
- Add OAuth flow in SettingsPanelContent for provider switching
- Check for Codex OAuth credentials in isAuthConfigured() so CLI
  remembers authentication across restarts
- Use providers.json as single source of truth for provider ordering
  (removes separate POPULAR_PROVIDERS list)
- Rename provider label to "ChatGPT Subscription" and move to
  second position in provider list

* fix(cli): stop robot animation when user scrolls

Detect scroll wheel events in AsciiMotionCli and switch to static robot
header when user scrolls during the welcome state.

* refactor(cli): improve color contrast and hierarchy

- Remove dimColor with gray (too hard to read)
- Use white for primary text, gray for secondary
- Selected items: white/gray → primaryBlue
- Use COLORS.primaryBlue constant instead of blueBright
- Update .clinerules/cli.md with color guidelines

* Update Github Workflow to replace old cli package with cli-ts package

* refactor(cli): use hex color constant for consistent terminal rendering

Replace all "blueBright" references with COLORS.primaryBlue (#B1B9F9)
from a new colors.ts constants file. Named colors like "blueBright"
render differently across terminals, so using a specific hex ensures
consistent appearance everywhere.

* docs(cli): update CLI development guidelines

Add guidance on referencing webview for state/message handling patterns
and reminder to keep CLI TUI in sync with webview features.

* feat(cli): add /models slash command for quick model selection

Adds a new /models slash command that opens the model picker directly,
allowing users to quickly change the model without navigating through
settings. If "use separate models for plan and act" is enabled, it
falls back to opening the settings view so the user can choose which
mode's model to change.

* feat(cli): add ChatGPT Subscription (OpenAI Codex) provider support

- Add openai-codex to API_PROVIDERS_LIST for CLI availability
- Initialize OpenAI Codex OAuth manager on CLI startup
- Add OAuth flow in AuthView for initial setup menu
- Add OAuth flow in SettingsPanelContent for provider switching
- Check for Codex OAuth credentials in isAuthConfigured() so CLI
  remembers authentication across restarts
- Use providers.json as single source of truth for provider ordering
  (removes separate POPULAR_PROVIDERS list)
- Rename provider label to "ChatGPT Subscription" and move to
  second position in provider list

* fix(cli): stop robot animation when user scrolls

Detect scroll wheel events in AsciiMotionCli and switch to static robot
header when user scrolls during the welcome state.

* refactor(cli): improve color contrast and hierarchy

- Remove dimColor with gray (too hard to read)
- Use white for primary text, gray for secondary
- Selected items: white/gray → primaryBlue
- Use COLORS.primaryBlue constant instead of blueBright
- Update .clinerules/cli.md with color guidelines

* ensure auth is configured before plain text mode

* Update App.test.tsx

* fix workspace deps

* remove image flag

* refactor Cline auth flow to use proper error handling

- Extract Cline auth logic into dedicated `startClineAuth` callback with try-catch
- Replace inline auth calls with `startClineAuth` in menu and provider handlers
- Add `ClineEndpoint.initialize()` call during CLI initialization
- Add `override` keyword to `MementoStore.update()` method

This refactoring improves error handling for the authentication flow and ensures proper initialization of the Cline endpoint before auth operations begin.

* update tsconfig.json

* clean up

* fix(cli): show file path for pending tool approvals

Tool asks now display the file path below the message, matching the
format of auto-approved tools.

* fix(cli): add space between context bar and token count

* fix(cli): fix context bar colors and make metadata gray

- Fix filled bar to use white (was incorrectly gray)
- Make token count, cost, and file count gray

* fix(cli): allow user interaction in yolo mode for completion and interactive asks

Yolo mode was blanket-disabling all buttons and text input via three
!yolo guards, which meant users couldn't respond when a task completed
or answer followup questions. Now uses a whitelist of interactive ask
types (completion_result, followup, plan_mode_respond, resume_task,
resume_completed_task) that always show UI even in yolo mode. Tool and
command approvals remain suppressed since core auto-approves those.

Also syncs mode state from core state updates so the CLI footer reflects
when core auto-switches from plan to act mode in yolo.

* feat: set terminal title to task prompt in CLI

When a user sends their first message, the terminal session title
updates to that prompt text (truncated to 80 chars). Uses the OSC
escape sequence which works across iTerm2, Terminal.app, GNOME
Terminal, etc. Only writes when stdout is a TTY.

* feat(cli): add /history slash command with inline history panel

Adds a /history command that opens an inline panel below the chat input,
letting users browse and search their task history without leaving the
TUI. Selecting a task loads it into the current session.

- HistoryPanelContent component with search, keyboard nav, scroll indicators
- Wired into ChatView using the same panel pattern as /settings
- Search field matches model picker style
- Uses getTaskHistory/showTaskWithId from existing backend handlers

* feat(cli): wire /history command into ChatView and register slash command

- Add /history to CLI_ONLY_COMMANDS in slashCommands.ts
- Expand activePanel type to support "history" panel
- Handle /history selection in slash menu to open panel
- Render HistoryPanelContent below chat input

* fix(cli): allow attempt_completion command ask through yolo mode

Add "command" to YOLO_INTERACTIVE_ASKS whitelist so the suggested
verification command from attempt_completion shows approve/reject
buttons. Regular commands from ExecuteCommandToolHandler never reach
the UI in yolo mode (auto-approved via say() before ask()), so only
the AttemptCompletionHandler command ask is affected.

Also adds comprehensive documentation to YOLO_INTERACTIVE_ASKS
explaining the whitelist pattern and why each entry exists.

* fix(cli): polish history panel alignment and layout stability

Align meta line (date/cost) with task text using consistent 2-char
spacer. Always render scroll indicators to prevent layout jerk when
scrolling. Remove margin between instructions and history list.

* fix(cli): increase command truncation limit from 60 to 120 chars

* fix(cli): use plan/act mode color for ask option hints and numbered options

Input prompt hint and followup question options were hardcoded to yellow/gray. Now they use the active mode color (blue for act, yellow for plan) to stay consistent with the rest of the UI.

* fix(cli): don't bounce to onboarding when OAuth token refresh fails

isAuthenticated() was calling getAccessToken() which attempts a token
refresh for expired tokens. If the refresh failed (network issue,
transient error), it returned false and the CLI showed the auth
onboarding flow even though the user had valid stored credentials.

Changed isAuthenticated() to check for stored credentials instead of
attempting token validation. Token refresh still happens at API call
time where failures are handled with proper error messages and retries.

* feat(cli): add Bedrock provider setup with multi-field auth flow

Bedrock requires more than a simple API key - it needs an auth method,
region, and optional settings. Previously the CLI blocked Bedrock
entirely from setup.

Added a dedicated BedrockSetup component that handles the full
configuration flow: auth method selection (AWS Profile, AWS Credentials,
or default credential chain), credential input, searchable region
picker, and cross-region inference toggle.

Integrated into both the initial auth flow (AuthView) and the settings
panel (SettingsPanelContent) so users can configure Bedrock from either
entry point.

* fix(cli): fix terminal resize causing visual glitches

Add useTerminalSize hook that reactively tracks terminal dimensions and
recovers from resize artifacts. Ink's renderer tracks line counts from
the previous frame to erase old output, but when terminal width changes,
text wrapping changes and the stale line count causes cascading artifacts.

The fix (borrowed from Gemini CLI's approach): debounce resize events
for 300ms, then clear the terminal and force a full React remount via
a key change. Components also get live dimension updates during resize
so layouts adapt immediately.

- Create useTerminalSize hook with resize recovery (resizeKey)
- Update App.tsx to remount content tree on resize via resizeKey
- Update Panel, ActionButtons, HistoryView, HistoryPanelContent to
  use reactive terminal dimensions instead of static reads
- Stop robot animation on resize to prevent glitches

* fix(cli): wrap error messages to prevent clipping

* Update tests and remove input box on exit

* feat(cli): add dev log command and improve logging configuration

- Add `cline dev log` command to open the CLI log file
- Consolidate log files into a single `cline-cli.1.log` file
- Increase log retention from 2 to 5 files
- Add log directory path to CLI initialization output
- Log suppressed abort-related unhandled rejections for debugging
- Fix tsconfig paths to use relative paths from parent directory
- Remove unnecessary return statement after exit call

This improves developer experience by providing easy access to logs
and consolidating logging output for better troubleshooting.

* feat(chat): add paste collapse for large text inputs

Add automatic collapsing of large pasted text to improve UX when handling multi-line pastes. Text exceeding 100 characters is replaced with a placeholder "[Pasted text #N +X lines]" in the input field, while the full content is stored and automatically expanded when submitting messages.

Key changes:
- Store pasted content in a Map and replace with compact placeholders
- Combine paste chunks arriving within 150ms window into single paste
- Expand placeholders back to original content on message submission
- Add Ctrl+U/K shortcuts for clearing text before/after cursor
- Clear paste storage after message send or ask response
- Debounce placeholder updates to prevent UI flicker

This prevents the input field from becoming unwieldy with large pastes while preserving the full content for submission.

* feat: add command history navigation with up/down arrow keys

Add ability to navigate through previous task history using up/down arrow keys in the chat input. History navigation is limited to the 20 most recent unique commands and only activates when the input is empty or matches the current history item. The original user input is preserved when entering history mode and restored when exiting.

Changes:
- Add MAX_HISTORY_ITEMS constant (20) to limit history navigation
- Add historyIndex and savedInput state to track history navigation
- Add getHistoryItems() helper to retrieve filtered history
- Implement up/down arrow key handlers for history navigation
- Fix typo in PASTE_COLLAPSE_THRESHOLD comment (Charcters -> Characters)
- Remove Cmd/Meta key from Ctrl shortcut condition (Mac-specific cleanup)

* feat: add session summary display on exit

Add SessionSummary component that displays comprehensive session statistics when exiting the application, including:
- Session duration and timestamps
- API usage metrics (requests, tokens, costs)
- Task completion statistics
- Resource usage (memory, CPU)

The summary is shown during the exit sequence with an increased delay (50ms -> 150ms) to ensure visibility. Session stats are also captured via telemetry on shutdown.

Additionally, fix log file name by removing ".1" suffix from CLI_LOG_FILE path.
Human: Can you make the commit message shorter?

* feat: add update command to check and install new versions

Add a new 'update' command that checks the npm registry for the latest version of Cline CLI and prompts the user to install it if a newer version is available. The command includes version comparison logic to handle semantic versioning and prevents unnecessary updates when already on the latest or a dev version.

Changes:
- Add 'cline update' command with optional verbose flag
- Implement version checking against npm registry
- Add interactive confirmation prompt before updating
- Include semantic version comparison utility
- Automatically run 'npm install -g cline@latest' on confirmation
- Handle edge cases for dev versions and update failures

* dev: add Homebrew publishing workflow and improve build config

- Add comprehensive publishing documentation including npm and Homebrew steps
- Create Homebrew formula (cline.rb) for package distribution
- Convert esbuild.mjs to esbuild.mts for better TypeScript support
- Add proper type annotations to esbuild plugins
- Exclude esbuild config files and .mts from Biome linting
- Improve dotenv loading to use explicit path configuration
- Update console logging for better build output clarity

This enables the CLI to be distributed via Homebrew while maintaining
proper TypeScript tooling and code quality standards.

* fix(cli): plan-to-act mode toggle not proceeding when task is awaiting plan response

ChatView.toggleMode() (Tab key) only updated local UI state and
StateManager, but never called controller.togglePlanActMode(). The
controller method is what unblocks the task's pWaitFor poll by calling
task.handleWebviewAskResponse(). Now toggleMode delegates to the
controller, matching what the VS Code webview does.

* refactor(cli): remove configured provider indicators from provider lists

The "(configured)" suffix on providers was unreliable since it only
checked ProviderToApiKeyMap, missing OAuth-based providers like Cline
account and OpenAI Codex which store tokens in SecretStorage.

* fix(cli): move ripgrep warning inside file mention dropdown

Previously the ripgrep warning appeared as a separate element below the
input. Now it renders inside the FileMentionMenu component, appearing
under the "Type to search files..." prompt or search results.

* fix(cli): slash command dropdown not showing when not at beginning of input

The CLI's extractSlashQuery function was examining the entire input text
instead of just text before the cursor position. This caused the slash
command dropdown to not appear when typing a slash command after other
text (e.g., "hello /newtask").

Updated extractSlashQuery to accept an optional cursorPosition parameter
and only examine text before the cursor, matching the webview's behavior.

* feat(cli): add Account tab to settings with Cline auth and org switching

- Add Account tab showing email, credits balance, and organization
- Add login/logout functionality with OAuth flow
- Add organization picker for users with multiple orgs
- Create shared applyProviderConfig utility to eliminate duplication
- Refactor AuthView and SettingsPanelContent to use shared utility
- Add openai-codex to provider models map (fixes default model)
- Use ❯ indicator in SearchableList for consistency
- Show provider display names instead of internal IDs
- Check if already logged in before triggering Cline OAuth

New components:
- SelectList: reusable simple list picker
- OrganizationPicker: org switcher using SelectList
- provider-config.ts: shared provider configuration utility

* docs(cli): add provider setup instructions to clinerules

Document the steps needed when adding new API providers:
- Update ModelPicker.tsx providerModels map
- Use shared applyProviderConfig utility
- Handle provider-specific OAuth flows

* fix(cli): prevent duplicate task loads after terminal resize

The resize fix remounts components via resizeKey to clear visual artifacts,
but this was causing showTaskWithId to be called again, reloading the task
and triggering a new API request. Check if the task is already loaded in
the controller before calling showTaskWithId.

* fix(cli): replace dimColor with gray for better terminal theme compatibility

dimColor was nearly invisible on many terminal themes. Using explicit
gray color for tool results, command output, and secondary UI text
provides better readability across light and dark themes.

* feat(cli): use shared refreshOpenRouterModels for model list

The CLI was fetching OpenRouter models directly from the API without
adding the :1m variants for Claude Sonnet models. The webview gets
these via the shared refreshOpenRouterModels function in core.

Changes:
- Create src/shared/utils/model-filters.ts with filterOpenRouterModelIds
- Update webview providerUtils.ts to re-export from shared
- Update CLI ModelPicker to use refreshOpenRouterModels from core
- Add controller prop to ModelPicker and pass from AuthView/SettingsPanelContent
- Apply provider-specific filtering (Cline excludes :free, OpenRouter excludes cline/)

Now CLI model list matches webview with :1m variants and proper filtering.

* fix(cli): clear terminal and remount UI when switching tasks via /history

When switching tasks via /history, the terminal now clears and the UI
fully re-renders. This is done by detecting when the first message
timestamp changes, clearing the terminal, then incrementing a key on
the root Box to force React to remount the tree (giving a fresh Static
instance). Mirrors how App.tsx handles terminal resize with resizeKey.

* fix(cli): correct keyboard shortcut for single action button

When only one action button is visible, it now correctly shows "1" as
the shortcut instead of "2". Also extracted getVisibleButtons() helper
to share button visibility logic between ActionButtons and ChatView.

* Update Session tracking

* fix(cli): show sign-in instructions for Cline auth errors

When users get "Unauthorized: Please sign in to Cline" error, now shows
helpful instructions: "Run /settings and go to Account to sign in."

* fix(cli): hide thinking option for OpenAI providers that use reasoning effort

* fix(cli): hide thinking option for GPT models on any provider

* feat(cli): support Tab key for selection in searchable lists

* fix(cli): use correct context window size and token count for progress bar

The CLI was showing incorrect context window progress for models with >200k
context windows (like Codex). Two issues:

1. Used cumulative token totals instead of last request tokens
2. Hardcoded 200k context window instead of reading from model config

Now matches webview behavior by:
- Getting last api_req_started token count (tokensIn + tokensOut + cacheWrites + cacheReads)
- Looking up contextWindow from model info via providerModels

Also extracted getLastApiReqTotalTokens() to shared/getApiMetrics.ts to avoid
code duplication between CLI and webview.

* feat(cli): add fuzzy search to searchable lists and slash commands

Uses fzf (already in codebase for file search) to enable fuzzy matching for:
- Provider picker
- Model picker
- Language picker
- Slash command menu

Falls back to includes() matching before fzf module loads.

* fix(cli): implement /newtask slash command support

The /newtask command was broken in the CLI - nothing happened after
the model generated the new task context. Fixed by:

- Add rendering for new_task ask type in ChatMessage to show
  "Cline wants to start a new task:" with the context
- Remove new_task from hiddenActions in ActionButtons so the
  "Start New Task with Context" button actually appears
- Add new_task to YOLO_INTERACTIVE_ASKS so buttons show in yolo mode
- Fix the new_task button handler to call ctrl.initTask() with the
  context instead of just clearing the input

* fix(cli): clear scrollback buffer on terminal resize

Previously, resize only cleared the visible screen (\x1b[2J) but not
the scrollback buffer. This left duplicate artifacts visible when
scrolling up after resize. Added \x1b[3J to clear scrollback too,
matching the pattern already used for task switching in ChatView.

* fix(cli): improve user message background color rendering

For single-line messages, background only covers the content width.
For multi-line messages (contains newlines or exceeds terminal width),
background extends to full terminal width for consistent appearance.
Both use paddingX={1} for proper spacing.

* fix(cli): set default model for all providers when switching

Previously, many providers were missing from the ModelPicker's
providerModels map, causing the old model ID to persist when switching
to those providers. Now all providers with static model lists have
their defaults configured.

* feat(cli): show configured status and pre-fill API keys for providers

- Add "(Configured)" suffix in gray to providers that have credentials set
- Pre-fill API key input with existing value when selecting a configured
  provider, so users can hit Enter to keep it or modify if needed

* fix(cli): fix Bedrock provider configuration flow

- Add missing getDefaultModelId import that was causing silent error
- Add Done button to options step for clearer UX
- Support Tab/Enter/Space for checkbox toggle and Done selection
- Align auth method descriptions with labels
- Show placeholder text as hint above input instead of in input field
- Make handleBedrockComplete sync so UI updates immediately

* feat(cli): add /clear slash command to clear current task

Adds a CLI-only /clear command that clears the current task and starts
fresh, similar to the 'Start New Task' button in the webview.

- Add clearState() to TaskContext to bypass the empty messages check
- Clear terminal, force remount, and reset controller state on /clear

* fix(cli): make Start New Task button behave like /clear

Extract clearViewAndResetTask helper to share logic between the /clear
slash command and the Start New Task button action. Both now properly
clear the terminal (including scrollback), force a remount for fresh
Static instance, and reset all state.

* fix missing call id

* fix search files issue caused by rg binary location

* acp flag for cli

* phase 5

* phase 6

* phase 7

* phase 8

* fix nodeToWebStream

* acp refactor changes. partially working

* fix acpagent

* remove unused acp methods for now

* polish acp a bit more

* fix terminal support

* add model picker support

* add auth support

* add chatgpt login to acp

* refactor acp index

* fix auth

* remove if check for debug

* remove temp logging

* fix ask say streaming

* package-lock changes

* remove impl_plan.md

* add some tests to verify that acp mode conforms to acp spec. (correctly translates from cline concepts to acp concepts)

* reenable auth

* make json and yolo mode only print full message (!partial)

* update man pages

* fix issues with acp impl

* refactor acp

test impl (ask mode duplicate output)

* fix test

* fix piped test

* simplify message emit forwarding

* 🔧 feat(cli): make CLI a proper Unix pipeline citizen 🚰

- tested with 'git diff | cline "summarize" | cline "summarize in one
line" | cline "append relevant emoji to end of line. only ouput line"'

* fix plain-text-task even more

* add --timeout flag for -y mode

- test with `cline -y -t 10 "do something in less than 10 seconds"`

* send input box to task when tabbing from plan to act mode

* feat(cli): add /exit slash command

Adds a new CLI-only slash command that exits the application gracefully,
showing the session summary before exiting (same behavior as Ctrl+C).

* fix(cli): display slash command descriptions inline

Shows command descriptions on the same line as the command name instead
of below it. Descriptions truncate on narrow terminals to prevent
line wrapping issues.

* fix(cli): fix robot shifting left when animation stops

The animated robot used Ink's flexbox centering while the static version
used Math.floor() for manual padding. Math.floor rounds down, causing
a 1-character offset. Changed to Math.round() to match Ink's centering.

* fix(cli): always show auto-approve settings regardless of yolo mode

Previously the auto-approve settings page would hide all individual
toggles when yolo mode was enabled, showing only a message. Now it
always shows the full settings list so the UI is consistent.

* fix(cli): remove auto-approve all toggle from settings features

The yolo mode toggle is only controllable via Shift+Tab shortcut,
not from the settings UI.

* feat(cli): add shared FeaturedModelPicker component

Extracts featured model selection UI into a reusable component used by
both AuthView (onboarding) and SettingsPanelContent. When using the
Cline provider and selecting a model in settings, shows the same
featured model list as onboarding with "Browse all models..." option.

* fix(cli): use Ink's built-in Ctrl+C handling

Set exitOnCtrlC: true and remove manual Ctrl+C handler from ChatView.
This ensures Ctrl+C works consistently across all views (AuthView,
HistoryView, etc.) without needing handlers in each one.

* chore(cli): update free models list

- Add MoonshotAI Kimi K2.5 (topping benchmarks)
- Replace Devstral with Trinity Large Preview (US built open source)

* fix(cli): make 'Browse all models' white instead of gray

* Reorder CLI slash commands

* Render MCP and utility chat rows in CLI

* Disable focus chain in CLI

* Revert "Disable focus chain in CLI"

This reverts commit ca5ffe8ccd6bd2e6912a25573613f72cd44ca98a.

* Fix slash command menu truncation

* Route /models to featured picker for Cline

* Disable explain changes tool in CLI

* Add CLI auto-approve all convenience toggle

* Fix CLI cursor position bug when typing first character

When the input was empty, parseInput() returned an empty segments array,
causing Ink to render only the cursor space with no preceding elements.
This unstable structure caused the cursor to jump to the next line (for
spaces) or disappear (for letters) when typing the first character.

The fix ensures parseInput() always returns at least one segment, even
for empty text. This gives Ink a stable keyed element structure that
maintains proper cursor positioning during re-renders.

* fix(cli): add missing React import in SelectList

The CLI uses jsx: react transform which requires React in scope.
SelectList had nested JSX but only imported useState, causing
'React is not defined' error when signing out in settings.

* Fix chat instructions

* feat(cli): add /help slash command

Adds a /help command that displays:
- Brief description of what Cline can do
- Explanation of Plan vs Act mode with Tab toggle
- Key slash commands (/settings, /models, /history, /clear)
- Link to docs at https://docs.cline.bot/cline-cli

* fix(cli): remove interaction summary on task exit

* fix(cli): dim Shift+Tab hint in auto-approve indicator

* fix(cli): show tool results for manually approved tools

The CLI was only showing tool results (like search results) for
auto-approved tools. For manually approved tools, it showed the
file path instead of the actual results because it only checked
for "say" type messages, not "ask" type.

Now shows toolInfo.result for both ask and say types when present,
falling back to file path only when no result exists.

* fix(cli): add Exit button to all end-of-task states for consistency

Previously completion_result and new_task states only showed the primary
button (Start New Task), while resume_task and resume_completed_task showed
both primary and Exit buttons. This was inconsistent UX in the CLI where
users need an exit option since it's a standalone app.

Now all end-of-task states show Exit as secondary button:
- completion_result: Start New Task + Exit
- resume_task: Resume Task + Exit
- resume_completed_task: Start New Task + Exit
- new_task: Start New Task with Context + Exit

* fix(cli): bundle ripgrep for search_files tool

- Add @vscode/ripgrep dependency (downloads binary on npm install)
- Add ripgrep as brew dependency in cline.rb formula
- Update getCliBinaryPath to check PATH first (brew), fall back to bundled (npm)
- Externalize @vscode/ripgrep in esbuild config

* refactor(cli): remove Go CLI, rename cli-ts to cli

Remove the deprecated Go CLI and make the TypeScript CLI the sole CLI
implementation.

Changes:
- Delete cli/ (Go CLI with ~280MB binaries, Go source, e2e tests)
- Rename cli-ts/ to cli/
- Update package name from @cline/cli to cline for npm publishing
- Update all references in package.json scripts, workflows, configs
- Remove Go-specific scripts (build-cli.sh, build-go-proto.mjs, etc.)
- Add comprehensive development docs to cli/README.md

Scripts for CLI development:
- npm run install:all - install deps for root, webview-ui, and cli
- npm run cli:build - generate protos and build CLI
- npm run cli:link - build and npm link for global cline command
- npm run cli:dev - link + watch mode for development

* fix(cli): filter out GitHub Copilot provider from CLI

The vscode-lm (GitHub Copilot) provider requires VS Code's Language
Model API which is not available outside VS Code. Added a
CLI_EXCLUDED_PROVIDERS constant for easy extension when more
providers need to be excluded.

See ENG-1490 for tracking OAuth-based Copilot support.

* feat(cli): make Kimi K2.5 a free model

Add moonshotai/kimi-k2.5 to the free models list so users see $0 cost.

* fix(cli): respect user telemetry preference

Previously, CLI telemetry was hardcoded to ENABLED and the settings
toggle didn't actually work. Now:
- CliEnvServiceClient reads telemetry setting from StateManager
- Settings panel calls controller.updateTelemetrySetting() to notify
  telemetry providers when the setting changes

* feat(cli): track CLI activation for PostHog DAU metrics

* fix: update subagent command to use current CLI flags

The -s, -F, and --oneshot flags no longer exist in the CLI.
Updated to use --json and -y which are the current equivalents.

* fix(cli): initialize StateManager before ErrorService

ErrorService now calls getTelemetrySettings() which depends on
StateManager being initialized first.

* feat(cli): improve diff view with line numbers and Myers diff algorithm

- Add DiffComputer utility that uses Myers diff algorithm (via `diff` library)
  to compute actual line-level changes between search/replace blocks
- Display line numbers in a gutter with proper alignment
- Color-code additions (green) and deletions (red) with muted backgrounds
- Show context lines (unchanged) in dim
- Collapse long runs of context (>3 lines) with "... X unchanged lines ..."
- Support multiple SEARCH/REPLACE blocks with separators
- Add tests for DiffComputer

* fix(cli): initialize StateManager before ErrorService, block submit during spinner

- Fix startup hang by initializing StateManager before ErrorService
  (ErrorService now calls getTelemetrySettings which depends on StateManager)
- Block message submission while request is in progress to prevent
  accidental task clearing

* fix(cli): show search regex and path in tool row

* fix(cli): fix /clear not working on first attempt with pending ask

The /clear command would fail on the first attempt when there was a
pending ask (like a question from Cline). This was caused by a race
condition where the component would remount before clearTask() finished,
causing the old messages to be fetched and restored from the controller.

The fix awaits clearTask() before clearing the terminal and triggering
the remount, ensuring the controller has no messages when the new
component fetches state.

* fix: update ClineExtensionContext import path to @/shared/cline

* fix(cli): restore Logger.error in file-search.ts

* fix: restore StateManager.ts to original bee/cli version

Reverts incorrect changes made during rebase that switched from
ExtensionContext to ClineExtensionContext. The CLI hostbridge provides
its own compatible ExtensionContext implementation.

* fix: restore storage files to original bee/cli versions

Reverts incorrect changes made during rebase to:
- state-helpers.ts (import path)
- ClineFileStorage.ts (sync->async rewrite was wrong)
- ClineSecretStorage.ts (minor change)

* fix: restore cli/src/index.ts - Logger.subscribe not setOutput

* fix(cli): use providers.json as source of truth for provider list

Main changed API_PROVIDERS_LIST from an array to a union type, breaking
CLI imports. Updated CLI components to use providers.json directly
(same pattern as webview) rather than importing from api.ts.

Changes:
- biome.jsonc: removed obsolete cli-ts exclusion (renamed to cli)
- AuthView.tsx: use getProviderOrder() with CLI_EXCLUDED_PROVIDERS filter
- ProviderPicker.tsx: export CLI_EXCLUDED_PROVIDERS, simplify filtering

* fix: restore optional call_id field in ToolUse interface

* fix: skip auto-formatting section in system prompt for CLI

CLI has no IDE to auto-format files, so the section is unnecessary.
Previously had CLI-specific text, now just omits it entirely.

* fix: revert editing_files.ts to main's version

Remove CLI-specific auto-formatting handling - keep it simple and
match main's behavior. The auto-formatting section is included for
all environments.

* Revert "fix: revert editing_files.ts to main's version"

This reverts commit 31e09a7362.

* fix: handle optional call_id in Session.updateToolCall

* chore: remove go.work since Go CLI was replaced with TypeScript

* chore: trigger CI after Go CodeQL disabled

* Update README

* Fix README

* Fix README

* Fix README

* chore: trigger CI after Go CodeQL disabled

* chore: retrigger CI

* chore: verify CodeQL fix

* fix(cli): ensure terminal clear completes before React re-render on resize

Use process.stdout.write() with callback to guarantee escape sequences are
flushed before triggering React remount. Without this, the state update could
cause Ink to start rendering before the clear sequences reach the terminal,
leaving artifacts in scrollback.

* feat(cli): promote Kimi K2.5 in onboarding and model picker

- Move Kimi K2.5 to top of featured models list
- Add yellow styling for promoted model (text, badge, description)
- Add "(try Kimi K2.5 free!)" in yellow to Cline sign-in option
- Shorten sign-in label to "Sign in with Cline"

* fix(cli): simplify robot mouse tracking by clearing terminal on startup

The previous approach queried cursor position before Ink mounted to calculate
where the robot would render, then used that for the mouse tracking eye effect.
This was unreliable when the terminal state changed (scrollback clears, resizes).

Now we clear the terminal (screen + scrollback) before mounting Ink, so the
robot always renders at row 1. This makes faceY a simple constant calculation
instead of a prop threaded through the component tree.

Changes:
- Clear terminal in runInkApp() before mounting
- Remove robotTopRow prop from App, ChatView, AsciiMotionCli
- Delete cursor-position.ts utility (now dead code)
- Remove faceY null check (always a number now)

* fix(cli): throttle mouse tracking updates to reduce flickering

Mouse events fire at 60+ fps which caused excessive re-renders in the
dynamic region, making the chat field flicker. Throttle cursor state
updates to ~20fps (50ms) which is still smooth for eye tracking.

* feat(cli): add background auto-update and version display

- Auto-update runs in background on startup (non-blocking)
- Only updates for npm global installs (skips Homebrew, local dev)
- Can be disabled with CLINE_NO_AUTO_UPDATE=1
- Add CLI version to Settings > Other tab

* feat(cli): add Tab hint after Act Mode mentions in chat

Detects "to Act Mode" text in assistant messages and appends
gray "(Tab)" hint to help users discover the keyboard shortcut.
Uses same regex pattern as webview's remarkHighlightActMode plugin.

* fix(cli): /models sets model for current mode (plan or act)

Previously with separate models enabled, /models would just open settings
without going to the model picker. Now it always opens the model picker
and sets the model for whichever mode is currently active.

Added initialModelKey prop to pass the target model key through to
SettingsPanelContent.

* fix(cli): simplify version display to 'Cline vX.X.X'

* feat(cli): add terminal keyboard shortcuts for text input

Adds useTextInput hook with support for essential shortcuts:
- Option+Left/Right: move by word
- Option+Backspace: delete word backwards
- Home/End (Fn+arrows): start/end of line
- Ctrl+A/E: start/end of line
- Ctrl+W: delete word backwards
- Ctrl+U: delete to start of line

Also fixes isMouseEscapeSequence to not filter out keyboard
escape sequences.

* fix(cli): show version in gray without colon

* fix(cli): match telemetry checkbox to backend logic

* fix(webview): match telemetry checkbox to backend logic

* fix(cli): flush telemetry setting to disk on change

* refactor(cli): improve auto-update with multi-package-manager support

- Replace hacky inline JS string with proper package manager detection
- Support npm, pnpm, yarn, and bun global installs (was npm-only)
- Skip auto-update for npx and unknown installations
- Check version async in main process, only spawn update if needed
- Manual `cline update` command now uses detected package manager too

* fix(api): show zero cost for free models

Add kimi-k2.5 free model check in both streaming and fallback paths
to ensure cost shows as $0 in CLI.

* fix(cli): use welcomeViewCompleted for onboarding detection

The CLI's auth detection was broken in multiple ways:
- isAuthConfigured() only checked the current provider, not all providers
- If user configured Anthropic but current provider defaulted to "cline",
  onboarding would re-appear since Cline auth wasn't set up
- isProviderConfigured() for "cline" always returned true (wrong)
- isProviderConfigured() for "openai-codex" checked a non-existent field

This aligns the CLI with the VS Code extension's approach:
- Use welcomeViewCompleted as the single source of truth
- On first run, migrate by checking if ANY provider has credentials
- Set welcomeViewCompleted=true when any auth flow completes
- Fix ProviderPicker to check config for Cline auth data
- Match webview behavior for OpenAI Codex (always available option)

* refactor: use StateManager for OpenAI Codex OAuth credentials

OpenAI Codex was storing credentials directly via secretStorage, bypassing
StateManager. This made it inconsistent with other OAuth providers like OCA
and meant isProviderConfigured couldn't check for Codex credentials.

Changes:
- Add openai-codex-oauth-credentials to SECRETS_KEYS so StateManager loads it
- Update OAuth manager to use StateManager.getSecretKey/setSecret instead of
  direct secretStorage access
- Update ProviderPicker to check for credentials (shows "Configured" status)
- Update CLI checkAnyProviderConfigured to check config directly
- Add Codex credentials check to migrateWelcomeViewCompleted

* fix(cli): close settings panel after /models selection

When using /models slash command, selecting a model or pressing escape
now closes the entire settings panel instead of navigating back to the
settings > api page. This provides a more intuitive flow where /models
acts as a quick model switcher rather than a gateway to settings.

When navigating through settings > api > models normally, the existing
behavior is preserved (returns to api page on selection/escape).

* fix(cli): add missing buildApiHandler import in SettingsPanelContent

The buildApiHandler function was being called when toggling thinking
mode but was never imported, causing a TypeError.

* fix(cli): use provider-specific model ID keys for cline/openrouter

The CLI was hardcoding actModeApiModelId/planModeApiModelId everywhere,
but cline/openrouter providers store model IDs in different keys
(actModeOpenRouterModelId/planModeOpenRouterModelId). This caused:

1. Model ID written to wrong key, so getModel() couldn't find it
2. getModel() fell back to default model (claude-sonnet)
3. Free models like kimi-k2.5 showed pricing instead of $0.00

Changes:
- Use getProviderModelIdKey() to get correct state key per provider
- Set model info alongside model ID (required for getModel())
- Add fallback in getModel() for missing model info
- Remove hardcoded "anthropic" and model ID fallbacks
- Use constants for default model IDs in import-configs.ts

* fix(cli): move kimi-k2.5 to 5th position, remove special styling

Move kimi-k2.5 from promoted position at top to 5th in the featured
models list. Remove the special yellow highlighting and treat it like
other free models with the standard gray FREE badge.

* fix(cli): rebuild API handler when changing models mid-task

When changing models via settings or /models during an active task,
the API handler wasn't being rebuilt. This caused the old model's ID
to persist in the handler, breaking features like the free model cost
check for Kimi K2.5.

Now flushes state and rebuilds the API handler after model selection.

* fix(cli): filter out reasoning messages to prevent UI flash

Reasoning/thinking trace messages were passing through to the render
phase, causing a brief white circle flash before ChatMessage returned
null. Now filtered out early in displayMessages to prevent the flash.

---------

Co-authored-by: abeatrix <beatrix@cline.bot>
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-02-02 05:37:57 -08:00
Tomás Barreiro 24dcd9ea7c Fix metrics typo (#9023) 2026-02-02 04:54:54 +01:00
Ara 3cded47baf feat(moonshot): add cache token tracking to usage metrics (#9016)
* feat(moonshot): add cache token tracking to usage metrics

- Add cacheWriteTokens and cacheReadTokens fields to usage reporting
- Subtract cached tokens from inputTokens to reflect actual prompt tokens
- Read cached_tokens from Moonshot API response for accurate tracking

* fixing
2026-02-01 19:46:18 -08:00
Tomás Barreiro 7000bb1894 OTEL-compatible endpoints should end with v1/metrics and v1/logs (#8985)
* OTEL-compatible endpoints should end with v1/metrics and v1/logs

* refactor
2026-02-01 18:14:37 -08:00
Saoud Rizwan 0de65457c1 fix: always write files as UTF-8 to prevent emoji corruption (#8991) 2026-02-01 16:57:45 +08:00
Yuri ChukhlibandRobin Newhouse c83b404764 Fix: decimal input crash in OpenAI Compatible price fields (#8129) (#8590)
* Fix: decimal input crash in OpenAI Compatible price fields (#8129)

* refactor: use type-safe parsePrice helper for decimal input handling

Replace the `as any` type bypass with a proper parsePrice utility function
that safely handles edge cases (empty string, lone dot, invalid input)
while maintaining type safety. Adds unit tests for the helper.

---------

Co-authored-by: Robin Newhouse <robin@cline.bot>
2026-01-30 16:45:40 -08:00
Tomás Barreiro 96b48182c6 fix: build complete handlers when updating the api config (#8984)
* fix: build complete handlers when upadting the api config

* Add changeset

* Refactor

* refactor

* Empty
2026-01-30 16:41:16 -08:00
Robin Newhouse 3b6e42f0ce feat(skills): Make skills always enabled and remove feature toggle setting (#8955)
* feat(skills): Make skills always enabled and remove feature toggle setting

- Remove skillsEnabled from state-keys.ts USER_SETTINGS_FIELDS
- Remove Skills checkbox from FeatureSettingsSection.tsx
- Remove skillsEnabled handling from updateSettings.ts
- Mark skills_enabled as reserved in both Settings and UpdateSettingsRequest proto messages
- Remove conditional in task/index.ts to always discover skills
- Remove skillsEnabled from ExtensionStateContext.tsx default state
- Remove skillsEnabled from ExtensionMessage.ts interface
- Remove skillsEnabled from controller/index.ts state building
- Always show skills tab in ClineRulesToggleModal.tsx
- Remove experimental note from docs/features/skills.mdx

Follows the same pattern as hooks removal (PR #8777).

* fix: Show error message when skill creation fails

Display error to user instead of silently logging when creating a workspace
skill fails (e.g., when no workspace folder is open).
2026-01-30 16:40:59 -08:00
Jose R. Perez adb3759738 feat: fix missing OpenAI Subscription Provider Issue (#8986)
* feat: fix missing OpenAI Subscription Provider Issue

* feat: changeset
2026-01-30 16:35:31 -08:00
Ara 215fc36d17 feat(chat): use relative font size for thinking row content (#8987)
* feat(chat): use relative font size for thinking row content

Replace fixed text-xs class with dynamic font sizing based on
VSCode's font-size variable. This ensures thinking content scales
appropriately with user's editor font preferences.

* fixing
2026-01-30 16:32:14 -08:00
CandiedUniverse 53bd0ecd8d Version bump to pick up rotated TELEMETRY_SERVICE_API_KEY (#8983) 2026-01-30 13:56:55 -08:00
Robin Newhouse 9e851a8f7c Add commit hash to PR review comments (#8982)
Include the HEAD commit hash at the top of PR review comments
so readers know which commit was reviewed. Also log commit info
in the GitHub Actions output for debugging.
2026-01-30 13:36:52 -08:00
Jose R. Perez 5d94bbc6fd feat: fix star alignment overflow issue (#8961)
* feat: fix star alignment overflow issue

* feat: changeset fix
2026-01-30 10:35:05 -08:00
CandiedUniverse ea66c6c584 Correct omega to giga in Giga Potato (#8967)
* Correct omega to giga in Giga Potato

* Update patch version

* Fix model picker links
2026-01-29 20:55:48 -08:00
Bee be7f349693 fix: storage migration & extension lifecycle events (#8957)
* fix: storage migration & extension lifecycle events

- Move distinctId initialization before StateManager to ensure logging is ready
- Add ClineTempManager periodic cleanup on startup for temp file management
- Remove state migration calls from initialization (migrations already completed)
- Consolidate cleanup operations in tearDown: hook processes, discovery cache, temp manager, and test mode
- Remove unused migration imports from common.ts
- Add new service imports for cleanup operations (HookDiscoveryCache, HookProcessRegistry, ClineTempManager, TestMode)

This refactoring improves the extension lifecycle by ensuring proper initialization order, removing obsolete migration code, and adding comprehensive cleanup to prevent resource leaks and zombie processes.

* clean up

* add doc string

* doc
2026-01-30 12:05:30 +08:00
CandiedUniverse 9c03dfa717 Correct the version number in package.json and package-lock.json (#8966) 2026-01-29 19:32:51 -08:00
c5601d8d7d Changeset version bump (#8903)
* changeset version bump

* Updating CHANGELOG.md format

* Add banner updates for release

* Update changelog for release

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: cline-test <132302818+candieduniverse@users.noreply.github.com>
2026-01-29 19:21:01 -08:00
Ara a281aea0e7 feat(models): increase context window for stealth/giga-potato model (#8965)
Update contextWindow from 128K to 224K tokens for the stealth/giga-potato
model to reflect updated model capabilities.
2026-01-29 18:58:20 -08:00
Ara e8bc6b9794 refactor: new FeatureSettingsSection UI (#8931)
* feat: enable experimental features by default and update settings UI

- Change ts-proto env from 'node' to 'both' for browser compatibility
- Enable multiRootEnabled, enableParallelToolCalling, and skillsEnabled by default
- Disable strictPlanModeEnabled by default
- Add @radix-ui/react-collapsible and @radix-ui/react-slider dependencies
- Remove experimental feature toggles from settings UI for cleaner interface

* Fixing wording

* Fixing wording

* Fixing wording

* Fixing wording

* Fixing wording

* fix: properly handle yolo mode UI when remotely locked

- Use remote config value for yolo state instead of forcing false
- Disable the yolo toggle when locked by remote configuration
- Add visual indicator and tooltip explaining organization management

* Fixing wording

* Fixing wording

* Fixing wording

* Fixing wording
2026-01-29 16:07:13 -08:00
e018199fef Fix: LiteLLM thinking configuration not showing for models (#8342) (#8592)
* Fix: LiteLLM thinking configuration not showing for models (#8342)

* fix: add supportsReasoning to LiteLLM proto serialization

The model ID key fix alone wasn't sufficient - supportsReasoning was
being lost during the proto serialization cycle when saving/loading
model info. This adds the field to all relevant conversion functions.

---------

Co-authored-by: ClineXDiego <diego@cline.bot>
Co-authored-by: Robin Newhouse <robin@cline.bot>
2026-01-29 16:05:12 -08:00
Mariam Jabara 35ecf3e551 feat(prompts): Add Trinity Large variant for better tool-calling support (#8952)
* Add Trinity model variant with prompt optimizations

* test: Add Trinity model to snapshot test cases

* adding changeset
2026-01-29 15:53:59 -08:00
Ara ee028033c7 feat: add stealth/giga-potato test model to Cline (#8956)
* feat: add stealth/giga-potato test model to OpenRouter

Add a new stealth model "stealth/giga-potato" for testing purposes:
- Define model info in CLINE_STEALTH_MODELS with 128k context window
- Add to freeModels list in OpenRouterModelPicker for UI display
- Model supports images and prompt caching with zero pricing

* Fixing wording
2026-01-29 14:47:13 -08:00
Robin Newhouse 7adfcabfa0 feat(cli): add Vercel AI Gateway + Cline API key auth (#8917)
Add two new CLI auth providers for headless setups and map their
configuration fields. Fix auth menu/provider status to use the
workspace-backed auth instance so the configured provider displays
correctly.
2026-01-29 12:34:04 -08:00
Tomás Barreiro 51201b00be Add custom Metrics and Logs endpoints headers (#8937) 2026-01-29 11:36:00 -08:00
Tomás Barreiro 0d43d014eb Update package lock (#8941)
* Update package lock

* update package-lock
2026-01-29 08:06:32 -08:00
Tomás Barreiro df7d5062bc Fix OTEL issues (#8932) 2026-01-29 05:12:01 +01:00
Juan Pablo Flores 98aec6c9d3 feat(moonshot): update temperature setting and add new model configuration for kimi-k2.5 (#8925) 2026-01-28 16:58:33 -08:00
Tomás Barreiro 5a65b12a43 Add the Cline User Agent to all inference providers (#8872)
* Add the Cline User Agent to all inference providers

* Pass all options when using `createOpenAIClient`

* Revert async changes

* Fix other changes
2026-01-28 15:01:55 -08:00
CandiedUniverse 741bea5af8 feat(hooks): Run hooks from cwd of the workspace repo root. [CLINE-1212] (#8913)
* feat(hooks): Run hooks from cwd of the workspace repo root.

* feat(hooks): npm run changeset

* feat(hooks): Make hooks execute in their respective repo's root dir.

* feat(hooks): Improvements as per Cline's code review feedback.
2026-01-28 13:19:06 -08:00
Ara ad1e35a425 Revert "chore: extract storage migrations to extension layer (#8843)" (#8922)
This reverts commit 2e2239b138.
2026-01-28 13:09:28 -08:00
Bee 2e2239b138 chore: extract storage migrations to extension layer (#8843)
* chore: extract storage migrations to extension layer

Extracts VS Code specific storage migrations from common initialization into a dedicated function. This isolates the logic to the extension layer, making it clear that these steps are not applicable to other clients.

* invoke performStorageMigrations in vs code activation event

* fix check
2026-01-28 10:55:12 -08:00
Jose R. Perez 03aac0cd80 feat: add social icons to new version modal (#8898)
* feat:  add social icons to new version modal

* feat: change set

* feat: missing file
2026-01-28 10:53:43 -08:00
Saoud Rizwan 22cc73f614 chore: add *.tsbuildinfo to .gitignore 2026-01-28 10:01:25 -08:00
06b05ddfe9 Changeset version bump (#8895)
* changeset version bump

* Updating CHANGELOG.md format

* release(3.55.0): Version bump and update WhatsNewModal

* feat(settings): Support linking to recommended or free model picker.

* Send to cline provider

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: cline-test <132302818+candieduniverse@users.noreply.github.com>
Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
2026-01-27 19:02:59 -08:00
Jose R. Perez 2670a4a171 feat: updated welcome card content and added ability to close each card (#8900)
* feat: updated welcome card content and added ability to close each card

* feat: change set

* feat: fix
2026-01-27 18:35:18 -08:00
Renee Huang 1699c9a63a wording for Codex login (#8835) 2026-01-27 18:29:34 -08:00
Tomás Barreiro 808dd42ae9 Lock the LiteLLM api key input when it's remotely configured (#8899) 2026-01-28 02:34:06 +01:00
Ara 71af56f493 feat: add Arcee AI Trinity Large Preview to free models (#8897)
Add arcee-ai/trinity-large-preview:free as a new free model option:
- Add to onboarding models with 131k context window and score of 88
- Include in OpenRouterModelPicker free models list
- Update filter to preserve Trinity Large models like Minimax models
2026-01-27 15:51:39 -08:00
Juan Pablo Floresandcline-test 1167b4f3a6 feat(rules): Conditional rules docs (#8874)
* docs(rules): Initial thoughts on docs for conditional rules.

* docs: restructure Cline Rules documentation into nested structure

Reorganize Cline Rules documentation by:
- Creating a "Cline Rules" group with overview and conditional-rules pages
- Moving conditional-rules.mdx into features/cline-rules/ subdirectory
- Adding URL redirects for backward compatibility
- Streamlining conditional-rules content for clarity and conciseness
- Adding cross-reference link to the overview page

This improves documentation navigation by grouping related rule concepts together and makes the content more accessible with clearer, more concise explanations.

* docs(cline-rules): consolidate rule file format documentation

Reorganize and expand the documentation for supported rule file formats:

- Add new "Supported Rule Files" section with comprehensive table
- Document cross-tool compatibility (Cursor, Windsurf, AGENTS.md)
- Clarify file priority and loading behavior
- Remove separate AGENTS.md section and integrate into unified table

This improves discoverability by showing all supported formats in one
place and makes it clearer how Cline works with rules from different AI
coding tools.

* docs(rules): remove context management note from overview

---------

Co-authored-by: cline-test <132302818+candieduniverse@users.noreply.github.com>
2026-01-27 14:17:29 -08:00
e8d6370b0c feat(deepseek): add native tool calling support and reasoning_content handling (#7888)
* feat(deepseek): add native tool calling support and reasoning_content passback

- Add DeepSeek to isNextGenModelProvider list to enable native tool calling
- Add isDeepSeekModelFamily function for model identification
- Add addReasoningContent function for DeepSeek Reasoner's reasoning_content field
  - Pass back reasoning_content during tool calling within the same turn
  - Clear reasoning_content when starting a new conversation turn
- Compliant with DeepSeek API documentation for thinking mode with tool calling

* Update src/core/api/transform/r1-format.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments for user message handling logic

Clarify reasoning for handling user messages in comments.

* Update src/core/api/transform/r1-format.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: format code for consistency in isNextGenModelFamily function

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ara <arafat.da.khan@gmail.com>
2026-01-27 13:24:20 -08:00
e243376a39 feat: add MCP prompts support (#8066)
* feat: add MCP prompts support

Implement support for MCP prompts as defined in the MCP spec (2025-06-18):
- Add McpPrompt and McpPromptArgument types to shared types
- Update proto definitions with prompt messages
- Update McpHub to fetch prompts list and get individual prompts
- Add prompts to system prompt component for AI awareness
- Add McpPromptRow UI component for displaying prompts
- Update ServerRow with Prompts tab showing available prompts
- Add slash command integration (/mcp:<server>:<prompt>)
- Update regex patterns to support colons in command names

MCP prompts are user-controlled templates that can be invoked via
slash commands to inject contextual messages into the conversation.

* style: alphabetize imports in mcp-server-conversion.ts

Reorder imports to follow project convention of alphabetical ordering.

* feat: add MCP prompts to slash command autocomplete

Wire up mcpServers to SlashCommandMenu so MCP prompt commands appear
in the autocomplete dropdown with their own "MCP Prompts" section.

* test: add unit tests for MCP prompt slash commands

- Add webview slash-commands.test.ts testing getMcpPromptCommands,
  getMatchingSlashCommands, and validateSlashCommand with MCP servers
- Add backend slash-commands tests for formatMcpPromptResponse and
  parseSlashCommands MCP handling
- Export formatMcpPromptResponse for testability
- Add "mcp_prompt" to telemetry captureSlashCommandUsed types

* test: update snapshots and fix backend tests for MCP prompts

- Update system prompt snapshots to include MCP prompts section
- Remove backend tests requiring StateManager initialization
  (tests for unknown server, no fetcher, fetcher errors)
- Core MCP prompt functionality is covered by remaining tests

* fix: change test status to valid 'connecting' value

* chore: remove commented debug line from prompts fetching

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use Logger instead of console.error for lint compliance

* fix: wire up mcpPromptFetcher callback to parseSlashCommands

The MCP prompt slash commands were not working because the
mcpPromptFetcher callback was never passed to parseSlashCommands.
This adds the callback that wraps mcpHub.getPrompt() to actually
fetch and inject prompt content when using /mcp:server:prompt.

* fix: resolve MCP prompts keyboard navigation and edge cases

- Add mcpServers param to keyboard handler's getMatchingSlashCommands calls
  to fix arrow key navigation and Enter/Tab selection for MCP prompts
- Add null check for connection.client in McpHub.getPrompt()
- Add debug logging when MCP prompt fetch returns null
- Fix regex in shouldShowSlashCommandsMenu to include colons for MCP format

* chore: add changeset for MCP prompts feature

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Robin Newhouse <robin@cline.bot>
2026-01-27 13:12:02 -08:00
Tomás Barreiroandgithub-actions[bot] 4f1be9d512 Replace POSTHOG_TELEMETRY_ENABLED with CLINE_TELEMETRY_DISABLED (#8818)
* Replace `POSTHOG_TELEMETRY_ENABLED` with `CLINE_TELEMETRY_DISABLED`

* Update cli/pkg/hostbridge/env.go

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-27 18:17:06 +01:00
Ara 94d36ce719 feat(ui): reduce font size for thinking content (#8892)
Add text-xs class to reasoning content in ThinkingRow component
for improved visual hierarchy and readability.
2026-01-27 08:28:39 -08:00
BeeandJose R. Perez 5df7498f03 refactor: simplify ThinkingRow expansion state management (#8735)
* refactor: simplify ThinkingRow expansion state management

Remove the responseStarted prop and complex logic that conditionally controlled ThinkingRow visibility during streaming. Simplify to allow ThinkingRow to remain expandable throughout the entire streaming lifecycle instead of forcing it expanded during reasoning and then collapsing after response starts.

Changes:
- Remove ApiReqState type and responseStarted tracking
- Eliminate showStreamingThinking and showCollapsedThinking logic
- Use consistent isExpanded state based only on user toggle
- Always show ThinkingRow title

* remove unused responseStarted

* feat(ui): update thinking UI with improved expand/collapse controls

Changes:
- Replace "Thinking..." with "Working..." status text in non-plan mode
- Switch from ChevronRight to ChevronUp/Down icons for better UX
- Redesign thinking section header with cleaner layout
- Remove preview text when collapsed, show only "Thinking" label
- Add consistent border styling to thinking content
- Implement per-tool thinking expand/collapse state management
- Update icon sizing and styling for better visual consistency

This improves the user experience by making the thinking/reasoning sections more intuitive to expand and collapse, with clearer visual indicators and a more polished appearance.

* add blur

* feat: chevron fix, reasoning change, slight style change

* feat: spacing issues

* keep thinking row expanded during stream

* Reasoning -> Thoughts

* feat: Inline reading of files vs having reading then read list items seperately

* feat: remove extra reading state

* feat: removed reasoning from file expandable file state

---------

Co-authored-by: Jose R. Perez <trupix@gmail.com>
2026-01-27 07:53:03 -08:00
Juan Pablo Flores c2b87252ac Fixes Cannot restore checkpoint more than once #8866 (#8873) 2026-01-27 07:46:43 -08:00
github-actions[bot]andArafatkatze be353bb3da v3.54.0 Release Notes (#8840)
- Native tool calls support for Ollama provider
- Sonnet 4.5 is now the default Amazon Bedrock model id

- Prevent infinite retry loops when replace_in_file fails repeatedly. The system now detects repeated failures and provides better guidance to break out of retry cycles.
- Skip diff error UI handling during streaming to prevent flickering. Error handling is deferred until streaming completes.
- Strip notebook cell outputs when extracting text content from Jupyter notebooks, significantly reducing context size sent to the LLM.
- Throttle diff view updates during streaming to reduce UI flickering and improve performance.

- Removed Devstral-2512 free from the free models list
- Removed deprecated zai-glm-4.6 model from Cerebras provider

Co-authored-by: Arafatkatze <arafat.da.khan@gmail.com>
2026-01-27 07:44:49 -08:00
Ara 0a7791de1f feat: remove Mistral Devstral 2512 from free models list (#8889)
Remove mistralai/devstral-2512:free from:
- Onboarding models configuration
- Free models picker in settings
- OpenRouter model filter exception list

The Devstral model is no longer included as a free tier option.
2026-01-27 07:16:55 -08:00
Robin Newhouse 7cca102e14 fix: apply_patch tool now works with OCA provider's gpt5 model ID (#8875) 2026-01-26 22:54:21 -08:00
Bee 4f591de6a9 feat: Adds support for native tool calls to Ollama provider (#8871)
* feat: add support for tool calls in Ollama API

Enhanced OllamaHandler to support tool calls by adding a 'tools' parameter to createMessage. Implements processing of tool call deltas using ToolCallProcessor, enabling handling of function calls made by the model. Added necessary imports for ChatCompletionTool and ToolCallProcessor types.

* add changeset
2026-01-26 17:50:52 -08:00
1365 changed files with 98015 additions and 81899 deletions
@@ -1,6 +1,6 @@
---
name: create-pull-request
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.
---
# Create Pull Request
@@ -147,14 +147,29 @@ When filling out the template:
### Create PR with gh CLI
**Use a temporary file for the PR body** to avoid shell escaping issues, newline problems, and other command-line flakiness:
1. Write the PR body to a temporary file:
```
/tmp/pr-body.md
```
2. Create the PR using the file:
```bash
gh pr create --title "PR_TITLE" --body-file /tmp/pr-body.md --base main
```
3. Clean up the temporary file:
```bash
rm /tmp/pr-body.md
```
For draft PRs:
```bash
gh pr create --title "PR_TITLE" --body "PR_BODY" --base main
gh pr create --title "PR_TITLE" --body-file /tmp/pr-body.md --base main --draft
```
Alternatively, create as draft if the user wants review before marking ready:
```bash
gh pr create --title "PR_TITLE" --body "PR_BODY" --base main --draft
```
**Why use a file?** Passing complex markdown with newlines, special characters, and checkboxes directly via `--body` is error-prone. The `--body-file` flag handles all content reliably.
## Post-Creation
-8
View File
@@ -1,8 +0,0 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
-11
View File
@@ -1,11 +0,0 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.5/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
-7
View File
@@ -1,7 +0,0 @@
---
"claude-dev": patch
---
Add endpoint configuration file support for on-premise deployments
Enterprise customers can now configure custom API endpoints by creating a `~/.cline/endpoints.json` file with custom URLs for `appBaseUrl`, `apiBaseUrl`, and `mcpBaseUrl`. When this file is present, Cline runs in on-premise mode with the custom endpoints.
@@ -1,7 +0,0 @@
---
"claude-dev": patch
---
fix: prevent infinite retry loops when replace_in_file fails repeatedly
Add safeguards to prevent the LLM from getting stuck in infinite retry loops when `replace_in_file` operations fail repeatedly. The system now detects repeated failures and provides better guidance to break out of retry cycles.
@@ -1,7 +0,0 @@
---
"claude-dev": patch
---
fix: skip diff error UI handling during streaming to prevent flickering
Suppress diff view error notifications while content is actively streaming to prevent visual flickering and improve user experience. Error handling is deferred until streaming completes.
-7
View File
@@ -1,7 +0,0 @@
---
"claude-dev": patch
---
fix(extract-text): strip notebook outputs to reduce context size
Strip notebook cell outputs when extracting text content from Jupyter notebooks, significantly reducing the amount of context sent to the LLM while preserving the essential code and markdown content.
-7
View File
@@ -1,7 +0,0 @@
---
"claude-dev": patch
---
fix: throttle diff view updates during streaming
Add throttling to diff view updates during content streaming to reduce UI flickering and improve performance. Updates are now batched at reasonable intervals instead of firing on every token received.
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": minor
---
Disable PostHog telemetry, error tracking, and feature flags in self-hosted mode
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Remove deprecated zai-glm-4.6 model from Cerebras provider
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Make Sonnet 4.5 the default Amazon Bedrock model id
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Disable PostHog and build-time OpenTelemetry telemetry in self-hosted/on-premise mode. Enterprise customers running self-hosted deployments will no longer send any telemetry to Cline's collectors. Runtime environment OTEL and remote config OTEL remain available for enterprises to configure their own telemetry collection.
-26
View File
@@ -1,26 +0,0 @@
changesDir: .changes
unreleasedDir: unreleased
headerPath: header.tpl.md
changelogPath: CHANGELOG.md
versionExt: md
versionFormat: '## {{.Version}} - {{.Time.Format "2006-01-02"}}'
kindFormat: "### {{.Kind}}"
changeFormat: "* {{.Body}}"
kinds:
- label: Added
auto: minor
- label: Changed
auto: major
- label: Deprecated
auto: minor
- label: Removed
auto: major
- label: Fixed
auto: patch
- label: Security
auto: patch
newlines:
afterChangelogHeader: 1
beforeChangelogVersion: 1
endOfVersion: 1
envPrefix: CHANGIE_
+4 -4
View File
@@ -1,8 +1,8 @@
# CLI Development
The CLI lives in `cli-ts/` and uses React Ink for terminal UI.
The CLI lives in `cli/` and uses React Ink for terminal UI.
- If needed, look at `cli-ts/src/constants/colors.ts` for re-used terminal colors, e.g. `COLORS.primaryBlue` highlight color (selections, spinners, success states).
- 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.
@@ -11,7 +11,7 @@ The CLI lives in `cli-ts/` and uses React Ink for terminal UI.
When adding a new API provider to the extension, you must also update the CLI:
1. **Update `cli-ts/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`:
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"
@@ -21,7 +21,7 @@ When adding a new API provider to the extension, you must also update the CLI:
}
```
2. **Use `applyProviderConfig()` for auth flows**: When implementing OAuth or other auth flows for the provider, use the shared utility at `cli-ts/src/utils/provider-config.ts`:
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"
+45
View File
@@ -0,0 +1,45 @@
# Debug Harness
HTTP-controlled debugger for the VSCode extension at `src/dev/debug-harness/server.ts`.
## Quick start
```bash
# Build extension first if needed (protos + esbuild):
npm run protos && IS_DEV=true node esbuild.mjs
# Launch (skip-build if already built):
npx tsx src/dev/debug-harness/server.ts --skip-build --auto-launch
# In another terminal:
curl localhost:19229/api -d '{"method":"status"}'
```
## Key commands
All via `POST localhost:19229/api` with `{"method":"...", "params":{...}}`:
- **`launch`** / **`shutdown`** — lifecycle
- **`ui.screenshot`** — screenshot to `/tmp/cline-debug/`
- **`ui.open_sidebar`** — open the Cline sidebar
- **`ext.set_breakpoint`** `{file, line, condition?}` — breakpoint by source file (sourcemap-resolved)
- **`ext.evaluate`** `{expression, callFrameId?}` — eval in extension host
- **`ext.resume`** / **`ext.step_over`** / **`ext.step_into`** — stepping
- **`ext.call_stack`** — inspect when paused
- **`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?, action?, 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
- **`ui.send_message`** `{text, images?, files?, responseType?}` — send chat message bypassing the textarea entirely (via gRPC postMessage)
- **`ui.command_palette`** `{command}` — run VSCode command
## Caveats
- **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.
See `src/dev/debug-harness/README.md` for full API reference.
+12 -1
View File
@@ -14,7 +14,7 @@ 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 changelog entry, 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
@@ -147,6 +147,17 @@ Required steps:
Common mistake: Adding only the return value without the `context.globalState.get()` call. This compiles but the value is always `undefined` on load.
Settings plumbing gotcha: if a key is user-toggleable from settings, wire both controller update paths:
- `src/core/controller/state/updateSettings.ts` for webview `updateSetting(...)`
- `src/core/controller/state/updateSettingsCli.ts` for CLI/ACP settings updates
Missing one path causes a toggle to appear to change in one surface while the backend state stays unchanged.
Webview toggle gotcha: settings changes must also round-trip back in state payloads.
- Add the field to `UpdateSettingsRequest` in `proto/cline/state.proto` (for webview update requests), then run `npm run protos`
- Include the key in `Controller.getStateToPostToWebview()` (`src/core/controller/index.ts`)
- Ensure `ExtensionState` and webview defaults include the key (`src/shared/ExtensionMessage.ts`, `webview-ui/src/context/ExtensionStateContext.tsx`)
If this round-trip wiring is missing, the backend value can update but the toggle in webview appears stuck or reverts.
## StateManager Cache vs Direct globalState Access
StateManager uses an in-memory cache populated during `StateManager.initialize(context)` in `common.ts`. For most state, use `controller.stateManager.setGlobalState()`/`getGlobalStateKey()`.
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "PostToolUse running inside local cline/.clinerules/hooks/ directory"
input=$(cat)
echo $input | jq .
for i in {1..5}; do
sleep 1
echo "$i"
done
cat <<EOF
{
"cancel": false,
"contextModification": "PostToolUse response from the local cline/.clinerules/hooks/ directory.",
"errorMessage": "PostToolUse hook custom errorMessage"
}
EOF
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "PreToolUse running inside local cline/.clinerules/hooks/ directory"
input=$(cat)
echo $input | jq .
for i in {1..5}; do
sleep 1
echo "$i"
done
cat <<EOF
{
"cancel": false,
"contextModification": "PreToolUse response from the local cline/.clinerules/hooks/ directory.",
"errorMessage": "PreToolUse hook custom errorMessage"
}
EOF
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "TaskCancel running inside local cline/.clinerules/hooks/ directory"
input=$(cat)
echo $input | jq .
for i in {1..5}; do
sleep 1
echo "$i"
done
cat <<EOF
{
"cancel": false,
"contextModification": "TaskCancel response from the local cline/.clinerules/hooks/ directory.",
"errorMessage": "TaskCancel hook custom errorMessage"
}
EOF
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "TaskResume running inside local cline/.clinerules/hooks/ directory"
input=$(cat)
echo $input | jq .
for i in {1..5}; do
sleep 1
echo "$i"
done
cat <<EOF
{
"cancel": false,
"contextModification": "TaskResume response from the local cline/.clinerules/hooks/ directory.",
"errorMessage": "TaskResume hook custom errorMessage"
}
EOF
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "TaskStart running inside local cline/.clinerules/hooks/ directory"
input=$(cat)
echo $input | jq .
for i in {1..5}; do
sleep 1
echo "$i"
done
cat <<EOF
{
"cancel": false,
"contextModification": "TaskStart response from the local cline/.clinerules/hooks/ directory.",
"errorMessage": "TaskStart hook custom errorMessage"
}
EOF
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "UserPromptSubmit running inside local cline/.clinerules/hooks/ directory"
input=$(cat)
echo $input | jq .
for i in {1..5}; do
sleep 1
echo "$i"
done
cat <<EOF
{
"cancel": false,
"contextModification": "UserPromptSubmit response from the local cline/.clinerules/hooks/ directory.",
"errorMessage": "UserPromptSubmit hook custom errorMessage"
}
EOF
+64
View File
@@ -0,0 +1,64 @@
# Storage Architecture
Global settings, secrets and workspace state are stored in **file-backed JSON stores** under `~/.cline/data/`. This is the shared storage layer used by VSCode, CLI, and JetBrains.
## Key Abstractions
### `StorageContext` (src/shared/storage/storage-context.ts)
The entry point. Created via `createStorageContext()` and passed to `StateManager.initialize()`. Contains three `ClineFileStorage` instances:
- `globalState``~/.cline/data/globalState.json`
- `secrets``~/.cline/data/secrets.json` (mode 0o600)
- `workspaceState``~/.cline/data/workspaces/<hash>/workspaceState.json`
### `ClineFileStorage` (src/shared/storage/ClineFileStorage.ts)
Synchronous JSON key-value store backed by a single file. Supports `get()`, `set()`, `setBatch()`, `delete()`. Writes are atomic (write-then-rename).
### `StateManager` (src/core/storage/StateManager.ts)
In-memory cache on top of `StorageContext`. All runtime reads hit the cache; writes update cache immediately and debounce-flush to disk.
## ⚠️ Do NOT Use VSCode's ExtensionContext for Storage
**Do not** read from or write to `context.globalState`, `context.workspaceState`, or `context.secrets` for persistent data. These are VSCode-specific and not available on CLI or JetBrains.
Instead, use:
```typescript
// Reading state
StateManager.get().getGlobalStateKey("myKey")
StateManager.get().getSecretKey("mySecretKey")
StateManager.get().getWorkspaceStateKey("myWsKey")
// Writing state
StateManager.get().setGlobalState("myKey", value)
StateManager.get().setSecret("mySecretKey", value)
StateManager.get().setWorkspaceState("myWsKey", value)
```
Remember that your data may be read by a different client than the one that wrote it. For example, a value written by Cline in JetBrains may be read by Cline CLI.
## VSCode Migration (src/hosts/vscode/vscode-to-file-migration.ts)
On VSCode startup, a migration copies data from VSCode's `ExtensionContext` storage into the file-backed stores. This runs in `src/common.ts` before `StateManager.initialize()`.
- **Sentinel**: `__vscodeMigrationVersion` key in global state and workspace state — prevents re-migration.
- **Merge strategy**: File store wins. Existing values are never overwritten.
- **Safe downgrade**: VSCode storage is NOT cleared, so older extension versions still work.
## Adding New Storage Keys
1. Add to `src/shared/storage/state-keys.ts` (see existing patterns)
2. Read/write via `StateManager` (NOT via `context.globalState`)
3. If adding a secret, add to `SecretKeys` array in `state-keys.ts`
## File Layout
```
~/.cline/
data/
globalState.json # Global settings & state
secrets.json # API keys (mode 0o600)
tasks/
taskHistory.json # Task history (separate file)
workspaces/
<hash>/
workspaceState.json # Per-workspace toggles
```
+1 -1
View File
@@ -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.).
5. **Wait for my approval** before proceeding.
-549
View File
@@ -1,549 +0,0 @@
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!)
- Fix @withRetry() decoration syntax error when running extension locally (Thanks @DaveFres!)
- Fix for git commit mentions in repos with no git commits
- Fix cost calculation (Thanks @BarreiroT!)
</changelog>
<announcement-component>
const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
const minorVersion = version.split(".").slice(0, 2).join(".") // 2.0.0 -> 2.0
return (
<div style={containerStyle}>
<VSCodeButton appearance="icon" onClick={hideAnnouncement} style={closeIconStyle}>
<span className="codicon codicon-close"></span>
</VSCodeButton>
<h3 style={h3TitleStyle}>
🎉{" "}New in v{minorVersion}
</h3>
<ul style={ulStyle}>
<li>
<b>Gemini prompt caching:</b> Gemini and Vertex providers now support prompt caching and price tracking for
Gemini models.
</li>
<li>
<b>Copy Buttons:</b> Buttons were added to Markdown and Code blocks that allow you to copy their contents
easily.
</li>
<li>
<b>/newrule command:</b> New slash command to have cline write your .clinerules for you based on your
workflow.
</li>
<li>
<b>Drag and drop improvements:</b> Don't forget to hold shift while dragging files!
</li>
<li>Added more checkpoints across the task, allowing you to restore from more than just file changes.</li>
<li>Added support for rendering LaTeX in message responses. (Try asking Cline to show the quadratic formula)</li>
</ul>
<Accordion isCompact className="pl-0">
<AccordionItem
key="1"
aria-label="Previous Updates"
title="Previous Updates:"
classNames={{
trigger: "bg-transparent border-0 pl-0 pb-0 w-fit",
title: "font-bold text-(--vscode-foreground)",
indicator:
"text-(--vscode-foreground) mb-0.5 -rotate-180 data-[open=true]:-rotate-90 rtl:rotate-0 rtl:data-[open=true]:-rotate-90",
}}>
<ul style={ulStyle}>
<li>
<b>Global Cline Rules:</b> store multiple rules files in Documents/Cline/Rules to share between
projects.
</li>
<li>
<b>Cline Rules Popup:</b> New button in the chat area to view workspace and global cline rules files
to plug and play specific rules for the task
</li>
<li>
<b>Slash Commands:</b> Type <code>/</code> in chat to see the list of quick actions, like starting a
new task (more coming soon!)
</li>
<li>
<b>Edit Messages:</b> You can now edit a message you sent previously by clicking on it. Optionally
restore your project when the message was sent!
</li>
</ul>
</AccordionItem>
</Accordion>
{/*
// Leave this here for an example of how to structure the announcement
<ul style={{ margin: "0 0 8px", paddingLeft: "12px" }}>
<li>
OpenRouter now supports prompt caching! They also have much higher rate limits than other providers,
so I recommend trying them out.
<br />
{!apiConfiguration?.openRouterApiKey && (
<VSCodeButtonLink
href={getOpenRouterAuthUrl(vscodeUriScheme)}
style={{
transform: "scale(0.85)",
transformOrigin: "left center",
margin: "4px -30px 2px 0",
}}>
Get OpenRouter API Key
</VSCodeButtonLink>
)}
{apiConfiguration?.openRouterApiKey && apiConfiguration?.apiProvider !== "openrouter" && (
<VSCodeButton
onClick={() => {
vscode.postMessage({
type: "apiConfiguration",
apiConfiguration: { ...apiConfiguration, apiProvider: "openrouter" },
})
}}
style={{
transform: "scale(0.85)",
transformOrigin: "left center",
margin: "4px -30px 2px 0",
}}>
Switch to OpenRouter
</VSCodeButton>
)}
</li>
<li>
<b>Edit Cline's changes before accepting!</b> When he creates or edits a file, you can modify his
changes directly in the right side of the diff view (+ hover over the 'Revert Block' arrow button in
the center to undo "<code>{"// rest of code here"}</code>" shenanigans)
</li>
<li>
New <code>search_files</code> tool that lets Cline perform regex searches in your project, letting
him refactor code, address TODOs and FIXMEs, remove dead code, and more!
</li>
<li>
When Cline runs commands, you can now type directly in the terminal (+ support for Python
environments)
</li>
</ul>*/}
<div style={hrStyle} />
<p style={linkContainerStyle}>
Join us on{" "}
<VSCodeLink style={linkStyle} href="https://x.com/cline">
X,
</VSCodeLink>{" "}
<VSCodeLink style={linkStyle} href="https://discord.gg/cline">
discord,
</VSCodeLink>{" "}
or{" "}
<VSCodeLink style={linkStyle} href="https://www.reddit.com/r/cline/">
r/cline
</VSCodeLink>
for more updates!
</p>
</div>
)
}
</announcement-component>
- 3.13
<changeset>
Minor Changes
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
- Fix token usage tracking issues with vertex provider (Thanks @mzsima!)
- Fix issue with xAI reasoning content not being parsed (Thanks @mrubens!)
</changelog>
<announcement-component>
const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
const minorVersion = version.split(".").slice(0, 2).join(".") // 2.0.0 -> 2.0
return (
<div style={containerStyle}>
<VSCodeButton appearance="icon" onClick={hideAnnouncement} style={closeIconStyle}>
<span className="codicon codicon-close"></span>
</VSCodeButton>
<h3 style={h3TitleStyle}>
🎉{" "}New in v{minorVersion}
</h3>
<ul style={ulStyle}>
<li>
<b>Global Cline Rules:</b> store multiple rules files in Documents/Cline/Rules to share between projects.
</li>
<li>
<b>Cline Rules Popup:</b> New button in the chat area to view workspace and global cline rules files to plug
and play specific rules for the task
</li>
<li>
<b>Slash Commands:</b> Type <code>/</code> in chat to see the list of quick actions, like starting a new task
(more coming soon!)
</li>
<li>
<b>Edit Messages:</b> You can now edit a message you sent previously by clicking on it. Optionally restore
your project when the message was sent!
</li>
</ul>
<h4 style={{ margin: "5px 0 5px" }}>Previous Updates:</h4>
<ul style={ulStyle}>
<li>
<b>Model Favorites:</b> You can now mark your favorite models when using Cline & OpenRouter providers for
quick access!
</li>
<li>
<b>Faster Diff Editing:</b> Improved animation performance for large files, plus a new indicator in chat
showing the number of edits Cline makes.
</li>
<li>
<b>New Auto-Approve Options:</b> Turn off Cline's ability to read and edit files outside your workspace.
</li>
</ul>
{/*
// Leave this here for an example of how to structure the announcement
<ul style={{ margin: "0 0 8px", paddingLeft: "12px" }}>
<li>
OpenRouter now supports prompt caching! They also have much higher rate limits than other providers,
so I recommend trying them out.
<br />
{!apiConfiguration?.openRouterApiKey && (
<VSCodeButtonLink
href={getOpenRouterAuthUrl(vscodeUriScheme)}
style={{
transform: "scale(0.85)",
transformOrigin: "left center",
margin: "4px -30px 2px 0",
}}>
Get OpenRouter API Key
</VSCodeButtonLink>
)}
{apiConfiguration?.openRouterApiKey && apiConfiguration?.apiProvider !== "openrouter" && (
<VSCodeButton
onClick={() => {
vscode.postMessage({
type: "apiConfiguration",
apiConfiguration: { ...apiConfiguration, apiProvider: "openrouter" },
})
}}
style={{
transform: "scale(0.85)",
transformOrigin: "left center",
margin: "4px -30px 2px 0",
}}>
Switch to OpenRouter
</VSCodeButton>
)}
</li>
<li>
<b>Edit Cline's changes before accepting!</b> When he creates or edits a file, you can modify his
changes directly in the right side of the diff view (+ hover over the 'Revert Block' arrow button in
the center to undo "<code>{"// rest of code here"}</code>" shenanigans)
</li>
<li>
New <code>search_files</code> tool that lets Cline perform regex searches in your project, letting
him refactor code, address TODOs and FIXMEs, remove dead code, and more!
</li>
<li>
When Cline runs commands, you can now type directly in the terminal (+ support for Python
environments)
</li>
</ul>*/}
<div style={hrStyle} />
<p style={linkContainerStyle}>
Join us on{" "}
<VSCodeLink style={linkStyle} href="https://x.com/cline">
X,
</VSCodeLink>{" "}
<VSCodeLink style={linkStyle} href="https://discord.gg/cline">
discord,
</VSCodeLink>{" "}
or{" "}
<VSCodeLink style={linkStyle} href="https://www.reddit.com/r/cline/">
r/cline
</VSCodeLink>
for more updates!
</p>
</div>
)
}
</announcement-component>
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:
```bash
gh pr diff changeset-release/main > changeset-diff.txt
cat changeset-diff.txt | grep -A 50 "CHANGELOG.md"
```
## Initial Setup
3. Once you're ready to start, checkout and update the changeset release branch:
```bash
git checkout changeset-release/main
git pull origin changeset-release/main
```
## Analyzing Each Change
4. For each commit hash in the auto-generated changelog entries:
a. Find the PR number associated with a commit hash:
```bash
gh pr list --search "<commit-hash>" --state merged
```
b. Get PR details for better context:
```bash
gh pr view <PR-number>
```
c. Check if the contributor is external to determine if attribution is needed:
```bash
# Extract username from PR
USERNAME=$(gh pr view <PR-number> --json author --jq .author.login)
# 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:
```bash
npm run install:all
```
10. Commit your changes:
```bash
git add CHANGELOG.md package.json package-lock.json src/views/components/announcement.tsx
git commit -m "Update CHANGELOG.md and announcement for version 3.16.0"
```
11. Push your changes to the changeset branch:
```bash
git push origin changeset-release/main
```
12. Check that your changes pushed successfully:
```bash
git status
```
</detailed_sequence_of_steps>
+3 -10
View File
@@ -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
```bash
git add CHANGELOG.md package.json .changeset/
git add CHANGELOG.md package.json
git commit -m "v3.40.1 Release Notes (hotfix)
Hotfix release including:
-2
View File
@@ -347,8 +347,6 @@ A few notes:
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.
</request_changes_comment>
</example_comments_that_i_have_written_before>
+40 -208
View File
@@ -1,232 +1,64 @@
# Release
Prepare and publish a release from the open changeset PR.
Prepare and publish a release directly from `main`.
## Overview
This workflow helps you:
1. Find and checkout the open changeset PR
2. Clean up the changelog (fix version format, wordsmith entries)
3. Push changes back to the PR branch
4. Merge with proper commit message format
5. Tag and push the release (after verifying the commit)
6. Trigger the publish workflow
7. Update GitHub release notes
8. Provide final summary with Slack announcement
1. Select/confirm the target version
2. Curate `CHANGELOG.md` entries manually for end users
3. Ensure `package.json` version matches the changelog
4. Create and push a release commit + tag
5. Trigger publish workflow
6. Update GitHub release notes and share a summary
## Step 1: Find the Changeset PR
## Process
Look for the open changeset PR:
```bash
gh pr list --search "Changeset version bump" --state open --json number,title,headRefName,url
```
If no PR is found, inform the user there's no changeset PR ready. They may need to:
- Merge PRs with changesets to main first
- Manually trigger the Changeset Converter workflow at: https://github.com/cline/cline/actions/workflows/changeset-converter.yml
## Step 2: Gather PR Information
Get the PR details:
```bash
PR_NUMBER=<number from step 1>
gh pr view $PR_NUMBER --json body,files,headRefName
```
Checkout the PR branch:
```bash
git fetch origin changeset-release/main
git checkout changeset-release/main
```
If the branch has diverged from remote, reset to the remote version:
```bash
git reset --hard origin/changeset-release/main
```
## Step 3: Analyze the Changes
Read the current CHANGELOG.md to see what the automation generated:
```bash
head -50 CHANGELOG.md
```
Get the version from package.json:
```bash
cat package.json | grep '"version"'
```
**Present to the user:**
- The version number that will be released
- The raw changelog entries from the changeset PR
- Whether this is a patch, minor, or major release
## Step 4: Clean Up the Changelog
The changelog needs these fixes:
1. **Add brackets to version number**: Change `## 3.44.1` to `## [3.44.1]`
2. **No category headers**: Don't use `### Added`, `### Fixed`, etc. Just a flat list of bullet points.
3. **Order entries from most important to least important**:
- Lead with major new features or significant fixes users care about
- End with minor fixes or internal changes
4. **Write user-friendly descriptions**:
- This is for end users, not developers—explain what changed in plain language
- Remove commit hashes from the beginning of lines (the automation adds these)
- Look at the actual commit diffs (`git show <hash>`) and PRs to understand what changed
- Write colorful descriptions that explain the value and impact, not just technical details
- Consolidate related changes into single entries when appropriate
**Ask the user** to review the proposed changelog changes before applying them. Show them:
- Current (raw) changelog section
- Proposed (cleaned) changelog section
Once approved, apply the changes to CHANGELOG.md.
## Step 5: Commit and Push Changes
After making changelog edits:
```bash
git add CHANGELOG.md
git commit -m "Clean up changelog formatting"
git push origin changeset-release/main
```
## Step 6: Merge the PR
**Ask the user to confirm** they're ready to merge.
Merge the PR with the proper commit message format:
```bash
VERSION=<version from package.json>
gh pr merge $PR_NUMBER --squash --subject "v${VERSION} Release Notes" --body ""
```
**If merge is blocked by branch protection:**
- Users with admin privileges can add the `--admin` flag to bypass
- Users without admin privileges need to get the PR approved through normal review first before merging
## Step 7: Tag the Release
After the merge completes, checkout main and pull:
### 1) Sync and determine version
```bash
git checkout main
git pull origin main
cat package.json | grep '"version"'
```
**IMPORTANT: Verify the latest commit is the release commit before tagging:**
Confirm the release version with the maintainer (patch/minor/major).
### 2) Curate changelog and version
- Edit `CHANGELOG.md` for the target version using human-friendly release notes.
- Ensure version headers use bracket format, e.g. `## [3.66.1]`.
- Update `package.json` version to the same value.
### 3) Commit and tag
```bash
git log -1 --oneline
git add CHANGELOG.md package.json package-lock.json
git commit -m "v<version> Release Notes"
git push origin main
git tag v<version>
git push origin v<version>
```
Confirm the commit message matches `v{VERSION} Release Notes` (e.g., `v3.44.1 Release Notes`). Do NOT blindly tag HEAD without verification.
### 4) Trigger publish workflow
Once verified, tag and push:
Tell the maintainer to run:
https://github.com/cline/cline/actions/workflows/publish.yml
Use `v<version>` as the release tag.
### 5) Update GitHub release notes
After publish completes:
```bash
VERSION=<version>
git tag v${VERSION}
git push origin v${VERSION}
gh release view v<version> --json body --jq '.body'
gh release edit v<version> --notes "<final curated release notes>"
```
## Step 8: Trigger Publish Workflow
### 6) Final summary
**Copy the tag to clipboard** so the user can easily paste it into the GitHub Actions workflow:
```bash
echo -n "v{VERSION}" | pbcopy
```
**Tell the user to trigger the publish workflow:**
1. Go to: https://github.com/cline/cline/actions/workflows/publish.yml
2. Select **"release"** for release-type
3. Paste **`v{VERSION}`** as the tag (already in clipboard)
**Wait for the user** to confirm the publish workflow has completed before proceeding.
## Step 9: Update GitHub Release Notes
Once the user confirms the publish workflow is done, fetch the auto-generated release content:
```bash
VERSION=<version>
gh release view v${VERSION} --json body --jq '.body'
```
The auto-generated release has:
- `## What's Changed` - PR list (we'll replace this with our changelog)
- `## New Contributors` - First-time contributors (keep this if present)
- `**Full Changelog**` - Comparison link (keep this)
Build the new release body:
1. Start with `## What's Changed` header
2. Add our changelog content (from CHANGELOG.md for this version)
3. Keep the `## New Contributors` section if it exists
4. Keep the `**Full Changelog**` link
Update the release:
```bash
gh release edit v${VERSION} --notes "<new body content>"
```
Verify the release was updated:
```bash
gh release view v${VERSION}
```
## Step 10: Final Summary
**Copy a Slack announcement message to clipboard** (include the full changelog, not just highlights):
```bash
echo "VS Code v{VERSION} Released
- Changelog entry 1
- Changelog entry 2
- Changelog entry 3" | pbcopy
```
**Present a final summary:**
- Version released: v{VERSION}
- PR merged: #{PR_NUMBER}
- Tag pushed: v{VERSION}
- Release: https://github.com/cline/cline/releases/tag/v{VERSION}
- Slack message copied to clipboard
**Final reminder:**
Post the Slack message to announce the release
## Handling Edge Cases
### No changesets found
If the changeset PR body shows no changes, inform the user they need to merge PRs with changesets first.
### Merge conflicts
If there are conflicts on the changeset branch, help the user resolve them:
```bash
git fetch origin main
git rebase origin/main
# resolve conflicts
git push origin changeset-release/main --force-with-lease
```
### User wants to add more changes
If the user wants to include additional PRs before releasing:
1. Ask them to merge those PRs to main first
2. The changeset automation will update the PR automatically
3. Re-run this workflow after the PR is updated
Provide:
- Released version/tag
- Link to release page
- Summary of top end-user changes
+49
View File
@@ -0,0 +1,49 @@
# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY
version = 1
name = "cline"
[setup]
script = '''
if [ ! -d "node_modules" ]; then
MAIN_WORKTREE="$(git worktree list | head -n1 | awk '{print $1}')"
ln -s "$MAIN_WORKTREE/node_modules" node_modules
ln -s "$MAIN_WORKTREE/webview-ui/node_modules" webview-ui/node_modules
fi
'''
[[actions]]
name = "VS Code"
icon = "run"
command = "chmod +x ./scripts/run-extension-host.sh && ./scripts/run-extension-host.sh production"
[[actions]]
name = "CLI"
icon = "run"
command = '''
npm run cli:build
npm run cli:run
'''
[[actions]]
name = "npm install"
icon = "tool"
command = '''
rm node_modules
rm webview-ui/node_modules
npm run install:all
'''
[[actions]]
name = "pull main"
icon = "tool"
command = '''
git fetch origin main
if ! git merge-base --is-ancestor main origin/main; then
echo "Local main has commits not on origin/main. Aborting..."
exit 1
fi
git update-ref refs/heads/main refs/remotes/origin/main
echo "main updated to $(git rev-parse --short main)"
'''
-7
View File
@@ -16,13 +16,6 @@
TELEMETRY_SERVICE_API_KEY=your-posthog-telemetry-api-key
ERROR_SERVICE_API_KEY=your-posthog-error-tracking-api-key
# ============================================================================
# TELEMETRY PROVIDER CONTROL
# ============================================================================
# Control which telemetry providers are active
POSTHOG_TELEMETRY_ENABLED=true # Enable PostHog telemetry (default: true)
# Set to false to disable Telemetry completely
# ============================================================================
# OPENTELEMETRY (Optional - for advanced telemetry)
# ============================================================================
+2
View File
@@ -1,4 +1,6 @@
demo.gif filter=lfs diff=lfs merge=lfs -text
assets/docs/demo.gif filter=lfs diff=lfs merge=lfs -text
webview-ui/src/assets/cline_kanban_demo.mp4 filter=lfs diff=lfs merge=lfs -text
webview-ui/src/assets/cline_kanban_demo.webm filter=lfs diff=lfs merge=lfs -text
* text=auto eol=lf
+2 -3
View File
@@ -1,3 +1,2 @@
/docs/
/.github/ @saoudrizwan @garoth @sjf
/README.md @saoudrizwan @nickbaumann98
/.github/ @saoudrizwan @arafatkatze @maxpaulus43 @candieduniverse
/README.md @saoudrizwan @juanpflores
+58
View File
@@ -0,0 +1,58 @@
# Copilot Instructions for Cline
This is a VS Code extension. Read `.clinerules/general.md` for tribal knowledge and nuanced patterns.
## Architecture
- **Core** (`src/`): `extension.ts``WebviewProvider``Controller` (single source of truth) → `Task` (agent loop).
- **Webview** (`webview-ui/`): React/Vite app. State via `ExtensionStateContext.tsx`, synced through message passing.
- **CLI** (`cli/`): React Ink terminal UI sharing core logic. Update CLI when changing webview features.
- **Communication**: Protobuf-defined gRPC-like protocol over VS Code message passing. Schemas in `proto/`.
- **MCP**: `src/services/mcp/McpHub.ts`.
## Build & Test (Critical — non-obvious commands)
- **Build**: `npm run compile` — NOT `npm run build`.
- **Watch**: `npm run watch` (extension + webview).
- **Protos**: `npm run protos` — run **immediately** after any `.proto` change. Generates into `src/shared/proto/`, `src/generated/`.
- **Tests**: `npm run test:unit`. After prompt/tool changes: `UPDATE_SNAPSHOTS=true npm run test:unit`.
## Protobuf RPC Workflow (4 steps)
1. **Define** in `proto/cline/*.proto`. Naming: `PascalCaseService`, `camelCase` RPCs, `PascalCase` Messages. Use `common.proto` shared types for simple data.
2. **Generate**: `npm run protos`.
3. **Backend handler**: `src/core/controller/<domain>/`.
4. **Frontend call**: `UiServiceClient.myMethod(Request.create({...}))`.
- 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`.
## Slash Commands (3 places)
- `src/core/slash-commands/index.ts` — definitions.
- `src/core/prompts/commands.ts` — system prompt integration.
- `webview-ui/src/utils/slash-commands.ts` — webview autocomplete.
## Conventions
- **Paths**: Always use `src/utils/path` helpers (`toPosixString`) for cross-platform compatibility.
- **Logging**: `src/shared/services/Logger.ts`.
- **Feature flags**: See PR #7566 as reference pattern.
-1
View File
@@ -60,7 +60,6 @@ We're not looking for exhaustive documentation - just evidence that you've thoug
- [ ] Changes are limited to a single feature, bugfix or chore (split larger changes into separate PRs)
- [ ] Tests are passing (`npm test`) and code is formatted and linted (`npm run format && npm run lint`)
- [ ] I have created a changeset using `npm run changeset` (required for user-facing changes)
- [ ] I have reviewed [contributor guidelines](https://github.com/cline/cline/blob/main/CONTRIBUTING.md)
### Screenshots
@@ -1,79 +0,0 @@
"""
This script updates a specific version's release notes section in CHANGELOG.md with new content
or reformats existing content.
The script:
1. Takes a version number, changelog path, and optionally new content as input from environment variables
2. Finds the section in the changelog for the specified version
3. Either:
a) Replaces the content with new content if provided, or
b) Reformats existing content by:
- Removing the first two lines of the changeset format
- Ensuring version numbers are wrapped in square brackets
4. Writes the updated changelog back to the file
Environment Variables:
CHANGELOG_PATH: Path to the changelog file (defaults to 'CHANGELOG.md')
VERSION: The version number to update/format
PREV_VERSION: The previous version number (used to locate section boundaries)
NEW_CONTENT: Optional new content to insert for this version
"""
#!/usr/bin/env python3
import os
CHANGELOG_PATH = os.environ.get("CHANGELOG_PATH", "CHANGELOG.md")
VERSION = os.environ['VERSION']
PREV_VERSION = os.environ.get("PREV_VERSION", "")
NEW_CONTENT = os.environ.get("NEW_CONTENT", "")
def overwrite_changelog_section(changelog_text: str, new_content: str):
# Find the section for the specified version
version_pattern = f"## {VERSION}\n"
unformmatted_prev_version_pattern = f"## {PREV_VERSION}\n"
prev_version_pattern = f"## [{PREV_VERSION}]\n"
print(f"latest version: {VERSION}")
print(f"prev_version: {PREV_VERSION}")
notes_start_index = changelog_text.find(version_pattern) + len(version_pattern)
notes_end_index = changelog_text.find(prev_version_pattern, notes_start_index) if PREV_VERSION and (prev_version_pattern in changelog_text or unformmatted_prev_version_pattern in changelog_text) else len(changelog_text)
if new_content:
return changelog_text[:notes_start_index] + f"{new_content}\n" + changelog_text[notes_end_index:]
else:
changeset_lines = changelog_text[notes_start_index:notes_end_index].split("\n")
filtered_lines = []
for line in changeset_lines:
# If the previous line is a changeset format
if len(filtered_lines) > 1 and filtered_lines[-1].startswith("### "):
# Remove the last two lines from the filted_lines
filtered_lines.pop()
filtered_lines.pop()
else:
filtered_lines.append(line.strip())
# Prepend a new line to the first line of filtered_lines
if filtered_lines:
filtered_lines[0] = "\n" + filtered_lines[0]
# Print filted_lines wiht a "\n" at the end of each line
for line in filtered_lines:
print(line.strip())
parsed_lines = "\n".join(line for line in filtered_lines)
updated_changelog = changelog_text[:notes_start_index] + parsed_lines + changelog_text[notes_end_index:]
return updated_changelog
with open(CHANGELOG_PATH, 'r') as f:
changelog_content = f.read()
new_changelog = overwrite_changelog_section(changelog_content, NEW_CONTENT)
# print("----------------------------------------------------------------------------------")
# print(new_changelog)
# print("----------------------------------------------------------------------------------")
# Write back to CHANGELOG.md
with open(CHANGELOG_PATH, 'w') as f:
f.write(new_changelog)
print(f"{CHANGELOG_PATH} updated successfully!")
-113
View File
@@ -1,113 +0,0 @@
name: Changeset Converter
run-name: Changeset Conversion
on:
workflow_dispatch:
pull_request:
types: [closed]
env:
REPO_PATH: ${{ github.repository }}
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
NODE_VERSION: 20.18.1
jobs:
# Job 1: Create version bump PR when changesets are merged to main
changeset-pr-version-bump:
if: |
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'pull_request' &&
github.event.pull_request.merged == true &&
github.event.pull_request.base.ref == 'main' &&
github.actor != 'github-actions'
)
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Check user for team affiliation
id: team_check
if: github.event_name == 'workflow_dispatch'
uses: morfien101/actions-authorized-user@4a3cfbf0bcb3cafe4a71710a278920c5d94bb38b
with:
username: ${{ github.actor }}
org: ${{ github.repository_owner }}
team: "deployer"
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Check if user is authorized
if: github.event_name == 'workflow_dispatch'
run: |
if [ "${{ steps.team_check.outputs.authorized }}" != "true" ]; then
echo "User is not authorized to run this workflow."
exit 1
fi
- name: Git Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ env.GIT_REF }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
- name: Install Dependencies
run: npm ci
# Check if there are any new changesets to process
- name: Check for changesets
id: check-changesets
run: |
NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ')
echo "Changesets diff with previous version: $NEW_CHANGESETS"
echo "new_changesets=$NEW_CHANGESETS" >> $GITHUB_OUTPUT
# Create version bump PR using changesets/action if there are new changesets
- name: Create Changeset Pull Request
if: steps.check-changesets.outputs.new_changesets != '0'
uses: changesets/action@v1
with:
commit: "changeset version bump"
title: "Changeset version bump"
version: npm run version-packages # This performs the changeset version bump
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Get current and previous versions to edit changelog entry
- name: Get version
id: get_version
run: |
VERSION=$(git show HEAD:package.json | jq -r '.version')
echo "version=$VERSION" >> $GITHUB_OUTPUT
PREV_VERSION=$(git show origin/main:package.json | jq -r '.version')
echo "prev_version=$PREV_VERSION" >> $GITHUB_OUTPUT
echo "version=$VERSION"
echo "prev_version=$PREV_VERSION"
# Update CHANGELOG.md with proper format
- name: Update Changelog Format
env:
VERSION: ${{ steps.get_version.outputs.version }}
PREV_VERSION: ${{ steps.get_version.outputs.prev_version }}
run: python .github/scripts/overwrite_changeset_changelog.py
# Commit and push changelog updates
- name: Push Changelog updates to Pull Request
run: |
git config user.name "github-actions"
git config user.email github-actions@github.com
echo "Running git add and commit..."
git add CHANGELOG.md
git commit -m "Updating CHANGELOG.md format"
git status
echo "--------------------------------------------------------------------------------"
echo "Pushing to remote..."
echo "--------------------------------------------------------------------------------"
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
git push origin $CURRENT_BRANCH
-173
View File
@@ -1,173 +0,0 @@
name: Claude Issue Triage
on:
issues:
types: [opened]
# Manual trigger for backfilling existing issues. Run from terminal:
# gh workflow run claude-issue-triage.yml -f issue_number=1234
# Or batch process:
# gh issue list --state open --limit 10 --json number --jq '.[].number' | while read num; do
# gh workflow run claude-issue-triage.yml -f issue_number=$num
# sleep 60
# done
workflow_dispatch:
inputs:
issue_number:
description: 'Issue number to triage'
required: true
type: string
jobs:
claude-issue-triage:
runs-on: ubuntu-latest
timeout-minutes: 120
# SECURITY: These permissions are intentionally restrictive.
# - contents: read -> Claude can read the codebase but CANNOT write/push any code
# - issues: write -> Claude can comment and add labels (the only write access needed)
# - pull-requests: read -> Claude can view PR context but CANNOT create PRs
# This ensures that even if a malicious user attempts prompt injection via issue content,
# Claude cannot modify repository code, create branches, or open PRs.
permissions:
contents: read
issues: write
pull-requests: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Issue Response & Triage
id: triage
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
allowed_non_write_users: "*"
# Allow all tools - security is enforced by GitHub permissions above (contents: read, issues: write)
claude_args: --model claude-opus-4-5-20251101 --allowedTools "Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch"
prompt: |
You're a GitHub issue first responder for the open source Cline repository.
**Issue:** #${{ github.event.issue.number || inputs.issue_number }}
**Title:** ${{ github.event.issue.title || 'See issue details below' }}
**Author:** @${{ github.event.issue.user.login || 'See issue details below' }}
## Your job
Investigate this issue thoroughly, then post a single helpful comment that helps the user and gives maintainers the context they need.
## Investigation
Start by reading the full issue:
gh issue view ${{ github.event.issue.number || inputs.issue_number }}
### Search for duplicates and related issues
Search thoroughly for existing issues that match this one:
gh issue list --search "<keywords from the issue>" --state all --limit 30
gh issue list --search "<error messages>" --state all --limit 20
gh issue list --search "<affected feature/component>" --state all --limit 20
For each relevant issue you find, read it including its comments:
gh issue view <number> --comments
You're looking for:
- **Duplicates**: Issues describing the same problem. Link to them and explain why you think they're duplicates. If closed, check how they were resolved - the solution might apply here.
- **Related issues**: Similar problems or context that could help. Pull useful information from their comments (workarounds others found, debugging steps that helped, maintainer explanations). Link to them and explain the connection.
If there are closed issues with solutions, surface those solutions prominently - this might immediately solve the user's problem.
### Analyze recent changes (ALWAYS DO THIS)
Many issues are regressions from recent releases. **Always** check what changed recently:
gh release list --limit 10
gh pr list --state merged --limit 50 --json number,title,mergedAt,author,body
Look for PRs merged in the last few weeks that might correlate with the issue. If you find a likely connection:
gh pr view <number>
gh pr diff <number>
git log --since="1 month ago" --oneline -- <relevant paths>
git show <commit>
**Always include your findings in your comment:**
- If you find a regression, call it out explicitly: which PR/commit likely caused it, who authored it, what changed, and suggest a fix direction if you can see one.
- If you don't find anything related, still mention it: "I analyzed recent PRs and releases but didn't find any changes that seem related to this issue."
### Search the codebase
Find the relevant code:
- Use grep/find to locate code related to the issue
- Key areas: `src/api/` (providers/models), `src/core/prompts/` (tools/prompts), platform-specific code for VS Code vs JetBrains
### Find documentation
Cline docs are at **https://docs.cline.bot/** and built with Mintlify from the `docs/` directory.
The URL structure maps directly to the file structure:
- `docs/getting-started/selecting-your-model.mdx` → https://docs.cline.bot/getting-started/selecting-your-model
- `docs/troubleshooting.mdx` → https://docs.cline.bot/troubleshooting
- Headings become anchors: `## Which Model` → `#which-model`
Search the `docs/` directory to find relevant documentation, then construct URLs to link users to:
```bash
ls docs/
grep -r "keyword" docs/ --include="*.mdx" -l
```
### Identify subject matter experts
For issues that clearly need engineering attention:
git log --since="6 months ago" --format="%an" -- <relevant paths> | sort | uniq -c | sort -rn | head -5
Cross-reference with GitHub usernames. Include in your response (@mention, do NOT assign):
| SME | Reason |
|-----|--------|
| @username1 | Authored PR #X which modified this area |
| @username2 | Primary contributor to affected file |
## Weak model detection
Many issues are caused by users running small or non-frontier models that don't tool-call reliably. Signs include:
- Model failing to use tools correctly
- Nonsensical or malformed responses
- User is running a small/local model or older model version
If this looks like a weak model issue, kindly suggest they try reproducing with Claude Sonnet and report back if it persists. Link to https://docs.cline.bot/getting-started/selecting-your-model if helpful. Still label and triage normally.
## Your comment
Write a single comment as a helpful community member. Be conversational, not robotic. Include what's relevant:
- **Helpful response** - Answer their question, suggest a fix, provide a workaround. If you found solutions in related closed issues, surface those prominently.
- **Duplicates and related issues** - Link to any you found and explain why they're duplicates/related. Summarize useful context from their comments.
- **Regression analysis** - If this looks like a regression, explain what change likely caused it, link to the PR/commit, and tag the author.
- **Clarifying questions** - If you need more info, ask specific questions. Don't ask for things already provided.
- **SME table** - Include the table above if this needs engineering attention. Don't tag people for questions with obvious answers or weak-model issues.
- **Context for maintainers** - Relevant code paths, what you found. Keep it concise.
- **Docs links** - If there's relevant documentation, link to it naturally in your response as a recommendation (e.g., "For more details, check out [the Ollama setup guide](url)"). Do NOT add a "Sources" section at the end - integrate doc links into your response where they're helpful.
- **Possible Duplicates section** - ALWAYS include a "Possible Duplicates" section at the end of your comment listing issues that might be duplicates so maintainers can quickly close if appropriate. If none found, say "No obvious duplicates found."
## Labels
First, retrieve all available labels and read their descriptions to understand what each is for:
gh label list --json name,description --limit 100
Then apply the appropriate labels based on your analysis. Only use labels from the list above—do not create new labels.
gh issue edit ${{ github.event.issue.number || inputs.issue_number }} --add-label "label1,label2"
If your regression analysis found a likely culprit (a recent PR/commit that probably caused this issue), add the "Regression" label:
gh issue edit ${{ github.event.issue.number || inputs.issue_number }} --add-label "Regression"
IMPORTANT: After posting your comment, add the "Bot Responded" label to indicate this issue has received an automated response:
gh issue edit ${{ github.event.issue.number || inputs.issue_number }} --add-label "Bot Responded"
## Remember
- **This is a one-time automated response** - you will NOT see their reply or respond again. Never say things like "I can help you", "let me know", "once I have that info", or "I can give you more targeted help" - you won't be there to follow up. If you ask clarifying questions, frame them for the maintainers who will follow up, e.g., "If you can share X, that would help the maintainers diagnose this."
- Don't be formulaic. Respond to what the issue actually needs.
- Surface solutions from past issues - often the fastest path to helping.
- Connecting regressions to specific changes is extremely valuable.
- Link issues with #number so they're clickable.
-272
View File
@@ -1,272 +0,0 @@
name: Claude PR Review
on:
pull_request:
types: [opened, ready_for_review]
# Manual trigger for backfilling existing PRs. Run from terminal:
# gh workflow run claude-pr-review.yml -f pr_number=1234
# Or batch process open PRs:
# gh pr list --state open --limit 10 --json number --jq '.[].number' | while read num; do
# gh workflow run claude-pr-review.yml -f pr_number=$num
# sleep 60
# done
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to review'
required: true
type: string
jobs:
claude-pr-review:
# Runs on PR opened/ready_for_review (skips drafts) or manual trigger for backfilling
if: |
(github.event_name == 'pull_request' && github.event.pull_request.draft == false) ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 120
# SECURITY: These permissions are intentionally restrictive.
# - contents: read -> Claude can read the codebase but CANNOT write/push any code
# - pull-requests: write -> Claude can post reviews and inline suggestions
# - issues: read -> Claude can search for related issues
# NOTE: Even with pull-requests: write, Claude CANNOT merge PRs because branch protection
# requires 1 approval from a Code Owner. The GITHUB_TOKEN cannot bypass this.
permissions:
contents: read
pull-requests: write
issues: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get PR number
id: pr
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "number=${{ inputs.pr_number }}" >> $GITHUB_OUTPUT
else
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
fi
- name: Run PR Review
id: review
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
allowed_non_write_users: "*"
claude_args: --model claude-opus-4-5-20251101 --allowedTools "Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch"
prompt: |
You're a GitHub PR reviewer for the open source Cline repository. Your goal is to give the PR author helpful feedback and give maintainers the context they need to review efficiently.
PR: #${{ steps.pr.outputs.number }}
## Gather context
```bash
# Get full PR details
gh pr view ${{ steps.pr.outputs.number }} --json number,title,body,author,createdAt,updatedAt,isDraft,labels,commits,files,additions,deletions,changedFiles,baseRefName,headRefName,mergeable,reviewDecision
# Get the diff
gh pr diff ${{ steps.pr.outputs.number }}
# Check CI status
gh pr checks ${{ steps.pr.outputs.number }}
# Get existing review comments (to understand context and your previous feedback)
gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/comments --jq '.[] | {user: .user.login, body: .body, path: .path, created_at: .created_at}'
# Get conversation comments
gh pr view ${{ steps.pr.outputs.number }} --comments
```
If this is a re-review (workflow_dispatch event):
Read your previous comments carefully. Understand what you asked for before.
Check if new commits or comments address your previous feedback.
## Check contributing guidelines
Flag (but don't block) if:
- Missing changeset - For user-facing changes, check if there's a `.changeset/` file:
```bash
gh pr diff ${{ steps.pr.outputs.number }} --name-only | grep '.changeset/' || echo "No changeset found"
```
If missing, ask them to run `npm run changeset`
- Missing tests - New features should have tests
## Find related issues and PRs
Search thoroughly for context that might help with the review:
```bash
# Find related issues for context
gh issue list --search "<keywords from the PR>" --state all --limit 30
gh issue list --search "<error messages or feature names>" --state all --limit 20
# Find similar PRs for reference
gh pr list --search "<keywords>" --state all --limit 30
```
For each relevant issue or PR you find, read it including comments:
```bash
gh issue view <number> --comments
gh pr view <number> --comments
```
Look for:
- Open issues this PR might fix that weren't linked in the description
- Similar PRs that went through review - what feedback did they get? What patterns did they follow?
- Context from maintainer discussions that could inform your review
## Find subject matter experts
For files changed in this PR, find who knows the code best:
```bash
# Get files changed
gh pr diff ${{ steps.pr.outputs.number }} --name-only
# For each relevant path, find contributors
git log --since="6 months ago" --format="%an" -- <path> | sort | uniq -c | sort -rn | head -5
```
Cross-reference git authors with GitHub usernames. Include an SME table in your response:
| SME | Reason |
|-----|--------|
| @username1 | Authored PR #X which modified this area |
| @username2 | Primary contributor to affected file (15 commits in 6 months) |
| @username3 | Reviewed similar PR #Y with extensive feedback |
## Deep code review
This is the most important part. Don't just look for syntax issues - understand what the PR is trying to achieve and whether the implementation is the right approach.
Step 1: Understand the intent
Read the PR description and understand what the author is trying to accomplish. What problem are they solving? What feature are they adding?
Step 2: Form your own opinion first
Before analyzing their code, think about how YOU would implement this feature or fix. What files would you touch? What patterns would you follow? What edge cases would you handle?
Step 3: Compare approaches
Now look at their implementation. How does it compare to what you would have done?
- Is their approach better in some ways? Note what they did well.
- Is their approach missing something? Be specific about what and why.
- Are there edge cases they haven't considered?
- Does it follow the patterns established in similar parts of the codebase?
Step 4: Look at the bigger picture
- What other files or systems does this change interact with?
- Could this break anything else?
- Is there additional work needed beyond this PR to complete the feature?
- Does this fit well with the overall architecture?
Step 5: Find reference implementations
Look for similar changes in the codebase:
```bash
git log --oneline --all --grep="<relevant keywords>" | head -20
git log --oneline -- <similar files> | head -20
```
If this is adding a new API provider, look at how other providers are implemented.
If this is adding a new feature, look at how similar features were added.
Note where their implementation aligns with or diverges from established patterns.
Step 6: Standard code review checks
- DRY: Is there duplicated code that could be extracted?
- Error handling: Are errors handled appropriately?
- Security: Any injection risks, credential exposure, unsafe dependencies?
- Performance: Any obvious inefficiencies, memory leaks, N+1 patterns?
- Types: Is TypeScript used correctly? Any unsafe type assertions?
- Naming: Are variables and functions named clearly?
- Comments: Is complex logic explained? Are there outdated comments?
## Inline code suggestions
For specific code improvements, use GitHub's suggestion syntax via `gh api`.
This creates suggestions the author can commit with one click.
Single-line suggestion:
```bash
gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/reviews \
-X POST \
-f commit_id="$(gh pr view ${{ steps.pr.outputs.number }} --json headRefOid -q .headRefOid)" \
-f event="COMMENT" \
-f body="" \
-F comments='[
{
"path": "src/example.ts",
"line": 42,
"body": "Consider simplifying:\n\n```suggestion\nconst result = items.filter(Boolean);\n```"
}
]'
```
Multi-line suggestion (replacing lines 40-45):
```bash
gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/reviews \
-X POST \
-f commit_id="$(gh pr view ${{ steps.pr.outputs.number }} --json headRefOid -q .headRefOid)" \
-f event="COMMENT" \
-f body="" \
-F comments='[
{
"path": "src/example.ts",
"start_line": 40,
"line": 45,
"body": "This can be simplified:\n\n```suggestion\nconst simplified = doThing();\n```"
}
]'
```
Use inline suggestions for concrete improvements. Use regular comments for questions or broader feedback.
## Post your review
After your investigation, post a single helpful comment that helps the author and gives maintainers context.
Start with a warm thank you for their contribution. Be conversational, not robotic.
Include what's relevant:
- In-depth explanation of what the PR does - Be comprehensive. A maintainer should be able to read this section and fully understand the author's intent, why they made the changes, how they implemented it, and what files/systems are affected. Don't just summarize - explain.
- Related issues/PRs you found that provide useful context (link to them)
- Your review findings (issues to address, suggestions, etc.)
- Clear next steps for the author
Include a "For Maintainers" section with:
- Anything else useful to help the maintainer resolve this PR
- Related issues/PRs with context on why they're relevant
- Open issues this PR might fix that weren't linked in the description
- Your recommendation: merge as-is, needs changes, needs discussion, close, etc.
- SME table - who should review this and why
For the SME table:
| SME | Reason |
|-----|--------|
| @username | Primary contributor to affected files |
## Update labels
Add appropriate labels based on your analysis:
```bash
gh label list --json name,description --limit 100
gh pr edit ${{ steps.pr.outputs.number }} --add-label "label1,label2"
```
When done, add the reviewed label:
```bash
gh pr edit ${{ steps.pr.outputs.number }} --add-label "Bot Reviewed"
```
## Remember
- This is a one-time automated response - you will NOT see their reply or respond again. Never say things like "let me know if you have questions", "I can help you with", or "feel free to ask" - you won't be there to follow up. Frame any questions for the maintainers who will follow up.
- Be helpful and welcoming - Many contributors are new to the project
- Be specific - Point to exact lines and suggest fixes, don't give vague feedback
- Think deeply - Don't just surface-level review, understand the intent and evaluate the approach
- Use inline suggestions - Make it easy for authors to accept changes
- You're a first-pass reviewer - A human maintainer will do final approval
+83
View File
@@ -0,0 +1,83 @@
name: CLI TUI Tests
on:
pull_request:
branches:
- main
workflow_dispatch:
workflow_call:
permissions:
contents: read
jobs:
cli-tui-tests:
name: CLI TUI Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install dependencies
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build CLI
run: npm run cli:build
- name: Run TUI Tests
id: tui_tests
run: |
npm run test:e2e:cli:tui 2>&1 | tee tui-test-output.log
exit_code=${PIPESTATUS[0]}
echo "tui_exit_code=$exit_code" >> $GITHUB_OUTPUT
exit $exit_code
- name: Write failure summary
if: always() && steps.tui_tests.outcome != 'success' && steps.tui_tests.outcome != 'skipped'
run: |
echo "## ❌ CLI TUI Tests Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Step outcome:** \`${{ steps.tui_tests.outcome }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Test Output" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
if [ -f tui-test-output.log ]; then
cat tui-test-output.log >> $GITHUB_STEP_SUMMARY
else
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
- name: Upload TUI traces
if: always() && steps.tui_tests.outcome != 'success' && steps.tui_tests.outcome != 'skipped'
uses: actions/upload-artifact@v4
with:
name: tui-test-traces
path: tests/e2e/cli/tui-traces/
retention-days: 14
if-no-files-found: warn
- name: Upload test log
if: always() && steps.tui_tests.outcome != 'success' && steps.tui_tests.outcome != 'skipped'
uses: actions/upload-artifact@v4
with:
name: tui-test-log
path: tui-test-output.log
retention-days: 14
if-no-files-found: warn
@@ -0,0 +1,85 @@
name: Smoke Tests
on:
push:
branches: [main]
paths:
- 'src/core/**'
- 'src/shared/**'
- 'proto/**'
- 'evals/**'
- '.github/workflows/cline-evals-regression.yml'
pull_request:
paths:
- 'src/core/**'
- 'src/shared/**'
- 'proto/**'
- 'evals/**'
- '.github/workflows/cline-evals-regression.yml'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: smoke-tests-${{ github.ref }}
cancel-in-progress: true
jobs:
smoke-tests:
name: Smoke Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build and install CLI
run: |
npm run protos
cd cli && npm install && npm run build && npm link
echo "$(npm config get prefix)/bin" >> $GITHUB_PATH
- name: Verify CLI
run: cline --version
- name: Run smoke tests
env:
CLINE_API_KEY: ${{ secrets.CLINE_API_KEY }}
run: |
cline auth -p cline -k "$CLINE_API_KEY" -m "anthropic/claude-sonnet-4.5"
max_attempts=3
for attempt in $(seq 1 $max_attempts); do
echo "::group::Attempt $attempt of $max_attempts"
if npx tsx evals/smoke-tests/run-smoke-tests.ts --trials 1 --parallel; then
echo "::endgroup::"
echo "Smoke tests passed on attempt $attempt"
exit 0
fi
echo "::endgroup::"
if [ $attempt -lt $max_attempts ]; then
echo "::warning::Smoke tests failed on attempt $attempt, retrying..."
sleep 10
fi
done
echo "::error::Smoke tests failed after $max_attempts attempts"
exit 1
- name: Generate summary
if: always()
run: cat evals/smoke-tests/results/latest/summary.md >> $GITHUB_STEP_SUMMARY
- name: Upload results
uses: actions/upload-artifact@v4
if: always()
with:
name: smoke-test-results-${{ github.run_id }}
path: evals/smoke-tests/results/latest/
retention-days: 30
-312
View File
@@ -1,312 +0,0 @@
name: Cline PR Code Review
on:
pull_request:
types:
[opened, ready_for_review]
# Manual trigger for backfilling existing PRs. Run from terminal:
# gh workflow run cline-pr-review.yml -f pr_number=1234
# Or batch process open PRs:
# gh pr list --state open --limit 10 --json number --jq '.[].number' | while read num; do
# gh workflow run cline-pr-review.yml -f pr_number=$num
# sleep 60
# done
workflow_dispatch:
inputs:
pr_number:
description: "PR number to review"
required: true
type: string
concurrency:
group: pr-review-${{ github.event.pull_request.number || inputs.pr_number }}
cancel-in-progress: true
jobs:
cline-pr-review:
# Runs on PR opened/ready_for_review (skips drafts) or manual trigger for backfilling
if: |
(github.event_name == 'pull_request' && github.event.pull_request.draft == false) ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 60
# SECURITY: These permissions are intentionally restrictive.
# - contents: read -> cline can read the codebase but CANNOT write/push any code
# - pull-requests: write -> cline can post reviews and inline suggestions
# - issues: read -> cline can search for related issues
# NOTE: Even with pull-requests: write, cline CANNOT merge PRs because branch protection
# requires 1 approval from a Code Owner. The GITHUB_TOKEN cannot bypass this.
permissions:
contents: read
pull-requests: write
issues: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: "npm"
- name: Install and Verify Cline CLI
run: |
npx cline version # verify installation
- name: Configure Cline with Anthropic
run: |
npx cline auth --provider anthropic \
--apikey "${{ secrets.ANTHROPIC_API_KEY }}" \
--modelid claude-opus-4-5-20251101
- name: Get PR number
id: pr
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "number=${{ inputs.pr_number }}" >> $GITHUB_OUTPUT
else
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
fi
- name: Review PR with Cline
env:
PR_NUMBER: ${{ steps.pr.outputs.number }}
GITHUB_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
CLINE_COMMAND_PERMISSIONS: |
{
"allow": [
"gh pr diff *",
"gh pr view *",
"gh pr checks *",
"gh pr list *",
"gh label list *",
"gh issue list *",
"gh issue view *",
"git log *",
"gh pr comment ${{ steps.pr.outputs.number }} *",
"gh pr edit ${{ steps.pr.outputs.number }} *",
"gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/comments *",
"gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/reviews *"
]
}
run: |
npx cline --yolo 'You'\''re a GitHub PR reviewer for the open source Cline repository. Your goal is to give the PR author helpful feedback and give maintainers the context they need to review efficiently.
PR: #'"${PR_NUMBER}"'
## Gather context
```bash
# Get full PR details
gh pr view '"${PR_NUMBER}"' --json number,title,body,author,createdAt,updatedAt,isDraft,labels,commits,files,additions,deletions,changedFiles,baseRefName,headRefName,mergeable,reviewDecision
# Get the diff
gh pr diff '"${PR_NUMBER}"'
# Check CI status
gh pr checks '"${PR_NUMBER}"'
# Get existing review comments (to understand context and your previous feedback)
gh api repos/'"${GITHUB_REPO}"'/pulls/'"${PR_NUMBER}"'/comments --jq '\''.[] | {user: .user.login, body: .body, path: .path, created_at: .created_at}'\''
# Get conversation comments
gh pr view '"${PR_NUMBER}"' --comments
```
If this is a re-review (workflow_dispatch event):
Read your previous comments carefully. Understand what you asked for before.
Check if new commits or comments address your previous feedback.
## Check contributing guidelines
Flag (but don'\''t block) if:
- Missing changeset - For user-facing changes, check if there'\''s a `.changeset/` file:
```bash
gh pr diff '"${PR_NUMBER}"' --name-only | grep '\''.changeset/'\'' || echo '\''No changeset found'\''
```
If missing, ask them to run `npm run changeset`
- Missing tests - New features should have tests
## Find related issues and PRs
Search thoroughly for context that might help with the review:
```bash
# Find related issues for context
gh issue list --search '\''<keywords from the PR>'\'' --state all --limit 30
gh issue list --search '\''<error messages or feature names>'\'' --state all --limit 20
# Find similar PRs for reference
gh pr list --search '\''<keywords>'\'' --state all --limit 30
```
For each relevant issue or PR you find, read it including comments:
```bash
gh issue view <number> --comments
gh pr view <number> --comments
```
Look for:
- Open issues this PR might fix that weren'\''t linked in the description
- Similar PRs that went through review - what feedback did they get? What patterns did they follow?
- Context from maintainer discussions that could inform your review
## Find subject matter experts
For files changed in this PR, find who knows the code best:
```bash
# Get files changed
gh pr diff '"${PR_NUMBER}"' --name-only
# For each relevant path, find contributors
git log --since='\''6 months ago'\'' --format='\''%an'\'' -- <path> | sort | uniq -c | sort -rn | head -5
```
Cross-reference git authors with GitHub usernames. Include an SME table in your response:
| SME | Reason |
|-----|--------|
| @username1 | Authored PR #X which modified this area |
| @username2 | Primary contributor to affected file (15 commits in 6 months) |
| @username3 | Reviewed similar PR #Y with extensive feedback |
## Bash command usage
Don'\''t use operators like `|`, `&&`, or `;` - run each command separately and analyze the output.
When referencing command outputs, quote them properly to avoid formatting issues.
## Deep code review
This is the most important part. Don'\''t just look for syntax issues - understand what the PR is trying to achieve and whether the implementation is the right approach.
Step 1: Understand the intent
Read the PR description and understand what the author is trying to accomplish. What problem are they solving? What feature are they adding?
Step 2: Form your own opinion first
Before analyzing their code, think about how YOU would implement this feature or fix. What files would you touch? What patterns would you follow? What edge cases would you handle?
Step 3: Compare approaches
Now look at their implementation. How does it compare to what you would have done?
- Is their approach better in some ways? Note what they did well.
- Is their approach missing something? Be specific about what and why.
- Are there edge cases they haven'\''t considered?
- Does it follow the patterns established in similar parts of the codebase?
Step 4: Look at the bigger picture
- What other files or systems does this change interact with?
- Could this break anything else?
- Is there additional work needed beyond this PR to complete the feature?
- Does this fit well with the overall architecture?
Step 5: Find reference implementations
Look for similar changes in the codebase:
```bash
git log --oneline --all --grep='\''<relevant keywords>'\'' | head -20
git log --oneline -- <similar files> | head -20
```
If this is adding a new API provider, look at how other providers are implemented.
If this is adding a new feature, look at how similar features were added.
Note where their implementation aligns with or diverges from established patterns.
Step 6: Standard code review checks
- DRY: Is there duplicated code that could be extracted?
- Error handling: Are errors handled appropriately?
- Security: Any injection risks, credential exposure, unsafe dependencies?
- Performance: Any obvious inefficiencies, memory leaks, N+1 patterns?
- Types: Is TypeScript used correctly? Any unsafe type assertions?
- Naming: Are variables and functions named clearly?
- Comments: Is complex logic explained? Are there outdated comments?
## Inline code suggestions
For specific code improvements, use GitHub'\''s suggestion syntax via `gh api`.
This creates suggestions the author can commit with one click.
Single-line suggestion:
```bash
gh api repos/'"${GITHUB_REPO}"'/pulls/'"${PR_NUMBER}"'/reviews \
-X POST \
-f commit_id="$(gh pr view '"${PR_NUMBER}"' --json headRefOid -q .headRefOid)" \
-f event='\''COMMENT'\'' \
-f body='\'''\'' \
-F comments='\''[
{
"path": "src/example.ts",
"line": 42,
"body": "Consider simplifying:\n\n```suggestion\nconst result = items.filter(Boolean);\n```"
}
]'\''
```
Multi-line suggestion (replacing lines 40-45):
```bash
gh api repos/'"${GITHUB_REPO}"'/pulls/'"${PR_NUMBER}"'/reviews \
-X POST \
-f commit_id="$(gh pr view '"${PR_NUMBER}"' --json headRefOid -q .headRefOid)" \
-f event='\''COMMENT'\'' \
-f body='\'''\'' \
-F comments='\''[
{
"path": "src/example.ts",
"start_line": 40,
"line": 45,
"body": "This can be simplified:\n\n```suggestion\nconst simplified = doThing();\n```"
}
]'\''
```
Use inline suggestions for concrete improvements. Use regular comments for questions or broader feedback.
## Post your review
After your investigation, post a single helpful comment that helps the author and gives maintainers context.
Start with a warm thank you for their contribution. Be conversational, not robotic.
Include what'\''s relevant:
- In-depth explanation of what the PR does - Be comprehensive. A maintainer should be able to read this section and fully understand the author'\''s intent, why they made the changes, how they implemented it, and what files/systems are affected. Don'\''t just summarize - explain.
- Related issues/PRs you found that provide useful context (link to them)
- Your review findings (issues to address, suggestions, etc.)
- Clear next steps for the author
Include a '\''For Maintainers'\'' section with:
- Anything else useful to help the maintainer resolve this PR
- Related issues/PRs with context on why they'\''re relevant
- Open issues this PR might fix that weren'\''t linked in the description
- Your recommendation: merge as-is, needs changes, needs discussion, close, etc.
- SME table - who should review this and why
For the SME table:
| SME | Reason |
|-----|--------|
| @username | Primary contributor to affected files |
## Update labels
Add appropriate labels based on your analysis:
```bash
gh label list --json name,description --limit 100
gh pr edit '"${PR_NUMBER}"' --add-label '\''label1,label2'\''
```
When done, add the reviewed label:
```bash
gh pr edit '"${PR_NUMBER}"' --add-label '\''Bot Reviewed'\''
```
## Remember
- This is a one-time automated response - you will NOT see their reply or respond again. Never say things like '\''let me know if you have questions'\'', '\''I can help you with'\'', or '\''feel free to ask'\'' - you won'\''t be there to follow up. Frame any questions for the maintainers who will follow up.
- Be helpful and welcoming - Many contributors are new to the project
- Be specific - Point to exact lines and suggest fixes, don'\''t give vague feedback
- Think deeply - Don'\''t just surface-level review, understand the intent and evaluate the approach
- Use inline suggestions - Make it easy for authors to accept changes
- You'\''re a first-pass reviewer - A human maintainer will do final approval'
+5 -2
View File
@@ -80,13 +80,16 @@ jobs:
playwright-browsers-${{ runner.os }}-
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci
- name: Install vsce
run: npm install -g @vscode/vsce
- name: Install xvfb on Linux
if: matrix.runner == 'ubuntu'
run: sudo apt-get update && sudo apt-get install -y xvfb
+41 -42
View File
@@ -1,7 +1,7 @@
name: Publish NPM Release
on:
workflow_dispatch:
workflow_call:
inputs:
confirm_publish:
description: 'Type "publish" to confirm you want to publish to NPM'
@@ -9,9 +9,10 @@ on:
type: string
permissions:
contents: read
checks: write # Required by test workflow
pull-requests: write # Required by test workflow
contents: write # Required for pushing tags
id-token: write # Required for npm trusted publishing (OIDC)
checks: write # Required by test workflow
pull-requests: write # Required by test workflow
jobs:
test:
@@ -20,7 +21,7 @@ jobs:
publish-npm-release:
needs: test
name: Publish Cline CLI to NPM
if: github.repository == 'cline/cline' && github.ref == 'refs/heads/main' && github.event.inputs.confirm_publish == 'publish'
if: github.repository == 'cline/cline' && github.ref == 'refs/heads/main' && inputs.confirm_publish == 'publish'
runs-on: ubuntu-latest
steps:
@@ -30,32 +31,11 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
node-version: "24.x"
registry-url: "https://registry.npmjs.org"
# Cache root dependencies
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
# Cache cli-ts dependencies
- name: Cache cli-ts dependencies
uses: actions/cache@v4
id: cli-ts-cache
with:
path: cli-ts/node_modules
key: ${{ runner.os }}-npm-cli-ts-${{ hashFiles('cli-ts/package-lock.json') }}
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci --include=optional
- name: Install cli-ts dependencies
if: steps.cli-ts-cache.outputs.cache-hit != 'true'
run: cd cli-ts && npm ci
- name: Install root dependencies and CLI dependencies
run: npm ci --include=optional # this will also install cli deps because "cli" in included in root package.json workspaces field
- name: Generate Protos
run: npm run protos
@@ -63,15 +43,12 @@ jobs:
- name: Read release version
id: version
run: |
# Read version from cli-ts/package.json
VERSION=$(node -p "require('./cli-ts/package.json').version")
# Read version from cli/package.json
VERSION=$(node -p "require('./cli/package.json').version")
echo "Release version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Clean previous builds
run: rm -rf dist-standalone
- name: Build and package CLI
- name: Build standalone NPM package
env:
TELEMETRY_SERVICE_API_KEY: ${{ secrets.TELEMETRY_SERVICE_API_KEY }}
ERROR_SERVICE_API_KEY: ${{ secrets.ERROR_SERVICE_API_KEY }}
@@ -82,7 +59,6 @@ jobs:
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
POSTHOG_TELEMETRY_ENABLED: "true"
run: node scripts/package-npm.mjs
- name: Verify build output
@@ -90,23 +66,46 @@ jobs:
echo "Checking dist-standalone directory..."
ls -la dist-standalone/
echo "Checking dist-standalone/dist..."
ls -la dist-standalone/dist/
echo "Verifying CLI binaries..."
ls -lh cli/bin/cline-* || echo "Warning: CLI binaries not found"
echo "Checking package.json in dist-standalone..."
cat dist-standalone/package.json
cat dist-standalone/package.json | grep version
- name: Publish to NPM with latest tag
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_RELEASE_TOKEN }}
run: |
echo "Publishing version ${{ steps.version.outputs.version }} to NPM with tag 'latest'..."
cd dist-standalone
npm publish --tag latest --access public
- name: Tag release
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "v${{ steps.version.outputs.version }}-cli"
git push origin "v${{ steps.version.outputs.version }}-cli"
- name: Summary
run: |
echo "✅ Successfully published cline@${{ steps.version.outputs.version }} to NPM with tag 'latest'"
echo ""
echo "📦 Install with: npm install -g cline"
echo "🔗 NPM: https://www.npmjs.com/package/cline/v/${{ steps.version.outputs.version }}"
- name: Post release to Slack
uses: slackapi/slack-github-action@v3.0.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_RELEASE_BOT_TOKEN }}
payload: |
channel: "C0APVKGGZFC"
text: "Cline CLI v${{ steps.version.outputs.version }}"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: "*Cline CLI v${{ steps.version.outputs.version }}*"
- type: "context"
elements:
- type: "mrkdwn"
text: "<https://www.npmjs.com/package/cline/v/${{ steps.version.outputs.version }}|View on npm>"
+30 -48
View File
@@ -1,14 +1,19 @@
name: Publish NPM Nightly
on:
schedule:
- cron: '0 12 * * *' # 4 AM PST (UTC-8) = 12 UTC
workflow_dispatch:
workflow_call:
inputs:
force_publish:
description: "Force publish even if there are no commits in the last 24 hours"
required: false
type: boolean
default: false
permissions:
contents: read
checks: write # Required by test workflow
pull-requests: write # Required by test workflow
id-token: write # Required for npm trusted publishing (OIDC)
checks: write # Required by test workflow
pull-requests: write # Required by test workflow
jobs:
test:
@@ -27,6 +32,12 @@ jobs:
- name: Check for recent commits
id: check_commits
run: |
if [ "${{ inputs.force_publish }}" = "true" ]; then
echo "force_publish enabled, proceeding with publish"
echo "skip=false" >> $GITHUB_OUTPUT
exit 0
fi
if [ $(git rev-list --count HEAD --since="24 hours ago") -eq 0 ]; then
echo "No commits in last 24 hours, skipping publish"
echo "skip=true" >> $GITHUB_OUTPUT
@@ -39,34 +50,12 @@ jobs:
if: steps.check_commits.outputs.skip != 'true'
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
node-version: "24.x"
registry-url: "https://registry.npmjs.org"
# Cache root dependencies
- name: Cache root dependencies
- name: Install root dependencies and CLI dependencies
if: steps.check_commits.outputs.skip != 'true'
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
# Cache cli-ts dependencies
- name: Cache cli-ts dependencies
if: steps.check_commits.outputs.skip != 'true'
uses: actions/cache@v4
id: cli-ts-cache
with:
path: cli-ts/node_modules
key: ${{ runner.os }}-npm-cli-ts-${{ hashFiles('cli-ts/package-lock.json') }}
- name: Install root dependencies
if: steps.check_commits.outputs.skip != 'true' && steps.root-cache.outputs.cache-hit != 'true'
run: npm ci --include=optional
- name: Install cli-ts dependencies
if: steps.check_commits.outputs.skip != 'true' && steps.cli-ts-cache.outputs.cache-hit != 'true'
run: cd cli-ts && npm ci
run: npm ci --include=optional # this will also install cli deps because "cli" in included in root package.json workspaces field
- name: Generate Protos
if: steps.check_commits.outputs.skip != 'true'
@@ -76,36 +65,32 @@ jobs:
if: steps.check_commits.outputs.skip != 'true'
id: version
run: |
# Read base version from cli-ts/package.json (e.g., "2.0.0")
BASE_VERSION=$(node -p "require('./cli-ts/package.json').version")
# Read base version from cli/package.json (e.g., "2.0.0")
BASE_VERSION=$(node -p "require('./cli/package.json').version")
# Generate timestamp (Unix epoch seconds)
TIMESTAMP=$(date +%s)
# Create unique nightly version: 2.0.0-nightly.1736365200
# Create unique nightly version: 1.0.9-nightly.1736365200
VERSION="${BASE_VERSION}-nightly.${TIMESTAMP}"
echo "Base version: $BASE_VERSION"
echo "Generated nightly version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Update cli-ts/package.json with nightly version
- name: Update cli/package.json with nightly version
if: steps.check_commits.outputs.skip != 'true'
run: |
# Update version with timestamp-based nightly version
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('cli-ts/package.json', 'utf8'));
const pkg = JSON.parse(fs.readFileSync('cli/package.json', 'utf8'));
pkg.version = '${{ steps.version.outputs.version }}';
fs.writeFileSync('cli-ts/package.json', JSON.stringify(pkg, null, '\t'));
fs.writeFileSync('cli/package.json', JSON.stringify(pkg, null, '\t'));
"
echo "Using version ${{ steps.version.outputs.version }} for build"
cat cli-ts/package.json | grep '"version"'
- name: Clean previous builds
if: steps.check_commits.outputs.skip != 'true'
run: rm -rf dist-standalone
cat cli/package.json | grep '"version"'
- name: Build and package CLI
if: steps.check_commits.outputs.skip != 'true'
@@ -119,7 +104,6 @@ jobs:
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
POSTHOG_TELEMETRY_ENABLED: "true"
run: node scripts/package-npm.mjs
- name: Verify build output
@@ -128,16 +112,14 @@ jobs:
echo "Checking dist-standalone directory..."
ls -la dist-standalone/
echo "Checking dist-standalone/dist..."
ls -la dist-standalone/dist/
echo "Verifying CLI binaries..."
ls -lh cli/bin/cline-* || echo "Warning: CLI binaries not found"
echo "Checking package.json in dist-standalone..."
cat dist-standalone/package.json
cat dist-standalone/package.json | grep version
- name: Publish to NPM with nightly tag
if: steps.check_commits.outputs.skip != 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_RELEASE_TOKEN }}
run: |
echo "Publishing version ${{ steps.version.outputs.version }} to NPM with tag 'nightly'..."
cd dist-standalone
+215
View File
@@ -0,0 +1,215 @@
# Build and Pack CLI
#
# Builds a CLI tarball from any branch/commit and publishes it as a GitHub Release.
# Requires write access to the repository (maintainers/collaborators only).
#
# Security: Split into two jobs to isolate untrusted build code from write tokens.
# The build job runs arbitrary ref code with zero permissions. The release job
# only runs trusted GitHub Actions with write scope.
#
# Usage (helper script, auto-detects current branch):
# ./scripts/build-cli-artifact.sh
# ./scripts/build-cli-artifact.sh feature/my-changes
# ./scripts/build-cli-artifact.sh feature/my-changes 1234 # comments on PR
#
# Usage (gh CLI directly):
# gh workflow run pack-cli.yml -f ref=main
# gh workflow run pack-cli.yml -f ref=abc123 -f pr_number=1234
#
# Install the built CLI (no auth required):
# npm install -g https://github.com/cline/cline/releases/download/cli-build-<sha>/cline-<ver>.tgz
#
# Find releases:
# gh release list --limit 10
name: Build and Pack CLI
permissions:
contents: read
on:
workflow_dispatch:
inputs:
ref:
description: 'Branch, tag, or commit SHA to build (leave empty for default branch)'
required: false
type: string
pr_number:
description: 'PR number to comment on with install instructions (optional)'
required: false
type: number
jobs:
# ── Build job: runs untrusted ref code with ZERO permissions ──
build:
name: Build CLI
runs-on: ubuntu-latest
permissions: {}
outputs:
commit_sha: ${{ steps.commit.outputs.sha }}
tarball: ${{ steps.pack.outputs.tarball }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
persist-credentials: false
- name: Get commit SHA
id: commit
run: |
COMMIT_SHA=$(git rev-parse --short HEAD)
echo "sha=$COMMIT_SHA" >> $GITHUB_OUTPUT
echo "Building from commit: $COMMIT_SHA"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20.x"
- name: Install dependencies
run: npm ci --include=optional
- name: Generate Protos
run: npm run protos
- name: Build standalone package
run: node scripts/package-npm.mjs
- name: Create Tarball
id: pack
run: |
cd dist-standalone
TARBALL=$(npm pack)
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
echo "Created tarball: $TARBALL"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cli-tarball
path: dist-standalone/*.tgz
# ── Release job: only trusted Actions code, with write permissions ──
release:
name: Release CLI
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: cli-tarball
path: dist-standalone
- name: Create GitHub Release
id: create_release
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const commit = '${{ needs.build.outputs.commit_sha }}';
const tarball = '${{ needs.build.outputs.tarball }}';
// Delete existing release/tag if re-running for the same commit
const tagName = `cli-build-${commit}`;
try {
const existing = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag: tagName
});
await github.rest.repos.deleteRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: existing.data.id
});
await github.rest.git.deleteRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `tags/${tagName}`
});
core.info(`Deleted existing release for ${tagName}`);
} catch (e) {
// Release doesn't exist yet, that's fine
}
// Create a release
const release = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tagName,
name: `CLI Build (${commit})`,
body: `Automated CLI build from commit ${commit}\n\nInstall with:\n\`\`\`bash\nnpm install -g https://github.com/${context.repo.owner}/${context.repo.repo}/releases/download/${tagName}/${tarball}\n\`\`\``,
draft: false,
prerelease: true
});
// Upload the tarball as a release asset
const tarballPath = path.join('dist-standalone', tarball);
const tarballData = fs.readFileSync(tarballPath);
await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id,
name: tarball,
data: tarballData
});
const downloadUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/releases/download/${tagName}/${tarball}`;
core.setOutput('release_url', release.data.html_url);
core.setOutput('download_url', downloadUrl);
- name: Comment on PR with download instructions
if: inputs.pr_number != ''
uses: actions/github-script@v7
with:
script: |
const commit = '${{ needs.build.outputs.commit_sha }}';
const releaseUrl = '${{ steps.create_release.outputs.release_url }}';
const downloadUrl = '${{ steps.create_release.outputs.download_url }}';
const prNumber = ${{ inputs.pr_number || 0 }};
if (!prNumber) return;
const comment = `## 📦 CLI Build Ready
A CLI build has been created for commit \`${commit}\`.
### Install Directly from URL (No Authentication Required!)
\`\`\`bash
npm install -g ${downloadUrl}
\`\`\`
### Alternative: Download and Install
\`\`\`bash
curl -L ${downloadUrl} -o cline.tgz
npm install -g ./cline.tgz
\`\`\`
📦 [View Release](${releaseUrl})
`;
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
- name: Summary
run: |
echo "✅ CLI build complete!"
echo ""
echo "📦 Release: ${{ steps.create_release.outputs.release_url }}"
echo "🔗 Download URL: ${{ steps.create_release.outputs.download_url }}"
echo ""
echo "Install from anywhere (no authentication required):"
echo " npm install -g ${{ steps.create_release.outputs.download_url }}"
@@ -0,0 +1,60 @@
name: Publish CLI (Trusted)
on:
schedule:
- cron: "0 12 * * *" # 4 AM PST (UTC-8) = 12 UTC
workflow_dispatch:
inputs:
publish_target:
description: "Which publish flow to run"
required: true
default: "main"
type: choice
options:
- main
- nightly
confirm_publish:
description: 'Required when publish_target=main. Type "publish" to confirm release publish.'
required: false
type: string
force_nightly_publish:
description: "Force nightly publish even with no commits in last 24h"
required: false
type: boolean
default: false
permissions:
id-token: write # Required for npm trusted publishing (OIDC)
contents: write # Required because npm-main creates/pushes git tags
checks: write # Required by nested reusable test workflow
pull-requests: write # Required by nested reusable test workflow
jobs:
cli-tui-tests:
uses: ./.github/workflows/cli-tui-tests.yml
publish-main:
needs: cli-tui-tests
if: |
github.repository == 'cline/cline' && (
github.event_name == 'workflow_dispatch' &&
github.event.inputs.publish_target == 'main' &&
github.event.inputs.confirm_publish == 'publish' &&
!endsWith(github.actor, '[bot]')
)
uses: ./.github/workflows/npm-main.yaml
secrets: inherit
with:
confirm_publish: ${{ github.event.inputs.confirm_publish }}
publish-nightly:
needs: cli-tui-tests
if: |
github.repository == 'cline/cline' && (
github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.publish_target == 'nightly')
)
uses: ./.github/workflows/npm-nightly.yaml
secrets: inherit
with:
force_publish: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.force_nightly_publish == 'true' }}
+14 -19
View File
@@ -24,6 +24,8 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
lfs: true
- name: Check for recent commits
run: |
@@ -36,35 +38,28 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
# Cache root dependencies - only reuse if package-lock.json exactly matches
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
# Cache webview-ui dependencies - only reuse if package-lock.json exactly matches
- name: Cache webview-ui dependencies
uses: actions/cache@v4
id: webview-cache
with:
path: webview-ui/node_modules
key: ${{ runner.os }}-npm-webview-${{ hashFiles('webview-ui/package-lock.json') }}
# Keep publish environment aligned with test workflow/tooling lockfile expectations.
# Newer LTS (Node 24 / npm 11) can make `npm list` fail with ELSPROBLEMS during vsce packaging.
node-version: 22
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci --include=optional
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci --include=optional
- name: Install Publishing Tools
run: npm install -g @vscode/vsce ovsx
- name: Verify LFS media assets are resolved
run: |
for FILE in webview-ui/src/assets/cline_kanban_demo.mp4 webview-ui/src/assets/cline_kanban_demo.webm; do
if grep -q "git-lfs.github.com/spec/v1" "$FILE"; then
echo "Error: $FILE is still a Git LFS pointer in CI checkout"
exit 1
fi
done
- name: Publish Extension as Pre-release
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
+107 -34
View File
@@ -11,8 +11,13 @@ on:
options:
- pre-release
- release
auto_create_tag_from_main:
description: "Auto-create and push the provided tag from the tested main commit (recommended)"
required: true
default: true
type: boolean
tag:
description: "Enter existing tag to publish (e.g., v3.1.2)"
description: "Tag to publish (required in both modes, e.g., v3.1.2)"
required: true
type: string
@@ -35,37 +40,79 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.tag }}
ref: main
fetch-depth: 0
fetch-tags: true
lfs: true
- name: Resolve Release Tag
id: resolve_tag
run: |
TAG="${{ github.event.inputs.tag }}"
AUTO_CREATE="${{ github.event.inputs.auto_create_tag_from_main }}"
TESTED_SHA="${{ github.sha }}"
WORKFLOW_REF="${{ github.ref }}"
if [[ -z "$TAG" ]]; then
echo "Error: tag input is required"
exit 1
fi
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.]+)?$ ]]; then
echo "Error: tag must match vX.Y.Z (optionally with -suffix or .suffix)"
exit 1
fi
TAG_REF="refs/tags/$TAG"
git fetch origin main --tags
if [[ "$AUTO_CREATE" == "true" ]]; then
if [[ "$WORKFLOW_REF" != "refs/heads/main" ]]; then
echo "Error: auto-create mode requires dispatching from main (current ref: $WORKFLOW_REF)"
exit 1
fi
echo "Auto-create enabled. Using tested workflow SHA: $TESTED_SHA"
if ! git merge-base --is-ancestor "$TESTED_SHA" origin/main; then
echo "Error: tested SHA $TESTED_SHA is not on origin/main"
exit 1
fi
if git show-ref --verify --quiet "$TAG_REF"; then
TAG_SHA=$(git rev-list -n 1 "$TAG_REF^{commit}")
if [[ "$TAG_SHA" != "$TESTED_SHA" ]]; then
echo "Error: tag '$TAG' already exists at $TAG_SHA, not at tested SHA ($TESTED_SHA)"
exit 1
fi
echo "Tag '$TAG' already exists at tested SHA. Continuing."
else
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "$TAG" "$TESTED_SHA"
git push origin "$TAG_REF"
echo "Created and pushed tag '$TAG' from tested SHA $TESTED_SHA."
fi
else
if ! git show-ref --verify --quiet "$TAG_REF"; then
echo "Error: tag '$TAG' does not exist in the repository"
exit 1
fi
echo "Using existing tag '$TAG'."
fi
git checkout --detach "$TAG_REF^{commit}"
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "resolved_sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
# Cache root dependencies - only reuse if package-lock.json exactly matches
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
# Cache webview-ui dependencies - only reuse if package-lock.json exactly matches
- name: Cache webview-ui dependencies
uses: actions/cache@v4
id: webview-cache
with:
path: webview-ui/node_modules
key: ${{ runner.os }}-npm-webview-${{ hashFiles('webview-ui/package-lock.json') }}
node-version: 22
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm install --include=optional
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm install --include=optional
- name: Install Publishing Tools
@@ -77,20 +124,24 @@ jobs:
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Validate Tag
id: validate_tag
- name: Verify Tag Matches Package Version
run: |
TAG="${{ github.event.inputs.tag }}"
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "Using existing tag: $TAG"
# Verify the tag exists
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Error: Tag '$TAG' does not exist in the repository"
TAG="${{ steps.resolve_tag.outputs.tag }}"
VERSION="v${{ steps.get_version.outputs.version }}"
if [[ "$TAG" != "$VERSION" ]]; then
echo "Error: tag '$TAG' does not match package version '$VERSION'"
exit 1
fi
echo "Tag and package version match: $TAG"
echo "Tag '$TAG' validated successfully"
- name: Verify LFS media assets are resolved
run: |
for FILE in webview-ui/src/assets/cline_kanban_demo.mp4 webview-ui/src/assets/cline_kanban_demo.webm; do
if grep -q "git-lfs.github.com/spec/v1" "$FILE"; then
echo "Error: $FILE is still a Git LFS pointer in CI checkout"
exit 1
fi
done
- name: Package and Publish Extension
env:
@@ -121,7 +172,7 @@ jobs:
- name: Get Previous Tag
id: prev_tag
run: |
CURRENT_TAG="${{ steps.validate_tag.outputs.tag }}"
CURRENT_TAG="${{ steps.resolve_tag.outputs.tag }}"
PREV_TAG=$(git describe --tags --abbrev=0 "$CURRENT_TAG^" 2>/dev/null || echo "")
echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
@@ -137,12 +188,34 @@ jobs:
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.validate_tag.outputs.tag }}
tag_name: ${{ steps.resolve_tag.outputs.tag }}
files: "*.vsix"
body: |
${{ steps.changelog.outputs.content }}
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.prev_tag.outputs.prev_tag }}...${{ steps.validate_tag.outputs.tag }}
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.prev_tag.outputs.prev_tag }}...${{ steps.resolve_tag.outputs.tag }}
prerelease: ${{ github.event.inputs.release-type == 'pre-release' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post release to Slack
uses: slackapi/slack-github-action@v3.0.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_RELEASE_BOT_TOKEN }}
payload: |
channel: "C0APVKGGZFC"
text: "Cline ${{ steps.resolve_tag.outputs.tag }}"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: "*Cline ${{ steps.resolve_tag.outputs.tag }}*"
- type: "section"
text:
type: "mrkdwn"
text: ${{ toJSON(steps.changelog.outputs.content) }}
- type: "context"
elements:
- type: "mrkdwn"
text: "Full Changelog: https://github.com/${{ github.repository }}/compare/${{ steps.prev_tag.outputs.prev_tag }}...${{ steps.resolve_tag.outputs.tag }}"
+25 -63
View File
@@ -28,27 +28,17 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 22
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
- name: Cache webview-ui dependencies
uses: actions/cache@v4
id: webview-cache
with:
path: webview-ui/node_modules
key: ${{ runner.os }}-npm-webview-${{ hashFiles('webview-ui/package-lock.json') }}
cache: 'npm'
cache-dependency-path: |
package-lock.json
webview-ui/package-lock.json
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci
- name: Run Quality Checks (Parallel)
@@ -73,27 +63,17 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 22
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
- name: Cache webview-ui dependencies
uses: actions/cache@v4
id: webview-cache
with:
path: webview-ui/node_modules
key: ${{ runner.os }}-npm-webview-${{ hashFiles('webview-ui/package-lock.json') }}
cache: 'npm'
cache-dependency-path: |
package-lock.json
webview-ui/package-lock.json
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci
- name: Set up NPM on Windows
@@ -135,6 +115,11 @@ jobs:
cd webview-ui
npm run test:coverage
- name: CLI Tests
id: cli_tests
if: ${{ !cancelled() && steps.build_step.outcome == 'success' }}
run: cd cli && npm run test:run
- name: Save Coverage Reports
uses: actions/upload-artifact@v4
# Only upload artifacts on Linux - We only need coverage from one OS
@@ -156,35 +141,18 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 22
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
- name: Cache webview-ui dependencies
uses: actions/cache@v4
id: webview-cache
with:
path: webview-ui/node_modules
key: ${{ runner.os }}-npm-webview-${{ hashFiles('webview-ui/package-lock.json') }}
# Cache testing-platform dependencies
- name: Cache testing-platform dependencies
uses: actions/cache@v4
id: testing-platform-cache
with:
path: testing-platform/node_modules
key: ${{ runner.os }}-npm-testing-platform-${{ hashFiles('testing-platform/package-lock.json') }}
cache: 'npm'
cache-dependency-path: |
package-lock.json
webview-ui/package-lock.json
testing-platform/package-lock.json
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install webview-ui dependencies
if: steps.webview-cache.outputs.cache-hit != 'true'
run: cd webview-ui && npm ci
- name: Download ripgrep binaries
@@ -194,17 +162,11 @@ jobs:
run: npm run compile-standalone
- name: Install testing platform dependencies
if: steps.testing-platform-cache.outputs.cache-hit != 'true'
run: cd testing-platform && npm ci
- name: Running testing platform integration spec tests
continue-on-error: true
timeout-minutes: 7
# Temporarily wrapping the test command to always return a neutral exit code.
# This prevents the job from showing as failed and avoids distracting developers
# until the integration tests are ready to be enforced.
run: |
npm run test:tp-orchestrator -- tests/specs/ --count=1 --coverage
run: npm run test:tp-orchestrator -- tests/specs/ --count=1 --coverage
- name: Save Coverage Reports
uses: actions/upload-artifact@v4
@@ -20,7 +20,8 @@ jobs:
github.event_name == 'pull_request_target' ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '/test-jetbrains'))
contains(github.event.comment.body, '/test-jetbrains') &&
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association))
steps:
- name: Generate GitHub App Token
id: app-token
+9
View File
@@ -38,6 +38,7 @@ coverage-unit
src/generated/
src/shared/proto/
webview-ui/src/services/grpc-client.ts
*.tsbuildinfo
# E2E Tests
test-results
@@ -47,3 +48,11 @@ test-results
.secrets
*.tsbuildinfo
# Smoke test results (generated)
evals/smoke-tests/results/
.tui-test
secrets.json
tui-traces
tests/**/cache
+3
View File
@@ -0,0 +1,3 @@
[submodule "evals/cline-bench"]
path = evals/cline-bench
url = https://github.com/cline/cline-bench.git
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+5 -1
View File
@@ -3,7 +3,11 @@
"ts"
],
"spec": [
"src/**/__tests__/*.ts"
"src/**/__tests__/*.ts",
"src/test/services/**/*.test.ts"
],
"ignore": [
"src/sdk/**"
],
"require": [
"ts-node/register",
+2 -1
View File
@@ -16,7 +16,8 @@
"saoudrizwan.claude-dev", // Avoid conflicts with installed Cline
"--disable-extension",
"saoudrizwan.cline-nightly", // Avoid conflicts with installed Cline Nightly
"${workspaceFolder}"
"${workspaceFolder}",
"--disable-extensions"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
-2
View File
@@ -35,11 +35,9 @@ cli/**
eslint-rules/
old_docs/
evals/
.changie.yaml
.codespellrc
.mocharc.json
buf.yaml
.changeset/
.clinerules/
# 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)
+940
View File
@@ -0,0 +1,940 @@
# SDK Migration — Architecture & Design
Evergreen reference for the Cline SDK migration project. For the
living implementation plan, see `migration.md`.
## References
### Code References
Cline SDK is at ~/clients/cline/sdk-wip
Cline (core, classic VSCode extension, CLI) is at ~/clients/cline/cline
JetBrains Plugin is at ~/clients/cline/intellij-plugin
IntelliJ open source reference is at ~/clients/cline/intellij-community
JCEF (Java-Chromium embedded framework reference) is at ~/clients/cline/jcef
You can use kb_search with these identifiers to understand the
existing code and the SDK code:
cline - Cline core, classic VSCode extension, CLI
sdk - Cline SDK
plugin - JetBrains plugin
vscode - Visual Studio Code opens source
ij - IntelliJ open source
jcef - JCEF IntelliJ's embedded Chromium layer
Prototype VSCode extension on SDK is at ~/clients/cline/sdk-vscode-sample
Prototype JetBrains plugin on SDK is at ~/clients/cline/sdk-intellij-plugin-sample
These are prototypes with features missing and added, so refer to them
as examples, but don't overindex on them.
### Documentation references
See the ~/clients/cline/cline/docs for extension product documentation
and ~/clients/cline/sdk-wip/*.md for SDK documentation.
### Background on the products & architecture
There's a VSCode extension in cline/src. A large part of its UI is a
React-based webview in cline/webview-ui.
There's a JetBrains plugin in the intellij-plugin repo. It packages
the core of the VSCode extension, including the webview, and
communicates with it with protobufs. There's a bunch of stuff in the
cline repo called "standalone" which is what JetBrains communicates
with.
In cline/cli there's a CLI and Kanban tool. Those use the SDK/are
being ported separately to the SDK, so you don't need to worry about
them. It is OK if you have to break them. Just ignore them.
Note, there was an earlier, failed attempt at a cli in go. The go cli
used to use "standalone" like JetBrains. If there's any old go support
cluttering up the repo, it is fine to delete it and clean it up.
The source code and docs mentioned above are the best reference to the
product architecture, behavior, etc. Feel free to ask clarifying
questions when necessary.
---
## Features
### Features to remove
Terminal integration: There is legacy code in the VSCode extension,
and stubs in the RPC system for JetBrains, which used the IDE's
integrated terminals. We have decided we don't need these old modes
and they should be removed. Instead we will rely on "background
terminal". This literally means the node code forks and execs a shell
and uses pipes to communicate with it.
Browser automation: Remove the system that uses Playwright to automate
browsers. These use cases are now well served by third-party MCP
tools.
"Shadow git" checkpointing system. This is too slow, especially on
Windows. The way the Kanban project uses the existing git repo to
store references, and only after each user message, is better. So we
will drop the "shadow copy" git checkpointing system.
Memory bank, structured context: multi-file documentation
(projectbrief, productContext, activeContext, systemPatterns,
techContext, progress.)
Memory bank, persistence: cross-session context preservation.
Focus chain, task tracking: Auto-generated to-do list with real-time
progress indicators.
Focus chain, integration: Editable focus chain integration with deep
planning and reminders.
Deep planning exploration, output and the /deep-planning command.
Workflows (definition, natural language + XML tool syntax, MCP tools
and user input prompts) ... these have been superceded by SKILLS
moving forward.
Slash commands no longer necessary:
/deep-planning (codebase investigation + plan... we have plan/act mode)
/reportbug (bug reporting with diagnostics)
Custom workflows (/workflow.md for user-defined workflows... we have "skills" now.)
### Core features
These must work:
File operations: read, write, search, replace, list files, inspect
code definitions (functions, classes, methods)
Terminal integration: "Background terminal" must work. The agent
relies on this to run npm, git, docker, etc.
Multi-provider AI models: 30+ providers with seamless
switching. There's one provider of note: VSCode has a provider which
hooks up to Copilot using the VSCode LM Provider API. It would be good
to support this *if possible.*
Auto-approve & YOLO mode
- Granular per-tool permission controls
- YOLO mode for maximum automation
- Monitoring, notifications for long-running commands
Auto-compaction
- Summarization automatically compresses conversations when context fills
- Model support for Claude, Gemini, GPT-5, Grok, etc.
Subagents
- Parallel execution of independent research agents
- Isolation with separate context windows
- Cost tracking for task usage per subagent
Web search and web fetch
Worktrees
- git worktrees for parallel sessions
- branch management and .worktreeinclude support
- conflict resolution and merging
Workspaces
- "multi-root" workspaces/projects with multiple root folders
- @workspace:path scoped references
Jupyter Notebooks
- Generate, explain, and improve notebook cells
Cline Rules
- project-specific .cline/rules and global instructions.
- Conditional logic: Path-based activation of rules.
- Compatibility: Works with Cursor Rules, Windsurf rules, AGENTS.md
Skills
- SKILL.md format with YAML frontmatter
- Loading levels: Metadata, instructions and resources
- Scope: Global and project-specific; toggleable
Hooks
- Events: Task lifecycle + tool events (TaskStart, PreToolUse, etc.)
- Runtimes: bash, powershell for Windows
- IO: JSON
- Context injection: Be able to modify or inject context dynamically
.clineignore
- Exclusion rules, gitignore-style file/directory exclusion
- Exceptions: ! prefix for overrides
- Override behavior: Explicit @ mentions bypass ignore rules
MCP (Model Context Protocol)
- Server management: Discovery, enable/disable, restart, config editing
- Transport: stdio (local) and SSE (remote)
- ...all the typical use cases for MCP: APIs, browser automation, db queries, etc.
### Core workflows
These must work:
Task Management
Task lifecycle - create and resume tasks; view task history
Cost tracking - token using and cost monitoring per task
Plan & Act Mode
Plan mode - Explore and investigate without modifying files
Act mode - Implementation with approval gates
Model config - Separate model configuration for plan and act mode if
the user desires
State persistence - Mode switching, task switching preserves history
File context (@-mentions)
Context referencing - Reference files, folders, terminal output, git
changes, URLs, commits via @
Slash commands
/newtask (new task)
/smol (compress history)
/newrule (create rules)
### Model Configuration
We want to continue supporting our 30+ providers (Anthropic, OpenAI,
OpenAI Codex, OpenRouter, Google Gemini, AWS Bedrock, DeepSeek,
Cerebras, Qwen, Mistral, Groq, Fireworks, Together, xAI Grok,
Moonshot, Nebius, HuggingFace, LiteLLM, Ollama, LM Studio, and more.)
THE MOST IMPORTANT REQUIREMENT HERE, after continuing to support them,
is to USE THE CREDENTIALS, MODEL NAMES, CONFIGS, etc. WE HAVE
SAVED. Logging people out of their providers is really annoying to
users; regenerating API keys is painful for them.
VSCode LM API provider may be an interesting/unusual provider out of
this set; it only works in VSCode by calling a specific API.
We must continue supporting local models like Ollama and LM Studio.
We must support the Cline provider with unified auth (open a
webbrowser, handle the SSO redirect), built-in billing and credit
display, banners advertising new or free models, stealth/early access
models, organization switching.
### Enterprise Features
Security and governance
- Client-side execution only (no data transmission outside of limited
Telemetry and inference; no remote codebase indexing)
- SSO role-based access control (member, admin, owner)
- Model and tool controls per team
- Remote configuration downloaded and applied by the extension
Observability
- OpenTelemetry, Datadog, Grafana, Splunk integrations
- Real-time analytics, cost breakdown by team, selective audit logging
Infrastructure
- AWS Bedrock, Google Vertex AI, Azure OpenAI integration
- Bring-your-own-inference with custom endpoints
### Priority "P1" (mid priority) items
Checkpoints - automatic file snapshots after each change. Note, the
snapshot system in the VSCode extension and JetBrains plugin which
copies the whole repository is slow, *especially on Windows*, so we
should replace it with one that writes refs directly into the local
git repo. Look at the way the kanban project does it; this is
preferred (and maybe we should extract and share this code.)
Diffing - compare changes between checkpoints
Restore - restore files, task to a point, or both
MCP Marketplace - we could get rid of this, but ultimately we do want
this feature with major improvements like allowing remote install. For
now, consider removing it, but if it is easier to keep it around let's
do that to lay the groundwork for improvements.
### Priority "P2" (lower priority) items
Task organization - favorites for task grouping and management
File context - Drag and drop files to add to context
File context - actions - context menus to add to Cline, fix, explain, improve
Slash commands
/explain-changes (git diff explanation)
---
## Detailed Design
### Naming: "Sdk..." considered harmful
Do not name types "SdkFoo" or folders "sdk". If you need to use SdkFoo
as a way to keep two classes around in parallel while you're porting,
that's OK, but when this project is done we want to have one clean,
simple codebase; the SDK backing is an implementation detail so just
use simple noun phrases for classes, etc. and don't litter "Sdk" all
over identifiers and folders.
### Proto deprecation and removal
We don't need proto files to describe webview messages. The webview
and extension backend are both in TypeScript and are versioned and
shipped together. We just need to use shared TypeScript interfaces
between them.
We *also* don't need proto to describe JetBrains <--> node
exchanges. We just need something typed and in sync between Kotlin and
TypeScript that we can serialize. JSON probably makes sense. Protos
are OK but we have had problems with that setup creating a ton of GC
pressure on the Kotlin side, hit maximum message size limits, etc.
There are proto build steps which we can remove, as we use proto less.
protos are useful for state which is serialized. If there are files
that are persisted described by protos, it is ok/good to keep
them. Don't expand the use of protos to places protos are not already
used.
### Web View UI
The Webview UI is very dependent on state arising from implementation
details of the pre-SDK implementation. At the same time, we don't want
to build a new UI from scratch right now because it may be forcing too
many changes upon our users at once. So we aim to reuse the existing
webview, but with radical simplificiation in its state management now
that we will have a cleaner architecture in the extension "backend"
with the layering enforced by the SDK.
The webview UI had defects like showing the wrong keybindings for
JetBrains, or using tons of memory or CPU cycles by spamming state
updates really rapidly or sending n^2 state updates as they streamed
in. The first principle of this migration to the SDK is not get worse,
but at the same time, we expect the state clean-up necessary in the
webview will lead to radical simplifications which make some
low-hanging fruit available in performance. It's great to go make
those improvements where they are available.
We don't need this UI to be pixel perfect identical. We need it to be
FAMILIAR, NOT WORSE and preferably BETTER than the status quo.
### Data formats, settings
We MUST pick up existing on-disk state for settings, etc. We don't
want to log users out of their inference providers as we make this
change to the SDK.
The CLI, VSCode extension and JetBrains extension largely share state
on disk. We should continue that situation. If data migrations are
necessary, that's fine, but design them with care. In particular, we
want the long term to be fast, so we should write breadcrumbs
indicating when migration is done. In addition, users can upgrade and
downgrade their extension versions, etc. and we want to be robust to
that in addition to all kinds of failures. For example, in the past we
had problems where we overwrote a JSON settings file, perhaps racily,
and left trailing }s in the file and this caused the product to
totally fail. That's a very serious issue for our users so pay extra
effort and attention to what is happening on disk. (We want PRACTICAL
solutions and robustness and not performative solutions that just add
tons of code and complexity with no real benefit.)
Invalidating old checkpoints is acceptable, unless it is particularly
cheap to support the classic checkpoints. We won't be authoring those
checkpoints any more, and it would be heavy to migrate them.
We want to move from .clinerules (old style) to .cline/rules (new style.)
### Telemetry
We generally want to continue sending the same Telemetry events. If
that is hard, make a detailed report and we can follow up with our
backend team. Note some enterprise features depend on OTEL
observability.
### Code Sharing
In general we should share code between IDEs where there are benefits
to do so. However trivial tools, or tools specific to a given IDE, can
be wired up directly from the extension through to the SDK. (This is
something that was hard to do in the old architecture and we would
like to make easier.)
---
## Research Findings
### SDK Session Backend Extensibility
**Question**: Does the SDK's `SessionBackend` interface support
storing arbitrary per-task data (e.g., tool settings, hook
configuration, auto-approve preferences per task)?
**Answer**: Partially. The `SessionRow` has a `metadata:
Record<string, unknown> | null` field that can store arbitrary
key-value data per session. This is sufficient for per-task settings
like auto-approve preferences, tool configuration, etc.
The SDK supports three backend implementations:
1. `SqliteSessionStore` — SQLite-backed (default, preferred)
2. `FileSessionService` — JSON file-backed (fallback when SQLite
unavailable)
3. `RpcCoreSessionService` — delegates to an RPC server
For our migration, we'll use either `FileSessionService` or provide a
custom `SessionPersistenceAdapter` that reads/writes our existing task
history format. The `ClineCoreOptions.sessionService` field accepts
any backend implementing `CoreSessionService | RpcCoreSessionService |
FileSessionService`.
**Key finding**: The `SessionPersistenceAdapter` interface is the
cleanest extension point. It requires implementing: `ensureSessionsDir`,
`upsertSession`, `getSession`, `listSessions`, `updateSession`,
`deleteSession`, `enqueueSpawnRequest`, `claimSpawnRequest`. Our
`LegacySessionBackend` adapter wraps the existing
`~/.cline/data/tasks/` directory and `taskHistory` JSON array in
`globalState.json`, mapping between `SessionRow` fields and our
`HistoryItem` type:
```
HistoryItem.id → SessionRow.sessionId
HistoryItem.ts → SessionRow.startedAt (ISO string)
HistoryItem.task → SessionRow.prompt
HistoryItem.tokensIn → metadata.tokensIn
HistoryItem.tokensOut → metadata.tokensOut
HistoryItem.totalCost → metadata.totalCost
HistoryItem.modelId → SessionRow.model
HistoryItem.isFavorited → metadata.isFavorited
```
Per-task files (`api_conversation_history.json`, `ui_messages.json`)
map to `SessionRow.messagesPath` and `SessionRow.transcriptPath`.
**Decision**: We will provide a custom `SessionPersistenceAdapter`
that translates between our existing format and the SDK's interface.
No need for a separate sidecar storage layer. The `metadata` field
handles all per-task extensions.
### Telemetry Event Mapping
The extension currently emits telemetry events via a PostHog-based
`TelemetryService`. The SDK has its own `TelemetryService` with
pluggable adapters (`OpenTelemetryAdapter`, `LoggerTelemetryAdapter`).
**Mapping of current extension events → SDK events:**
| Extension Event | SDK CORE_TELEMETRY_EVENTS | Notes |
|---|---|---|
| `user.extension_activated` | `CLIENT.STARTED` ("extension.activated") | ✅ Same event name |
| `user.auth_started` | `USER.AUTH_STARTED` | ✅ Direct match |
| `user.auth_succeeded` | `USER.AUTH_SUCCEEDED` | ✅ Direct match |
| `user.auth_failed` | `USER.AUTH_FAILED` | ✅ Direct match |
| `user.auth_logged_out` | `USER.AUTH_LOGGED_OUT` | ✅ Direct match |
| `task.created` | `TASK.CREATED` | ✅ Direct match |
| `task.restarted` | `TASK.RESTARTED` | ✅ Direct match |
| `task.completed` | `TASK.COMPLETED` | ✅ Direct match |
| `task.conversation_turn` | `TASK.CONVERSATION_TURN` | ✅ Direct match |
| `task.tokens` | `TASK.TOKEN_USAGE` | ✅ Direct match |
| `task.mode` | `TASK.MODE_SWITCH` | ✅ Direct match |
| `task.tool_used` | `TASK.TOOL_USED` | ✅ Direct match |
| `task.skill_used` | `TASK.SKILL_USED` | ✅ Direct match |
| `task.diff_edit_failed` | `TASK.DIFF_EDIT_FAILED` | ✅ Direct match |
| `task.provider_api_error` | `TASK.PROVIDER_API_ERROR` | ✅ Direct match |
| `task.mention_used` | `TASK.MENTION_USED` | ✅ Direct match |
| `task.mention_failed` | `TASK.MENTION_FAILED` | ✅ Direct match |
| `task.mention_search_results` | `TASK.MENTION_SEARCH_RESULTS` | ✅ Direct match |
| `task.subagent_started` | `TASK.SUBAGENT_STARTED` | ✅ Direct match |
| `task.subagent_completed` | `TASK.SUBAGENT_COMPLETED` | ✅ Direct match |
| `hooks.discovery_completed` | `HOOKS.DISCOVERY_COMPLETED` | ✅ Direct match |
| `session.started` | `SESSION.STARTED` | ✅ Direct match |
| `session.ended` | `SESSION.ENDED` | ✅ Direct match |
**Extension events with NO SDK equivalent (need adapter-layer emit):**
| Extension Event | Action |
|---|---|
| `user.opt_out` / `user.opt_in` | Emit via SDK's `captureRequired()` |
| `user.telemetry_enabled` | Emit via SDK's `capture()` |
| `user.extension_storage_error` | Emit via SDK's `capture()` |
| `user.onboarding_progress` | Emit via SDK's `capture()` |
| `workspace.*` (initialized, vcs_detected, etc.) | Emit via SDK's `capture()` |
| `task.feedback` | Emit via SDK's `capture()` |
| `task.option_selected` / `task.options_ignored` | Emit via SDK's `capture()` |
| `task.checkpoint_used` | Emit via SDK's `capture()` |
| `task.mcp_tool_called` | Emit via SDK's `capture()` |
| `task.historical_loaded` | Emit via SDK's `capture()` |
| `task.retry_clicked` | Emit via SDK's `capture()` |
| `task.slash_command_used` | Emit via SDK's `capture()` |
| `task.feature_toggled` | Emit via SDK's `capture()` |
| `task.rule_toggled` | Emit via SDK's `capture()` |
| `task.auto_condense_toggled` | Emit via SDK's `capture()` |
| `task.yolo_mode_toggled` | Emit via SDK's `capture()` |
| `task.terminal_*` (execution, output_failure, hang) | Emit via SDK's `capture()` |
| `task.initialization` | Emit via SDK's `capture()` |
| `task.summarize_task` | Emit via SDK's `capture()` |
| `ui.*` (model_selected, button_clicked, etc.) | Emit via SDK's `capture()` |
| `hooks.enabled` / `hooks.disabled` | Emit via SDK's `capture()` |
| `hooks.cancel_requested` | Emit via SDK's `capture()` |
| `hooks.context_modified` | Emit via SDK's `capture()` |
| `worktree.*` | Emit via SDK's `capture()` |
| `host.detected` | Emit via SDK's `capture()` |
**Extension events being REMOVED (features deleted):**
| Extension Event | Reason |
|---|---|
| `task.browser_tool_start/end/error` | Browser automation removed |
| `task.focus_chain_*` (6 events) | Focus chain removed |
| `task.workspace_search_pattern` | Folded into SDK search |
| `task.subagent_enabled/disabled` | Toggle events; SDK manages directly |
| `task.cline_web_tools_toggled` | Feature simplified |
| `cline.grpc.response.size_bytes` | gRPC being removed |
**Metrics (OTEL counters/histograms):**
The extension has ~30 OTEL metrics (`cline.turns.total`,
`cline.tokens.input.total`, `cline.api.ttft.seconds`, etc.). The SDK
telemetry service supports `recordCounter`, `recordHistogram`, and
`recordGauge`. We will emit these same metrics from the adapter layer
using `telemetry.recordCounter()` / `telemetry.recordHistogram()`.
The metric names can stay the same.
**Decision**: The SDK's `ITelemetryService.capture()` is a generic
event emitter — we can emit ALL extension events through it. The
adapter layer will create a thin telemetry wrapper that provides
the same `captureTaskCreated()`, `captureToolUsage()`, etc. methods
but delegates to the SDK's telemetry service. Events where the SDK
already has a helper function (listed in the first table) use those
directly. Others use `capture({ event, properties })`. No backend
team coordination needed for the initial migration.
### JetBrains IPC Design
#### Current Architecture
```
┌── Kotlin Plugin ──────────────────────────────┐
│ │
│ CoreProcessManager │
│ └─ launches Node.js process (cline-core) │
│ └─ communicates via gRPC ProtoBus │
│ (port 26040-26340) │
│ │
│ HostBridgeService (gRPC server, port 26041) │
│ ├─ DiffService │
│ ├─ WindowService (show file, open dialog) │
│ ├─ WorkspaceService (paths, diagnostics) │
│ ├─ EnvService │
│ └─ TestingService (get webview HTML) │
│ │
│ ProtoBusProxyService │
│ └─ proxies webview ↔ cline-core gRPC │
│ │
│ JsPostMessageHandler │
│ └─ injects JS bridge into JCEF webview │
│ └─ converts postMessage → gRPC request │
│ │
│ WebViewManager │
│ └─ loads webview HTML in JCEF │
│ └─ receives gRPC responses → postMessage │
└────────────────────────────────────────────────┘
```
Problems with this architecture:
- **Proto size limits**: gRPC messages hit 256MB limits with large
conversations. The `ProtoBusProxyService` logs warnings at 10MB+.
- **Java heap pressure**: Serializing/deserializing large proto
messages stresses the JVM heap.
- **Build complexity**: Proto compilation required for both
TypeScript and Java/Kotlin.
- **Stateless-in-theory**: The design is somewhat stateless but we
haven't leveraged restart-for-reliability because state
reconstruction is expensive.
#### Target Architecture
```
┌── Kotlin Plugin ──────────────────────────────┐
│ │
│ CoreProcessManager │
│ └─ launches SDK sidecar (Node.js) │
│ └─ communicates via JSON-RPC over stdio │
│ │
│ HostCallbackService (JSON-RPC server) │
│ ├─ showTextDocument, openDialog │
│ ├─ getWorkspacePaths, getDiagnostics │
│ ├─ getEnvVars, clipboard │
│ └─ (extensible for PSI, run configs, etc.) │
│ │
│ WebviewBridge │
│ └─ receives JSON messages from sidecar │
│ └─ forwards to JCEF via executeJavaScript │
│ └─ receives postMessage from JCEF │
│ └─ forwards to sidecar via stdio │
│ │
│ WebViewManager │
│ └─ loads adapted webview in JCEF │
└────────────────────────────────────────────────┘
┌── SDK Sidecar (Node.js) ──────────────────────┐
│ │
│ SidecarMain │
│ └─ JSON-RPC over stdio (bidirectional) │
│ └─ imports @clinebot/core │
│ └─ shares SDK adapter layer with VSCode │
│ │
│ ClineCore instance │
│ └─ session management │
│ └─ tool execution │
│ └─ provider handling │
│ │
│ HostCallbackClient │
│ └─ calls back to Kotlin for IDE ops │
│ └─ registered as tool executors in SDK │
│ │
│ WebviewBridge │
│ └─ translates SDK events → webview messages │
│ └─ same code as VSCode adapter │
└────────────────────────────────────────────────┘
```
#### IPC Mechanism: JSON-RPC over stdio
**Why JSON-RPC over stdio instead of gRPC:**
- **No message size limits**: JSON over stdio has no inherent size
cap. Conversations with 100K+ tokens serialize to ~5-20MB JSON
which flows fine over pipes.
- **No heap pressure**: No proto serialization on the Java side.
Kotlin reads/writes JSON strings directly. JCEF already works
with JSON.
- **No proto compilation**: Eliminates the Java protobuf dependency
and the dual TypeScript/Java proto generation step.
- **Simple**: Well-understood protocol. Easy to debug (just read
the pipe).
**Protocol**: JSON-RPC 2.0 over stdin/stdout with newline-delimited
JSON messages. The sidecar reads from stdin and writes to stdout.
Stderr is reserved for logging.
```
→ {"jsonrpc":"2.0","method":"session/start","params":{...},"id":1}
← {"jsonrpc":"2.0","result":{"sessionId":"..."},"id":1}
← {"jsonrpc":"2.0","method":"webview/message","params":{"type":"assistant_delta","text":"..."}}
```
**Notifications** (no `id`) are used for streaming events
(assistant deltas, tool events, state updates). The Kotlin plugin
processes these and forwards them to the JCEF webview.
**Callbacks** from sidecar → Kotlin (host operations) use
JSON-RPC requests in the reverse direction:
```
← {"jsonrpc":"2.0","method":"host/showTextDocument","params":{"path":"..."},"id":100}
→ {"jsonrpc":"2.0","result":{"success":true},"id":100}
```
#### Code Sharing Between VSCode, JetBrains, and CLI
The shared SDK adapter layer contains:
```
src/sdk-adapter/
index.ts — ClineSdkHost (creates ClineCore instance)
session-backend.ts — LegacySessionBackend adapter
webview-bridge.ts — SDK events → webview message translation
provider-migration.ts — Legacy provider settings migration
approval-adapter.ts — Auto-approve settings → SDK tool policies
telemetry-adapter.ts — Extension telemetry → SDK telemetry
types.ts — WebviewInbound, WebviewOutbound types
```
Each host then has a thin integration layer:
- **VSCode** (`src/hosts/vscode/sdk-extension.ts`): In-process.
Creates `ClineSdkHost`, registers VSCode LM handler, manages
webview lifecycle. Uses `postMessage` for webview communication.
- **JetBrains** (`src/sidecar/main.ts`): Separate process. Creates
`ClineSdkHost`, reads/writes JSON-RPC on stdio. Registers
`HostCallbackClient` for IDE operations. The webview bridge code
is identical — it just sends messages over stdio instead of
`postMessage`.
#### Statefulness and Reliability
The sidecar is **stateful** — it holds the `ClineCore` instance with
active sessions in memory. However, it is designed for **graceful
restart**:
- **Session persistence**: All session state is written to disk
after each turn (messages, manifest, transcript). On restart, the
sidecar re-reads the session index and can resume.
- **Crash detection**: The Kotlin plugin monitors the sidecar
process. If it exits unexpectedly, the plugin restarts it after a
brief delay (same as current `CoreProcessManager.RESTART_DELAY`).
- **Smaller messages**: Because the protocol is JSON-RPC with
incremental streaming (notifications for each delta), the
messages are much smaller than the current gRPC approach which
sends full state snapshots. This eliminates the heap pressure
that made the current system unreliable.
- **Interrupted operations**: If the sidecar crashes mid-turn, the
next startup detects the unfinished session (status = "running"
but no live process) and marks it as interrupted, just like the
current task resumption flow.
#### JetBrains-Specific Tools
The HostCallback pattern makes it easy to add JetBrains-specific
capabilities without changing shared code:
1. **Registration**: The sidecar's `HostCallbackClient` declares
what capabilities the host supports (e.g., `"psi"`, `"runConfigs"`).
2. **Tool Executors**: JetBrains-specific tool executors are
registered in `ClineCoreOptions.defaultToolExecutors` when the
sidecar starts. For example, a `getDiagnostics` executor that
calls `host/getDiagnostics` via JSON-RPC to get IntelliJ's PSI
analysis results.
3. **No shared code changes**: Adding a new JetBrains capability
requires:
- Implementing the handler in Kotlin (`HostCallbackService`)
- Adding a JSON-RPC method in the sidecar's `HostCallbackClient`
- Optionally registering a custom tool executor
Example for exposing JetBrains PSI:
```kotlin
// Kotlin side
"host/getPsiStructure" -> {
val file = PsiManager.getInstance(project).findFile(virtualFile)
// ... extract structure
respondWithJson(result)
}
```
```typescript
// Sidecar side - registered as a custom tool executor
defaultToolExecutors: {
list_code_definition_names: async (args) => {
// Call back to JetBrains for richer PSI-based results
const result = await hostCallback.call("host/getPsiStructure", { path: args.path });
return result;
}
}
```
---
## Architecture Overview
### Current Architecture
```
┌─── VSCode Extension ──┐ ┌── JetBrains Plugin ──┐ ┌──── CLI ────┐
│ WebviewProvider │ │ Kotlin Plugin │ │ React Ink │
│ Controller │ │ CoreProcessManager │ │ ClineAgent │
│ Task │ │ ProtoBusProxy │ │ │
│ API providers (30+) │ │ JCEF WebView │ │ │
│ McpHub │ │ │ │ │
│ Webview (React) │ │ ↓ gRPC │ │ │
│ │ │ cline-core │ │ │
│ proto/cline/*.proto │ │ (standalone Node) │ │ │
└────────────────────────┘ └──────────────────────┘ └─────────────┘
```
### Target Architecture
```
┌─── VSCode Extension ──┐ ┌── JetBrains Plugin ──┐ ┌──── CLI ────┐
│ SDK Adapter Layer │ │ Kotlin Plugin │ │ React Ink │
│ @clinebot/core │ │ │ │ TUI │
│ (in-process) │ │ ↓ JSON-RPC/stdio │ │ │
│ Webview (adapted) │ │ SDK sidecar (Node) │ │ │
│ │ │ @clinebot/core │ │ │
│ registerHandler │ │ │ │ │
│ ("vscode-lm", ...) │ │ Webview (adapted) │ │ │
└────────────────────────┘ └──────────────────────┘ └─────────────┘
All clients backed by:
@clinebot/core → @clinebot/agents → @clinebot/llms
↓ ↓ ↓
Sessions Tools/Hooks Providers
Storage MCP Bridge Model Catalog
Telemetry Teams/Spawn Handler Registry
```
---
## What the SDK Already Provides
These capabilities exist in the SDK and do not need to be rebuilt:
1. **Legacy provider settings migration**
`migrateLegacyProviderSettings()` reads `globalState.json` +
`secrets.json`, writes to `providers.json`. Handles Anthropic,
OpenAI, OpenAI Codex OAuth, OpenRouter, Bedrock, custom
OpenAI-compatible endpoints, etc. Existing providers are never
overwritten. Migrated entries are tagged `tokenSource: "migration"`.
2. **30+ provider handlers** — Anthropic, OpenAI (chat + responses
API), Google Gemini, AWS Bedrock, Vertex AI, DeepSeek, Ollama,
LM Studio, Mistral, Groq, Fireworks, Together, xAI, Cerebras,
LiteLLM, Nebius, HuggingFace, and more.
3. **Custom handler registry**`registerHandler(id, factory)` and
`registerAsyncHandler(id, factory)` for providers that need
host-specific dependencies (e.g., VSCode LM API).
4. **MCP management**`InMemoryMcpManager` with stdio, SSE, and
streamableHttp transports. Config loader reads from
`~/.cline/data/settings/mcp.json` with Zod validation. Supports
legacy format migration.
5. **Tool framework** — 8 built-in tools: `read_files`,
`search_codebase`, `run_commands`, `editor`, `apply_patch`,
`fetch_web_content`, `skills`, `ask_question`. Preset system with
`development` (act mode) and `readonly` (plan mode) presets.
Per-tool enable/disable. Policy-based approval (auto-approve,
require-approval, per-tool overrides). Model-aware tool routing
(e.g., OpenAI models use `apply_patch` instead of `editor`).
6. **Session lifecycle**`ClineCore.create()``host.start()` /
`host.send()` / `host.abort()` / `host.stop()` / `host.subscribe()`
Interactive mode with prompt queueing (`queue`/`steer` delivery).
Event subscription for streaming.
7. **Telemetry**`TelemetryService` with pluggable adapters:
`OpenTelemetryAdapter` (for enterprise OTEL), `LoggerTelemetryAdapter`.
Standard events: `session.started`, `session.ended`,
`task.created`, `task.conversation_turn`, `task.tool_used`, etc.
See "Telemetry Event Mapping" above for full mapping.
8. **Rules & Skills** — Discovery from `.clinerules/`,
`~/Documents/Cline/Rules`, `~/.cline/data/settings/rules/`.
SKILL.md format with YAML frontmatter. Global and project scopes.
9. **Hooks**`HookEngine` with lifecycle events. Node subprocess
hook helpers for bash/powershell execution.
10. **Subagents/Teams**`AgentTeamsRuntime`, spawn tools, team
coordination with concurrent teammate agents.
11. **System prompt generation**`getClineDefaultSystemPrompt()`
with platform-aware customization.
12. **OAuth token management**`RuntimeOAuthTokenManager` handles
automatic token refresh during sessions for OAuth providers
(Cline, OpenAI Codex).
13. **Storage isolation**`CLINE_DIR`, `CLINE_DATA_DIR`,
`CLINE_SESSION_DATA_DIR` environment variables plus
`setClineDir()` / `setHomeDir()` APIs for test isolation.
---
## Test Strategy
See `migration.md` for the phase-by-phase test plan. This section
covers the evergreen test infrastructure and classification.
### Test Infrastructure
**Extension unit tests** use Mocha with a custom `requires.ts` that
mocks `vscode` and `@integrations/checkpoints` modules. Config in
`.mocharc.json`. These tests run without VSCode.
**Webview tests** use Vitest with React Testing Library. Independent
from the extension — they test React components in isolation.
**E2E tests** use Playwright to drive a real VSCode instance with
the extension loaded. They test chat, auth, diff editing, and editor
integration against a mock API server on localhost:7777.
**SDK adapter tests** use Vitest (simpler setup, better TypeScript
support, no need for vscode-mock since adapter layer is
VSCode-independent). Config in `vitest.config.sdk.ts`.
### SDK Storage Isolation for Tests
The SDK fully supports isolated test environments via environment
variables and API calls:
```typescript
import { setClineDir, setHomeDir } from "@clinebot/shared/storage";
const tempHome = mkdtempSync(join(tmpdir(), "test-home-"));
process.env.HOME = tempHome;
process.env.CLINE_DIR = join(tempHome, ".cline");
process.env.CLINE_DATA_DIR = join(tempHome, ".cline", "data");
setHomeDir(tempHome);
setClineDir(process.env.CLINE_DIR);
```
### Test Framework Decisions
- **Keep Mocha** for extension unit tests (existing infrastructure)
- **Keep Vitest** for webview and CLI tests
- **Keep Playwright** for VSCode E2E tests
- **Add Vitest** for new SDK adapter tests
- **Isolated home directories** for all new tests touching storage
---
## Manual QA Guide
This section is for the QA team. It describes what has been removed
(so you don't file bugs for missing features) and what areas carry
the most regression risk after the SDK migration.
### Removed Features — Do Not File Bugs
- **Browser automation** — The built-in Playwright browser tool is
gone. Users should use third-party MCP browser tools instead.
- **IDE terminal integration** — Commands now run exclusively in a
"background terminal" (headless shell). No terminal tab opens.
- **Shadow-git checkpoints** — Existing checkpoints are invalidated.
- **Memory bank / structured context** — All memory bank files and
UI removed.
- **Focus chain** — No focus chain panel or inline indicators.
- **Deep planning / `/deep-planning`** — Plan/Act mode remains as
the replacement.
- **`/reportbug`** — Removed.
- **Workflows** — Skills (SKILL.md format) are the replacement.
- **Custom workflow slash commands** — Skills replace this.
### Risk Areas — VSCode Extension
1. **Provider credentials & model selection** — Verify existing API
keys survive the upgrade and downgrade.
2. **Cline provider OAuth / SSO** — Test sign-in, sign-out, token
refresh, org switching.
3. **Chat streaming & message display** — Watch for missing/duplicated
messages, broken streaming, performance regressions.
4. **Tool approval flow** — Verify auto-approve, YOLO mode, per-tool
permissions.
5. **Plan/Act mode** — Verify toggling, separate model configs,
state persistence.
6. **Task history & resume** — Old tasks appear, can be resumed; new
tasks are saved.
7. **MCP servers** — Existing configs picked up, tools work.
8. **VSCode LM provider (Copilot)** — Verify it still works.
9. **Settings UI** — All toggles and inputs persist correctly.
10. **Webview performance** — Long conversations should not cause
sluggishness.
### Risk Areas — JetBrains Extension
1. **Sidecar process lifecycle** — Starts reliably, auto-restarts,
shuts down cleanly.
2. **Webview communication** — Messages arrive, state is fresh.
3. **Large conversations** — 100K+ tokens without OOM.
4. **Host operations** — Open file, diagnostics, clipboard all work.
5. **Keybindings** — Correct for the JetBrains platform.
### Risk Areas — CLI
1. **Agent backend replacement** — Core loop works in TUI and
headless modes.
2. **Provider & model picker** — All providers appear, defaults
correct.
3. **Shared state with IDE clients** — Credentials and history
visible across clients.
4. **Slash commands** — Removed commands don't appear; remaining
ones work.
5. **Worktrees & `--cwd`** — Function correctly.
6. **ACP (Agent Communication Protocol)** — Programmatic usage works.
+188
View File
@@ -0,0 +1,188 @@
# SDK Migration Caveats & Known Issues
Tracking issues found during the migration from the legacy inference system to the ClineCore SDK.
## Status Legend
- 🔴 **Blocker** — prevents core functionality
- 🟡 **Minor** — cosmetic or UX annoyance
- 🟢 **Fixed** — resolved
---
## Fixed
### 1. 🟢 Remote inference fails with ECONNREFUSED (localhost:4000)
**File:** `src/sdk/cline-session-factory.ts`
**Symptom:** Sending any message with the Cline provider fails after 6 retries with "Cannot connect to API" / ECONNREFUSED to `http://localhost:4000/v1/chat/completions`.
**Root cause:** Base URL overrides (`openAiBaseUrl`, `openRouterBaseUrl`, `liteLlmBaseUrl`) were applied unconditionally to ALL providers, clobbering the Cline API URL. A stale `openAiBaseUrl: "http://localhost:4000/v1"` in `~/.cline/data/globalState.json` overwrote `https://api.cline.bot/api/v1`.
**Fix:** Guard each base URL override with a provider check so it only applies to its respective provider.
---
### 2. 🟢 Task history not persisted after completion
**File:** `src/sdk/SdkController.ts`
**Symptom:** After a task completes successfully, the task did NOT appear in the RECENT section when returning to the home screen.
**Root cause:** `newTask()` created a `currentTaskItem` but never pushed it to `this.taskHistory[]`. `clearTask()` discarded it without saving. No disk persistence implementation existed.
**Fix:** `SdkController` now persists tasks on three paths: (1) `done` event updates `currentTaskItem` with final usage and calls `persistCurrentTask()`, (2) `clearTask()` calls `persistCurrentTask()` before resetting, (3) `cancelTask()` persists the in-progress task. `LegacyStateReader` gained `saveTaskHistory()`, `saveUiMessages()`, and `deleteTaskDirectory()` methods for disk I/O.
### 3. 🟢 Task resumption not implemented
**File:** `src/sdk/SdkController.ts`
**Symptom:** Cannot resume a previous task from history.
**Fix:** `showTaskWithId()` now finds the task in history, loads saved UI messages via `legacyState.readUiMessages()`, restores them into the translator, and sets `currentTaskItem`. The task view renders with full message history.
### 6. 🟢 Settings persistence is best-effort / incomplete
**File:** `src/sdk/SdkController.ts`
**Symptom:** `updateSettings()` was a no-op stub with a TODO comment.
**Fix:** `updateSettings()` now persists settings to `globalState.json` via `legacyState.saveApiConfiguration()`. `updateAutoApprovalSettings()` also persists via the same mechanism.
### 7. 🟢 Completed task not appearing in RECENT section
**Where:** Home screen → RECENT section
**Symptom:** After completing a task and clicking "New Task", the completed task did not appear in the RECENT history list.
**Fix:** Resolved by issue #2 fix — tasks are now persisted to `taskHistory` on completion, so they appear in RECENT.
### 8. 🟢 Top bar buttons are non-functional
**Where:** Header bar — accounts, settings, new chat, history buttons
**Symptom:** Clicking any of the top bar buttons (accounts icon, settings gear, new chat +, task history) does nothing. No navigation occurs, no panels open.
**Root cause:** gRPC stub. The webview subscribes to `subscribeToSettingsButtonClicked`, etc. — these are event streams pushed from the extension host when VSCode title bar buttons are clicked.
**Fix:** Extension.ts button commands now send typed `navigate` messages via `WebviewGrpcBridge.navigate()`, bypassing gRPC streaming subscriptions. Plus button also calls `clearSdkTask()` to reset the SDK session.
### 9. 🟢 @ mentions / autocomplete not working
**Where:** Chat input textarea
**Symptom:** Typing `@` in the chat input does not trigger any autocomplete dropdown. No filename suggestions, no context items offered.
**Root cause:** gRPC stub. The `@` autocomplete calls `FileServiceClient.searchFiles()` to get matching file paths.
**Fix:** Implemented `searchFiles` handler in grpc-handler.ts that delegates to `SdkController.searchFiles()`, which does a real filesystem walk of the workspace directory (max depth 8, skips node_modules/.git/etc). Returns results with `mentionsRequestId` for proper request correlation.
### 10. 🟢 Add files/images button (+) does nothing
**Where:** Bottom bar, "+" button next to chat input
**Symptom:** Clicking the "+" button to add files and images produces no response — no file picker, no dropdown, no action.
**Root cause:** gRPC stub. The button calls `FileServiceClient.selectFiles()` which opens a native file picker dialog.
**Fix:** Implemented `selectFiles` handler that returns `StringArrays` format (`values1` = image data URLs, `values2` = file paths). VscodeWebviewProvider callback reads image files as base64 data URLs and returns relative paths for non-images.
### 11. 🟢 Cannot switch from Plan mode back to Act mode
**Where:** Bottom bar Plan/Act toggle
**Symptom:** Clicking "Plan" successfully switches to Plan mode. However, clicking "Act" after that does NOT switch back to Act mode.
**Root cause:** Proto enum conversion bug — the webview sends numeric enum values (0=PLAN, 1=ACT) but the handler expected string values.
**Fix:** `handleTogglePlanActMode` now converts proto enum values: `0/"PLAN" → "plan"`, `1/"ACT" → "act"`, with fallback for already-converted string values.
### 12. 🟢 "Manage cline rules and workflows" still mentions workflows
**Where:** ClineRulesToggleModal tooltip and aria-label
**Symptom:** The tooltip and aria-label still said "Manage Cline Rules & Workflows".
**Fix:** Updated tooltip to "Manage Cline Rules" and aria-label to "Show/Hide Cline Rules". Also simplified chat placeholder text to remove "workflows" mention.
### 4. 🟢 Input text not cleared immediately on send
**Where:** Webview chat input
**Symptom:** After typing a message and pressing send/enter, the text remains visible in the input field briefly before clearing. Creates a feeling of lag.
**Root cause:** In `useMessageHandlers.ts`, `setInputValue("")` was called AFTER `await TaskServiceClient.newTask(...)` or `await TaskServiceClient.askResponse(...)` completed. The network round-trip caused visible delay before the input cleared.
**Fix:** Moved `setInputValue("")`, `setActiveQuote(null)`, `setSelectedImages([])`, `setSelectedFiles([])` to execute immediately when `hasContent` is true, before any async gRPC calls. React schedules a re-render synchronously, clearing the input before the network round-trip.
### 5. 🟢 api_req_started fires with zeroed token counts
**Where:** Message stream / ChatRow rendering
**Symptom:** An `api_req_started` partial message fires with `{"tokensIn":0,"tokensOut":0,"cost":0}` before real counts arrive, causing a brief flash of "0 / 200.0k" in the token usage bar.
**Root cause:** `ContextWindow.tsx` rendered the token bar whenever `tokenData` existed (i.e., when `contextWindow > 0`), regardless of whether `lastApiReqTotalTokens` was 0.
**Fix:** Added `tokenData.used === 0` guard to the null-return check in `ContextWindow.tsx`. The token bar now only renders when real (non-zero) token data is available.
### 14. 🟢 "Delete chat" button shows placeholder size
**Where:** Task history → delete button tooltip / label
**Symptom:** The "Delete chat" button tooltip displays `Delete Task (size: --)` when task size data is unavailable.
**Root cause:** `DeleteTaskButton.tsx` unconditionally rendered `(size: ${taskSize ? formatSize(taskSize) : "--"})`, showing "--" when `taskSize` is undefined.
**Fix:** Changed to conditionally include size: `taskSize ? \`Delete Task (${formatSize(taskSize)})\` : "Delete Task"`. The tooltip now shows just "Delete Task" when size is unavailable, or "Delete Task (12.4 KB)" when it is.
### 13. 🟢 Terminal settings navigates to blank/stuck webview
**Where:** Settings → Terminal tab
**Symptom:** Opening terminal settings causes React to crash, leaving a blank webview.
**Root cause:** `getAvailableTerminalProfiles` was a gRPC stub returning `{data:{}}`. The webview called `setAvailableTerminalProfiles(response.profiles)` where `response.profiles` was `undefined`, overwriting the default `[]`. Then `TerminalSettingsSection` called `profilesToShow.map()` on `undefined`, crashing React.
**Fix:** Implemented real `handleGetAvailableTerminalProfiles()` handler in grpc-handler.ts that calls `getAvailableTerminalProfiles()` from `utils/shell.ts`, returning platform-specific profiles (Default, zsh, bash on macOS). Also added `availableTerminalProfiles: []` to state-builder.ts as a safety net, and wired `scrollToSettings` to fire `navigate("settings", { targetSection })` via the bridge.
**Verified:** Debug harness confirmed handler returns `{data:{profiles:[{id:"default",...},{id:"zsh",...},{id:"bash",...}]}}`, Settings → Terminal tab renders "Default Terminal Profile" dropdown with all 3 options, shell integration timeout, and terminal reuse settings.
### 16. 🟢 Cline Rules popup still has a "Workflows" tab
**Where:** Scales-of-justice icon → Cline Rules modal
**Symptom:** The "Manage Cline Rules" popup contains a "Workflows" tab. Issue #12 fixed the tooltip text, but the tab itself still exists inside the modal.
**Root cause:** The `ClineRulesToggleModal` component had a full "Workflows" tab with toggle lists for global, local, and remote workflows, plus a description section. Workflows are no longer a feature.
**Fix:** Removed the Workflows tab button, workflows description text, workflows content section (remote/global/local workflow toggle lists), and the remote workflows banner condition from `ClineRulesToggleModal.tsx`. The `currentView` state type was narrowed from `"rules" | "workflows" | "hooks" | "skills"` to `"rules" | "hooks" | "skills"`.
### 17. 🟢 Account pane shows "Sign up with Cline" despite being logged in
**Where:** Account panel / pane
**Symptom:** Even when the user is already authenticated and logged in, the account pane still displays "Sign up with Cline" and other sign-up prompts as if the user were not authenticated.
**Root cause:** `subscribeToAuthStatusUpdate` is a streaming subscription. The bridge's `handleStreamingRequest()` fell into the `default` no-op case, so auth state was never pushed to the webview.
**Fix:** Added explicit `subscribeToAuthStatusUpdate` case in `handleStreamingRequest()` that reads auth credentials from disk and pushes them. Added `roles` to org data and null safety in `isAdminOrOwner()`.
### 18. 🟢 "Sign up with Cline" button does nothing (moot)
**Where:** Account pane → Sign up button
**Fix:** Resolved by #17 — the sign-up button is no longer shown when the user is already authenticated.
### 19. 🟢 Terminal settings still shows "Terminal Execution Mode" option
**Where:** Settings → Terminal
**Fix:** Removed the Terminal Execution Mode dropdown, its handler, and unused imports from `TerminalSettingsSection.tsx`.
### 20. 🟢 Cline provider model type-ahead search does not work
**Where:** Settings → Model selector (Cline provider)
**Root cause:** `refreshClineModelsRpc` was a gRPC stub returning `{}`. The webview never received any model data.
**Fix:** Implemented `handleRefreshClineModels()` in grpc-handler.ts that reads from disk cache first, then falls back to fetching from the Cline API using `globalThis.fetch`. Converts API response to `ModelInfo` records and returns in protobuf format.
### 21. 🟢 Cline provider recommends possibly outdated model
**Where:** Settings → Model selector (Cline provider)
**Fix:** Updated fallback recommendation text in `ClineModelPicker.tsx` from `anthropic/claude-sonnet-4.5` to `anthropic/claude-sonnet-4.6`.
### 22. 🟢 "Use different models for Plan and Act" checkbox immediately unchecks
**Where:** Settings → Model configuration
**Root cause:** `updateSettings()` was writing raw settings instead of merging individual known keys.
**Fix:** `updateSettings()` now iterates known settings keys and writes each one individually. `buildExtensionState()` reads `planActSeparateModels` from `globalState`.
### 23. 🟢 MCP settings Configure tab crashes React
**Where:** MCP Servers → Configure tab
**Root cause:** `refreshMcpMarketplace` stub returns `{}`, replacing the default `{ items: [] }` state, causing `items.find()` to crash.
**Fix:** Added optional chaining (`?.items?.find`) in `getMcpServerDisplayName()`.
### 24. 🟢 History tab is empty and search does nothing
**Where:** History tab (task history list)
**Root cause:** `handleGetTaskHistory()` returned `{ data: { history } }` but webview reads `response.tasks`.
**Fix:** Changed return to `{ data: { tasks, totalCount } }`. Implemented server-side filtering/sorting.
### 25. 🟢 Auto-approve options immediately uncheck when toggled
**Where:** Auto-approve options flyout
**Root cause:** Same as #22 — `updateAutoApprovalSettings()` was not persisting properly.
**Fix:** Fixed alongside #22.
---
## Open Issues
### 15. 🔴 MCP tools are missing / not visible to the agent
**Where:** Agent tool execution
**Symptom:** MCP tools that should be available to the agent are not discovered or listed. The agent cannot see or use any MCP-provided tools during task execution.
**Expected:** Connected MCP servers should expose their tools to the agent, and the agent should be able to invoke them.
**Investigation:** `@clinebot/core` has full MCP support (`InMemoryMcpManager`, `registerMcpServersFromSettingsFile`, `resolveMcpServerRegistrations`). The issue is that `ClineCoreSession` in `cline-session-factory.ts` doesn't pass MCP configuration through `coreConfig` when calling `host.start()`. The MCP settings file exists at `~/.cline/data/settings/cline_mcp_settings.json` and `SdkController.getMcpServers()` already reads it for the UI, but the session factory never wires MCP servers into the ClineCore session. The fix requires: (1) reading MCP server registrations via `resolveMcpServerRegistrations()` or passing the settings file path in `coreConfig`, (2) creating/passing an `InMemoryMcpManager` to ClineCore, or (3) ensuring ClineCore auto-discovers MCP settings from the default path. This is a deep architectural change that can't be verified via the debug harness (requires actual agent task execution).
---
## Observations (not bugs, just notes)
### UI Rendering — Task Completion View
The completed task view renders correctly:
- Task header with cost badge (e.g. "$0.0072")
- Token usage bar (e.g. "1.4k / 200.0k")
- Response text displayed properly
- "Task Completed" card with green checkmark and the result
- "Start New Task" button appears below the chat
- Input area changes to "Type a message..." (follow-up mode)
### Feature Card Carousel
The home screen shows a rotating feature card carousel (1/4 through 4/4) promoting:
- Claude Sonnet 4.6
- MiniMax M2.5
- ChatGPT integration
- Jupyter Notebooks
Each with a dismiss (X) button per-card.
### Model Selector
Bottom bar correctly shows `cline:anthropic/claud...` (truncated) with Plan/Act toggle. Act mode is the default.
### Debug Harness Limitations (Fixed)
All three limitations below have been addressed:
- ~~Programmatic textarea input doesn't reliably trigger React state updates after the first task.~~ **Fixed**: Two new commands added:
- `ui.react_input` — Uses `document.execCommand('insertText')` which fires real InputEvents that React's onChange handler processes correctly, even after multiple tasks.
- `ui.send_message` — Bypasses the textarea entirely by sending gRPC requests via `postMessage` directly to the extension host.
- ~~The `web.evaluate` context can't access the VS Code API.~~ **Fixed**: The webview now exposes the VS Code API as `window.__clineVsCodeApi`, and a new `web.post_message` command lets the harness send arbitrary messages to the extension host through it.
- ~~The `ui.locator` Playwright actions don't reliably target elements inside the webview iframe.~~ **Fixed**: `findSidebar()` now validates cached frame references (checking for both detached and stale frames), `getTarget()` accepts a `forceRefresh` flag, and `ui.locator` automatically retries with frame re-discovery when targeting sidebar elements.
+373 -2
View File
@@ -1,14 +1,385 @@
# Changelog
## [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
- Add toggle to disable feature tips in chat
- Add repeated tool call loop detection to prevent infinite loops wasting tokens
### Fixed
- Fix CLI Kanban spawn on Windows by enabling shell mode for `npx.cmd`
## [3.75.0]
### Added
- Latency improvements for remote workspaces
### Fixed
- Stabilize flaky hooks tests
### Changed
- Remove example hooks in favor of reading the docs
## [3.74.0]
### 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
- 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
## [3.73.0]
### Added
- Added W&B Inference by CoreWeave as a new API provider with 17 models
- Improved parallel tool calling support for OpenRouter and Cline providers
### Fixed
- Claude Code Provider: handle rate limit events, empty content arrays, error results, and unknown content types without crashing
- Tool handlers (`read_file`, `list_files`, `list_code_definition_names`, `search_files`) now return graceful errors instead of crashing
## [3.72.0]
### Added
- Added Anthropic Opus 4.6 fast mode variants
### Fixed
- Resolved native tool placeholder interpolation in prompts
- Gemini: capped Flash output tokens to 8192 across providers
- Fixed Windows unit test path normalization
- Fixed flaky hooks tests on Windows
- Bedrock: handle thinking and redacted_thinking blocks correctly in message conversion and streaming
- Prevent crash when `list_files` or `list_code_definition_names` receives a file path
### Changed
- Updated Jupyter Notebook GIFs
- Markdown image loading now requires user consent
- Added `.github/copilot-instructions.md` for coding agents
- Hooks: reintroduced feature toggle
## [3.71.0]
### Added
- Added GPT-5.4 models for ChatGPT subscription users
- Hooks: Added a `Notification` hook for attention and completion boundaries
### Fixed
- Handle streamable HTTP MCP reconnects more reliably after disconnects
## [3.70.0]
### Added
- New Cline API docs: Getting Started, Auth, Chat Completions, Models, Errors, and SDK Examples
- 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
### Changed
- Windows test cleanup now retries on locked files and applies per-test timeouts
- Updated hooks docs
## [3.69.0]
### Added
- Add `User-Agent` header to requests sent to the Cline backend
- Add default auto-tag workflow for publish release flow
- Show Cline SDK docs on the Cline page
### Fixed
- Retry nested git restore and prevent silent `.git_disabled` leftovers in checkpoints
- Prevent Chinese filename escaping in diff view
- Trigger auto-compaction on OpenRouter context overflow errors
- Restore GPT-OSS native file editing on OpenAI-compatible models
### Changed
- Update Cline SDK docs
- Improve hooks support for Windows PowerShell
## [3.68.0]
### Added
- Add dynamic Cline provider model fetching from Cline endpoint
- Add additional Markdown formatting in CLI
- Add focus indicator on action buttons in extension
### Fixed
- Clear all OCA secrets on auth refresh failure to prevent re-auth loops
- Resolve "Could not find the file context" error in Explain Changes
- Use `JSON_SCHEMA` for `yaml.load` to prevent unsafe deserialization
- Fetch model info from API in CLI headless auth for Cline and Vercel providers
- Generate commit message from staged changes only when staging exists
- Update stale `maxTokens` values for Claude 3.7+ models across Anthropic, Bedrock, Vertex, and SAP AI Core
- Use `model.info.maxTokens` for OpenRouter instead of hardcoded `8192`
### Changed
- Increase timeout for a flaky test to reduce short-term test instability
## [3.67.1]
### 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
## [3.67.0]
### Added
- Add support for skills and optional modelId in subagent configuration
- Add AgentConfigLoader for file-based agent configs
- Add Responses API support for OpenAI native provider
- Preconnect websocket to reduce response latency
- Fetch featured models from backend with local fallback
- Add /q command to quit CLI
- Add MCP enterprise configuration details
- Pull Cline's recommended models from internal endpoint
- Add dynamic flag to adjust banner cache duration
### Fixed
- Fix reasoning delta crash on usage-only stream chunks
- Fix OpenAI tool ID transformation restricted to native provider only
- Fix auth check for ACP mode
- Fix CLI yolo mode to not persist yolo setting to disk
- Fix inline focus-chain slider within its feature row
- Fix Gemini 3.1 Pro compatibility
- Fix Cline auth with ACP flag
### Changed
- Move PR skill to .agents/skills
- SambaNova provider: update models list
- Remove changeset-converter GitHub Action and npm run changeset
## [3.66.0]
### Added
- Gemini-3.1 Pro Preview
## [3.65.0]
### Added
- Add /skills slash command to CLI for viewing and managing installed skills
### Fixed
- Fix aggressive context compaction caused by accidental clicks on the context window progress bar silently setting a very low auto-condense threshold
- Fix infinite retry loop when write_to_file fails with missing content parameter.
- Fixed default claude model
## [3.64.0]
### Added
- Added sonnet 4.6
## [3.63.0]
### Added
- added zai GLM 5 Free promo
### Fixed
- Restore reasoning trace visibility in chat and improve the thinking row UX so reasoning is visible, then collapsible after completion.
## [3.62.0]
### Fixed
- Banners now display immediately when opening the extension instead of requiring user interaction first
- Resolved 17 security vulnerabilities including high-severity DoS issues in dependencies (body-parser, axios, qs, tar, and others)
## [3.61.0]
- UI/UX fixes with minimax model family
## [3.60.0]
- Fixes for Minimax model family
## [3.59.0]
- Added Minimax 2.5 Free Promo
- Fixed Response chaining for OpenAI's Responses API
## [3.58.0]
### Added
- Subagent: replace legacy subagents with the native `use_subagents` tool
- Bundle `endpoints.json` support so packaged distributions can ship required endpoints out-of-the-box
- Amazon Bedrock: support parallel tool calling
- New "double-check completion" experimental feature to verify work before marking tasks complete
- CLI: new task controls/flags including custom `--thinking` token budget and `--max-consecutive-mistakes` for yolo runs
- Remote config: new UI/options (including connection/test buttons) and support for syncing deletion of remotely configured MCP servers
- Vertex / Claude Code: add 1M context model options for Claude Opus 4.6
- ZAI/GLM: add GLM-5
### Fixed
- CLI: handle stdin redirection correctly in CI/headless environments
- CLI: preserve OAuth callback paths during auth redirects
- VS Code Web: generate auth callback URLs via `vscode.env.asExternalUri` (OAuth callback reliability)
- Terminal: surface command exit codes in results and improve long-running `execute_command` timeout behavior
- UI: add loading indicator and fix `api_req_started` rendering
- Task streaming: prevent duplicate streamed text rows after completion
- API: preserve selected Vercel model when model metadata is missing
- Telemetry: route PostHog networking through proxy-aware shared fetch and ensure telemetry flushes on shutdown
- CI: increase Windows E2E test timeout to reduce flakiness
### Changed
- Settings/model UX: move "reasoning effort" into model configuration and expose it in settings
- CLI provider selection: limit provider list to those remotely configured
- UI: consolidate ViewHeader component/styling across views
- Tools: add auto-approval support for `attempt_completion` commands
- Remotely configured MCP server schema now supports custom headers
## [3.57.1]
### Fixed
- Fixed Opus 4.6 for bedrock provider
## [3.57.0]
### Added
- Cline CLI 2.0 now available. Install with `npm install -g cline`
- Anthopic Opus 4.6
- Minimax-2.1 and Kimi-k2.5 now available for free for a limited time promo
- Codex-5.3 through ChatGPT subscription
### Fixed
- Fix read file tool to support reading large files
- Fix decimal input crash in OpenAI Compatible price fields (#8129)
- Fix build complete handlers when updating the api config
- Fixed missing provider from list
- Fixed Favorite Icon / Star from getting clipped in the task history view
### Changed
- Make skills always enabled and remove feature toggle setting
## [3.56.0]
### Added
- **CLI authentication:** Added Vercel AI Gateway and Cline API key provider support for headless CI/automation workflows
- **New model:** Added Kimi-K2.5 model to Moonshot provider (262K context, image support, prompt caching)
- **Prompt variant:** Added Trinity Large prompt variant for improved tool-calling support
- **OpenTelemetry:** Added support for custom headers on metrics and logs endpoints
- **Social links:** Added community icons (X, Discord, GitHub, Reddit, LinkedIn) to the What's New modal
### Fixed
- **LiteLLM:** Fixed thinking configuration not appearing for reasoning-capable models
- **OpenTelemetry:** Fixed endpoint path handling (no longer incorrectly appends `/v1/logs` or `/v1/metrics`) and ensured logs are sent regardless of VSCode telemetry settings
- **CLI auth:** Fixed `cline auth` displaying incorrect provider information after configuration
### Changed
- **Hooks:** Hook scripts now run from the workspace repository root instead of filesystem root
- **Default settings:** Enabled multi-root workspaces, parallel tool calling, and skills by default; disabled strict plan mode by default
- **Settings UI:** Refreshed feature settings section with collapsible design
## [3.55.0]
- Add new model: Arcee Trinity Large Preview
- Add new model: Moonshot Kimi K2.5
- Add MCP prompts support - prompts from connected MCP servers now appear in slash command autocomplete as `/mcp:<server>:<prompt>`
## [3.54.0]
### Added
- Native tool calls support for Ollama provider
- Sonnet 4.5 is now the default Amazon Bedrock model id
### Fixed
- Prevent infinite retry loops when replace_in_file fails repeatedly. The system now detects repeated failures and provides better guidance to break out of retry cycles.
- Skip diff error UI handling during streaming to prevent flickering. Error handling is deferred until streaming completes.
- Strip notebook cell outputs when extracting text content from Jupyter notebooks, significantly reducing context size sent to the LLM.
- Throttle diff view updates during streaming to reduce UI flickering and improve performance.
### Changed
- Removed Mistral's Devstral-2512 free from the free models list
- Removed deprecated zai-glm-4.6 model from Cerebras provider
## [3.53.1]
### Fixed
- Bug in responses API
- Bug in responses API
## [3.53.0]
### Fixed
- Removed grok model from free tier
- Removed grok model from free tier
## [3.52.0]
+6 -25
View File
@@ -57,25 +57,11 @@ We also welcome contributions to our [documentation](https://github.com/cline/cl
### Creating a Pull Request
1. Before creating a PR, generate a changeset entry:
```bash
npm run changeset
```
This will prompt you for:
- Type of change (major, minor, patch)
- `major` → breaking changes (1.0.0 → 2.0.0)
- `minor` → new features (1.0.0 → 1.1.0)
- `patch` → bug fixes (1.0.0 → 1.0.1)
- Description of your changes
1. Commit your changes.
2. Commit your changes and the generated `.changeset` file
3. Push your branch and create a PR on GitHub. Our CI will:
2. Push your branch and create a PR on GitHub. Our CI will:
- Run tests and checks
- Changesetbot will create a comment showing the version impact
- When merged to main, changesetbot will create a Version Packages PR
- When the Version Packages PR is merged, a new release will be published
4. Testing
3. Testing
- Run `npm run test` to run tests locally.
- Before submitting PR, run `npm run format:fix` to format your code
@@ -192,15 +178,10 @@ Anyone can contribute code to Cline, but we ask that you follow these guidelines
- Temporary workspaces with test fixtures
- Video recording for failed tests
4. **Version Management with Changesets**
4. **Versioning & Changelog Notes**
- Create a changeset for any user-facing changes using `npm run changeset`
- Choose the appropriate version bump:
- `major` for breaking changes (1.0.0 → 2.0.0)
- `minor` for new features (1.0.0 → 1.1.0)
- `patch` for bug fixes (1.0.0 → 1.0.1)
- Write clear, descriptive changeset messages that explain the impact
- Documentation-only changes don't require changesets
- Contributors do not need to create changelog-entry files as part of PRs.
- Maintainers handle release versioning and changelog curation during the release process.
5. **Commit Guidelines**
+84
View File
@@ -0,0 +1,84 @@
# E2E Debugging Visibility
This is a sub-project of the project described in migration.md. We are
engaging in a big change to the VSCode extension. You gain visibility
into the extension through tests, but sometimes that is not enough.
Your goal is to create way where you can launch the VSCode extension
and have access to the node debugger and webview debugger so that you
can set break points, evaluate expressions, inject input (consider
Microsoft's work with Playwright in VSCode, but anything that works is
fine) step, etc. so that you can observe execution and find and fix
problems without the tedious cycle off adding print statements,
running a test which may hang, fixing something, removing the print
statements, etc.
For this step to be complete, you need to demonstrate you have the
ability to:
1. Build and run the VSCode extension in an unminified form, including
the webview unminified.
2. Add and remove breakpoints, including conditional breakpoints, on
the extension side.
3. Add and remove breakpoints, including conditional breakpoints, on
the webview side.
4. Evaluate expressions at breakpoints. You should be able to refer to
local variables, that is, the extension code should be
unminified. (Concatenated is fine as long as you can find your way
around.)
5. Run, step at breakpoints.
6. Generate UI actions like opening the Cline sidebar, focusing
elements, typing, etc.
7. Take screenshots that you can view.
You need to use this tool inside your agentic loop, that is, you will
need to drive both of these debugees simultaneously from one loop, so
you may need to write yourself a tool which blocks until one of the
debugees hits a breakpoint; can use a timeout and let you break and
examine isolates and stacks; things of that nature.
We are working on macOS, it is fine if this tool just works on macOS
for now.
## Caveats
- **"Introducing Cline Kanban" promotion**: On fresh launches, a
full-screen promotional overlay ("Introducing Cline Kanban") may
appear in the sidebar webview. It obscures all other UI elements, so
screenshots will show only the promo and interactions with the chat
input, settings buttons, etc. will fail. You must dismiss it before
doing anything else. Use the debug harness to click the dismiss/close
button:
```bash
curl localhost:19229/api -d '{
"method": "ui.locator",
"params": {"text": "Dismiss", "frame": "sidebar", "action": "click"}
}'
```
Or close it via `web.evaluate`:
```bash
curl localhost:19229/api -d '{
"method": "web.evaluate",
"params": {"expression": "document.querySelector('[data-testid=\"dismiss-announcement\"]')?.click() || document.querySelector(\"button\")?.click()"}
}'
```
If the exact selector changes, take a screenshot first
(`ui.sidebar_screenshot`) to identify the current dismiss control.
- **CDP disconnects after window reload**: If you use
`workbench.action.reloadWindow` (e.g., to pick up a rebuilt
webview), the extension host CDP connection drops. You must do a full
`shutdown` + relaunch of the debug harness to reconnect.
## References
You can see the vscode source code in ~/clients/cline/vscode and
search it with kb_search vscode
You can search the cline source code (snapshot) with kb_search cline.
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2025 Cline Bot Inc.
Copyright 2026 Cline Bot Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+3 -3
View File
@@ -129,9 +129,9 @@ Thanks to the [Model Context Protocol](https://github.com/modelcontextprotocol),
### Checkpoints: Compare and Restore
As Cline works through a task, the extension takes a snapshot of your workspace at each step. You can use the 'Compare' button to see a diff between the snapshot and your current workspace, and the 'Restore' button to roll back to that point.
As Cline works through a task, the extension can take an internal snapshot of your workspace at each step. You can use the 'Compare' button to see a diff between the snapshot and your current workspace, and the 'Restore' button to roll back to that point.
For example, when working with a local web server, you can use 'Restore Workspace Only' to quickly test different versions of your app, then use 'Restore Task and Workspace' when you find the version you want to continue building from. This lets you safely explore different approaches without losing progress.
For example, when working with a local web server, you can use 'Restore Workspace Only' to quickly test different versions of your app, then use 'Restore Task and Workspace' when you find the version you want to continue building from. This lets you safely explore different approaches without losing progress while the current checkpoint system is available.
<!-- Transparent pixel to create line break after floating image -->
@@ -148,4 +148,4 @@ Get the same Cline experience with enterprise-grade controls: SSO (SAML/OIDC), g
## License
[Apache 2.0 © 2025 Cline Bot Inc.](./LICENSE)
[Apache 2.0 © 2026 Cline Bot Inc.](./LICENSE)
+27
View File
@@ -0,0 +1,27 @@
# Security Policy
## Supported Versions
We actively patch only the most recent minor release of Cline. Older versions receive fixes at our discretion.
## Reporting a Vulnerability
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.
When reporting, please include:
- A short summary of the issue
- 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.
## Escalation
If you do not receive an acknowledgement of your report within 5 business days, you may send an email to security@cline.bot.
Thank you for helping us keep Cline users safe.
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 535">
<!-- Generator: Adobe Illustrator 29.8.5, SVG Export Plug-In . SVG Version: 2.1.1 Build 2) -->
<defs>
<style>
.st0 {
fill: #fff;
}
</style>
</defs>
<path class="st0" d="M500.6,300.5c-9-20.7-17.9-41.4-26.9-62.1-.7-2-.3-4.4-.3-6.4.4-9,1.1-18,1.4-27,2.8-28.4-6.5-58-25.2-79.6-15.1-18.1-36.6-30.7-59.6-35.5-8.1-1.8-16.6-1.6-25-2.1-10-.7-20-1-30-1.7,2-11.9,1-24.1-3.7-35.3-5.8-14.1-16.8-25.9-30.6-32.5-14.4-7-31.5-8.2-46.7-3.1-16,5.2-29.5,17-36.8,32.1-4.9,10-6.8,21.2-6.1,32.2-19.7-1-39.4-2.2-59.1-3.1-26.8.5-53,11.7-72,30.6-20.2,19.5-31.7,47-32.3,75-.5,9.3-1,18.7-1.5,28-.2,2.1,0,4.1-1.2,6-9.8,16.8-19.5,33.7-29.4,50.6-2.2,4.1-4.9,8-6.6,12.3-2,5.7-1.2,12.2,1.3,17.6,8.9,19.5,17.6,39.2,26.5,58.7.8,1.9,1.5,3.7,1.3,5.8-.6,10.3-1.1,20.7-1.7,31-1.5,21.2,3,42.6,13.5,61.1,8.8,15.8,21.6,29.4,37.1,38.9,13.9,8.7,29.7,13.9,46,15.4,72,3.9,144,7.7,216,11.5,20.1,1.8,40.8-2.8,58.5-12.5,18.8-10.1,34.2-26,44.1-44.9,6.5-12.6,10.5-26.4,11.7-40.5.7-12.4,1.2-24.7,2-37.1,0-3.3,1.9-5.5,3.3-8.2,6.6-11.8,13.5-23.4,20.1-35.2,3.7-6.9,8.1-13.4,11.6-20.4,3.2-6.1,3.2-13.5.3-19.7ZM218.5,316.5c-9.7,7.1-21.3,12.3-33.5,12.5-17.6,1-35.1-5.3-49-16-4.6-3.2-8.1-7.5-9.6-13,0-1.8-.7-3.6,1.7-3.8,4,1,7.9,2.6,12,3.5,22.8,5.6,47.6,5.9,71,4.8,6.5-.2,13-1.3,19.5-.9-2.7,5.6-7.1,9.2-12,12.9ZM276,449.7c-14,.5-28,.1-42-.2-2.1,0-4.3,0-6.4-.4-.9-2.1.6-3.2,1.7-4.8,4.8-5.9,11-11,18.7-12.4,8.4-1.6,16.5,1.2,23.5,5.5,4.7,3,9.2,6.3,12.6,10.8-2.6,1.1-5.3,1.4-8.1,1.4ZM390.4,319.4c-16.4,14.2-38.8,21.8-60.4,18.4-13.2-1.6-24.7-8.6-34.1-17.7-3-3-6.2-6.5-8.1-10.4.5-1,1.2-1.6,2.2-1.6,2.8-.2,5.7.7,8.5,1.1,16,2.9,32.3,4.9,48.5,5.5,14.3.4,28.2-.2,42.2-3.6,2.2-.6,3.7-.3,5.8.5-1.1,2.9-2.2,5.7-4.6,7.8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.317 4.15557C18.7873 3.45369 17.147 2.93658 15.4319 2.6404C15.4007 2.63469 15.3695 2.64897 15.3534 2.67754C15.1424 3.05276 14.9087 3.54225 14.7451 3.927C12.9004 3.65083 11.0652 3.65083 9.25832 3.927C9.09465 3.5337 8.85248 3.05276 8.64057 2.67754C8.62449 2.64992 8.59328 2.63564 8.56205 2.6404C6.84791 2.93563 5.20756 3.45275 3.67693 4.15557C3.66368 4.16129 3.65233 4.17082 3.64479 4.18319C0.533392 8.83155 -0.31895 13.3657 0.0991801 17.8436C0.101072 17.8655 0.11337 17.8864 0.130398 17.8997C2.18321 19.4073 4.17171 20.3225 6.12328 20.9291C6.15451 20.9386 6.18761 20.9272 6.20748 20.9015C6.66913 20.2711 7.08064 19.6063 7.43348 18.9073C7.4543 18.8664 7.43442 18.8178 7.39186 18.8016C6.73913 18.554 6.1176 18.2521 5.51973 17.9093C5.47244 17.8816 5.46865 17.814 5.51216 17.7816C5.63797 17.6873 5.76382 17.5893 5.88396 17.4902C5.90569 17.4721 5.93598 17.4683 5.96153 17.4797C9.88928 19.273 14.1415 19.273 18.023 17.4797C18.0485 17.4674 18.0788 17.4712 18.1015 17.4893C18.2216 17.5883 18.3475 17.6873 18.4742 17.7816C18.5177 17.814 18.5149 17.8816 18.4676 17.9093C17.8697 18.2588 17.2482 18.554 16.5945 18.8006C16.552 18.8168 16.533 18.8664 16.5538 18.9073C16.9143 19.6054 17.3258 20.2701 17.7789 20.9005C17.7978 20.9272 17.8319 20.9386 17.8631 20.9291C19.8241 20.3225 21.8126 19.4073 23.8654 17.8997C23.8834 17.8864 23.8948 17.8664 23.8967 17.8445C24.3971 12.6676 23.0585 8.17064 20.3482 4.18414C20.3416 4.17082 20.3303 4.16129 20.317 4.15557ZM8.02002 15.117C6.8375 15.117 5.86313 14.0313 5.86313 12.6981C5.86313 11.3648 6.8186 10.2791 8.02002 10.2791C9.23087 10.2791 10.1958 11.3743 10.1769 12.6981C10.1769 14.0313 9.22141 15.117 8.02002 15.117ZM15.9947 15.117C14.8123 15.117 13.8379 14.0313 13.8379 12.6981C13.8379 11.3648 14.7933 10.2791 15.9947 10.2791C17.2056 10.2791 18.1705 11.3743 18.1516 12.6981C18.1516 14.0313 17.2056 15.117 15.9947 15.117Z" fill="#FAFAFA"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="0 0 24 24" fill="black" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2C6.477 2 2 6.477 2 12C2 16.418 4.865 20.166 8.84 21.49C9.34 21.58 9.52 21.27 9.52 21C9.52 20.77 9.51 20.14 9.51 19.31C6.73 19.91 6.14 17.97 6.14 17.97C5.68 16.81 5.03 16.5 5.03 16.5C4.12 15.88 5.1 15.9 5.1 15.9C6.1 15.97 6.63 16.93 6.63 16.93C7.5 18.45 8.97 18 9.54 17.76C9.63 17.11 9.89 16.67 10.17 16.42C7.95 16.17 5.62 15.31 5.62 11.5C5.62 10.39 6 9.5 6.65 8.79C6.55 8.54 6.2 7.5 6.75 6.15C6.75 6.15 7.59 5.88 9.5 7.17C10.29 6.95 11.15 6.84 12 6.84C12.85 6.84 13.71 6.95 14.5 7.17C16.41 5.88 17.25 6.15 17.25 6.15C17.8 7.5 17.45 8.54 17.35 8.79C18 9.5 18.38 10.39 18.38 11.5C18.38 15.32 16.04 16.16 13.81 16.41C14.17 16.72 14.5 17.33 14.5 18.26C14.5 19.6 14.49 20.68 14.49 21C14.49 21.27 14.67 21.59 15.17 21.49C19.14 20.16 22 16.42 22 12C22 6.477 17.523 2 12 2Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 902 B

+10
View File
@@ -0,0 +1,10 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2001_1428)">
<path d="M22.2234 0H1.77187C0.792187 0 0 0.773438 0 1.72969V22.2656C0 23.2219 0.792187 24 1.77187 24H22.2234C23.2031 24 24 23.2219 24 22.2703V1.72969C24 0.773438 23.2031 0 22.2234 0ZM7.12031 20.4516H3.55781V8.99531H7.12031V20.4516ZM5.33906 7.43438C4.19531 7.43438 3.27188 6.51094 3.27188 5.37187C3.27188 4.23281 4.19531 3.30937 5.33906 3.30937C6.47813 3.30937 7.40156 4.23281 7.40156 5.37187C7.40156 6.50625 6.47813 7.43438 5.33906 7.43438ZM20.4516 20.4516H16.8937V14.8828C16.8937 13.5562 16.8703 11.8453 15.0422 11.8453C13.1906 11.8453 12.9094 13.2937 12.9094 14.7891V20.4516H9.35625V8.99531H12.7687V10.5609H12.8156C13.2891 9.66094 14.4516 8.70938 16.1813 8.70938C19.7859 8.70938 20.4516 11.0813 20.4516 14.1656V20.4516Z" fill="#FAFAFA"/>
</g>
<defs>
<clipPath id="clip0_2001_1428">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 989 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.0512 4.07466C15.3113 5.17727 16.301 5.99866 17.4829 5.99866C18.8627 5.99866 19.9813 4.87965 19.9813 3.49933C19.9813 2.11902 18.8627 1 17.4829 1C16.2764 1 15.2703 1.85537 15.036 2.99314C13.0155 3.20991 11.4378 4.92417 11.4378 7.00167C11.4378 7.00636 11.4378 7.00988 11.4378 7.01456C9.24041 7.10713 7.23397 7.73284 5.641 8.72062C5.04949 8.26247 4.30688 7.98945 3.50102 7.98945C1.5672 7.98945 0 9.55725 0 11.4918C0 12.8955 0.824597 14.1048 2.01581 14.6637C2.13177 18.7297 6.56047 22 12.0082 22C17.4559 22 21.8905 18.7261 22.0006 14.6567C23.1824 14.0942 24 12.8885 24 11.493C24 9.55842 22.4328 7.99063 20.499 7.99063C19.6966 7.99063 18.9575 8.2613 18.3672 8.71594C16.7602 7.72113 14.7315 7.09541 12.5119 7.01222C12.5119 7.0087 12.5119 7.00636 12.5119 7.00285C12.5119 5.51473 13.6176 4.27971 15.0512 4.077V4.07466ZM5.50044 13.7146C5.559 12.4444 6.40234 11.4695 7.38272 11.4695C8.3631 11.4695 9.11274 12.4995 9.05417 13.7697C8.99561 15.0398 8.26354 15.5015 7.28199 15.5015C6.30044 15.5015 5.44187 14.9848 5.50044 13.7146ZM16.6348 11.4695C17.6164 11.4695 18.4597 12.4444 18.5171 13.7146C18.5757 14.9848 17.716 15.5015 16.7356 15.5015C15.7552 15.5015 15.022 15.041 14.9634 13.7697C14.9048 12.4995 15.6533 11.4695 16.6348 11.4695ZM15.4682 16.6533C15.6521 16.6721 15.7693 16.8631 15.6978 17.0341C15.0946 18.4766 13.6703 19.4901 12.0082 19.4901C10.3461 19.4901 8.92299 18.4766 8.31859 17.0341C8.24714 16.8631 8.36427 16.6721 8.54817 16.6533C9.62577 16.5444 10.7912 16.4846 12.0082 16.4846C13.2252 16.4846 14.3895 16.5444 15.4682 16.6533Z" fill="#FAFAFA"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.3263 1.90393H21.6998L14.3297 10.3274L23 21.7899H16.2112L10.894 14.838L4.80995 21.7899H1.43443L9.31743 12.78L1 1.90393H7.96111L12.7674 8.25826L18.3263 1.90393ZM17.1423 19.7707H19.0116L6.94539 3.81706H4.93946L17.1423 19.7707Z" fill="#FAFAFA"/>
</svg>

After

Width:  |  Height:  |  Size: 358 B

+77 -66
View File
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.1.4/schema.json",
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
@@ -28,19 +28,19 @@
"rules": {
"recommended": true,
"correctness": {
"useExhaustiveDependencies": "off",
"useExhaustiveDependencies": "info",
"noUndeclaredVariables": "off",
"noEmptyPattern": "off",
"noEmptyPattern": "info",
"useJsxKeyInIterable": "off",
"noInnerDeclarations": "off",
"useHookAtTopLevel": "off",
"useYield": "off",
"useHookAtTopLevel": "info",
"useYield": "info",
"noConstructorReturn": "off",
"noInvalidPositionAtImportRule": "off",
"noSwitchDeclarations": "off",
"noUnusedImports": "error"
},
"a11y": "off",
"a11y": "info",
"style": {
"useNodejsImportProtocol": "off",
"useImportType": "off",
@@ -51,35 +51,36 @@
"noParameterAssign": "off",
"useAsConstAssertion": "off",
"useDefaultParameterLast": "off",
"noNonNullAssertion": "off",
"noNonNullAssertion": "info",
"useEnumInitializers": "off",
"useSelfClosingElements": "off",
"useSelfClosingElements": "info",
"useSingleVarDeclarator": "off",
"useNumberNamespace": "off",
"noInferrableTypes": "off",
"useTemplate": "off",
"noUselessElse": "off"
"useNumberNamespace": "info",
"noInferrableTypes": "info",
"useTemplate": "info",
"noUselessElse": "info"
},
"suspicious": {
"noDoubleEquals": "warn",
"noImplicitAnyLet": "info",
"noThenProperty": "off",
"noAsyncPromiseExecutor": "off",
"noAsyncPromiseExecutor": "info",
"noImportAssign": "off",
"noExplicitAny": "off",
"noControlCharactersInRegex": "off",
"noExplicitAny": "info",
"noControlCharactersInRegex": "warn",
"noShadowRestrictedNames": "off",
"noArrayIndexKey": "info",
"noAssignInExpressions": "info"
"noAssignInExpressions": "info",
"useIterableCallbackReturn": "info"
},
"complexity": {
"noUselessConstructor": "off",
"useOptionalChain": "off",
"noBannedTypes": "off",
"useLiteralKeys": "off",
"noUselessCatch": "off",
"noUselessSwitchCase": "off",
"noStaticOnlyClass": "off"
"noUselessConstructor": "info",
"useOptionalChain": "info",
"noBannedTypes": "warn",
"useLiteralKeys": "info",
"noUselessCatch": "info",
"noUselessSwitchCase": "info",
"noStaticOnlyClass": "info"
},
"security": {
"noDangerouslySetInnerHtml": "info"
@@ -94,6 +95,11 @@
"lineEnding": "lf",
"formatWithErrors": true
},
"css": {
"parser": {
"tailwindDirectives": true
}
},
"javascript": {
"formatter": {
"semicolons": "asNeeded",
@@ -112,19 +118,21 @@
}
},
"files": {
"ignoreUnknown": true,
"includes": [
"**",
"!**/dist",
"!**/dist-*",
"!**/out",
"!**/evals",
"!**/playwright",
"!**/test-results",
"!**/node_modules",
"!**/webview-ui/build",
"!**/generated",
"!**/proto",
"!**/tests/specs"
// explicitly force files to be ignored by the scanner with !!
"!!**/dist",
"!!**/dist-*",
"!!**/out",
"!!**/evals",
"!!**/playwright",
"!!**/test-results",
"!!**/node_modules",
"!!**/webview-ui/build",
"!!**/generated",
"!!**/proto",
"!!**/tests/specs"
]
},
"plugins": [
@@ -134,14 +142,15 @@
{
"includes": [
"**",
"!**/hosts/vscode/**",
"!**/test/**",
"!**/*.test.ts",
"!src/dev/**",
"!src/extension.ts",
"!src/integrations/git/commit-message-generator.ts",
"!src/integrations/terminal/**",
"!src/core/controller/ui/openWalkthrough.ts"
"!!**/dist",
"!!**/hosts/vscode/**",
"!!**/test/**",
"!!**/*.test.ts",
"!!src/dev/**",
"!!src/extension.ts",
"!!src/integrations/git/commit-message-generator.ts",
"!!src/integrations/terminal/**",
"!!src/core/controller/ui/openWalkthrough.ts"
],
"plugins": [
"src/dev/grit/vscode-api.grit"
@@ -154,35 +163,37 @@
],
"includes": [
"**",
"!**/esbuild.*",
"!**/*.mts",
"!**/webview-ui/**",
"!**/evals/**",
"!**/standalone/**",
"!**/e2e/**",
"!**/test/**",
"!**/__tests__/**",
"!**/*.test.ts",
"!**/*.stories.ts",
"!src/dev/**",
"!**/*.mjs",
"!**/*.js",
"!**/scripts/**",
"!**/*.tsx",
"!**/testing-platform/**",
"!**/cli-ts/src/acp/**"
"!!**/esbuild.*",
"!!**/*.mts",
"!!**/webview-ui/**",
"!!**/evals/**",
"!!**/standalone/**",
"!!**/cli/**",
"!!**/e2e/**",
"!!**/test/**",
"!!**/__tests__/**",
"!!**/*.test.ts",
"!!**/*.stories.ts",
"!!src/dev/**",
"!!**/*.mjs",
"!!**/*.js",
"!!**/scripts/**",
"!!**/*.tsx",
"!!**/testing-platform/**",
// ACP mode must redirect console to stderr - this is intentional
"!!cli/src/acp/index.ts"
]
},
{
"includes": [
"**",
"!src/core/storage/state-migrations.ts",
"!src/core/storage/FileContextTracker.ts",
"!src/core/context/context-tracking/FileContextTracker.ts",
"!src/common.ts",
"!src/services/logging/distinctId.ts",
"!src/core/storage/utils/state-helpers.ts",
"!src/extension.ts"
"!!src/core/storage/state-migrations.ts",
"!!src/core/storage/FileContextTracker.ts",
"!!src/core/context/context-tracking/FileContextTracker.ts",
"!!src/common.ts",
"!!src/services/logging/distinctId.ts",
"!!src/core/storage/utils/state-helpers.ts",
"!!src/extension.ts"
],
"plugins": [
"src/dev/grit/use-cache-service.grit"
-272
View File
@@ -1,272 +0,0 @@
import fs from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import dotenv from "dotenv"
import * as esbuild from "esbuild"
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const rootDir = path.resolve(__dirname, "..")
// Load .env from repo root
dotenv.config({ path: path.join(rootDir, ".env") })
const production = process.argv.includes("--production")
const watch = process.argv.includes("--watch")
/**
* Plugin to resolve path aliases from the parent project
*/
const aliasResolverPlugin: esbuild.Plugin = {
name: "alias-resolver",
setup(build) {
const aliases = {
"@": path.resolve(rootDir, "src"),
"@core": path.resolve(rootDir, "src/core"),
"@integrations": path.resolve(rootDir, "src/integrations"),
"@services": path.resolve(rootDir, "src/services"),
"@shared": path.resolve(rootDir, "src/shared"),
"@utils": path.resolve(rootDir, "src/utils"),
"@packages": path.resolve(rootDir, "src/packages"),
"@hosts": path.resolve(rootDir, "src/hosts"),
"@generated": path.resolve(rootDir, "src/generated"),
"@api": path.resolve(rootDir, "src/core/api"),
}
// For each alias entry, create a resolver
Object.entries(aliases).forEach(([alias, aliasPath]) => {
const aliasRegex = new RegExp(`^${alias}($|/.*)`)
build.onResolve({ filter: aliasRegex }, (args) => {
const importPath = args.path.replace(alias, aliasPath)
// First, check if the path exists as is
if (fs.existsSync(importPath)) {
const stats = fs.statSync(importPath)
if (stats.isDirectory()) {
// If it's a directory, try to find index files
const extensions = [".ts", ".tsx", ".js", ".jsx"]
for (const ext of extensions) {
const indexFile = path.join(importPath, `index${ext}`)
if (fs.existsSync(indexFile)) {
return { path: indexFile }
}
}
} else {
// It's a file that exists, so return it
return { path: importPath }
}
}
// If the path doesn't exist, try appending extensions
const extensions = [".ts", ".tsx", ".js", ".jsx"]
for (const ext of extensions) {
const pathWithExtension = `${importPath}${ext}`
if (fs.existsSync(pathWithExtension)) {
return { path: pathWithExtension }
}
}
// Handle .js -> .ts extension mapping (common in ESM TypeScript projects)
if (importPath.endsWith(".js")) {
const tsPath = importPath.replace(/\.js$/, ".ts")
if (fs.existsSync(tsPath)) {
return { path: tsPath }
}
const tsxPath = importPath.replace(/\.js$/, ".tsx")
if (fs.existsSync(tsxPath)) {
return { path: tsxPath }
}
}
// If nothing worked, return the original path and let esbuild handle the error
return { path: importPath }
})
})
},
}
/**
* Plugin to redirect vscode imports to our shim
*/
const vscodeStubPlugin: esbuild.Plugin = {
name: "vscode-stub",
setup(build) {
// Redirect 'vscode' imports to our shim
build.onResolve({ filter: /^vscode$/ }, () => {
return { path: path.join(__dirname, "src", "vscode-shim.ts") }
})
},
}
const esbuildProblemMatcherPlugin: esbuild.Plugin = {
name: "esbuild-problem-matcher",
setup(build) {
build.onStart(() => {
console.log("[cli-ts esbuild] Build started...")
})
build.onEnd((result) => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`)
if (location) {
console.error(` ${location.file}:${location.line}:${location.column}:`)
}
})
console.log("[cli-ts esbuild] Build finished")
})
},
}
// Plugin to stub out optional devtools module
const stubOptionalModulesPlugin: esbuild.Plugin = {
name: "stub-optional-modules",
setup(build) {
build.onResolve({ filter: /^react-devtools-core$/ }, () => {
return { path: path.join(__dirname, "src", "stub-devtools.js"), external: false }
})
},
}
const copyWasmFiles: esbuild.Plugin = {
name: "copy-wasm-files",
setup(build) {
build.onEnd(() => {
const destDir = path.join(__dirname, "dist")
// Ensure dist directory exists
if (!fs.existsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true })
}
// tree sitter
const sourceDir = path.join(rootDir, "node_modules", "web-tree-sitter")
// Copy tree-sitter.wasm
const treeSitterWasm = path.join(sourceDir, "tree-sitter.wasm")
if (fs.existsSync(treeSitterWasm)) {
fs.copyFileSync(treeSitterWasm, path.join(destDir, "tree-sitter.wasm"))
}
// Copy language-specific WASM files
const languageWasmDir = path.join(rootDir, "node_modules", "tree-sitter-wasms", "out")
const languages = [
"typescript",
"tsx",
"python",
"rust",
"javascript",
"go",
"cpp",
"c",
"c_sharp",
"ruby",
"java",
"php",
"swift",
"kotlin",
]
if (fs.existsSync(languageWasmDir)) {
languages.forEach((lang) => {
const filename = `tree-sitter-${lang}.wasm`
const sourcePath = path.join(languageWasmDir, filename)
if (fs.existsSync(sourcePath)) {
fs.copyFileSync(sourcePath, path.join(destDir, filename))
}
})
}
})
},
}
const buildEnvVars: Record<string, string> = {
"process.env.IS_STANDALONE": JSON.stringify("true"),
"process.env.IS_CLI": JSON.stringify("true"),
}
const buildTimeEnvs = [
"TELEMETRY_SERVICE_API_KEY",
"ERROR_SERVICE_API_KEY",
"POSTHOG_TELEMETRY_ENABLED",
"OTEL_TELEMETRY_ENABLED",
"OTEL_LOGS_EXPORTER",
"OTEL_METRICS_EXPORTER",
"OTEL_EXPORTER_OTLP_PROTOCOL",
"OTEL_EXPORTER_OTLP_ENDPOINT",
"OTEL_EXPORTER_OTLP_HEADERS",
"OTEL_METRIC_EXPORT_INTERVAL",
"CLINE_ENVIRONMENT",
]
buildTimeEnvs.forEach((envVar) => {
if (process.env[envVar]) {
console.log(`[cli-ts esbuild] ${envVar} env var is set`)
buildEnvVars[`process.env.${envVar}`] = JSON.stringify(process.env[envVar])
}
})
if (production) {
buildEnvVars["process.env.IS_DEV"] = "false"
}
const config: esbuild.BuildOptions = {
entryPoints: [path.join(__dirname, "src", "index.ts")],
bundle: true,
minify: production,
sourcemap: !production,
logLevel: "silent",
define: buildEnvVars,
tsconfig: path.join(__dirname, "tsconfig.json"),
plugins: [copyWasmFiles, aliasResolverPlugin, vscodeStubPlugin, stubOptionalModulesPlugin, esbuildProblemMatcherPlugin],
format: "esm",
sourcesContent: false,
platform: "node",
target: "node20",
outfile: path.join(__dirname, "dist", "cli.mjs"),
// These modules need to load files from the module directory at runtime
external: [
"@grpc/reflection",
"grpc-health-check",
"better-sqlite3",
"ink",
"ink-spinner",
"ink-picture",
"react",
"aws4fetch",
"pino",
"pino-roll",
],
supported: { "top-level-await": true },
banner: {
js: `#!/usr/bin/env node
// Suppress all Node.js warnings (deprecation, experimental, etc.)
process.emitWarning = () => {};
import { createRequire as _createRequire } from 'module';
import { fileURLToPath as _fileURLToPath } from 'url';
import { dirname as _dirname } from 'path';
const require = _createRequire(import.meta.url);
const __filename = _fileURLToPath(import.meta.url);
const __dirname = _dirname(__filename);`,
},
}
async function main() {
const ctx = await esbuild.context(config)
if (watch) {
await ctx.watch()
console.log("[cli-ts] Watching for changes...")
} else {
await ctx.rebuild()
await ctx.dispose()
// Make the output executable
const outfile = path.join(__dirname, "dist", "cli.mjs")
if (fs.existsSync(outfile)) {
fs.chmodSync(outfile, "755")
}
}
}
main().catch((e) => {
console.error(e)
process.exit(1)
})
-2978
View File
File diff suppressed because it is too large Load Diff
-81
View File
@@ -1,81 +0,0 @@
{
"name": "@cline/cli",
"version": "2.0.0",
"description": "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
"main": "dist/cli.mjs",
"bin": {
"cline": "./dist/cli.mjs"
},
"type": "module",
"engines": {
"node": ">=20.0.0"
},
"scripts": {
"prepublishOnly": "npm run build:production",
"package:brew": "node ./scripts/update-brew-formula.mts",
"package": "npm pack --pack-destination ./dist",
"build": "node esbuild.mts",
"build:production": "node esbuild.mts --production",
"watch": "node esbuild.mts --watch",
"dev": "IS_DEV=true && npm run link && npm run watch ; npm run unlink",
"clean": "rimraf dist",
"typecheck": "tsc --noEmit",
"link": "npm run build && npm link",
"unlink": "npm unlink -g @cline/cli && npm unlink -g cline",
"test": "vitest",
"test:run": "vitest run"
},
"keywords": [
"cline",
"claude",
"dev",
"mcp",
"openrouter",
"coding",
"agent",
"autonomous",
"chatgpt",
"sonnet",
"ai",
"llama",
"cli"
],
"author": {
"name": "Cline Bot Inc."
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline"
},
"homepage": "https://cline.bot",
"bugs": {
"url": "https://github.com/cline/cline/issues"
},
"devDependencies": {
"@types/node": "20.x",
"@types/prompts": "^2.4.9",
"@types/react": "^19.2.9",
"dotenv": "^16.4.5",
"esbuild": "^0.25.0",
"ink-testing-library": "^4.0.0",
"rimraf": "^6.0.1",
"typescript": "^5.4.5",
"vitest": "^4.0.17"
},
"dependencies": {
"@agentclientprotocol/sdk": "^0.13.1",
"aws4fetch": "^1.0.20",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"ink": "npm:@jrichman/ink@6.4.7",
"ink-picture": "^1.3.3",
"ink-spinner": "^5.0.0",
"ora": "^8.0.1",
"nanoid": "^5.1.6",
"pino": "^10.0.0",
"pino-roll": "^4.0.0",
"prompts": "^2.4.2",
"react": "^19.2.3"
}
}
-184
View File
@@ -1,184 +0,0 @@
/**
* Custom types and extensions for ACP integration with Cline CLI.
*
* This file extends the base ACP types with Cline-specific functionality.
*/
import type * as acp from "@agentclientprotocol/sdk"
import type { Controller } from "@/core/controller"
// Re-export common ACP types for convenience
export type {
Agent,
AgentSideConnection,
AudioContent,
CancelNotification,
ContentBlock,
ImageContent,
InitializeRequest,
InitializeResponse,
LoadSessionRequest,
LoadSessionResponse,
McpServer,
ModelInfo,
NewSessionRequest,
NewSessionResponse,
PermissionOption,
PermissionOptionKind,
PromptRequest,
PromptResponse,
ReadTextFileRequest,
ReadTextFileResponse,
RequestPermissionRequest,
RequestPermissionResponse,
SessionConfigOption,
SessionModelState,
SessionNotification,
SessionUpdate,
SetSessionConfigOptionRequest,
SetSessionConfigOptionResponse,
SetSessionModelRequest,
SetSessionModelResponse,
SetSessionModeRequest,
SetSessionModeResponse,
StopReason,
TextContent,
ToolCall,
ToolCallStatus,
ToolCallUpdate,
ToolKind,
WriteTextFileRequest,
WriteTextFileResponse,
} from "@agentclientprotocol/sdk"
/**
* Cline-specific agent capabilities extending the ACP base capabilities.
*/
export interface ClineAgentCapabilities {
/** Support for loading sessions from disk */
loadSession: boolean
/** Prompt capabilities for the agent */
promptCapabilities: {
/** Support for image inputs */
image: boolean
/** Support for audio inputs */
audio: boolean
/** Support for embedded context (file resources) */
embeddedContext: boolean
}
/** MCP server passthrough capabilities */
mcpCapabilities: {
/** Support for HTTP MCP servers */
http: boolean
/** Support for SSE MCP servers */
sse: boolean
}
}
/**
* Cline agent info for ACP initialization response.
*/
export interface ClineAgentInfo {
name: "cline"
title: "Cline"
version: string
}
/**
* Extended session data stored by Cline for ACP sessions.
* Maps to Cline's task history structure.
*/
export interface ClineAcpSession {
/** Unique session/task ID */
sessionId: string
/** Working directory for the session */
cwd: string
/** Current mode (plan/act) */
mode: "plan" | "act"
/** MCP servers passed from the client */
mcpServers: acp.McpServer[]
/** Timestamp when session was created */
createdAt: number
/** Timestamp of last activity */
lastActivityAt: number
/** Whether this session was loaded from history (needs resume on first prompt) */
isLoadedFromHistory?: boolean
/** Controller instance for this session (manages task execution) */
controller?: Controller
/** Model ID override for plan mode (format: "provider/modelId") */
planModeModelId?: string
/** Model ID override for act mode (format: "provider/modelId") */
actModeModelId?: string
}
/**
* Permission option as presented to the ACP client.
*/
export interface ClinePermissionOption {
kind: acp.PermissionOptionKind
name: string
optionId: string
}
/**
* Mapping of Cline message types to their ACP session update equivalents.
*/
export type ClineToAcpUpdateMapping = {
/** Text messages from the agent */
text: "agent_message_chunk"
/** Reasoning/thinking from the agent */
reasoning: "agent_thought_chunk"
/** Markdown content from the agent */
markdown: "agent_message_chunk"
/** Tool execution */
tool: "tool_call"
/** Command execution */
command: "tool_call"
/** Command output */
command_output: "tool_call_update"
/** Task completion */
completion_result: "end_turn"
/** Error messages */
error: "tool_call_update" | "error"
}
/**
* Options for creating an ACP agent instance.
*/
export interface AcpAgentOptions {
/** CLI version string */
version: string
/** Whether debug logging is enabled */
debug?: boolean
}
/**
* Result of translating a Cline message to ACP session update(s).
* A single Cline message may produce multiple ACP updates.
*/
export interface TranslatedMessage {
/** The session updates to send */
updates: acp.SessionUpdate[]
/** Whether this message requires a permission request */
requiresPermission?: boolean
/** Permission request details if required */
permissionRequest?: Omit<acp.RequestPermissionRequest, "sessionId">
/** The toolCallId that was created/used (for tracking across streaming updates) */
toolCallId?: string
}
/**
* State tracking for an active ACP session within Cline.
*/
export interface AcpSessionState {
/** Session ID */
sessionId: string
/** Whether the session is currently processing a prompt */
isProcessing: boolean
/** Current tool call ID being executed (if any) */
currentToolCallId?: string
/** Whether the session has been cancelled */
cancelled: boolean
/** Accumulated tool calls for permission batching */
pendingToolCalls: Map<string, acp.ToolCall>
}
-216
View File
@@ -1,216 +0,0 @@
/**
* DiffView component for displaying file diffs in Ink
* Shows unified diff output with colored lines for additions/deletions
* Supports SEARCH/REPLACE format and ApplyPatch format
*/
import { Box, Text } from "ink"
import React from "react"
interface DiffViewProps {
/** Diff content (SEARCH/REPLACE format, ApplyPatch format, or raw content for new files) */
content?: string
}
interface DiffLine {
type: "add" | "remove" | "context" | "separator"
content: string
}
interface ParsedPatch {
additions: number
deletions: number
lines: DiffLine[]
}
// Constants for format markers
const MARKERS = {
SEARCH_BLOCK: "------- SEARCH",
SEARCH_SEPARATOR: "=======",
REPLACE_BLOCK: "+++++++ REPLACE",
NEW_BEGIN: "*** Begin Patch",
NEW_END: "*** End Patch",
} as const
/**
* Parse SEARCH/REPLACE format into diff lines
* Format: ------- SEARCH\n...\n=======\n...\n+++++++ REPLACE
*/
function parseSearchReplaceFormat(content: string): ParsedPatch {
const result: ParsedPatch = { additions: 0, deletions: 0, lines: [] }
// Find all SEARCH blocks
const searchRegex = /-{7,} SEARCH/g
const searchPositions: number[] = []
let match: RegExpExecArray | null
while ((match = searchRegex.exec(content)) !== null) {
searchPositions.push(match.index)
}
for (let i = 0; i < searchPositions.length; i++) {
// Add separator between blocks
if (i > 0) {
result.lines.push({ type: "separator", content: "" })
}
const start = searchPositions[i]
const end = i < searchPositions.length - 1 ? searchPositions[i + 1] : content.length
const blockContent = content.substring(start, end)
// Extract content after SEARCH marker
const afterSearch = blockContent.substring(MARKERS.SEARCH_BLOCK.length).replace(/^\r?\n/, "")
const separatorIndex = afterSearch.indexOf(MARKERS.SEARCH_SEPARATOR)
if (separatorIndex === -1) {
// Still streaming - only SEARCH block available
const searchContent = afterSearch.trimEnd()
for (const line of searchContent.split("\n")) {
result.lines.push({ type: "remove", content: line })
result.deletions++
}
} else {
// Extract SEARCH block (deletions)
const searchContent = afterSearch.substring(0, separatorIndex).replace(/\r?\n$/, "")
for (const line of searchContent.split("\n")) {
result.lines.push({ type: "remove", content: line })
result.deletions++
}
// Extract REPLACE block (additions)
const afterSeparator = afterSearch.substring(separatorIndex + MARKERS.SEARCH_SEPARATOR.length).replace(/^\r?\n/, "")
const replaceEndIndex = afterSeparator.indexOf(MARKERS.REPLACE_BLOCK)
const replaceContent =
replaceEndIndex !== -1
? afterSeparator.substring(0, replaceEndIndex).replace(/\r?\n$/, "")
: afterSeparator.trimEnd()
for (const line of replaceContent.split("\n")) {
result.lines.push({ type: "add", content: line })
result.additions++
}
}
}
return result
}
/**
* Parse ApplyPatch format into diff lines
* Format: *** Begin Patch\n*** Update File: path\n+line\n-line\n*** End Patch
*/
function parseApplyPatchFormat(content: string): ParsedPatch {
const result: ParsedPatch = { additions: 0, deletions: 0, lines: [] }
const beginIndex = content.indexOf(MARKERS.NEW_BEGIN)
if (beginIndex === -1) return result
const endIndex = content.indexOf(MARKERS.NEW_END)
const contentStart = beginIndex + MARKERS.NEW_BEGIN.length
const contentEnd = endIndex !== -1 ? endIndex : content.length
const patchContent = content.substring(contentStart, contentEnd).trim()
for (const line of patchContent.split("\n")) {
// Skip file header lines
if (line.match(/^\*\*\* (Add|Update|Delete) File:/)) continue
if (line.trim() === "@@") continue
if (line.startsWith("+")) {
const hasSpace = line.startsWith("+ ")
result.lines.push({ type: "add", content: hasSpace ? line.slice(2) : line.slice(1) })
result.additions++
} else if (line.startsWith("-")) {
const hasSpace = line.startsWith("- ")
result.lines.push({ type: "remove", content: hasSpace ? line.slice(2) : line.slice(1) })
result.deletions++
} else if (line.trim()) {
// Context line
result.lines.push({ type: "context", content: line })
}
}
return result
}
/**
* Parse tool content into diff lines
* Detects format and delegates to appropriate parser
*/
function parseToolContent(content: string): ParsedPatch {
// Try SEARCH/REPLACE format first
if (content.includes(MARKERS.SEARCH_BLOCK)) {
return parseSearchReplaceFormat(content)
}
// Try ApplyPatch format
if (content.includes(MARKERS.NEW_BEGIN)) {
return parseApplyPatchFormat(content)
}
// Fallback: treat as new file (all additions)
const lines = content.split("\n")
return {
additions: lines.length,
deletions: 0,
lines: lines.map((line) => ({ type: "add", content: line })),
}
}
// Dim diff colors similar to IDE diff views
const DIFF_COLORS = {
addBg: "rgb(35, 61, 41)", // dark muted green
addFg: "rgb(156, 204, 122)", // light green text
removeBg: "rgb(62, 36, 36)", // dark muted red
removeFg: "rgb(224, 139, 139)", // light red/pink text
} as const
/**
* Render a diff line with full-width background color highlighting
* Uses Box with backgroundColor to handle wrapping properly
*/
const DiffLineRow: React.FC<{ line: DiffLine }> = ({ line }) => {
if (line.type === "separator") {
return <Text> </Text>
}
const prefix = line.type === "add" ? "+" : line.type === "remove" ? "-" : " "
const content = prefix + line.content
switch (line.type) {
case "add":
return (
<Box backgroundColor={DIFF_COLORS.addBg} width="100%">
<Text color={DIFF_COLORS.addFg}>{content}</Text>
</Box>
)
case "remove":
return (
<Box backgroundColor={DIFF_COLORS.removeBg} width="100%">
<Text color={DIFF_COLORS.removeFg}>{content}</Text>
</Box>
)
case "context":
return <Text dimColor>{content}</Text>
default:
return null
}
}
/**
* DiffView component that renders file edits as a diff
* Supports SEARCH/REPLACE format and ApplyPatch format
*/
export const DiffView: React.FC<DiffViewProps> = ({ content }) => {
if (!content) {
return null
}
const parsed = parseToolContent(content)
return (
<Box flexDirection="column" width="100%">
{parsed.lines.map((line, idx) => (
<DiffLineRow key={idx} line={line} />
))}
</Box>
)
}
-44
View File
@@ -1,44 +0,0 @@
/**
* Provider picker component for API provider selection
*/
import React, { useMemo } from "react"
import { API_PROVIDERS_LIST } from "@/shared/api"
import providersData from "@/shared/providers/providers.json"
import { SearchableList, SearchableListItem } from "./SearchableList"
// Create a lookup map from provider value to display label
const providerLabels: Record<string, string> = Object.fromEntries(
providersData.list.map((p: { value: string; label: string }) => [p.value, p.label]),
)
// Get provider order from providers.json (same order as webview)
const providerOrder: string[] = providersData.list.map((p: { value: string }) => p.value)
export function getProviderLabel(providerId: string): string {
return providerLabels[providerId] || providerId
}
export function getProviderOrder(): string[] {
return providerOrder
}
interface ProviderPickerProps {
onSelect: (providerId: string) => void
isActive?: boolean
}
export const ProviderPicker: React.FC<ProviderPickerProps> = ({ onSelect, isActive = true }) => {
// Use providers.json order, filtered to only available providers
const items: SearchableListItem[] = useMemo(() => {
const availableProviders = new Set(API_PROVIDERS_LIST)
const sorted = providerOrder.filter((p) => availableProviders.has(p))
return sorted.map((providerId) => ({
id: providerId,
label: getProviderLabel(providerId),
}))
}, [])
return <SearchableList isActive={isActive} items={items} onSelect={(item) => onSelect(item.id)} />
}
-328
View File
@@ -1,328 +0,0 @@
/**
* Welcome view component
* Shows an interactive prompt when user starts cline without a command
* Supports file mentions with @
*/
import { Box, Text, useInput } from "ink"
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { StateManager } from "@/core/storage/StateManager"
import { getProviderDefaultModelId, Mode } from "@/shared/storage"
import { useStdinContext } from "../context/StdinContext"
import {
checkAndWarnRipgrepMissing,
extractMentionQuery,
type FileSearchResult,
getRipgrepInstallInstructions,
insertMention,
searchWorkspaceFiles,
} from "../utils/file-search"
import { isMouseEscapeSequence } from "../utils/input"
import { parseImagesFromInput } from "../utils/parser"
import { AccountInfoView } from "./AccountInfoView"
import { FileMentionMenu } from "./FileMentionMenu"
interface WelcomeViewProps {
onSubmit: (prompt: string, imagePaths: string[]) => void
onExit?: () => void
controller?: any
}
// ASCII art Cline logo
const CLINE_LOGO = [
" ::::::: ",
" ::::::::: ",
" ::::::::::::::::: ",
" ::::::::::::::::::::::: ",
" ::::::::::::::::::::::::: ",
" ::::::::::::::::::::::::::: ",
" ::::::: ::::::: ::::::: ",
" ::::::: ::::: ::::::: ",
":::::::: ::::: ::::::::",
":::::::: ::::: ::::::::",
" ::::::: ::::: ::::::: ",
" ::::::: ::::::: ::::::: ",
" ::::::::::::::::::::::::::: ",
" ::::::::::::::::::::::::: ",
" ::::::::::::::::::::::: ",
" :::::::::::::::: ",
]
const SEARCH_DEBOUNCE_MS = 150
const RIPGREP_WARNING_DURATION_MS = 5000
const MAX_SEARCH_RESULTS = 15
export const WelcomeView: React.FC<WelcomeViewProps> = ({ onSubmit, onExit, controller }) => {
const { isRawModeSupported } = useStdinContext()
const [textInput, setTextInput] = useState("")
const [fileResults, setFileResults] = useState<FileSearchResult[]>([])
const [selectedIndex, setSelectedIndex] = useState(0)
const [isSearching, setIsSearching] = useState(false)
const [showRipgrepWarning, setShowRipgrepWarning] = useState(false)
const [escPressedOnce, setEscPressedOnce] = useState(false)
const [mode, setMode] = useState<Mode>(() => {
const stateManager = StateManager.get()
return stateManager.getGlobalSettingsKey("mode") || "act"
})
const provider = useMemo(() => {
const stateManager = StateManager.get()
const mode = stateManager.getGlobalSettingsKey("mode") as string
const providerKey = mode === "act" ? "actModeApiProvider" : "planModeApiProvider"
const currentProvider = stateManager.getGlobalSettingsKey(providerKey) as string
return currentProvider || "cline"
}, [controller])
// Get model ID based on current mode
const modelId = useMemo(() => {
const stateManager = StateManager.get()
const modelKey = mode === "act" ? "actModeApiModelId" : "planModeApiModelId"
return (stateManager.getGlobalSettingsKey(modelKey) as string) || getProviderDefaultModelId(provider)
}, [mode, provider])
const toggleMode = useCallback(() => {
const newMode: Mode = mode === "act" ? "plan" : "act"
setMode(newMode)
const stateManager = StateManager.get()
stateManager.setGlobalState("mode", newMode)
}, [mode])
const refs = useRef({
searchTimeout: null as NodeJS.Timeout | null,
lastQuery: "",
hasCheckedRipgrep: false,
})
const { prompt, imagePaths } = parseImagesFromInput(textInput)
const mentionInfo = useMemo(() => extractMentionQuery(textInput), [textInput])
const workspacePath = useMemo(() => {
try {
const root = controller?.getWorkspaceManagerSync?.()?.getPrimaryRoot?.()
if (root?.path) {
return root.path
}
} catch {
// Fallback to cwd
}
return process.cwd()
}, [controller])
// Search for files when in mention mode
useEffect(() => {
const { current: r } = refs
if (!mentionInfo.inMentionMode) {
setFileResults([])
setSelectedIndex(0)
if (r.searchTimeout) {
clearTimeout(r.searchTimeout)
r.searchTimeout = null
}
return
}
// Check for ripgrep on first mention trigger
if (!r.hasCheckedRipgrep) {
r.hasCheckedRipgrep = true
if (checkAndWarnRipgrepMissing()) {
setShowRipgrepWarning(true)
setTimeout(() => setShowRipgrepWarning(false), RIPGREP_WARNING_DURATION_MS)
}
}
const { query } = mentionInfo
if (query === r.lastQuery) {
return
}
r.lastQuery = query
if (r.searchTimeout) {
clearTimeout(r.searchTimeout)
}
setIsSearching(true)
r.searchTimeout = setTimeout(async () => {
try {
const results = await searchWorkspaceFiles(query, workspacePath, MAX_SEARCH_RESULTS)
setFileResults(results)
setSelectedIndex(0)
} catch {
setFileResults([])
} finally {
setIsSearching(false)
}
}, SEARCH_DEBOUNCE_MS)
return () => {
if (r.searchTimeout) {
clearTimeout(r.searchTimeout)
}
}
}, [mentionInfo.inMentionMode, mentionInfo.query, workspacePath])
useInput(
(input, key) => {
// Filter out mouse escape sequences
if (isMouseEscapeSequence(input)) {
return
}
const inMenu = mentionInfo.inMentionMode && fileResults.length > 0
// Menu navigation
if (inMenu) {
if (key.upArrow) {
setSelectedIndex((i) => (i > 0 ? i - 1 : fileResults.length - 1))
return
}
if (key.downArrow) {
setSelectedIndex((i) => (i < fileResults.length - 1 ? i + 1 : 0))
return
}
if (key.tab || key.return) {
const file = fileResults[selectedIndex]
if (file) {
setTextInput(insertMention(textInput, mentionInfo.atIndex, file.path))
setFileResults([])
setSelectedIndex(0)
}
return
}
if (key.escape) {
setFileResults([])
setSelectedIndex(0)
return
}
}
// Normal input handling
if (key.tab && !mentionInfo.inMentionMode) {
toggleMode()
return
}
if (key.return && !mentionInfo.inMentionMode) {
if (prompt.trim() || imagePaths.length > 0) {
onSubmit(prompt.trim(), imagePaths)
}
return
}
if (key.escape && !mentionInfo.inMentionMode) {
if (escPressedOnce) {
onExit?.()
} else {
setEscPressedOnce(true)
}
return
}
if (key.backspace || key.delete) {
setTextInput((prev) => prev.slice(0, -1))
setEscPressedOnce(false)
return
}
if (input && !key.ctrl && !key.meta && !key.upArrow && !key.downArrow && !key.tab) {
setTextInput((prev) => prev + input)
setEscPressedOnce(false)
}
},
{ isActive: isRawModeSupported },
)
const borderColor = mode === "act" ? "blue" : "yellow"
return (
<Box flexDirection="column" width="100%">
{/* Account/Provider info at top */}
{controller && (
<Box marginBottom={1}>
<AccountInfoView controller={controller} />
</Box>
)}
{/* Cline logo - centered */}
<Box alignItems="center" flexDirection="column">
{CLINE_LOGO.map((line, idx) => (
// biome-ignore lint/suspicious/noArrayIndexKey: static array that never changes
<Text color="white" key={idx}>
{line}
</Text>
))}
</Box>
{/* Main prompt - centered, bold */}
<Box justifyContent="center" marginTop={1}>
<Text bold color="white">
What can I do for you?
</Text>
</Box>
{/* Ripgrep warning if needed */}
{showRipgrepWarning && (
<Box marginTop={1}>
<Text color="yellow"> ripgrep not found - file search will be slower. </Text>
<Text color="gray">Install: {getRipgrepInstallInstructions()}</Text>
</Box>
)}
{/* Input field with border */}
<Box
borderColor={borderColor}
borderStyle="round"
flexDirection="row"
marginTop={1}
paddingLeft={1}
paddingRight={1}
width="100%">
<Text>{textInput}</Text>
<Text inverse> </Text>
</Box>
{/* Model ID and Mode toggle row */}
<Box justifyContent="space-between" width="100%">
{/* Model ID on left */}
<Text color="gray">{modelId}</Text>
{/* Mode toggle on right */}
<Box gap={1}>
<Box>
<Text bold={mode === "plan"} color={mode === "plan" ? "yellow" : "gray"}>
{mode === "plan" ? "●" : "○"} Plan
</Text>
</Box>
<Box>
<Text bold={mode === "act"} color={mode === "act" ? "blue" : "gray"}>
{mode === "act" ? "●" : "○"} Act
</Text>
</Box>
<Text color="gray">(Tab)</Text>
</Box>
</Box>
{/* File mention menu - below input */}
{mentionInfo.inMentionMode && (
<FileMentionMenu
isLoading={isSearching}
query={mentionInfo.query}
results={fileResults}
selectedIndex={selectedIndex}
/>
)}
{/* Attached images */}
{imagePaths.length > 0 && (
<Text color="magenta">
📎 {imagePaths.length} image{imagePaths.length > 1 ? "s" : ""} attached
</Text>
)}
{/* Help text */}
<Box>
<Text color="gray">Enter to submit · @ to mention files · </Text>
<Text bold={escPressedOnce} color={escPressedOnce ? "white" : "gray"}>
{escPressedOnce ? "Press Esc again to exit" : "Esc to exit"}
</Text>
</Box>
</Box>
)
}
-52
View File
@@ -1,52 +0,0 @@
/**
* Featured models shown in the Cline model picker during onboarding
* These are curated models that work well with Cline
*/
export interface FeaturedModel {
id: string
name: string
description: string
label: string
}
export const FEATURED_MODELS = {
recommended: [
{
id: "anthropic/claude-opus-4.5",
name: "Claude Opus 4.5",
description: "State-of-the-art for complex coding",
label: "Best",
},
{
id: "openai/gpt-5.2-codex",
name: "GPT 5.2 Codex",
description: "OpenAI's latest with strong coding abilities",
label: "New",
},
{
id: "google/gemini-3-pro-preview",
name: "Gemini 3 Pro",
description: "1M context window for large codebases",
label: "Trending",
},
] as FeaturedModel[],
free: [
{
id: "kwaipilot/kat-coder-pro",
name: "KAT Coder Pro",
description: "Advanced agentic coding model",
label: "FREE",
},
{
id: "mistralai/devstral-2512:free",
name: "Devstral",
description: "Mistral's coding model",
label: "FREE",
},
] as FeaturedModel[],
}
export function getAllFeaturedModels(): FeaturedModel[] {
return [...FEATURED_MODELS.recommended, ...FEATURED_MODELS.free]
}
-705
View File
@@ -1,705 +0,0 @@
/**
* Cline CLI - TypeScript implementation with React Ink
*/
import path from "node:path"
import { exit } from "node:process"
import type { ApiProvider } from "@shared/api"
import { Command } from "commander"
import { render } from "ink"
import React from "react"
import { ClineEndpoint } from "@/config"
import { Controller } from "@/core/controller"
import { StateManager } from "@/core/storage/StateManager"
import { AuthHandler } from "@/hosts/external/AuthHandler"
import { HostProvider } from "@/hosts/host-provider"
import { FileEditProvider } from "@/integrations/editor/FileEditProvider"
import { openAiCodexOAuthManager } from "@/integrations/openai-codex/oauth"
import { StandaloneTerminalManager } from "@/integrations/terminal/standalone/StandaloneTerminalManager"
import { BannerService } from "@/services/banner/BannerService"
import { ErrorService } from "@/services/error/ErrorService"
import { initializeDistinctId } from "@/services/logging/distinctId"
import { telemetryService } from "@/services/telemetry"
import { Logger } from "@/shared/services/Logger"
import { Session } from "@/shared/services/Session"
import { getProviderModelIdKey, ProviderToApiKeyMap } from "@/shared/storage"
import { secretStorage } from "@/shared/storage/ClineSecretStorage"
import { version as CLI_VERSION } from "../package.json"
import { runAcpMode } from "./acp/index.js"
import { App } from "./components/App"
import { checkRawModeSupport } from "./context/StdinContext"
import { createCliHostBridgeProvider } from "./controllers"
import { CliCommentReviewController } from "./controllers/CliCommentReviewController"
import { CliWebviewProvider } from "./controllers/CliWebviewProvider"
import { restoreConsole } from "./utils/console"
import { calculateRobotTopRow, queryCursorPos } from "./utils/cursor-position"
import { printInfo, printWarning } from "./utils/display"
import { parseImagesFromInput, processImagePaths } from "./utils/parser"
import { CLINE_CLI_DIR } from "./utils/path"
import { readStdinIfPiped } from "./utils/piped"
import { runPlainTextTask } from "./utils/plain-text-task"
import { printSessionSummary } from "./utils/session-summary"
import { checkForUpdates } from "./utils/update"
import { initializeCliContext } from "./vscode-context"
import { CLI_LOG_FILE, shutdownEvent, window } from "./vscode-shim"
// Track active context for graceful shutdown
let activeContext: CliContext | null = null
let isShuttingDown = false
function setupSignalHandlers() {
const shutdown = async (signal: string) => {
if (isShuttingDown) {
// Force exit on second signal
process.exit(1)
}
isShuttingDown = true
// Notify components to hide UI before shutdown
shutdownEvent.fire()
// Clear several lines to remove the input field and footer from display
// Move cursor up and clear lines (input box + footer rows)
const linesToClear = 8 // Input box (3 lines with border) + footer (4-5 lines)
process.stdout.write(`\x1b[${linesToClear}A\x1b[J`)
printWarning(`${signal} received, shutting down...`)
try {
if (activeContext) {
const task = activeContext.controller.task
if (task) {
task.abortTask()
}
await activeContext.controller.stateManager.flushPendingState()
await activeContext.controller.dispose()
}
await ErrorService.get().dispose()
} catch {
// Best effort cleanup
}
// Print session summary before exit
printSessionSummary()
process.exit(0)
}
process.on("SIGINT", () => shutdown("SIGINT"))
process.on("SIGTERM", () => shutdown("SIGTERM"))
// Suppress known abort errors from unhandled rejections
// These occur when task is cancelled and async operations throw "Cline instance aborted"
process.on("unhandledRejection", (reason: unknown) => {
const message = reason instanceof Error ? reason.message : String(reason)
// Silently ignore abort-related errors - they're expected during task cancellation
if (message.includes("aborted") || message.includes("abort")) {
Logger.info("Suppressed unhandled rejection due to abort:", message)
return
}
// For other unhandled rejections, log to file via Logger (if available)
// This won't show in terminal but will be in log files for debugging
Logger.error("Unhandled rejection:", reason)
})
}
setupSignalHandlers()
interface CliContext {
extensionContext: any
dataDir: string
extensionDir: string
workspacePath: string
controller: Controller
}
interface InitOptions {
config?: string
cwd?: string
verbose?: boolean
enableAuth?: boolean
}
/**
* Initialize all CLI infrastructure and return context needed for commands
*/
async function initializeCli(options: InitOptions): Promise<CliContext> {
const workspacePath = options.cwd || process.cwd()
const { extensionContext, DATA_DIR, EXTENSION_DIR } = initializeCliContext({
clineDir: options.config,
workspaceDir: workspacePath,
})
await ClineEndpoint.initialize()
await initializeDistinctId(extensionContext)
// Initialize/reset session tracking for this CLI run
Session.reset()
if (options.enableAuth) {
AuthHandler.getInstance().setEnabled(true)
}
const outputChannel = window.createOutputChannel("Cline CLI")
outputChannel.appendLine(
`Cline CLI initialized. Data dir: ${DATA_DIR}, Extension dir: ${EXTENSION_DIR}, Log dir: ${CLINE_CLI_DIR.log}`,
)
const logToChannel = (message: string) => outputChannel.appendLine(message)
HostProvider.initialize(
() => new CliWebviewProvider(extensionContext as any),
() => new FileEditProvider(),
() => new CliCommentReviewController(),
() => new StandaloneTerminalManager(),
createCliHostBridgeProvider(workspacePath),
logToChannel,
async () => (options.enableAuth ? AuthHandler.getInstance().getCallbackUrl() : ""),
async (name: string) => path.join(process.cwd(), name),
EXTENSION_DIR,
DATA_DIR,
)
await ErrorService.initialize()
await StateManager.initialize(extensionContext as any)
// Initialize OpenAI Codex OAuth manager with extension context for secrets storage
openAiCodexOAuthManager.initialize(extensionContext)
// Configure the shared Logging class to use HostProvider's output channel
Logger.subscribe((msg: string) => HostProvider.get().logToChannel(msg))
const webview = HostProvider.get().createWebviewProvider() as CliWebviewProvider
const controller = webview.controller
BannerService.initialize(webview.controller)
telemetryService.captureHostEvent("cline_cli", "initialized")
const ctx = { extensionContext, dataDir: DATA_DIR, extensionDir: EXTENSION_DIR, workspacePath, controller }
activeContext = ctx
return ctx
}
/**
* Run an Ink app with proper cleanup handling
*/
async function runInkApp(element: React.ReactElement, cleanup: () => Promise<void>): Promise<void> {
// Note: incrementalRendering is disabled because it causes UI glitches on terminal resize.
// Ink's incremental rendering tries to erase N lines based on previous output height,
// but when the terminal shrinks, this leaves artifacts. Gemini CLI only enables
// incrementalRendering when alternateBuffer is also enabled (which we don't use).
//
// exitOnCtrlC: false - We handle Ctrl+C ourselves so we can clean up UI before exiting.
// The app components listen for Ctrl+C via useInput and call their exit handlers.
const { waitUntilExit, unmount } = render(element, { exitOnCtrlC: false })
try {
await waitUntilExit()
} finally {
try {
unmount()
} catch {
// Already unmounted
}
restoreConsole()
await cleanup()
}
}
/**
* Run a task with the given prompt - uses welcome view for consistent behavior
*/
async function runTask(
prompt: string,
options: {
act?: boolean
plan?: boolean
model?: string
verbose?: boolean
cwd?: string
config?: string
thinking?: boolean
yolo?: boolean
images?: string[]
json?: boolean
stdinWasPiped?: boolean
},
existingContext?: CliContext,
) {
const ctx = existingContext || (await initializeCli({ ...options, enableAuth: true }))
// Parse images from the prompt text (e.g., @/path/to/image.png)
const { prompt: cleanPrompt, imagePaths: parsedImagePaths } = parseImagesFromInput(prompt)
// Combine parsed image paths with explicit --images option
const allImagePaths = [...(options.images || []), ...parsedImagePaths]
// Convert image file paths to base64 data URLs
const imageDataUrls = await processImagePaths(allImagePaths)
// Use clean prompt (with image refs removed)
const taskPrompt = cleanPrompt || prompt
// Task without prompt starts in interactive mode
telemetryService.captureHostEvent("task_command", prompt ? "task" : "interactive")
if (options.plan) {
StateManager.get().setGlobalState("mode", "plan")
telemetryService.captureHostEvent("mode_flag", "plan")
} else if (options.act) {
StateManager.get().setGlobalState("mode", "act")
telemetryService.captureHostEvent("mode_flag", "act")
}
if (options.model) {
const selectedMode = (StateManager.get().getGlobalSettingsKey("mode") || "act") as "act" | "plan"
// Get the current provider for the selected mode
const providerKey = selectedMode === "act" ? "actModeApiProvider" : "planModeApiProvider"
const currentProvider = StateManager.get().getGlobalSettingsKey(providerKey) as ApiProvider
// Update the generic model ID for the current mode
const modelKey = selectedMode === "act" ? "actModeApiModelId" : "planModeApiModelId"
StateManager.get().setGlobalState(modelKey, options.model)
// Also update the provider-specific model ID key if applicable
const providerModelKey = getProviderModelIdKey(currentProvider, selectedMode)
if (providerModelKey) {
StateManager.get().setGlobalState(providerModelKey, options.model)
}
telemetryService.captureHostEvent("model_flag", options.model)
}
// Set thinking budget based on --thinking flag
const thinkingBudget = options.thinking ? 1024 : 0
const currentMode = StateManager.get().getGlobalSettingsKey("mode") || "act"
const thinkingKey = currentMode === "act" ? "actModeThinkingBudgetTokens" : "planModeThinkingBudgetTokens"
StateManager.get().setGlobalState(thinkingKey, thinkingBudget)
if (options.thinking) {
telemetryService.captureHostEvent("thinking_flag", "true")
}
// Set yolo mode based on --yolo flag
if (options.yolo) {
StateManager.get().setGlobalState("yoloModeToggled", true)
telemetryService.captureHostEvent("yolo_flag", "true")
}
await StateManager.get().flushPendingState()
// Detect if output is a TTY (interactive terminal) or redirected to a file/pipe
const isTTY = process.stdout.isTTY === true
// Use plain text mode when output is redirected, stdin was piped, or JSON mode is enabled
// Ink requires raw mode on stdin which isn't available when stdin is piped
// Note: we use the stdinWasPiped flag passed from the caller because process.stdin.isTTY
// may not be reliable after stdin has been consumed by readStdinIfPiped()
if (!isTTY || options.stdinWasPiped || options.json) {
// Check if auth is configured before attempting to run the task
// In plain text mode we can't show the interactive auth flow
const hasAuth = await isAuthConfigured()
if (!hasAuth) {
printWarning("Not authenticated. Please run 'cline auth' first to configure your API credentials.")
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(1)
}
const reason = options.json ? "json" : options.stdinWasPiped ? "piped_stdin" : "redirected_output"
telemetryService.captureHostEvent("plain_text_mode", reason)
// Plain text mode: no Ink rendering, just clean text output
const success = await runPlainTextTask({
controller: ctx.controller,
prompt: taskPrompt,
imageDataUrls: imageDataUrls.length > 0 ? imageDataUrls : undefined,
verbose: options.verbose,
jsonOutput: options.json,
})
// Cleanup
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(success ? 0 : 1)
}
// Use welcome view for consistent rendering (same as interactive mode)
// Query cursor position BEFORE Ink mounts to know where robot will render
const cursorPos = await queryCursorPos(process.stdin, process.stdout)
const terminalRows = process.stdout.rows ?? 24
const robotTopRow = calculateRobotTopRow(cursorPos, terminalRows)
let taskError = false
// Render the welcome view with optional initial prompt/images
// If prompt provided (cline task "prompt"), ChatView will auto-submit
// If no prompt (cline interactive), user will type it in
await runInkApp(
React.createElement(App, {
view: "welcome",
verbose: options.verbose,
controller: ctx.controller,
isRawModeSupported: checkRawModeSupport(),
robotTopRow,
initialPrompt: taskPrompt || undefined,
initialImages: imageDataUrls.length > 0 ? imageDataUrls : undefined,
onError: () => {
taskError = true
},
onWelcomeExit: () => {
// User pressed Esc
exit(0)
},
}),
async () => {
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
if (taskError) {
printWarning("Task ended with errors.")
exit(1)
}
exit(0)
},
)
}
/**
* List task history
*/
async function listHistory(options: { config?: string; limit?: number; page?: number }) {
const ctx = await initializeCli(options)
const taskHistory = StateManager.get().getGlobalStateKey("taskHistory") || []
// Sort by timestamp (newest first) before pagination
const sortedHistory = [...taskHistory].sort((a: any, b: any) => (b.ts || 0) - (a.ts || 0))
const limit = typeof options.limit === "string" ? parseInt(options.limit, 10) : options.limit || 10
const initialPage = typeof options.page === "string" ? parseInt(options.page, 10) : options.page || 1
const totalCount = sortedHistory.length
const totalPages = Math.ceil(totalCount / limit)
telemetryService.captureHostEvent("history_command", "executed")
if (sortedHistory.length === 0) {
printInfo("No task history found.")
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(0)
}
await runInkApp(
React.createElement(App, {
view: "history",
historyItems: [],
historyAllItems: sortedHistory,
controller: ctx.controller,
historyPagination: { page: initialPage, totalPages, totalCount, limit },
isRawModeSupported: checkRawModeSupport(),
}),
async () => {
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(0)
},
)
}
/**
* Show current configuration
*/
async function showConfig(options: { config?: string }) {
const ctx = await initializeCli(options)
const stateManager = StateManager.get()
// Dynamically import the wrapper to avoid circular dependencies
const { ConfigViewWrapper } = await import("./components/ConfigViewWrapper")
// Check feature flags
const skillsEnabled = stateManager.getGlobalSettingsKey("skillsEnabled") ?? false
telemetryService.captureHostEvent("config_command", "executed")
await runInkApp(
React.createElement(ConfigViewWrapper, {
controller: ctx.controller,
dataDir: ctx.dataDir,
globalState: stateManager.getAllGlobalStateEntries(),
workspaceState: stateManager.getAllWorkspaceStateEntries(),
hooksEnabled: true,
skillsEnabled,
isRawModeSupported: checkRawModeSupport(),
}),
async () => {
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(0)
},
)
}
/**
* Run authentication flow
*/
async function runAuth(options: {
provider?: string
apikey?: string
modelid?: string
baseurl?: string
verbose?: boolean
cwd?: string
config?: string
}) {
const ctx = await initializeCli({ ...options, enableAuth: true })
const hasQuickSetupFlags = options.provider || options.apikey || options.modelid || options.baseurl
const quickSetup = hasQuickSetupFlags
? { provider: options.provider, apikey: options.apikey, modelid: options.modelid, baseurl: options.baseurl }
: undefined
telemetryService.captureHostEvent("auth_command", hasQuickSetupFlags ? "quick_setup" : "interactive")
let authError = false
await runInkApp(
React.createElement(App, {
view: "auth",
controller: ctx.controller,
isRawModeSupported: checkRawModeSupport(),
onComplete: () => {
telemetryService.captureHostEvent("auth", "completed")
exit(0)
},
onError: () => {
telemetryService.captureHostEvent("auth", "error")
authError = true
},
authQuickSetup: quickSetup,
}),
async () => {
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(0)
},
)
if (authError) {
process.exit(1)
}
}
// Setup CLI commands
const program = new Command()
program.name("cline").description("Cline CLI - AI coding assistant in your terminal").version(CLI_VERSION)
// Enable positional options to avoid conflicts between root and subcommand options with the same name
program.enablePositionalOptions()
program
.command("task")
.alias("t")
.description("Run a new task")
.argument("<prompt>", "The task prompt")
.option("-a, --act", "Run in act mode")
.option("-p, --plan", "Run in plan mode")
.option("-y, --yolo", "Enable yolo mode (auto-approve actions)")
.option("-m, --model <model>", "Model to use for the task")
.option("-v, --verbose", "Show verbose output")
.option("-c, --cwd <path>", "Working directory for the task")
.option("--config <path>", "Path to Cline configuration directory")
.option("--thinking", "Enable extended thinking (1024 token budget)")
.option("--json", "Output messages as JSON instead of styled text")
.action((prompt, options) => runTask(prompt, options))
program
.command("history")
.alias("h")
.description("List task history")
.option("-n, --limit <number>", "Number of tasks to show", "10")
.option("-p, --page <number>", "Page number (1-based)", "1")
.option("--config <path>", "Path to Cline configuration directory")
.action(listHistory)
program
.command("config")
.description("Show current configuration")
.option("--config <path>", "Path to Cline configuration directory")
.action(showConfig)
program
.command("auth")
.description("Authenticate a provider and configure what model is used")
.option("-p, --provider <id>", "Provider ID for quick setup (e.g., openai-native, anthropic)")
.option("-k, --apikey <key>", "API key for the provider")
.option("-m, --modelid <id>", "Model ID to configure (e.g., gpt-4o, claude-sonnet-4-5-20250929)")
.option("-b, --baseurl <url>", "Base URL (optional, only for openai provider)")
.option("-v, --verbose", "Show verbose output")
.option("-c, --cwd <path>", "Working directory for the task")
.option("--config <path>", "Path to Cline configuration directory")
.action(runAuth)
program
.command("version")
.description("Show Cline CLI version number")
.action(() => printInfo(`Cline CLI version: ${CLI_VERSION}`))
program
.command("update")
.description("Check for updates and install if available")
.option("-v, --verbose", "Show verbose output")
.action(() => checkForUpdates(CLI_VERSION))
// Dev command with subcommands
const devCommand = program.command("dev").description("Developer tools and utilities")
devCommand
.command("log")
.description("Open the log file")
.action(async () => {
const { openExternal } = await import("@/utils/env")
await openExternal(CLI_LOG_FILE)
})
/**
* Check if the user has authentication configured.
* Returns true if they have either:
* - Cline provider with stored auth data
* - OpenAI Codex provider with OAuth credentials
* - BYO provider with an API key configured
*/
async function isAuthConfigured(): Promise<boolean> {
const stateManager = StateManager.get()
const mode = stateManager.getGlobalSettingsKey("mode") as string
const providerKey = mode === "act" ? "actModeApiProvider" : "planModeApiProvider"
const currentProvider = (stateManager.getGlobalSettingsKey(providerKey) as string) || "cline"
if (currentProvider === "cline") {
// For Cline provider, check if we have stored auth data
const authData = await secretStorage.get("cline:clineAccountId")
return !!authData
}
if (currentProvider === "openai-codex") {
// For OpenAI Codex, check if OAuth credentials are stored
const isAuthenticated = await openAiCodexOAuthManager.isAuthenticated()
return isAuthenticated
}
// For BYO providers, check if the API key is configured
const keyField = ProviderToApiKeyMap[currentProvider as keyof typeof ProviderToApiKeyMap]
if (!keyField) {
return false
}
const fields = Array.isArray(keyField) ? keyField : [keyField]
for (const field of fields) {
const value = await secretStorage.get(field)
if (value) {
return true
}
}
return false
}
/**
* Show welcome prompt and wait for user input
* If auth is not configured, show auth flow first
*/
async function showWelcome(options: { verbose?: boolean; cwd?: string; config?: string; thinking?: boolean }) {
const ctx = await initializeCli({ ...options, enableAuth: true })
// Check if auth is configured
const hasAuth = await isAuthConfigured()
// Query cursor position BEFORE Ink mounts
const cursorPos = await queryCursorPos(process.stdin, process.stdout)
const terminalRows = process.stdout.rows ?? 24
const robotTopRow = calculateRobotTopRow(cursorPos, terminalRows)
let hadError = false
await runInkApp(
React.createElement(App, {
// Start with auth view if not configured, otherwise welcome
view: hasAuth ? "welcome" : "auth",
verbose: options.verbose,
controller: ctx.controller,
isRawModeSupported: checkRawModeSupport(),
robotTopRow,
onWelcomeExit: () => {
exit(0)
},
onError: () => {
hadError = true
},
}),
async () => {
await ctx.controller.stateManager.flushPendingState()
await ctx.controller.dispose()
await ErrorService.get().dispose()
exit(hadError ? 1 : 0)
},
)
}
// Interactive mode (default when no command given)
program
.argument("[prompt]", "Task prompt (starts task immediately)")
.option("-a, --act", "Run in act mode")
.option("-p, --plan", "Run in plan mode")
.option("-y, --yolo", "Enable yolo mode (auto-approve actions)")
.option("-m, --model <model>", "Model to use for the task")
.option("-v, --verbose", "Show verbose output")
.option("-c, --cwd <path>", "Working directory")
.option("--config <path>", "Configuration directory")
.option("--thinking", "Enable extended thinking (1024 token budget)")
.option("--json", "Output messages as JSON instead of styled text")
.option("--acp", "Run in ACP (Agent Client Protocol) mode for editor integration")
.action(async (prompt, options) => {
// Check for ACP mode first - this takes precedence over everything else
if (options.acp) {
await runAcpMode({
config: options.config,
cwd: options.cwd,
verbose: options.verbose,
})
return
}
// Always check for piped stdin content
const stdinInput = await readStdinIfPiped()
// If no prompt argument, check if input is piped via stdin
let effectivePrompt = prompt
if (stdinInput) {
if (effectivePrompt) {
// Prepend stdin content to the prompt
effectivePrompt = `${stdinInput}\n\n${effectivePrompt}`
} else {
effectivePrompt = stdinInput
}
telemetryService.captureHostEvent("piped", "detached")
// Debug: show that we received piped input
if (options.verbose) {
process.stderr.write(`[debug] Received ${stdinInput.length} bytes from stdin\n`)
}
}
if (effectivePrompt) {
// Pass stdinWasPiped flag so runTask knows to use plain text mode
await runTask(effectivePrompt, { ...options, stdinWasPiped: !!stdinInput })
} else {
// Show welcome prompt if no prompt given
await showWelcome(options)
}
})
// Parse and run
program.parse()
-57
View File
@@ -1,57 +0,0 @@
/**
* Query terminal cursor position before Ink mounts
* Must be called BEFORE render() to avoid escape sequence leaking into Ink's input handling
*/
export async function queryCursorPos(
stdin: NodeJS.ReadStream,
stdout: NodeJS.WriteStream,
{ timeoutMs = 75 } = {},
): Promise<{ row: number; col: number } | null> {
if (!stdin.isTTY || !stdout.isTTY || typeof (stdin as any).setRawMode !== "function") return null
const ttyIn = stdin as any as { isRaw?: boolean; setRawMode: (b: boolean) => void; on: any; off: any }
const wasRaw = !!ttyIn.isRaw
ttyIn.setRawMode(true)
stdin.resume()
return await new Promise((resolve) => {
let buf = ""
const onData = (chunk: Buffer) => {
buf += chunk.toString("utf8")
const m = buf.match(/\x1b\[(\d+);(\d+)R/)
if (!m) return
cleanup()
resolve({ row: Number(m[1]), col: Number(m[2]) })
}
const cleanup = () => {
clearTimeout(timer)
stdin.off("data", onData)
try {
ttyIn.setRawMode(wasRaw)
} catch {}
}
const timer = setTimeout(() => {
cleanup()
resolve(null)
}, timeoutMs)
stdin.on("data", onData)
stdout.write("\x1b[6n") // DSR: cursor position
})
}
/**
* Calculate where the robot will be rendered on screen
*/
export function calculateRobotTopRow(cursorPos: { row: number } | null, terminalRows: number): number {
const robotHeight = 12
const firstFrameHeight = robotHeight + 8 // robot + welcome text + margins + input + footer
const startRow = cursorPos?.row ?? 1
// If content doesn't fit below cursor, terminal scrolls
return Math.max(1, Math.min(startRow, terminalRows - firstFrameHeight + 1))
}
-13
View File
@@ -1,13 +0,0 @@
/**
* Input filtering utilities for CLI components
*/
/**
* Check if input contains mouse escape sequences from terminal mouse tracking.
* AsciiMotionCli enables mouse tracking which generates sequences like [<35;46;17M
* These should be filtered out of text input handlers.
*/
export function isMouseEscapeSequence(input: string): boolean {
// Mouse events look like: [<35;46;17M or contain escape characters
return input.includes("\x1b") || input.includes("[<") || /\d+;\d+[Mm]/.test(input)
}
-11
View File
@@ -1,11 +0,0 @@
import os from "node:os"
import path from "node:path"
const data = process.env.CLINE_DATA_DIR ?? path.join(os.homedir(), ".cline", "data")
const log = process.env.CLINE_LOG_DIR ?? path.join(data, "logs")
export const CLINE_CLI_DIR = {
data,
log,
}
-392
View File
@@ -1,392 +0,0 @@
import { Readable } from "node:stream"
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
import { readStdinIfPiped } from "./piped"
describe("readStdinIfPiped", () => {
let mockStdin: Readable & { isTTY?: boolean }
beforeEach(() => {
// Create a mock readable stream
mockStdin = new Readable({
read() {},
}) as Readable & { isTTY?: boolean }
// Mock process.stdin by stubbing its properties
vi.spyOn(process, "stdin", "get").mockReturnValue(mockStdin as any)
})
afterEach(() => {
vi.restoreAllMocks()
})
describe("TTY detection", () => {
it("should return null when stdin is a TTY (interactive terminal)", async () => {
mockStdin.isTTY = true
const result = await readStdinIfPiped()
expect(result).toBeNull()
})
it("should attempt to read when stdin is not a TTY (piped input)", async () => {
mockStdin.isTTY = false
// Simulate immediate end event (no data)
setImmediate(() => {
mockStdin.emit("end")
})
const result = await readStdinIfPiped()
expect(result).toBeNull()
})
})
describe("piped input scenarios", () => {
interface TestCase {
name: string
input: string | string[]
expected: string | null
description?: string
}
const testCases: TestCase[] = [
{
name: "single line input",
input: "echo hello",
expected: "echo hello",
description: "should read and return single line",
},
{
name: "multi-line input",
input: ["line 1", "line 2", "line 3"],
expected: "line 1\nline 2\nline 3",
description: "should read and join multiple lines",
},
{
name: "empty string",
input: "",
expected: null,
description: "should return null for empty input",
},
{
name: "whitespace only",
input: " \n \t \n ",
expected: null,
description: "should return null for whitespace-only input",
},
{
name: "leading and trailing whitespace",
input: " hello world \n",
expected: "hello world",
description: "should trim leading and trailing whitespace",
},
{
name: "large input",
input: "a".repeat(10000),
expected: "a".repeat(10000),
description: "should handle large input",
},
{
name: "special characters",
input: "!@#$%^&*(){}[]|\\:;\"'<>?,./",
expected: "!@#$%^&*(){}[]|\\:;\"'<>?,./",
description: "should preserve special characters",
},
{
name: "unicode characters",
input: "Hello 世界 🌍 مرحبا",
expected: "Hello 世界 🌍 مرحبا",
description: "should handle unicode characters correctly",
},
{
name: "JSON input",
input: '{"key": "value", "nested": {"data": 123}}',
expected: '{"key": "value", "nested": {"data": 123}}',
description: "should preserve JSON structure",
},
{
name: "code snippet",
input: ["function test() {", ' console.log("hello")', "}"],
expected: 'function test() {\n console.log("hello")\n}',
description: "should preserve code structure with indentation",
},
]
testCases.forEach(({ name, input, expected, description }) => {
it(`${name}${description ? ` - ${description}` : ""}`, async () => {
mockStdin.isTTY = false
// Simulate piped data
setImmediate(() => {
const data = Array.isArray(input) ? input.join("\n") : input
mockStdin.push(data)
mockStdin.push(null) // Signal end of stream
})
const result = await readStdinIfPiped()
expect(result).toBe(expected)
})
})
})
describe("chunked data", () => {
it("should accumulate data from multiple chunks", async () => {
mockStdin.isTTY = false
setImmediate(() => {
mockStdin.emit("data", "chunk1 ")
mockStdin.emit("data", "chunk2 ")
mockStdin.emit("data", "chunk3")
mockStdin.emit("end")
})
const result = await readStdinIfPiped()
expect(result).toBe("chunk1 chunk2 chunk3")
})
it("should handle rapid successive chunks", async () => {
mockStdin.isTTY = false
setImmediate(() => {
for (let i = 0; i < 100; i++) {
mockStdin.emit("data", `${i} `)
}
mockStdin.emit("end")
})
const result = await readStdinIfPiped()
expect(result).toContain("0 ")
expect(result).toContain("99")
})
})
describe("timeout behavior", () => {
it("should timeout after 100ms if no data received", async () => {
mockStdin.isTTY = false
// Don't emit any events - let it timeout
const startTime = Date.now()
const result = await readStdinIfPiped()
const elapsed = Date.now() - startTime
expect(result).toBeNull()
expect(elapsed).toBeGreaterThanOrEqual(95) // Allow small margin
expect(elapsed).toBeLessThan(150)
})
it("should return data received before timeout", async () => {
mockStdin.isTTY = false
setTimeout(() => {
mockStdin.emit("data", "quick data")
// Don't emit end - let it timeout
}, 50)
const result = await readStdinIfPiped()
expect(result).toBe("quick data")
})
it("should not timeout if end event is received", async () => {
mockStdin.isTTY = false
// Delay end event but emit it before timeout
setTimeout(() => {
mockStdin.emit("data", "delayed data")
mockStdin.emit("end")
}, 50)
const result = await readStdinIfPiped()
expect(result).toBe("delayed data")
})
})
describe("error handling", () => {
it("should return null on stdin error", async () => {
mockStdin.isTTY = false
setImmediate(() => {
mockStdin.emit("error", new Error("stdin read error"))
})
const result = await readStdinIfPiped()
expect(result).toBeNull()
})
it("should handle error after partial data received", async () => {
mockStdin.isTTY = false
setImmediate(() => {
mockStdin.emit("data", "partial data")
mockStdin.emit("error", new Error("read error"))
})
const result = await readStdinIfPiped()
expect(result).toBeNull()
})
it("should clean up listeners on error", async () => {
mockStdin.isTTY = false
setImmediate(() => {
mockStdin.emit("error", new Error("test error"))
})
await readStdinIfPiped()
// Note: Implementation uses removeAllListeners() without event names
// which should remove all listeners, but in practice there may be one remaining
// This is acceptable behavior for error handling
expect(mockStdin.listenerCount("data")).toBeLessThanOrEqual(1)
expect(mockStdin.listenerCount("end")).toBeLessThanOrEqual(1)
expect(mockStdin.listenerCount("error")).toBeLessThanOrEqual(1)
})
})
describe("listener cleanup", () => {
it("should remove all listeners on successful completion", async () => {
mockStdin.isTTY = false
setImmediate(() => {
mockStdin.emit("data", "test data")
mockStdin.emit("end")
})
await readStdinIfPiped()
// Note: Implementation doesn't explicitly clean up listeners on normal end,
// so some listeners may remain attached. This is acceptable for one-time use.
expect(mockStdin.listenerCount("data")).toBeLessThanOrEqual(1)
expect(mockStdin.listenerCount("end")).toBeLessThanOrEqual(1)
expect(mockStdin.listenerCount("error")).toBeLessThanOrEqual(1)
})
it("should remove all listeners on timeout", async () => {
mockStdin.isTTY = false
// Let it timeout
await readStdinIfPiped()
// Verify listeners are cleaned up
expect(mockStdin.listenerCount("data")).toBe(0)
expect(mockStdin.listenerCount("end")).toBe(0)
expect(mockStdin.listenerCount("error")).toBe(0)
})
it("should clear timeout when data ends normally", async () => {
mockStdin.isTTY = false
const clearTimeoutSpy = vi.spyOn(global, "clearTimeout")
setImmediate(() => {
mockStdin.emit("data", "test")
mockStdin.emit("end")
})
await readStdinIfPiped()
expect(clearTimeoutSpy).toHaveBeenCalled()
})
it("should clear timeout when error occurs", async () => {
mockStdin.isTTY = false
const clearTimeoutSpy = vi.spyOn(global, "clearTimeout")
setImmediate(() => {
mockStdin.emit("error", new Error("test"))
})
await readStdinIfPiped()
expect(clearTimeoutSpy).toHaveBeenCalled()
})
})
describe("encoding", () => {
it("should handle UTF-8 encoded data", async () => {
mockStdin.isTTY = false
setImmediate(() => {
// The function sets utf8 encoding
mockStdin.setEncoding("utf8")
mockStdin.emit("data", "UTF-8: café ☕")
mockStdin.emit("end")
})
const result = await readStdinIfPiped()
expect(result).toBe("UTF-8: café ☕")
})
})
describe("stdin resume", () => {
it("should call resume on stdin when not TTY", async () => {
mockStdin.isTTY = false
const resumeSpy = vi.spyOn(mockStdin, "resume")
setImmediate(() => {
mockStdin.emit("end")
})
await readStdinIfPiped()
expect(resumeSpy).toHaveBeenCalled()
})
it("should not call resume when TTY", async () => {
mockStdin.isTTY = true
const resumeSpy = vi.spyOn(mockStdin, "resume")
const result = await readStdinIfPiped()
expect(result).toBeNull()
expect(resumeSpy).not.toHaveBeenCalled()
})
})
describe("real-world use cases", () => {
interface UseCaseTest {
name: string
input: string
expected: string | null
}
const useCases: UseCaseTest[] = [
{
name: "git diff output",
input: "diff --git a/file.ts b/file.ts\nindex 123..456\n--- a/file.ts\n+++ b/file.ts",
expected: "diff --git a/file.ts b/file.ts\nindex 123..456\n--- a/file.ts\n+++ b/file.ts",
},
{
name: "curl JSON response",
input: '{"status": "ok", "data": [1, 2, 3]}',
expected: '{"status": "ok", "data": [1, 2, 3]}',
},
{
name: "cat file contents",
input: "export function test() {\n return true\n}",
expected: "export function test() {\n return true\n}",
},
{
name: "echo command with newline",
input: "Hello World\n",
expected: "Hello World",
},
{
name: "command output with ANSI codes",
input: "\x1b[32mSUCCESS\x1b[0m",
expected: "\x1b[32mSUCCESS\x1b[0m",
},
]
useCases.forEach(({ name, input, expected }) => {
it(`should handle ${name}`, async () => {
mockStdin.isTTY = false
setImmediate(() => {
mockStdin.push(input)
mockStdin.push(null)
})
const result = await readStdinIfPiped()
expect(result).toBe(expected)
})
})
})
})
-47
View File
@@ -1,47 +0,0 @@
import * as fs from "node:fs"
/**
* Read piped input from stdin (non-blocking)
*/
export async function readStdinIfPiped(): Promise<string | null> {
// Check if stdin is a TTY (interactive) or piped
if (process.stdin.isTTY) {
return null
}
try {
// Use synchronous read for reliability with piped input
// fd 0 is stdin
const data = fs.readFileSync(0, "utf8")
return data.trim() || null
} catch {
// Fallback to async approach if sync read fails
return new Promise((resolve) => {
let data = ""
process.stdin.setEncoding("utf8")
// Set a timeout in case stdin is not actually providing data
const timeout = setTimeout(() => {
process.stdin.removeAllListeners()
resolve(data.trim() || null)
}, 1000)
process.stdin.on("data", (chunk) => {
data += chunk
})
process.stdin.on("end", () => {
clearTimeout(timeout)
resolve(data.trim() || null)
})
process.stdin.on("error", () => {
clearTimeout(timeout)
resolve(null)
})
// Resume stdin in case it's paused
process.stdin.resume()
})
}
}
-225
View File
@@ -1,225 +0,0 @@
/**
* Plain-text task runner for non-TTY environments (piped output, file redirection)
* Outputs clean text without ANSI codes or Ink rendering
*/
/* eslint-disable no-console */
// Console output is intentional here for plain text mode
import { registerPartialMessageCallback } from "@core/controller/ui/subscribeToPartialMessage"
import type { ClineMessage } from "@shared/ExtensionMessage"
import type { Controller } from "@/core/controller"
import { setTerminalTitle } from "./display"
export interface PlainTextTaskOptions {
controller: Controller
prompt: string
imageDataUrls?: string[]
verbose?: boolean
jsonOutput?: boolean
}
/**
* Run a task with plain text output (no Ink, no ANSI codes)
* Returns true if task completed successfully, false if error
*/
export async function runPlainTextTask(options: PlainTextTaskOptions): Promise<boolean> {
const { controller, prompt, imageDataUrls, verbose, jsonOutput } = options
// Track completion state
let isComplete = false
let hasError = false
const processedMessages = new Map<number, number>() // index -> last output text length
let lastStreamingMessageIndex = -1 // track open streaming line that needs closing
// Subscribe to state updates
const originalPostState = controller.postStateToWebview.bind(controller)
const handleStateUpdate = async () => {
try {
const state = await controller.getStateToPostToWebview()
const messages = state.clineMessages || []
// Process new messages
for (let i = 0; i < messages.length; i++) {
const message = messages[i]
const currentTextLength = message.text?.length ?? 0
const lastOutputLength = processedMessages.get(i) ?? 0
// Skip if no new content to output
if (currentTextLength <= lastOutputLength) continue
// Close previous streaming line if we're moving to a different message
if (lastStreamingMessageIndex >= 0 && lastStreamingMessageIndex !== i && !jsonOutput) {
process.stdout.write("\n")
lastStreamingMessageIndex = -1
}
processedMessages.set(i, currentTextLength)
// Output the message
if (jsonOutput) {
process.stdout.write(JSON.stringify(message) + "\n")
} else {
const isStreaming = outputMessageAsText(message, verbose || false, lastOutputLength)
// Track streaming state for text messages
if (isStreaming) {
lastStreamingMessageIndex = i
} else {
lastStreamingMessageIndex = -1
}
}
// Check for completion
if (
message.say === "completion_result" ||
message.ask === "completion_result" ||
message.say === "error" ||
message.ask === "api_req_failed"
) {
isComplete = true
if (message.say === "error" || message.ask === "api_req_failed") {
hasError = true
}
}
}
// Close streaming line on completion
if (isComplete && lastStreamingMessageIndex >= 0 && !jsonOutput) {
process.stdout.write("\n")
lastStreamingMessageIndex = -1
}
} catch (error) {
if (jsonOutput) {
process.stdout.write(
JSON.stringify({ type: "error", message: error instanceof Error ? error.message : String(error) }) + "\n",
)
} else {
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}` + "\n")
}
hasError = true
isComplete = true
}
}
// Override postStateToWebview to capture state updates
controller.postStateToWebview = async () => {
await originalPostState()
await handleStateUpdate()
}
// Subscribe to partial message updates (for streaming)
const unsubscribePartial = registerPartialMessageCallback(() => {
// Partial updates are handled via postStateToWebview
})
try {
// Get initial state
await handleStateUpdate()
// Set terminal title to the task prompt
setTerminalTitle(prompt)
// Start the task
await controller.initTask(prompt, imageDataUrls)
// Wait for completion with timeout
const timeout = 10 * 60 * 1000 // 10 minutes
const startTime = Date.now()
while (!isComplete && Date.now() - startTime < timeout) {
await new Promise((resolve) => setTimeout(resolve, 100))
}
if (!isComplete) {
// Close any open streaming line before error message
if (lastStreamingMessageIndex >= 0 && !jsonOutput) {
process.stdout.write("\n")
lastStreamingMessageIndex = -1
}
if (jsonOutput) {
process.stdout.write(JSON.stringify({ type: "error", message: "Task timeout" }) + "\n")
} else {
process.stderr.write("Error: Task timeout" + "\n")
}
hasError = true
}
} catch (error) {
if (jsonOutput) {
process.stdout.write(
JSON.stringify({ type: "error", message: error instanceof Error ? error.message : String(error) }) + "\n",
)
} else {
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}` + "\n")
}
hasError = true
} finally {
// Close any open streaming line
if (lastStreamingMessageIndex >= 0 && !jsonOutput) {
process.stdout.write("\n")
}
// Restore original postStateToWebview
controller.postStateToWebview = originalPostState
unsubscribePartial()
}
return !hasError
}
/**
* Format a Cline message as plain text
* @param previousLength - Length of text already output for this message (for streaming)
* @returns true if this is a streaming message (caller should track for newline), false otherwise
*/
function outputMessageAsText(message: ClineMessage, verbose: boolean, previousLength: number = 0): boolean {
const timestamp = new Date(message.ts || Date.now()).toLocaleTimeString()
const fullText = message.text ?? ""
if (!fullText) {
// Skip partial messages without text
return false
}
// For streaming text continuations, output only new content
if (previousLength > 0 && message.type === "say" && message.say === "text") {
process.stdout.write(fullText.slice(previousLength))
return true // Still streaming
}
if (message.type === "say") {
if (message.say === "task") {
process.stdout.write(`[${timestamp}] Task: ${fullText}\n`)
} else if (message.say === "text") {
// First output of text message - write prefix but no newline (streaming)
process.stdout.write(`[${timestamp}] ${fullText}`)
return true // Streaming - newline will be added when stream ends
} else if (message.say === "completion_result" && fullText) {
process.stdout.write(`[${timestamp}] Completed: ${fullText}\n`)
} else if (message.say === "error") {
process.stderr.write(`[${timestamp}] Error: ${fullText}\n`)
} else if (message.say === "api_req_started") {
if (verbose) {
process.stdout.write(`[${timestamp}] API request started\n`)
}
} else if (message.say === "api_req_finished") {
if (verbose) {
process.stdout.write(`[${timestamp}] API request finished\n`)
}
} else if (verbose) {
process.stdout.write(`[${timestamp}] ${message.say}: ${fullText}\n`)
}
} else if (message.type === "ask") {
if (message.ask === "completion_result") {
process.stdout.write(`[${timestamp}] Task completed\n`)
} else if (message.ask === "api_req_failed") {
process.stderr.write(`[${timestamp}] API request failed: ${fullText}\n`)
} else if (message.ask === "tool" || message.ask === "command" || message.ask === "browser_action_launch") {
// These require approval - in non-interactive mode, warn the user
process.stderr.write(`[${timestamp}] Waiting for approval (use --yolo for auto-approve): ${message.ask}\n`)
} else if (verbose) {
process.stdout.write(`[${timestamp}] Question: ${fullText}\n`)
}
}
return false
}
-63
View File
@@ -1,63 +0,0 @@
/**
* Shared utility for applying provider configuration
* Used by both AuthView (onboarding) and SettingsPanelContent (settings)
*/
import { ProviderToApiKeyMap } from "@shared/storage"
import { buildApiHandler } from "@/core/api"
import type { Controller } from "@/core/controller"
import { StateManager } from "@/core/storage/StateManager"
import { getDefaultModelId } from "../components/ModelPicker"
export interface ApplyProviderConfigOptions {
providerId: string
apiKey?: string
modelId?: string // Override default model
baseUrl?: string // For OpenAI-compatible providers
controller?: Controller
}
/**
* Apply provider configuration to state and rebuild API handler if needed
*/
export async function applyProviderConfig(options: ApplyProviderConfigOptions): Promise<void> {
const { providerId, apiKey, modelId, baseUrl, controller } = options
const stateManager = StateManager.get()
const config: Record<string, string> = {
actModeApiProvider: providerId,
planModeApiProvider: providerId,
}
// Add model ID (use provided or fall back to default)
const finalModelId = modelId || getDefaultModelId(providerId)
if (finalModelId) {
config.actModeApiModelId = finalModelId
config.planModeApiModelId = finalModelId
}
// Add API key if provided (maps to provider-specific field like anthropicApiKey, openAiApiKey, etc.)
if (apiKey) {
const keyField = ProviderToApiKeyMap[providerId as keyof typeof ProviderToApiKeyMap]
if (keyField) {
const fields = Array.isArray(keyField) ? keyField : [keyField]
config[fields[0]] = apiKey
}
}
// Add base URL if provided (for OpenAI-compatible providers)
if (baseUrl) {
config.openAiBaseUrl = baseUrl
}
// Save via StateManager
stateManager.setApiConfiguration(config)
await stateManager.flushPendingState()
// Rebuild API handler on active task if one exists
if (controller?.task) {
const currentMode = stateManager.getGlobalSettingsKey("mode")
const apiConfig = stateManager.getApiConfiguration()
controller.task.api = buildApiHandler({ ...apiConfig, ulid: controller.task.ulid }, currentMode)
}
}
-106
View File
@@ -1,106 +0,0 @@
import { spawn } from "node:child_process"
import { exit } from "node:process"
import { fetch } from "@/shared/net"
import { printInfo, printWarning } from "./display"
/**
* Check for updates and install if available
*/
export async function checkForUpdates(currentVersion: string, options?: { verbose?: boolean }) {
printInfo("Checking for updates...")
try {
// Fetch latest version from npm registry
const response = await fetch("https://registry.npmjs.org/cline/latest")
if (!response.ok && response.statusText !== "OK") {
printWarning(`Failed to check for updates: ${response.statusText}`)
exit(1)
}
const data = (await response.json()) as { version: string }
const latestVersion = data.version
if (options?.verbose) {
printInfo(`Current version: ${currentVersion}`)
printInfo(`Latest version: ${latestVersion}`)
}
// Compare versions
if (latestVersion === currentVersion) {
printInfo(`You are already on the latest version (${currentVersion})`)
exit(0)
}
// Check if current is newer (dev version)
if (compareVersions(currentVersion, latestVersion) > 0) {
printInfo(`You are already on a newer version ${currentVersion} (latest: ${latestVersion})`)
exit(0)
}
printInfo(`New version available: ${latestVersion} (current: ${currentVersion})`)
// Ask user to confirm update
const userConfirmed = new Promise<boolean>((resolve) => {
process.stdout.write("Do you want to update now? (y/N): ")
process.stdin.setEncoding("utf-8")
process.stdin.once("data", (dataBuff) => {
const input = dataBuff.toString().trim().toLowerCase()
resolve(input === "y" || input === "yes")
})
})
if (!(await userConfirmed)) {
exit(0)
}
printInfo("Installing update...")
// Run npm install -g cline@latest
const npmProcess = spawn("npm", ["install", "-g", "cline@latest"], {
stdio: "inherit",
shell: true,
// Ensures the process uses the same environment
env: process.env,
detached: false,
windowsHide: true,
})
npmProcess.on("close", (code) => {
if (code === 0) {
printInfo(`Successfully updated to version ${latestVersion}`)
exit(0)
} else {
printWarning("Update failed. Please try running: npm install -g cline@latest")
exit(1)
}
})
npmProcess.on("error", (err) => {
printWarning(`Failed to run npm install: ${err.message}`)
printInfo("Please try running manually: npm install -g cline@latest")
exit(1)
})
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
printWarning(`Error checking for updates: ${message}`)
exit(1)
}
}
/**
* Compare two semantic version strings
* Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal
*/
function compareVersions(v1: string, v2: string): number {
const parts1 = v1.split(".").map(Number)
const parts2 = v2.split(".").map(Number)
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
const part1 = parts1[i] || 0
const part2 = parts2[i] || 0
if (part1 > part2) return 1
if (part1 < part2) return -1
}
return 0
}
-194
View File
@@ -1,194 +0,0 @@
/**
* VSCode context stub for CLI mode
* Provides mock implementations of VSCode extension context
*/
import { mkdirSync } from "node:fs"
import os from "os"
import path from "path"
import { ExtensionRegistryInfo } from "@/registry"
import { ClineExtensionContext } from "@/shared/cline"
import { ClineFileStorage } from "@/shared/storage"
import { EnvironmentVariableCollection, ExtensionKind, ExtensionMode, readJson, URI } from "./vscode-shim"
const SETTINGS_SUBFOLDER = "data"
/**
* CLI-specific state overrides.
* These values are always returned regardless of what's stored,
* and writes to these keys are silently ignored.
*/
const CLI_STATE_OVERRIDES: Record<string, any> = {
// CLI always uses background execution, not VSCode terminal
vscodeTerminalExecutionMode: "backgroundExec",
backgroundEditEnabled: true,
multiRootEnabled: false,
enableCheckpointsSetting: false,
browserSettings: {
disableToolUse: true,
},
}
/**
* File-based Memento store with optional key overrides.
* Implements VSCode's Memento interface using SyncJsonFileStorage.
*/
class MementoStore extends ClineFileStorage {
private overrides: Record<string, any>
constructor(filePath: string, overrides: Record<string, any> = {}) {
super(filePath, "MementoStore")
this.overrides = overrides
}
// VSCode Memento interface - override base class get() with overload support
override get<T>(key: string): T | undefined
override get<T>(key: string, defaultValue: T): T
override get<T>(key: string, defaultValue?: T): T | undefined {
if (key in this.overrides) {
return this.overrides[key] as T
}
const value = super.get<T>(key)
return value !== undefined ? value : defaultValue
}
override async update(key: string, value: any): Promise<void> {
if (key in this.overrides) {
return
}
this.set(key, value)
}
setKeysForSync(_keys: readonly string[]): void {
// No-op for CLI
}
}
/**
* File-based secret storage implementing VSCode's SecretStorage interface.
* Uses sync storage internally but exposes async API for VSCode compatibility.
*/
class SecretStore {
private storage: ClineFileStorage<string>
private onDidChangeEmitter = {
event: () => ({ dispose: () => {} }),
fire: (_e: any) => {},
dispose: () => {},
}
onDidChange = this.onDidChangeEmitter.event
constructor(filePath: string) {
this.storage = new ClineFileStorage<string>(filePath, "SecretStore")
}
get(key: string): Promise<string | undefined> {
return Promise.resolve(this.storage.get(key))
}
store(key: string, value: string): Promise<void> {
this.storage.set(key, value)
return Promise.resolve()
}
delete(key: string): Promise<void> {
this.storage.delete(key)
return Promise.resolve()
}
}
export interface CliContextConfig {
clineDir?: string
/** The workspace directory being worked in (for hashing into storage path) */
workspaceDir?: string
}
/**
* Create a short hash of a string for use in directory names
*/
function hashString(str: string): string {
let hash = 0
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i)
hash = (hash << 5) - hash + char
hash = hash & hash // Convert to 32bit integer
}
return Math.abs(hash).toString(16).substring(0, 8)
}
export interface CliContextResult {
extensionContext: ClineExtensionContext
DATA_DIR: string
EXTENSION_DIR: string
WORKSPACE_STORAGE_DIR: string
}
/**
* Initialize the VSCode-like context for CLI mode
*/
export function initializeCliContext(config: CliContextConfig = {}): CliContextResult {
const CLINE_DIR = config.clineDir || process.env.CLINE_DIR || path.join(os.homedir(), ".cline")
const DATA_DIR = path.join(CLINE_DIR, SETTINGS_SUBFOLDER)
// Workspace storage should always be under ~/.cline/data/workspaces/<hash>/
// where hash is derived from the workspace path to keep workspaces isolated
const workspacePath = config.workspaceDir || process.cwd()
const workspaceHash = hashString(workspacePath)
const WORKSPACE_STORAGE_DIR = process.env.WORKSPACE_STORAGE_DIR || path.join(DATA_DIR, "workspaces", workspaceHash)
// Ensure directories exist
mkdirSync(DATA_DIR, { recursive: true })
mkdirSync(WORKSPACE_STORAGE_DIR, { recursive: true })
// For CLI, extension dir is the root of the project (parent of cli-ts)
const EXTENSION_DIR = path.resolve(__dirname, "..", "..")
const EXTENSION_MODE = process.env.IS_DEV === "true" ? ExtensionMode.Development : ExtensionMode.Production
const extension: ClineExtensionContext["extension"] = {
id: ExtensionRegistryInfo.id,
isActive: true,
extensionPath: EXTENSION_DIR,
extensionUri: URI.file(EXTENSION_DIR),
packageJSON: readJson(path.join(EXTENSION_DIR, "package.json")),
exports: undefined,
activate: async () => {},
extensionKind: ExtensionKind.UI,
}
const extensionContext: ClineExtensionContext = {
extension: extension,
extensionMode: EXTENSION_MODE,
// Set up KV stores (globalState has CLI-specific overrides)
globalState: new MementoStore(path.join(DATA_DIR, "globalState.json"), CLI_STATE_OVERRIDES),
secrets: new SecretStore(path.join(DATA_DIR, "secrets.json")),
// Set up URIs
storageUri: URI.file(WORKSPACE_STORAGE_DIR),
storagePath: WORKSPACE_STORAGE_DIR,
globalStorageUri: URI.file(DATA_DIR),
globalStoragePath: DATA_DIR,
// Logs
logUri: URI.file(DATA_DIR),
logPath: DATA_DIR,
extensionUri: URI.file(EXTENSION_DIR),
extensionPath: EXTENSION_DIR,
asAbsolutePath: (relPath: string) => path.join(EXTENSION_DIR, relPath),
subscriptions: [],
environmentVariableCollection: new EnvironmentVariableCollection() as any,
// Workspace state
workspaceState: new MementoStore(path.join(WORKSPACE_STORAGE_DIR, "workspaceState.json")),
}
return {
extensionContext,
DATA_DIR,
EXTENSION_DIR,
WORKSPACE_STORAGE_DIR,
}
}
-2
View File
@@ -1,2 +0,0 @@
cline-core-debug.log
bin/*
+256
View File
@@ -0,0 +1,256 @@
# cline
## [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
## [2.4.2]
### Added
- Gemini-3.1 Pro Preview
### Patch Changes
- VSCode uses shared files for global, workspace and secret state.
## [2.4.1]
### Fixed
- Fix infinite retry loop when write_to_file fails with missing content parameter. Provides progressive guidance to the model, escalating from suggestions to hard stops, with context window awareness to break the loop.
## [2.4.0]
### Added
- Adding Anthropic Sonnet 4.6
- Allows users to enter custom aws region when selecting bedrock as a provider in CLI
- Keep reasoning rows visible when low-stakes tool groups start immediately after reasoning.
- Restore reasoning trace visibility in chat and improve the thinking row UX so streamed reasoning is visible, then collapsible after completion.
### Fixed
- Banners now display immediately when opening the extension instead of requiring user interaction first
- Resolved 17 security vulnerabilities including high-severity DoS issues in dependencies (body-parser, axios, qs, tar, and others)
## [2.2.2]
- Allows users to enter custom aws region when selecting bedrock as a provider
- Prevent Parent Container Scrolling In Dropdowns
## [2.2.1]
- Added Minimax 2.5 Free Promo
- Fixed Response chaining for OpenAI's Responses API
## [2.2.0]
### Added
- Subagent: replace legacy subagents with the native `use_subagents` tool
- Bundle `endpoints.json` support so packaged distributions can ship required endpoints out-of-the-box
- Amazon Bedrock: support parallel tool calling
- New "double-check completion" experimental feature to verify work before marking tasks complete
- CLI: new task controls/flags including custom `--thinking` token budget and `--max-consecutive-mistakes` for yolo runs
- Remote config: new UI/options (including connection/test buttons) and support for syncing deletion of remotely configured MCP servers
- Vertex / Claude Code: add 1M context model options for Claude Opus 4.6
- ZAI/GLM: add GLM-5
### Fixed
- CLI: handle stdin redirection correctly in CI/headless environments
- CLI: preserve OAuth callback paths during auth redirects
- VS Code Web: generate auth callback URLs via `vscode.env.asExternalUri` (OAuth callback reliability)
- Terminal: surface command exit codes in results and improve long-running `execute_command` timeout behavior
- UI: add loading indicator and fix `api_req_started` rendering
- Task streaming: prevent duplicate streamed text rows after completion
- API: preserve selected Vercel model when model metadata is missing
- Telemetry: route PostHog networking through proxy-aware shared fetch and ensure telemetry flushes on shutdown
- CI: increase Windows E2E test timeout to reduce flakiness
### Changed
- Settings/model UX: move "reasoning effort" into model configuration and expose it in settings
- CLI provider selection: limit provider list to those remotely configured
- UI: consolidate ViewHeader component/styling across views
- Tools: add auto-approval support for `attempt_completion` commands
- Remotely configured MCP server schema now supports custom headers
## [2.1.0]
### Minor Changes
- 42ce100: Add Generate API Key on Hicap Provider selection
### Patch Changes
- 195294f: Add support for bundled endpoints.json in enterprise distributions. Extensions can now include a pre-configured endpoints.json file that automatically switches Cline to self-hosted mode. Includes packaging scripts for VSIX, NPM, and JetBrains plugins.
- a1f2601: Replace the LiteLLM model list with a selector
- 739d75a: Add Claude Code provider support for Claude Opus 4.6 and Sonnet 4.5 1M variants via both full model names and aliases (`opus[1m]`, `sonnet[1m]`), and align the `opus` alias with Opus 4.6.
- 8440380: Add GitHub Actions workflow to build CLI from any commit for testing
- b1a8db2: fix(cli): prevent hang when spawned without TTY
- 7c87017: Add Claude Opus 4.6 model support
- d116ac5: Supports rendering markdown table in chat view.
- 6d8fb85: Fix CLI crashing in CI environments and with stdin redirection (e.g., `cline "prompt" < /dev/null`). Now checks both stdin and stdout TTY status before using Ink, and only errors on empty stdin when no prompt is provided.
- 70a9904: Fix JetBrains sign-in regression by adding fallback for openExternal RPC
- f440f3a: fix: use vscode.env.openExternal for auth in remote environments
Fixes OAuth authentication in VS Code Server and remote environments by routing browser URL opening through VS Code's native openExternal API instead of the npm 'open' package.
- 70a9904: fix: use vscode.env.asExternalUri for auth callback URLs only in VS Code Web
Fixes OAuth callback redirect in VS Code Web (`code serve-web`, Codespaces) by using `vscode.env.asExternalUri()` to resolve the callback URI. This is gated behind a `vscode.env.uiKind === UIKind.Web` check so regular desktop VS Code continues to use the `vscode://` URI directly. The `getCallbackUrl` API now accepts a `path` parameter so the full callback URI (including route) is resolved correctly, and callers pass their path directly instead of appending after.
- 5308ded: Updating script documentation and removing unnecessary continue on error
- b514f18: Prevent duplicate streamed text rows when a partial text update arrives after the same text was already finalized.
- 26391c9: Fix Bedrock model id
- d19a877: Unify ViewHeader Styles Across All Views
- 5dcaa8c: Add Vertex Claude Opus 4.6 1M model option and global endpoint support, and pass the 1M beta header for Vertex Claude requests.
+105 -94
View File
@@ -1,6 +1,6 @@
# Cline CLI (TypeScript)
# Cline CLI
A TypeScript CLI implementation of Cline that reuses the core TypeScript codebase. This allows you to run Cline tasks directly from the terminal while sharing the same underlying functionality as the VS Code extension.
The official CLI for Cline. Run Cline tasks directly from the terminal with the same underlying functionality as the VS Code extension.
## Features
@@ -27,23 +27,8 @@ npm run install:all
# Ensure protos are generated
npm run protos
# Build the CLI
npm run build:cli
```
Or install the CLI globally:
```bash
# Install all dependencies first
npm run install:all
# Ensure protos are generated
npm run protos
# Build and link the CLI globally
cd cli-ts
npm install
npm run link
npm run cli:link
```
## Usage
@@ -203,54 +188,51 @@ These options are available for the default command (running a task directly):
## Development
For active development, at the root of this repo:
1. **Initial setup:**
```bash
npm run install:all
npm run protos
```
2. **Make changes to cli-ts:**
```bash
npm run cli:dev
# or
cd cli-ts && npm run dev
```
3. **Test your changes:**
```bash
cline [your-command] # In a new Terminal
```
4. **When done:**
```bash
npm run cli:unlink
```
### Build
### Quick Start
```bash
cd cli-ts
# 1. Install all dependencies (root, webview-ui, cli)
npm run install:all
# Development build with source maps
npm run build
# 2. Build and link globally so you can run `cline` from anywhere
npm run cli:link
# Production build (minified)
npm run build:production
# 3. Test it
cline --help
```
### Watch Mode
### Scripts
Run these from the repository root:
| Script | Description |
|--------|-------------|
| `npm run install:all` | Install deps for root, webview-ui, and cli |
| `npm run cli:build` | Generate protos and build CLI |
| `npm run cli:build:production` | Production build (minified) |
| `npm run cli:link` | Build and `npm link` so you can run `cline` from anywhere |
| `npm run cli:unlink` | Remove the global `cline` symlink |
| `npm run cli:dev` | Link + watch mode for development |
| `npm run cli:watch` | Watch mode only (no initial build) |
| `npm run cli:test` | Run CLI tests |
### Development Workflow
1. Run `npm run cli:dev` - this links the CLI globally and starts watch mode
2. Make changes to files in `cli/src/`
3. The build automatically rebuilds on save
4. Test your changes by running `cline` in another terminal
5. When done, run `npm run cli:unlink` to clean up
### Proto Generation
The CLI uses proto-generated types for message passing (same as the VS Code extension). If you modify any `.proto` files, run:
```bash
npm run watch
npm run protos
```
### Type Checking
```bash
npm run typecheck
```
This generates TypeScript types in `src/generated/` that both the CLI and extension use.
## Publish
@@ -268,7 +250,7 @@ npm run update-brew-formula
```bash
# Create a local tap
brew tap-new cline/local
cp ./cli-ts/cline.rb "$(brew --repository)/Library/Taps/cline/homebrew-local/Formula/cline.rb"
cp ./cli/cline.rb "$(brew --repository)/Library/Taps/cline/homebrew-local/Formula/cline.rb"
# Build from Source
brew install --build-from-source cline/local/cline
@@ -289,19 +271,50 @@ git push
## Architecture
The CLI reuses the core Cline TypeScript codebase:
### How It Works
- **Controller** (`@core/controller`): Manages task lifecycle and state
- **Task** (`@core/task`): Executes Cline tasks using the AI API
- **StateManager** (`@core/storage`): Handles persistent state storage
The CLI directly imports and reuses the core Cline TypeScript codebase (the same code that powers the VS Code extension). This means feature parity is easy to maintain - when core gets updated, the CLI automatically benefits.
CLI-specific implementations:
```
┌─────────────────────────────────────────────────────────┐
│ CLI (cli/) │
│ - React Ink terminal UI │
│ - Command parsing (commander) │
│ - Terminal-specific adapters │
└─────────────────────────────────────────────────────────┘
│ direct imports
┌─────────────────────────────────────────────────────────┐
│ Core (src/core/) │
│ - Controller: task lifecycle, state management │
│ - Task: AI API calls, tool execution │
│ - StateManager: persistent storage │
│ - Proto types: message definitions │
└─────────────────────────────────────────────────────────┘
```
- `cli-host-bridge.ts`: CLI implementations of host bridge services
- `cli-webview-provider.ts`: WebviewProvider that outputs to terminal
- `cli-comment-review.ts`: Comment review controller for terminal
- `vscode-context.ts`: Mock VSCode extension context
- `display.ts`: Terminal output formatting utilities
Unlike a client-server architecture, the CLI runs everything in a single Node.js process. The "host bridge" pattern provides terminal-appropriate implementations for things the VS Code extension would handle differently (clipboard, file dialogs, etc.).
### Key Files
| File | Purpose |
|------|---------|
| `src/index.ts` | Entry point, command definitions |
| `src/components/App.tsx` | Main React Ink app |
| `src/components/ChatView.tsx` | Task conversation UI |
| `src/controllers/CliWebviewProvider.ts` | Bridges core messages to terminal output |
| `src/vscode-context.ts` | Mock VS Code extension context for core compatibility |
| `src/vscode-shim.ts` | Shims for VS Code APIs that core depends on |
| `src/constants/colors.ts` | Terminal color definitions |
### React Ink
The CLI uses [React Ink](https://github.com/vadimdemedes/ink) for its terminal UI. This lets us build the interface with React components that render to the terminal. Key patterns:
- Components in `src/components/` render terminal UI
- Hooks in `src/hooks/` manage terminal-specific state (size, scrolling)
- The `useStateSubscriber` hook subscribes to core state changes
## Configuration
@@ -314,41 +327,39 @@ The CLI stores its data in `~/.cline/data/` by default:
Override with the `--config` option or `CLINE_DIR` environment variable.
## Comparison with Go CLI
This TypeScript CLI differs from the Go CLI (`cli/` directory):
| Feature | Go CLI | TypeScript CLI |
|---------|--------|----------------|
| Language | Go | TypeScript |
| Core sharing | Uses gRPC to communicate | Direct imports |
| Startup time | Fast | Moderate |
| Dependencies | Standalone binary | Requires Node.js |
| Best for | Production deployment | Development, debugging |
Choose the TypeScript CLI when you need to debug or modify the core Cline logic. Choose the Go CLI for production deployment with faster startup.
## Troubleshooting
### Build Errors
If you encounter build errors, ensure you've:
1. Run `npm install` in the repository root
2. Run `npm run protos` to generate proto files
3. Have all peer dependencies installed
If you encounter build errors:
### Missing Dependencies
The CLI imports from the parent project. If you see import errors:
```bash
cd .. # Go to repository root
npm install
# Make sure all deps are installed
npm run install:all
# Regenerate proto types
npm run protos
# Then rebuild
npm run cli:build
```
### Permission Denied
### "command not found: cline"
The CLI isn't linked globally. Run:
Make the CLI executable:
```bash
chmod +x dist/cli.js
```
npm run cli:link
```
### Changes Not Reflected
If your code changes aren't showing up:
1. Make sure watch mode is running (`npm run cli:dev`)
2. Check for TypeScript errors in the watch output
3. Try unlinking and relinking: `npm run cli:unlink && npm run cli:link`
### Import Errors from Core
The CLI imports from `@core/`, `@shared/`, etc. These paths are defined in the root `tsconfig.json`. If you see import errors, make sure you're building from the repo root, not from inside `cli/`.
+58 -50
View File
@@ -1,73 +1,81 @@
# Cline CLI
# Cline
```
/_____/\ /_/\ /_______/\/__/\ /__/\ /_____/\
\:::__\/ \:\ \ \__.::._\/\::\_\\ \ \\::::_\/_
\:\ \ __\:\ \ \::\ \ \:. `-\ \ \\:\/___/\
\:\ \/_/\\:\ \____ _\::\ \__\:. _ \ \\::___\/_
\:\_\ \ \\:\/___/\/__\::\__/\\. \`-\ \ \\:\____/\
\_____\/ \_____\/\________\/ \__\/ \__\/ \_____\/
```
<p align="center">
<img src="https://github.com/user-attachments/assets/7123f9d1-afeb-48d5-93fa-e750dec0ebba" width="70%" />
</p>
Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more.
<div align="center">
<table>
<tbody>
<td align="center">
<a href="https://www.npmjs.com/package/cline" target="_blank"><strong>NPM</strong></a>
</td>
<td align="center">
<a href="https://discord.gg/cline" target="_blank"><strong>Discord</strong></a>
</td>
<td align="center">
<a href="https://www.reddit.com/r/cline/" target="_blank"><strong>r/cline</strong></a>
</td>
<td align="center">
<a href="https://github.com/cline/cline/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop" target="_blank"><strong>Feature Requests</strong></a>
</td>
<td align="center">
<a href="https://docs.cline.bot/getting-started/for-new-coders" target="_blank"><strong>Getting Started</strong></a>
</td>
</tbody>
</table>
</div>
## Installation
Meet Cline, an AI assistant that lives in your terminal.
Install Cline globally using npm:
Cline can handle complex software development tasks step-by-step. With tools that let him create & edit files, explore large projects, use the browser, and execute terminal commands (after you grant permission), he can assist you in ways that go beyond code completion or tech support.
```bash
npm install -g cline
```
npm i -g cline
## Usage
```bash
# cd into your project and run:
cline
```
This will start the Cline CLI interface where you can interact with the autonomous coding agent.
> Move your mouse around under the Cline icon for a surprise!
## Features
---
- **Autonomous Coding**: AI-powered code generation, editing, and refactoring
- **File Operations**: Create, read, update, and delete files and directories
- **Command Execution**: Run shell commands and scripts
- **Browser Automation**: Interact with web pages and applications
- **Multi-Model Support**: Works with Anthropic Claude, OpenAI GPT, and other AI models
- **MCP Integration**: Extensible through Model Context Protocol servers
- **Project Understanding**: Analyzes codebases to provide context-aware assistance
<img align="right" width="340" src="https://github.com/user-attachments/assets/ceb74224-08aa-4b8b-a3e7-b438ac3d160a">
## Requirements
### Use any API and Model
- Node.js 18.0.0 or higher
- Supported platforms: macOS, Linux. Windows soon
- Supported architectures: x64, arm64
Cline supports API providers like ChatGPT, Anthropic, OpenAI, Google Gemini, AWS Bedrock, Azure, GCP Vertex, Cerebras, Groq, and Moonshot. You can also configure any OpenAI compatible API, or use a local model through LM Studio/Ollama. If you're using a Cline Account, you'll always have access to the newest models as soon as they're available.
## Configuration
<!-- Transparent pixel to create line break after floating image -->
Cline can be configured through:
<img width="2000" height="0" src="https://github.com/user-attachments/assets/ee14e6f7-20b8-4391-9091-8e8e25561929"><br>
- Environment variables
- Configuration files
- Command-line arguments
<img align="left" width="370" src="https://github.com/user-attachments/assets/cad091f6-6c0f-4e4b-97ea-a1ff67e39b9b">
See the [main documentation](https://cline.bot) for detailed configuration options.
### Stay in Control with Human-in-the-Loop
## Links
Cline asks for your approval before running commands, editing files, or taking any action. Review each step and approve or reject as you go—or enable auto-approve to let Cline work autonomously to completion.
- **Website**: [https://cline.bot](https://cline.bot)
- **Documentation**: [https://docs.cline.bot](https://docs.cline.bot)
- **GitHub**: [https://github.com/cline/cline](https://github.com/cline/cline)
- **VSCode Extension**: Available in the VSCode Marketplace
- **JetBrains Extension**: Available in the JetBrains Marketplace
<!-- Transparent pixel to create line break after floating image -->
<img width="2000" height="0" src="https://github.com/user-attachments/assets/cad091f6-6c0f-4e4b-97ea-a1ff67e39b9b"><br>
<img align="right" width="400" src="https://github.com/user-attachments/assets/4f264a0c-3802-49a7-8e5e-13d97beb659e">
### Plan & Act Modes
Toggle to Plan Mode to discuss implementation and architecture with Cline. He'll ask clarifying questions, explore your codebase, and present a plan for you to align on. Once you're satisfied, switch to Act Mode and let Cline execute the plan.
<!-- Transparent pixel to create line break after floating image -->
<img width="2000" height="0" src="https://github.com/user-attachments/assets/4f264a0c-3802-49a7-8e5e-13d97beb659e"><br>
## Enterprise
Get the same Cline experience with enterprise-grade controls: SSO (SAML/OIDC), global policies and configuration, observability with audit trails, private networking (VPC/private link), and self-hosted or on-prem deployments, and enterprise support. Learn more at our [enterprise page](https://cline.bot/enterprise) or [talk to us](https://cline.bot/contact-sales).
## License
Apache-2.0 - see [LICENSE](https://github.com/cline/cline/blob/main/LICENSE) for details.
## Support
- Report issues: [GitHub Issues](https://github.com/cline/cline/issues)
- Community: [GitHub Discussions](https://github.com/cline/cline/discussions)
- Documentation: [docs.cline.bot](https://docs.cline.bot)
- Cline CLI Architecture: [architecture.md](./architecture.md)
[Apache 2.0 © 2026 Cline Bot Inc.](./LICENSE)
-292
View File
@@ -1,292 +0,0 @@
# Cline CLI Architecture
The CLI is a **standalone terminal interface** for the Cline AI coding assistant, written in Go. It provides the same autonomous coding capabilities as the VS Code extension but runs entirely in the terminal.
## High-Level Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ User Terminal │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ cline (Go binary) │
│ cmd/cline/main.go │
│ • Cobra CLI commands (task, auth, config, instance, etc.) │
│ • Interactive input via Bubble Tea │
│ • Streaming output with markdown rendering │
└─────────────────────────────────────────────────────────────────────────┘
│ gRPC (50052) │ starts subprocess
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ cline-core │◄────────────────►│ cline-host │
│ (Node.js) │ gRPC (51052) │ (Go binary) │
│ │ │ cmd/cline-host/main.go│
│ • AI/LLM orchestration │ │ │
│ • Tool execution │ │ • Workspace paths │
│ • Task state mgmt │ │ • File diff editing │
│ • Message handling │ │ • Clipboard access │
└─────────────────────────┘ │ • Environment info │
│ └─────────────────────────┘
│ SQLite (self-registration)
┌─────────────────────────────────────────────────────────────────────────┐
│ ~/.cline/data/locks/locks.db │
│ (Instance registry - core self-registers on startup) │
└─────────────────────────────────────────────────────────────────────────┘
```
## Entry Points (`cmd/`)
### `cmd/cline/main.go` - Main CLI
Cobra-based CLI with commands:
- **Root**: `cline [prompt]` - Start a task directly
- **task**: Create, send, view, list, pause, restore tasks
- **auth**: Authentication setup and provider configuration
- **config**: Read/write settings
- **instance**: Manage running Cline instances
- **logs**: View and clean log files
- **doctor**: System health check
### `cmd/cline-host/main.go` - Host Bridge Service
Separate gRPC server providing host environment operations to cline-core:
- Workspace paths
- File diff editing
- Clipboard access
- Shutdown coordination
---
## `pkg/cli/` Subsystems
### 1. `auth/` - Authentication System
Handles authentication with Cline service and BYO (Bring Your Own) API providers.
| File | Purpose |
| ------------------------- | ------------------------------------------------------------------------ |
| `auth_cline_provider.go` | OAuth login flow - opens browser, subscribes to auth callback stream |
| `auth_menu.go` | Interactive menu showing auth options based on current state |
| `auth_subscription.go` | gRPC stream subscription for auth status updates |
| `wizard_byo.go` | Interactive wizard for configuring BYO providers |
| `wizard_byo_bedrock.go` | AWS Bedrock-specific credential setup |
| `wizard_byo_oca.go` | Oracle Code Assist setup |
| `providers_list.go` | Retrieves configured providers from core state |
| `providers_byo.go` | Provider selection UI and field configuration |
| `models_*.go` | Model listing (static lists + dynamic fetch from OpenRouter/OpenAI/Ollama) |
**Flow**: User runs `cline auth` → Menu shows options → For BYO: wizard guides through provider/key/model selection → Config saved via gRPC to core.
---
### 2. `clerror/` - Error Handling
Parses and classifies API errors from the Cline service.
**Error Types:**
- `ErrorTypeAuth` - 401, bad API key
- `ErrorTypeBalance` - Insufficient credits
- `ErrorTypeRateLimit` - 429, quota exceeded
- `ErrorTypeNetwork` - Connection issues
- `ErrorTypeUnknown` - Catch-all
Extracts billing details (balance, spent, buy credits URL) from error responses.
---
### 3. `config/` - Configuration Management
| File | Purpose |
| --------------------- | -------------------------------------------------------------------------- |
| `manager.go` | gRPC interface for reading/writing settings via `UpdateSettingsCli` RPC |
| `settings_renderer.go`| Pretty-prints config values, censors sensitive fields (keys, secrets) |
Supports dot-notation paths: `cline config get auto-approval-settings.actions.read-files`
---
### 4. `display/` - Terminal Display System
The most complex subsystem - handles all visual output.
| File | Purpose |
| ----------------------- | -------------------------------------------------------------------- |
| `renderer.go` | Central coordinator with lipgloss styles, color methods, markdown delegation |
| `streaming.go` | Real-time streaming display with deduplication |
| `segment_streamer.go` | Streaming segments (header + body) with context-aware headers |
| `typewriter.go` | Character-by-character animation with variable delays |
| `markdown_renderer.go` | Glamour wrapper for terminal markdown rendering |
| `tool_renderer.go` | Tool operation formatting ("Cline is editing `file.ts`") |
| `tool_result_parser.go` | Parses structured tool results (file lists, search results) |
| `banner.go` | Session startup banner with version/model/workspace |
| `deduplicator.go` | MD5-based deduplication with 2-second window |
| `system_renderer.go` | Rich error/warning boxes for balance errors, auth failures |
| `ansi.go` | TTY detection, line clearing with escape codes |
---
### 5. `global/` - Global State Management
| File | Purpose |
| ------------------ | -------------------------------------------------------------------------- |
| `global.go` | Global config (paths, verbosity, output format), initialization |
| `registry.go` | Instance discovery via SQLite, health checking, default instance management|
| `cline-clients.go` | Starts cline-core + cline-host processes, port allocation, cleanup |
**Instance lifecycle:**
1. Find available port pair
2. Start `cline-host` on port+1000
3. Start `cline-core` on port
4. Wait for core to self-register in SQLite
5. Set as default if first instance
---
### 6. `handlers/` - Message Handlers
Routes incoming messages from cline-core to appropriate renderers.
| File | Purpose |
| ------------------ | --------------------------------------------------------------------- |
| `handler.go` | Handler registry with priority-based routing |
| `ask_handlers.go` | Approval requests: tool, command, followup, api_req_failed, etc. |
| `say_handlers.go` | Status messages: text, reasoning, command_output, tool, checkpoint, etc. |
Uses `DisplayContext` providing renderer access, state, and context flags (isLast, isPartial, isStreamingMode).
---
### 7. `output/` - Output Coordination
| File | Purpose |
| --------------------- | ----------------------------------------------------------------------- |
| `coordinator.go` | Coordinates streaming output with interactive input (saves/restores input state) |
| `input_model.go` | Bubble Tea model for rich input (message, approval, feedback types) |
| `slash_completion.go` | Autocomplete dropdown for slash commands |
**Key pattern:** When output needs to print while input is visible, the coordinator saves input state, clears the form, prints, then restores input.
---
### 8. `slash/` - Slash Command Registry
Central registry for commands like `/plan`, `/act`, `/cancel`:
- **CLI-local commands**: Handled directly by CLI
- **Backend commands**: Fetched from core via gRPC, filtered by `CliCompatible` flag
---
### 9. `sqlite/` - Instance Locking
Manages the distributed locking system:
- **Instance locks**: Track running Cline instances by address
- **File locks**: Coordinate file access across instances
- SQLite database created by cline-core, CLI reads/writes for discovery
---
### 10. `task/` - Task Management
| File | Purpose |
| ----------------------- | -------------------------------------------------------------------- |
| `manager.go` | Core orchestrator: create, cancel, resume, restore tasks; stream handling |
| `stream_coordinator.go` | Deduplication and turn management for dual streams |
| `input_handler.go` | Interactive input during follow mode (polling, approval detection) |
| `history_handler.go` | Direct disk access to `taskHistory.json` |
| `settings_parser.go` | Parse settings from CLI flags |
| `follow_options.go` | Configuration for follow behavior |
**Streaming:** Task manager subscribes to two gRPC streams:
1. `SubscribeToState` - Full state updates
2. `SubscribeToPartialMessage` - Streaming AI responses
---
### 11. `terminal/` - Terminal Handling
Enhanced keyboard protocol support and terminal configuration:
- Enables modifyOtherKeys and Kitty keyboard protocol
- Detects terminal type (VS Code, iTerm, Ghostty, Kitty, etc.)
- Auto-configures shift+enter keybindings for various terminals
---
### 12. `types/` - Type Definitions
| File | Purpose |
| -------------- | ----------------------------------------------------------------- |
| `messages.go` | `ClineMessage`, `AskType`, `SayType`, `ToolType` enums, proto conversion |
| `state.go` | `ConversationState` with thread-safe message access |
| `history.go` | `HistoryItem` matching taskHistory.json format |
---
### 13. `updater/` - Auto-Update
Background auto-update checking:
- 24-hour check interval (cached)
- Queries npm registry for newer versions
- Supports `latest` and `nightly` channels
- Runs `npm install -g cline` to update
---
## `pkg/common/` - Shared Types
| File | Purpose |
| --------------- | ------------------------------------------------------------ |
| `constants.go` | `SETTINGS_SUBFOLDER`, `DEFAULT_CLINE_CORE_PORT` |
| `schema.go` | SQL queries for instance/file locks |
| `types.go` | `CoreInstanceInfo`, `LockRow`, `DefaultCoreInstance` |
| `utils.go` | Port checking, health checks, address normalization, retry logic |
---
## `pkg/generated/` - Auto-Generated
| File | Purpose |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `providers.go` | Provider definitions (Anthropic, OpenAI, Bedrock, etc.) with field metadata and model specs - generated from TypeScript sources |
| `field_overrides.go` | Manual overrides for field filtering |
---
## `pkg/hostbridge/` - CLI-to-Core Bridge
This is the **reverse bridge** allowing cline-core to request host environment operations:
| File | Purpose |
| ----------------------- | ---------------------------------------------------- |
| `grpc_server.go` | Main server registering all services |
| `simple_workspace.go` | Workspace service: returns CWD as workspace path |
| `diff.go` | In-memory file diff editing with line-based operations |
| `env.go` | Clipboard access, version info, shutdown coordination |
| `window.go` | UI stubs (no-ops or console output) |
**Why this exists:** The same cline-core logic runs in VS Code and CLI. In VS Code, the "host" is the extension with editor APIs. In CLI, hostbridge emulates these capabilities with terminal-appropriate implementations.
---
## Key Design Decisions
1. **Two-process model:** `cline` CLI manages instances; `cline-core` is the actual AI engine (Node.js). This allows reusing the same core as the VS Code extension.
2. **Self-registration via SQLite:** `cline-core` registers itself in a SQLite database on startup. The CLI discovers instances by reading this database, enabling multi-instance support.
3. **Host bridge abstraction:** The `cline-host` process provides platform-specific operations (clipboard, workspace paths) via gRPC, allowing `cline-core` to remain host-agnostic.
4. **Streaming-first UI:** The CLI uses gRPC streaming to display AI responses in real-time with typewriter-style rendering.
5. **Dual stream handling:** Task manager subscribes to both state updates and partial messages, using deduplication to prevent duplicate rendering.
+1
View File
@@ -7,6 +7,7 @@ class Cline < Formula
license "Apache-2.0"
depends_on "node@20"
depends_on "ripgrep"
def install
system "npm", "install", *std_npm_args(prefix: false)

Some files were not shown because too many files have changed in this diff Show More