sdk/ARCHITECTURE.md
This document is the architecture source of truth for the Cline SDK repository. It describes how the system is organized, how components interact, and the design principles that guide development decisions.
Who should read this?
@cline/coreWhat this covers:
What this is NOT:
The workspace is organized as a layered runtime stack.
flowchart LR
shared["@cline/shared"]
llms["@cline/llms"]
agents["@cline/agents"]
core["@cline/core"]
apps["Host Apps"]
llms --> shared
agents --> llms
agents --> shared
core --> agents
core --> llms
core --> shared
apps --> core
@cline/sharedOwns reusable low-level contracts and infrastructure:
Design rule:
shared should not depend on higher-level runtime packages.@cline/llmsOwns model/provider runtime concerns:
Design rule:
core or apps.@cline/agentsOwns the stateless runtime loop:
Design rule:
agents should not own persistent storage or host lifecycle concerns.@cline/coreOwns stateful orchestration:
src/hub/@cline/core/hub/daemon-entry subpathNodeHubClient, HubSessionClient, HubUIClient, connectToHub) exported from @cline/core/hubDesign rules:
core is the app-facing orchestration layer over agents.packages/core/src/hub/, grouped by service:
client/ contains host-facing hub clients and browser connection helpersdaemon/ contains detached daemon startup, entrypoint, and local runtime handler wiringdiscovery/ contains endpoint defaults, discovery records, and workspace owner resolutionserver/ contains WebSocket server startup, native/browser socket adapters, server transport, server helpers, and handlers/ for hub command dispatchsettings.* hub command family and react to settings.changed.RuntimeHost through @cline/core.@cline/core selects LocalRuntimeHost through packages/core/src/runtime/host.ts.RuntimeSessionConfig plus localRuntime overrides before calling RuntimeHost.start(...).@cline/core prepares a local bootstrap artifact from localRuntime, then builds the runtime from it.@cline/core creates an Agent from @cline/agents.@cline/agents runs the loop using @cline/llms handlers.@cline/core persists state, artifacts, and metadata.Completion telemetry is anchored to the assistant's explicit completion
declaration, not session shutdown. After each agent turn, the local
runtime inspects AgentResult.toolCalls and emits task.completed the
moment a successful submit_and_exit (the SDK analog of original
Cline's attempt_completion) is observed. shutdownSession(...)
retains a fallback emission for completed sessions that finished
without an explicit completion-tool observation, so non-interactive
runs not using the yolo preset still produce a task.completed signal.
Each session emits at most one task.completed. See DOC.md for the
event payload and source field.
RuntimeHost through @cline/core.@cline/core selects HubRuntimeHost or RemoteRuntimeHost through packages/core/src/runtime/host.ts.@cline/core can spawn a detached hub daemon and reconnect through discovery.@cline/agents and @cline/llms.@cline/core hub services broker sessions, events, approvals, schedules, and client-owned runtime capabilities such as session-local tool executors.run.started is emitted only after the target session is resolved and carries the originating command's requestId and clientId, allowing multi-client hosts to correlate delivery acknowledgments.@cline/core/hub (NodeHubClient, HubSessionClient, HubUIClient, connectToHub) translate command/reply and event streams into host-facing APIs.session.get records include both canonical root-session usage and explicit aggregate usage from the hub-owned RuntimeHost, so attached clients can intentionally render either root-only or root-plus-teammate costs without replaying event streams.Session status is reported, never fabricated. A session's initial status
reflects whether a turn actually runs inside start(...): prompt-bearing
starts (one-shot or interactive) begin running, interactive starts without a
prompt begin idle until their first turn, and resumed sessions report their
persisted status. Each turn owns its running → idle transition. On the
client side, HubRuntimeHost projects a status event only when the hub
session record or the session snapshot actually carries one; snapshot-only
session.updated events (asynchronous persistence updates, which can trail a
turn's final idle update) report the snapshot's real status. Hosts that gate
workspace-wide operations on busy sessions (for example the desktop's
checkpoint-restore gate) depend on this: a defaulted running with no owning
turn leaves such gates blocked with nothing to clear them.
Command progress follows the same runtime event boundary as other agent output.
Shell executors emit structured stdout/stderr chunks through
AgentToolContext.emitUpdate; the agent runtime projects them as tool
content_update events, and the Hub publishes them as tool.updated with the
session, tool-call, and tool identifiers intact. Hub clients reconstruct the
tool update for their host-facing event stream. Client-contributed executors
must forward capability progress through this same path rather than creating a
host-specific side channel. The built-in shell executor coalesces output on a
short interval and bounds each stream's pending tail before it enters the event
pipeline; consumers independently coalesce and cap their rendered scrollback.
Proceed-while-running is an explicit command lifecycle, separate from client
or session detachment. A shell process advertises detachability only after it
has spawned and registered with the host-scoped command execution controller.
The client sends run.proceed_while_running with the owning sessionId and,
when available, toolCallId; the Hub delegates to the authoritative
RuntimeHost, which releases every matching registered process from the tool
call. The executor removes its abort and timeout ownership, resolves the tool
call with the current bounded output and a temporary log path, and continues
draining the process into that log. Detached logs are size-capped, retained for
a bounded inspection window after the command exits, and then their temporary
directories are removed. Every process that constructs a LocalRuntimeHost
starts one detached-log reconciliation: it reaps completed logs outside the
retention window, reschedules retained logs, and follows active detached-command
identities until they exit, so cleanup does not depend on timers from the process
that launched the command. Hub daemons and direct embedders therefore share the
same detachment and restart lifecycle instead of relying on a daemon-specific
entrypoint. Active-command markers pair the PID with a process-generation start
token, preventing an unrelated process that later reuses the PID from extending
the log lifetime. Completion markers distinguish a live, possibly silent command
from a completed log. Process probes distinguish an absent process from an
unavailable identity provider. Transient probe failures retain the active marker
and are never treated as evidence of command completion. Reconciliation keeps
the advertised log and retries until the provider can prove that the original
process still exists, its PID belongs to a replacement process, or the process
is absent. A host exit alone never starts the retention window for a surviving
command; the replacement host continues polling the process identity and begins
retention only after the command ends. During persistent provider unavailability,
the capped log may outlive the normal retention window because preserving a
potentially live command's advertised path takes precedence over guessing that
it exited. A detached client connection alone never changes process ownership or
command execution.
Model modalities and provider operations are separate facts. Modalities describe
values a model accepts or produces; the explicit operation selects the provider
transport. Language models keep the normal agent loop even when they can emit
media, while operation: "image-generation" selects generateImage and
operation: "transcription" selects a declared speech-to-text transport.
Operation-specific execution variants such as recorded and realtime
transcription live in operationModes, not in the generic capability list.
Specialized operations fail closed unless the provider manifest and adapter
both implement them, so an OpenAI-compatible chat endpoint never implies an
image, audio, transcription, or video endpoint.
Generated media crosses package boundaries as follows:
@cline/llms validates provider output once and creates canonical
GeneratedMedia values. The contract carries a stable ID, modality, MIME type,
and a discriminated base64, HTTP(S), or artifact source. Current producers emit
images; audio, video, and large artifact-backed files use the same contract.@cline/agents appends media events at their exact stream position in the
assistant message. That message is the canonical replay and persistence source;
observational provider-tool activity remains display-only metadata.@cline/core projects live media as content_end(media). The hub publishes
assistant.media, preserving the same media ID, and clients deduplicate live
and hydrated content by that ID.GeneratedMediaContent from @cline/ui for image, audio,
video, file, and unavailable-source rendering. Inline bytes are exposed only
through short-lived browser-owned object URLs; remote and artifact sources
require a client-owned trusted resolver. CLI and ACP clients provide
transport-appropriate materialization or fallback output without changing
the canonical message.Image-edit inference is intentionally local: when a dedicated image model accepts image input and the current user message has no explicit image, only an image on the immediately preceding assistant message is reused. Older images are not implicitly attached across intervening turns.
Session history provenance keeps the client surface and initiation mode separate.
StartSessionInput.source identifies the client (vscode, desktop, cli,
core, and so on), while top-level StartSessionInput.mode identifies how the
session began (user, automation, subagent, or team). The persisted messages
envelope records both values, along with client version and child-session
lineage. Missing initiation mode defaults to user; automation runtime adapters
must pass mode: "automation" explicitly.
Root-session persistence is lazy. Starting a runtime allocates its session ID and keeps configuration or seeded history in memory, but does not create a database row, manifest, or messages artifact. The first accepted user turn persists that same ID and its artifacts. Closing a runtime before a user turn therefore leaves no empty history entry, and persistence code never allocates a replacement ID for an unknown session.
Workspace bootstrap is owned by the runtime that executes the session. Hub
clients preserve an omitted cwd and workspaceRoot across the transport so
the hub-side execution host can place the session in the shared chat
workspace on its own filesystem at
<cline-data-dir>/workspaces/chat (by default
~/.cline/data/workspaces/chat). The chat workspace is seeded with an
AGENTS.md rules file that tells the agent to treat the session as a chat
and to create a named project folder only when the user asks for one.
The resolved paths are returned in the session snapshot and are the source of
truth for client-side manifests; transport clients must not invent a local path
for a remote runtime.
Detached daemon startup retries transient ETXTBSY spawn failures before
polling discovery. This covers package-manager updates that replace the CLI
binary immediately before a command restarts the shared hub.
Local hub discovery also carries the authentication contract for the shared
daemon. On startup, the hub server generates a cryptographically random
per-process auth token, stores it in the owner discovery record, and writes that
record with owner-only file permissions. Local clients resolve the token from
the discovery file at connection time rather than embedding it in endpoint URLs.
The server validates the token with a constant-time comparison before accepting
/hub WebSocket upgrades or /shutdown requests; WebSocket clients send it via
the Sec-WebSocket-Protocol header and shutdown requests use an
Authorization: Bearer header. Unauthenticated local processes can still probe
public health/build metadata, but they cannot attach to sessions, issue
commands, or stop the daemon.
Local hub rediscovery is limited to managed shared-daemon endpoints obtained
through discovery or ensure*HubServer(...) startup paths. Managed local hubs
must match both the supported wire protocol and the current Hub build identity;
a protocol-compatible daemon from another build is retired before its
replacement starts so upgrades cannot keep executing stale runtime code. SDK
builds embed a deterministic fingerprint of the runtime sources, package
manifests, build configuration, and dependency lock, so the identity changes
with the executable Hub code even before package versions are bumped. Builds
also embed a build epoch that orders them in time: when the fingerprints
differ, a managed Hub produced after the client's own build is reused over
the compatible wire protocol instead of being retired (replacing it would
downgrade the daemon), and the client's build-mismatch watcher prompts the
user to update and restart. Hubs that are older, unordered, or missing build
metadata are retired and replaced as before, so two concurrently running
installations converge on the newest build instead of repeatedly replacing
each other's daemons.
Explicit endpoints, including loopback URLs such as
ws://127.0.0.1:<port>/hub, are sticky exact targets and remain protocol-only:
reconnects may retry the same socket URL, but command recovery and
startup-deadlock recovery must not replace them with the workspace-discovered
hub. This keeps custom local hubs and remote hubs from silently drifting to a
different process.
apps/cli owns OpenTUI startup and must render the first frame without waiting for detached hub startup.backendMode: "auto" so an already-compatible hub can be reused immediately, while a missing hub is only prewarmed in the background and the TUI falls back to a local runtime for responsiveness.cline hub, schedules, connectors, and --zen may still call the explicit ensure path because those commands require a live hub before proceeding.renderOpenTui() so loading previous messages cannot block initial TUI paint.@cline/shared/db owns the low-level SQLite connector store and the one-time legacy JSON import.@cline/core owns connector autostart persistence and reconnect orchestration. The detached hub daemon is the sole startup reconnect owner, preventing dashboard startup from racing it and launching duplicate processes.hubDaemonReady, which resolves only after the WebSocket server is listening. It begins reconnect attempts after signaling readiness, and reconnect failures remain best-effort rather than taking down the hub.RemoteConfigBundle.@cline/shared/remote-config caches the bundle when configured..cline/<plugin>/.@cline/core exposes the app-facing integration wrapper that applies extensions, telemetry, and session metadata to StartSessionInput.@cline/core consumes the prepared local overrides during local bootstrap.This keeps reusable remote-config behavior in shared while the session-specific bridge remains in core.
The codebase relies on a few repeated seams instead of one-off integration paths.
Core uses file-based discovery and watchers for:
Design implication:
packages/core, config-facing discovery, parsing, watching, and slash-command projection live under src/extensions/configDefaultRuntimeBuilder composes a runtime from generic inputs:
Design implication:
packages/core/src/services/local-runtime-bootstrap.ts and feeds the builder rather than bypassing itCore exposes one shared execution boundary: RuntimeHost.
Concrete implementations:
LocalRuntimeHost for in-process executionHubRuntimeHost for shared local hub executionRemoteRuntimeHost for explicit remote hub endpointsDesign implication:
packages/core/src/runtime/host.tsClineCore delegates uniformly to RuntimeHost and does not branch on local vs hub behaviorRuntimeHost inputs stay transport-safe, while ClineCore.start(...) is the app-facing facade that normalizes broad local config before delegationRuntimeSessionConfig is transport-neutral across local, shared hub, and remote hub modes; host-local bootstrap concerns stay under localRuntimedefaultToolExecutors, are attached at session start and proxied through hub capability requests instead of changing host selectionClineCore.pendingPrompts service. Usage summary lookup and active-session
model switching are also service-style capabilities exposed through
ClineCore when the concrete transport implements them. These service APIs
are intentionally outside the minimal RuntimeHost primitive vocabulary.getAccumulatedUsage(sessionId) method returns a summary
with two explicit buckets: usage for the root/lead agent and
aggregateUsage for root plus teammates/subagents. Local execution tracks
root usage and teammate usage as separate buckets, then derives aggregate
totals from those buckets while telemetry remains scoped to the primary
lead/root agent.Core owns settings snapshots and mutations through packages/core/src/settings.
The hub exposes the same path through settings.list and settings.toggle.
Design implication:
settings.changed with the changed settings typesClineCore.create(...) exposes a generic prepare(input) hook.
Design implication:
Cross-package logging uses a small injected interface exported from @cline/shared:
BasicLogger — required debug and log; optional error. Hosts map these to their backend (Pino, VS Code OutputChannel, etc.). Many runtime options take logger?: BasicLogger; when omitted, components skip logging or use noopBasicLogger where a full object is required.BasicLogMetadata — optional structured fields (sessionId, runId, providerId, toolName, durationMs, …) plus severity on log when a single method must represent both informational and warning-style messages (for example the CLI Pino bridge maps severity: "warn" to Pino warn).Naming clarity:
CliLoggerAdapter (CLI) — a host bundle: holds the raw pino logger (for file paths, rotation, and CLI-only concerns) and exposes .core: BasicLogger for anything that consumes the SDK contract. It is not an ITelemetryAdapter.TelemetryLoggerSink (@cline/core) — an ITelemetryAdapter that mirrors telemetry events and metrics into a BasicLogger. It is a telemetry sink, not a host logging implementation.The agent and other call sites route former info / warn semantics through log (warnings include severity: "warn" in metadata). Errors prefer error when implemented; otherwise log with severity: "error" is used as a fallback.
Design implication:
logger?: BasicLogger parameter insteadStateful persistence should be isolated behind adapter/service layers.
Design implication:
Extensibility is split deliberately:
Design implication:
Context compaction is owned by core.
@cline/agents owns the generic turn-preparation seam:
@cline/core owns compaction policy:
Design implications:
core${sessionId}.compaction.jsonagents stays focused on the stateless loop and provider/tool orchestrationpackages/core/src/extensions is split by concern:
extensions/config: config loaders, parsers, watchers, and watcher projections such as runtime slash-command expansionextensions/plugin: runtime plugin discovery, loading, and sandboxingextensions/context: core-owned context/message pipeline concerns such as compactionDesign implications:
Sandboxed plugin subprocesses are session-local but lazily recreatable. Core
reclaims a sandbox after 30 minutes without an in-flight RPC call (configurable
through PluginSandboxOptions.idleTimeoutMs or
CLINE_PLUGIN_IDLE_TIMEOUT_MS), and the next plugin call starts and
reinitializes it transparently. Pending requests are associated with the child
generation that owns them so an old process exiting cannot reject work sent to
its replacement. The bootstrap also exits when its parent IPC channel
disconnects. The parent is the single authority for idle shutdown so competing
deadlines cannot terminate a child while the parent is dispatching new work.
Design implications:
agents StatelessDo not move these concerns into @cline/agents:
core GenericDo not make @cline/core organization- or provider-specific.
If a capability is truly generic and app-facing, add a generic core seam. Reusable remote-config parsing, materialization, and upload primitives belong in @cline/shared/remote-config.
Optional higher-level integrations may depend on lower layers. Lower layers should not depend on optional feature packages.
For remote config, that means shared owns the reusable bundle/materialization/blob primitives and core owns only the session-oriented wrapper exported to apps.
Agenda tasks are durable proposals for future work. They are intentionally
separate from cron specs, queued prompts inside an existing session, and the
agent-team task board. Shared, browser-safe contracts use AgendaTaskRecord
and AgendaTaskRunRecord; orchestration and persistence remain in
@cline/core.
AgendaTaskManagerApi boundary is the only place allowed to change task
lifecycle, approval, run, or session-link state. Hub commands, file import,
and the agent tool all route mutations through that boundary.~/.cline/tasks/*.task.md for global tasks and
<workspace>/.cline/tasks/*.task.md for workspace tasks. Operational fields
such as status, revision, approval, and session IDs are not writable in a
spec. AgendaTaskSpecFileStore confines paths to the selected task directory
and writes specs atomically.SqliteAgendaTaskStore owns tasks.db (resolved by
resolveTasksDbPath()). SQLite is the operational source of truth for task
status, revisions, run attempts, session links, and the automation policy;
the Markdown file is the canonical editable task description, not an
append-only queue or a substitute for concurrency control.system:file_reconciler and
always leave changed intent awaiting manual task approval. File edits never
reopen completed, cancelled, or expired tasks; terminal records remain
terminal and retain their last-known-good operational state.pending_approval. Approval is bound to the exact
task revision through approvedRevision; an execution-relevant edit
increments the revision and revokes stale approval. An approved revision is
therefore immutable at the point it is claimed for execution.task.create and task.update payloads omit actor fields; the command
service derives the user actor from the calling Hub client. Update,
approval, cancellation, and run requests carry the caller's displayed
expectedRevision; specifically, task.approve, task.cancel, and
task.run reject a missing or stale revision.expiresAt is a
required latest-start boundary: expiry prevents a new run but does not abort
a session that already started.AgendaTaskRunRecord and a normal Hub session.
The run owns the task/revision/session association, while the task keeps
currentRunId, lastRunId, and lastSessionId projections for UI lookup.
A global task remains globally scoped and resolves the Hub's shared chat
workspace only when its session starts.task.create, task.list, task.get,
task.update, task.approve, task.cancel, task.run,
task.automation.get, and task.automation.set. Registered task events are
task.created, task.updated, task.deleted, task.run.started,
task.run.completed, task.run.failed, and task.automation.updated.
Events are invalidation and lifecycle signals; clients re-read the current
task or policy projection rather than rebuilding authority state from the
event stream.tasks tool with a required
kind discriminator. kind: "todo" creates, updates, lists, and gets durable
Agenda items within the current session's workspace (or the global scope for
chat sessions). It cannot approve, cancel, or start a Todo, so an agent cannot
self-authorize or terminate queue work.kind: "scheduled" routes to HubScheduleService and manages the same
records shown by the desktop Routine view; the unified tool does not merge
the two persistence or lifecycle domains. Scheduled operations inherit the
current session workspace, cwd, and model, filter reads and mutations to that
workspace, and allow mutations only from an interactive session. One-time
schedules accept an exact future ISO timestamp; recurring schedules accept a
five-field cron expression and optional IANA timezone.tasks. It
distinguishes reviewed Todo work from autonomous scheduled execution, states
that Todo available_at is not a timer, requires clarification for ambiguous
“remind me” requests, and prevents creating both record kinds unless the user
explicitly requests both.AgendaAutomationPolicy is user-owned Hub state. manual preserves the
per-task review gate; auto_start and unattended are explicit opt-ins. The
manager's automation pump enforces the policy's concurrency, chain-depth,
and hourly-start guardrails. auto_start waits for a connected client with
the tool-approval capability and starts an interactive task session that
conservatively requires approval for each tool. Explicit unattended mode
may run headlessly and auto-approves enabled tools.applyToAgentCreated governs tasks originally
created by an agent and tasks whose latest manager-backed edit came from an
agent; disabling it leaves those revisions pending manual approval.suggestion/reminder quick actions below
the welcome composer. The sidebar supports review, start, cancellation,
linked-session navigation, and the automation toggle; it does not maintain a
second task store.ClineCore / CronService)@cline/core ships a file-based automation subsystem under
packages/core/src/cron/. It lets operators author recurring and one-off
tasks as Markdown files under global ~/.cline/cron/ by default, and
event-driven tasks as events/*.event.md specs. All trigger kinds run
through the same durable queue and runtime handlers. ClineCore exposes the
SDK-facing cline.automation.* entry points; CronService is the internal
orchestrator used by core and hub layers.
cron/specs/cron-spec-parser.ts): parses YAML frontmatter + body
into a CronSpec discriminated union (one_off | schedule | event).
Types live in @cline/shared under src/cron/cron-spec-types.ts
so other packages can consume them without the YAML parser. Schedule
expressions and timezones are validated before a spec can become
runnable.cron/store/sqlite-cron-store.ts): owns cron.db at
resolveCronDbPath() (default .cline/data/db/cron.db). Schema is
bootstrapped from cron/store/cron-schema.ts — sessions and cron live in separate
DBs so their lifecycles stay decoupled.cron/specs/cron-reconciler.ts): scans the configured cron specs
directory (global ~/.cline/cron/ by default, or workspace-scoped when
configured), parses each file independently, and upserts spec state.
Invalid specs are recorded
with parse_status='invalid' so state is durable rather than silently
dropped. Files that disappear between scans get removed=1 and their
queued runs are cancelled.cron/specs/cron-watcher.ts): node:fs watch({ recursive: true })
with a ~250ms per-path debounce. Watcher events always trigger a
re-reconcile — the reconciler is always the source of truth, not the
watcher stream.cron/runner/cron-materializer.ts): turns file-triggered specs into
queued cron_runs. One-off: at most one run record per (spec_id, revision), including failed runs so specs do not retry accidentally.
Schedule: "one overdue catch-up on startup then advance" using
timezone-aware getNextCronTime.cron/events/cron-event-ingress.ts): accepts already-normalized
AutomationEventEnvelope values, persists them into cron_event_log,
matches enabled event specs by event_type plus declarative filters,
applies dedupe/debounce/cooldown policy, and enqueues cron_runs with
trigger_kind='event'. It never executes agents directly. Plugins can
declare automationEvents and submit normalized events through
ctx.automation.ingestEvent(...); sandboxed plugins forward those events
through the core plugin event bridge.cron/runner/cron-runner.ts): polls cron.db, atomically claims
queued runs, executes them via the existing HubScheduleRuntimeHandlers
(startSession → sendSession → stopSession / abortSession),
renews the run claim while execution is active, writes a markdown report
per run, and transactionally updates status. File specs can constrain
tool availability, config extension loading (rules, skills,
plugins), trigger source, and a notes directory that is injected into
the system prompt. The automation runtime adapters explicitly persist
mode: "automation" for every run and record the spec-defined trigger
source as sessionHistoryOrigin.trigger in session metadata. Event runs
include the normalized trigger event context in the prompt.cron/reports/cron-report-writer.ts): writes
.cline/cron/reports/<run-id>.md with run frontmatter plus
## Summary, ## Usage, ## Tool Calls, and, for event runs,
## Trigger Event sections.cron/service/cron-service.ts): orchestrates all of the above.
ClineCore.create({ automation }) owns the SDK-facing lifecycle and exposes
cline.automation.* methods. Hub-side callers can submit normalized events
through the cron.event.ingest command.The detached hub daemon passes its workspace root as cronOptions, so
normal CLI/hub startup watches ${workspaceRoot}/.cline/cron/ without a
custom host needing to opt in.
Programmatic hub schedules are stored as cron_specs with source
hub-schedule and execute through the same cron_runs
claim/requeue/report flow as file-backed one-off, recurring, and
event-driven specs. The hub schedule command surface remains a thin adapter;
there is no separate schedules table, schedule store, or schedule runner.
I want to understand the agent loop and tool execution:
packages/agents/src/agent.ts — the stateless runtime looppackages/agents/src/agent-step.ts — individual iteration stepspackages/core/src/extensions/plugin/ — plugin discovery and sandboxingI want to understand session persistence and state:
packages/core/src/runtime/host/local-runtime-host.ts — local session lifecyclepackages/core/src/runtime/orchestration/ — session orchestrationpackages/core/src/settings/ — settings mutation and stateI want to understand the hub system:
packages/core/src/hub/server/ — WebSocket server and hub command handlerspackages/core/src/hub/client/ — host-side hub clientspackages/core/src/hub/runtime-host/ — hub-backed runtime hostsI want to add a new tool:
packages/core/src/extensions/tools/ — built-in tool definitionspackages/agents/src/tool-use.ts — how tools are calledpackages/core/src/extensions/plugin/ — plugin-registered toolsI want to understand settings and configuration:
packages/core/src/extensions/config/ — file watching and loadingpackages/core/src/runtime/config/ — provider settings resolutionpackages/core/src/settings/ — settings state and mutationI want to add a new runtime feature (hook/extension):
packages/shared/src/hooks/ — hook types and enginepackages/core/src/extensions/plugin/ — plugin discovery and executionpackages/core/src/services/local-runtime-bootstrap.ts — how runtime is composed*.ts — TypeScript source*.test.ts — unit tests (Vitest)*.e2e.test.ts — end-to-end tests requiring full integration*.ts in examples — runnable example files (plugins, hooks)*.md files in apps/examples/ — documentation and markdown-based specs (cron, events)ClineCore — packages/core/src/index.ts — the main SDK orchestratorAgent — packages/agents/src/agent.ts — the agent loopRuntimeHost — packages/core/src/runtime/host/runtime-host.ts — execution abstractionAgentPlugin — packages/shared/src/plugin/ — plugin contractCronSpec — packages/shared/src/cron/cron-spec-types.ts — automation specsThis repo has both publishable SDK packages and internal workspace packages.
Architectural consequence:
The following packages are published to npm:
@cline/shared — shared types, contracts, and low-level utilities@cline/llms — provider integrations and model manifests@cline/agents — the agent loop and tool orchestration@cline/core — the main SDK with session management, hub, and configurationThe following workspace apps are internal and not published as SDK packages:
apps/cli — CLI implementationapps/webview — VS Code webviewapps/examples — example plugins and integrations