Files
cline/apps/examples
Saoud RizwanandSaoud Rizwan d84d09c543 desktop: fix silent turn failures, message duplication, and stuck composer; add first-run setup guidance (#12984)
* desktop: fix silent turn failures, message duplication, and stuck composer; add first-run setup guidance

Findings from two full computer-use UX audits of the desktop app:

- Surface failed turns in the transcript: queued turns (incl. the first
  prompt of a fresh session) only signal errors via chat_done, which the
  UI previously ignored - sending a message with no credentials failed
  in complete silence. Failed turns now show an error message enriched
  with the latest core error log and a pointer to Settings -> Models.
- Fix duplicated user messages: a live send's optimistic user message
  was materialized a second time by the runtime's queued-prompt-start
  event.
- Fix composer stuck on 'Agent is working...': drop prompts from the
  local queue snapshot when they start, emit a fresh queue snapshot from
  the sidecar on pending_prompt_submitted, and double-check the server
  queue on turn completion.
- Add a 'Connect a model' notice on the welcome screen when no provider
  has credentials, with actions to reopen onboarding at the connect step
  or jump to model settings; it reacts live to credential changes.
- Add 'Get an API key' links for popular providers in onboarding and
  Settings -> Models (the catalog docUrl is never populated), and link
  the Cline dashboard from the Cline API key form.
- Explain what Cline is on the onboarding welcome step.
- Make the stop button visible (was 8px with no padding) and support
  Esc to stop; add Cmd/Ctrl+N (new session) and Cmd/Ctrl+, (settings).
- Remove leftover [webview:delete] console.error debug logging that
  surfaced an error badge after deleting a session.

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

* desktop: remove remaining delete debug logging in session history hook

The sidebar right-click delete path had the same leftover [webview:delete]
console.error instrumentation, which made the Next dev-mode issues badge
appear after every deletion.

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

* desktop: fix Biome a11y error in WelcomeSetupNotice

biome's lint/a11y/useSemanticElements errors on role="status" divs;
use the semantic <output> element (implicit status role) instead. This
was failing the repo's 'bun run lint'.

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

* desktop: count structured-config and keyless providers as connected

The welcome setup notice previously only recognized apiKey/OAuth
credentials, so users running Bedrock/Vertex (structured configValues)
or a deliberately enabled keyless local endpoint (e.g. Ollama) were
nagged to connect a model they already use. isProviderConnected now
also counts an enabled provider whose required config fields are all
filled, or an enabled provider that has no API-key field at all.

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

* desktop: keep re-key eligible when chat_done lands in the same batch as its prompt start

When a turn fails fast, chat_queued_prompt_start and chat_done can be
dispatched in one React batch. Clearing the outstanding-optimistic-
bubble registry synchronously in the chat_done handler ran before the
re-key updater enqueued by the prompt-start event, so the optimistic
bubble was appended a second time instead of re-keyed. Clear the
registry inside a state updater so it executes in event order after
the re-key. Caught by the queued-turn-failure regression test.

* desktop: make the queued-prompt re-key updater idempotent under StrictMode

React StrictMode double-invokes state updaters in dev. The
chat_queued_prompt_start re-key updater consumed the optimistic
bubble's id from outstandingOptimisticUserIdsRef on its first run, so
the second run against the same prev found no eligible candidate and
appended the same user message a second time (and, without a promptId,
makeId() minted a different id per invocation). Hoist the message id
out of the updater and remember which optimistic bubble each queued
message id re-keyed so a re-run reaches the identical result. The memo
resets alongside the outstanding set (error state, reset, hydration).

Root-caused with runtime instrumentation: the duplicate only appeared
on turns that exercised the queue-drain re-key path, and hydration
later collapsed it to one message because the duplicate never existed
in persisted state.

* desktop: preserve failure messages across post-send canonical hydration

Persisted history never contains UI-only error bubbles, so the two
post-send read_session_messages replacements in sendPrompt wiped the
failure explanation appended from chat_done ~40ms after it rendered
(confirmed with runtime instrumentation). Re-append the active
session's error messages after the canonical history. Includes a
regression test reproducing the chat_done-error-then-RPC-resolution
race.

* desktop: don't let an optional API-key field veto a connected provider

Greptile P1 follow-up: Bedrock's catalog entry carries an optional
apiKey field ('Optional Bedrock bearer token') alongside IAM/profile
authentication, and keyless local endpoints can also surface one — so
treating the mere presence of an apiKey field as proof of disconnection
kept nagging configured users. An enabled provider (the user
deliberately persisted settings for it) now counts as connected unless
a required config field is unmet; auth may legitimately live outside
the catalog (IAM, env vars, local endpoints). Brand-new users have no
enabled providers, so the first-run notice still shows for them.

* desktop: tighten credential-error guidance and stop re-pinning stale failure bubbles

* desktop: invalidate the shared provider catalog after settings OAuth login

Greptile P1 follow-up: runOAuthProviderLogin only updated the settings
view's local provider state, so the shared catalog cache and its
invalidation subscribers (the composer selector and the welcome
screen's 'Connect a model' notice) kept reporting the provider as
disconnected until an unrelated invalidation or a pane remount. Notify
the shared cache on successful OAuth login, like the account view and
the API-key save path already do.

* desktop: clear the remembered core error on turn end, reset, and hydration

Greptile flagged that turn-start events are the only thing clearing
lastCoreErrorBySessionRef, and websocket events are not replayed: a
transport interruption that drops a turn's start event lets a later
detail-less failure resurrect an earlier turn's error. The remembered
error belongs to exactly one turn, so clear it whenever a turn ends
(chat_done, any reason) as well as on reset() and history hydration.
Regression test covers the dropped-start-event sequence.

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-06 19:25:42 -07:00
..
2026-06-03 01:49:57 +02:00

Cline SDK Examples

Learn how to build with the Cline SDK through working examples, ordered from simple to complex.

SDK Skill

If you use a coding agent (Claude Code, Codex, Cline, etc.), install the Cline SDK skill to give your agent context on the SDK's APIs and best practices to help you build with the Cline SDK.

npx skills add cline/sdk-skill

Prompt it to scaffold agents, create custom tools, wire up plugins, configure providers, and more.

Getting started

All examples live in this directory. Each is a standalone project with its own package.json and README. To run any example:

cd apps/examples/<example-name>
bun install
bun run build:sdk
export CLINE_API_KEY="cline_..."
bun dev

Requires Node.js 22+.

Examples

Beginner

Example Description Concepts
quickstart Send one prompt, stream the response. ~15 lines of code. Agent, subscribe, run()
cli-agent Interactive terminal chat with a shell tool. createTool, multi-turn run()/continue(), streaming
cline-core-cli-agent Interactive terminal chat powered by ClineCore. ClineCore.create(), cline.start(), cline.send(), built-in tools, streaming

Intermediate

Example Description Concepts
code-review-bot AI code reviewer that reads git diffs and produces structured comments. Multiple tools, completesRun lifecycle, systemPrompt, zod schemas
multi-agent Web app that fans out to three specialist agents in parallel, streams results via SSE, then synthesizes a unified answer. Concurrent agents, Promise.all, per-agent subscribe(), SSE streaming, agent composition

Advanced

Example Description Concepts
desktop-app Full Tauri + Next.js desktop app for running and inspecting chat sessions. Sidecar runtime, websocket transport, session persistence
menubar macOS menu bar app with Tauri. Native app integration, compact UI
vscode VS Code extension with chat panel. Extension API, webview, workspace context

SDK packages

When building your own app, install the public SDK package:

npm add @cline/sdk

@cline/sdk re-exports everything from @cline/core. You only need @cline/agents or @cline/llms if you want lower-level control over the agent runtime or model gateway directly.

Learn more