Public Wiki31,290View on GitHub
Want continuedev/continue knowledge in your AI?

React

Continue is an open-source AI coding assistant platform that integrates with IDEs (VS Code, JetBrains) and CLI to provide LLM-powered code completion, chat, editing, and agentic workflows. It acts as a middleware layer connecting 60+ LLM providers (OpenAI, Anthropic, AWS Bedrock, Google Gemini, local models, etc.) to developer workflows with features like codebase indexing, context retrieval, tool use, and Model Context Protocol (MCP) support.

Tech Stack

ReactJestTypeScriptNext.jsExpress.jsPostgreSQLRedisTailwind CSSVitestZod

Key Features

  • Multi-Provider LLM Abstraction
  • Intelligent Code Autocomplete
  • Next Edit Prediction
  • Codebase Indexing & Retrieval
  • 30+ Context Providers
  • Model Context Protocol (MCP) Integration
  • Diff Streaming & Code Edit Engine
  • YAML/JSON Configuration & Profile Management
  • Tools & Slash Commands
  • Control Plane & Team Features
  • CLI & Background Agents
  • Custom Prompt Files
  • Terminal Security

Entry Points

Start here when working with this codebase

Core Orchestrator
core/core.ts

Central hub that coordinates IDE events, manages LLM chat/completion flows, handles configuration, and delegates to specialized services. All major subsystems are wired together here.

Start here when adding new message handlers, understanding how subsystems connect, or tracing any request from IDE to core.

Core Type Definitions
core/index.d.ts

Central type definitions and contracts for the entire Continue system including IDE interface, context providers, LLM types, tool definitions, and configuration schemas.

Start here when you need to understand or modify any shared type, interface contract, or when adding a new feature that requires new types.

Binary Build Pipeline
binary/build.js

Orchestrates the complete build: cleanup → asset preparation → esbuild bundling → binary compilation for multiple platforms → verification.

Start here when modifying the build process, adding new build targets, or debugging build failures.

Binary Dev Server
binary/core-dev-server.js

Bootstraps the development server with appropriate environment configuration for local development.

Start here when setting up local development or debugging the dev server startup.

Package Build Orchestrator
scripts/build-packages.js

Orchestrates multi-package builds in correct dependency order with parallel execution and error handling.

Start here when adding a new package to the monorepo or modifying build order dependencies.

Control Plane Client
core/control-plane/client.ts

Client for the Continue platform API: auth, secrets sync, policy, credits, agents, and model proxy endpoints.

Start here when adding new platform API integrations or modifying authentication flows.

Config YAML Package
packages/config-yaml/src/index.ts

YAML config parsing, schema validation, assistant and block definitions for the configuration system.

Start here when modifying config schema, adding new config fields, or changing how YAML configs are parsed.

GUI Tailwind Config
gui/tailwind.config.cjs

Configures Tailwind CSS with custom design tokens, breakpoints, and color palette for the GUI application.

Start here when modifying the GUI's design system, adding new colors, or changing responsive breakpoints.

Binary Integration Tests
binary/test/binary.test.ts

Integration tests that exercise the binary messenger protocol including ping, config, history, and LLM endpoints.

Start here when adding integration tests for new endpoints or debugging protocol-level issues.

CLI Entry Point
extensions/cli/src/index.ts

CLI extension entry point that handles agent status reporting and serve mode.

Start here when modifying CLI behavior or adding new CLI commands.

How to Make Changes

Common modification patterns for this codebase

Add a new IPC/messenger API endpoint

1
core/index.d.ts

Define the request/response types for your new endpoint. Add the endpoint name to the appropriate protocol type map (e.g., add to the request type union).

Pattern: See how 'history/save' and 'config/getSerializedProfileInfo' are typed — each endpoint has a request payload type and response type defined in the central type definitions.

2
core/protocol/index.ts

Register the new endpoint in the protocol message type definitions. Add the endpoint string literal to the appropriate protocol mapping.

Pattern: See how existing endpoints like 'ping', 'history/list', 'config/addModel' are registered as protocol message types with their corresponding request/response shapes.

3
core/core.ts

Add the handler for your new endpoint in the core orchestrator. Wire it into the message handling dispatch logic.

Pattern: See how 'history/save' and 'llm/complete' handlers are registered — each handler receives the request payload, performs logic (often delegating to a service), and returns the response type.

4
binary/test/binary.test.ts

Add an integration test for the new endpoint that sends a request through the binary messenger and validates the response.

Pattern: See how the existing tests for 'ping', 'config/getSerializedProfileInfo', and 'history/list' send requests via the messenger and assert on the response shape.

Conventions to follow:

Endpoint names use slash-separated namespaces like 'history/save' or 'config/addModel'All request/response types must be defined in core/index.d.tsHandlers in core/core.ts should delegate business logic to specialized service modules rather than containing logic inlineEvery new endpoint needs an integration test in binary/test/binary.test.ts

Add a new LLM provider

1
packages/llm-info/src/index.ts

Add the new provider's metadata including provider name, supported models, capabilities, and default parameters.

Pattern: See how existing providers are defined with their model lists, context lengths, and capability flags in the llm-info package.

2
packages/openai-adapters/src/index.ts

Create or register an OpenAI-compatible adapter for the new provider if it uses a compatible API. Map the provider name to the adapter configuration.

Pattern: See how other providers are mapped to adapters with their base URLs, auth header formats, and any request/response transformations needed.

3
core/llm/index.ts

Register the new provider in the LLM abstraction layer. Add the provider to the provider factory/registry so it can be instantiated from config.

Pattern: See how existing providers are registered with their constructor functions and config-to-instance mapping logic.

4
core/index.d.ts

Add the provider name to the ModelProvider type union and define any provider-specific configuration options.

Pattern: See how existing provider names are listed in the type union and how provider-specific config fields are typed.

5
packages/config-yaml/src/index.ts

Ensure the YAML config schema validates the new provider name and any provider-specific fields.

Pattern: See how existing provider names are included in the schema validation for model configuration blocks.

Conventions to follow:

Provider implementations should use the OpenAI adapter layer in packages/openai-adapters when the provider has an OpenAI-compatible APIModel metadata (context length, pricing, capabilities) goes in packages/llm-info, not in the provider implementationProvider names must be added to the type union in core/index.d.tsAll providers must support the common LLM interface defined in core/index.d.ts (complete, chat, streamChat, streamComplete)

Add a new context provider

1
core/index.d.ts

Define the context provider's type by adding its name to the ContextProviderName type and defining any provider-specific options interface.

Pattern: See how existing context provider names like 'github', 'discord' are typed and how their options interfaces are structured.

2
core/context/providers/

Create a new file for your context provider (e.g., core/context/providers/MyNewContextProvider.ts). Implement the IContextProvider interface with getContextItems() and loadSubmenuItems() methods.

Pattern: See core/context/providers/GitHubIssuesContextProvider.ts for a provider that fetches from an external API, or core/context/providers/DiscordContextProvider.ts for one that handles multiple channels/submenu items.

3
core/context/index.ts

Register the new context provider in the context provider registry/factory. Import your provider and add it to the mapping from provider name string to provider class.

Pattern: See how existing providers like GitHubIssuesContextProvider and DiscordContextProvider are imported and registered in the provider map.

4
core/index.d.ts

If your provider needs configuration, add the config fields to the ContextProviderWithParams type or the relevant config interface.

Pattern: See how existing providers define their params (API keys, repo names, etc.) in the type definitions.

Conventions to follow:

Each context provider lives in its own file under core/context/providers/Provider class names follow the pattern {Name}ContextProviderProviders must implement getContextItems() which returns ContextItem[] and optionally loadSubmenuItems() for hierarchical selectionExternal API calls should use the fetch package from packages/fetch for SSL/proxy supportProvider names are lowercase strings used as identifiers in config

Add a new tool

1
core/index.d.ts

Define the tool's type interface including its name, description, parameters schema, and return type.

Pattern: See how existing tool types are defined with their parameter schemas and descriptions in the central type definitions.

2
core/tools/index.ts

Create the tool definition and register it in the tools system. Implement the tool's execute function that receives parameters and returns results.

Pattern: See how existing tools are defined with their JSON schema parameters, execution logic, and how they're registered in the tool registry.

3
core/core.ts

If the tool needs special handling or IDE integration, wire it into the core orchestrator's tool execution flow.

Pattern: See how existing tool calls are dispatched from the chat flow in core.ts — tools are invoked during LLM streaming when the model emits tool_call messages.

Conventions to follow:

Tools are defined with JSON Schema parameter definitions for LLM function callingTool execution functions receive validated parameters and return structured resultsTools that interact with the IDE must go through the IDE interface defined in core/index.d.ts, not directly access filesystem or editorMCP tools follow the Model Context Protocol and are managed separately in core/context/mcp/

Add a new slash command

1
core/index.d.ts

Add the slash command name to the SlashCommandName type union and define its description and parameter types.

Pattern: See how existing slash command names are typed in the central type definitions.

2
core/commands/index.ts

Create the slash command handler. Implement the command's run function that receives the user input and context, then produces output.

Pattern: See how existing slash commands are defined with their name, description, and async run() function that yields content items.

3
core/core.ts

Verify the command is picked up by the slash command dispatch logic in the core orchestrator. Most commands are auto-registered but some may need explicit wiring.

Pattern: See how the chat message handler in core.ts detects slash command prefixes and routes to the commands system.

Conventions to follow:

Slash commands are prefixed with '/' in user inputCommand handlers are async generators that yield content itemsCommands should be registered in core/commands/index.ts with name, description, and run functionCommands that need LLM access receive it through the context parameter, not by importing directly

Add a new configuration option

1
core/index.d.ts

Add the new config field to the appropriate configuration interface (e.g., SerializedContinueConfig, ModelDescription, etc.).

Pattern: See how existing config fields like 'model', 'provider', 'apiKey' are typed in the config interfaces.

2
packages/config-types/src/index.ts

Add the config field type to the shared config types package so it's available across all packages.

Pattern: See how existing shared config types are exported and used by both core and extension packages.

3
packages/config-yaml/src/index.ts

Update the YAML schema validation to accept and validate the new config field. Add default values if applicable.

Pattern: See how existing config fields are validated with their types, constraints, and defaults in the YAML schema.

4
core/config/index.ts

Handle the new config field in the config loading/resolution pipeline. Apply defaults, validate, and pass it to the appropriate subsystem.

Pattern: See how existing config fields are loaded from YAML/JSON, merged with defaults, and resolved into the runtime config object.

Conventions to follow:

Config types are defined in both core/index.d.ts and packages/config-types/src/index.ts — keep them in syncYAML config schema in packages/config-yaml must validate all config fieldsNew config fields should have sensible defaults so existing configs don't breakConfig resolution happens in core/config/ — that's where defaults are applied and validation occurs

Add a new MCP (Model Context Protocol) integration

1
core/context/mcp/index.ts

Add or modify the MCP server connection logic. Register the new MCP server type or modify how MCP connections are established.

Pattern: See how existing MCP server connections are managed — each server has a connection lifecycle (connect, list tools/resources, disconnect) and exposes tools and context through the MCP protocol.

2
core/tools/index.ts

If the MCP server provides tools, ensure they're properly surfaced through the tools system. MCP tools are dynamically discovered and registered.

Pattern: See how MCP tools are integrated alongside built-in tools — they follow the same tool interface but are discovered at runtime from MCP server connections.

3
packages/config-yaml/src/index.ts

Add the MCP server configuration to the YAML schema so users can configure the new MCP server in their config files.

Pattern: See how existing MCP server configs are defined in the YAML schema with their connection parameters (command, args, env, url).

Conventions to follow:

MCP integrations live in core/context/mcp/MCP servers are configured in YAML config and connected at runtimeMCP tools are dynamically discovered — don't hardcode tool definitions for MCP serversMCP connections should handle reconnection and error states gracefully

Add a new indexing pipeline or codebase indexer

1
core/indexing/index.ts

Create or register the new indexing pipeline. Define how documents are chunked, embedded, and stored.

Pattern: See how existing indexing pipelines handle the flow: file discovery → chunking → embedding generation → storage in the index.

2
core/index.d.ts

Define any new types needed for the indexing pipeline (e.g., new chunk types, index entry types, query result types).

Pattern: See how existing indexing types like CodebaseIndex, IndexTag, and chunk types are defined.

3
core/core.ts

Wire the new indexing pipeline into the core orchestrator so it's triggered during indexing operations (on workspace open, file changes, etc.).

Pattern: See how existing indexing is triggered from core.ts — indexing runs on workspace initialization and file change events.

Conventions to follow:

Indexing pipelines live in core/indexing/Indexers should be incremental — only re-index changed files, not the entire codebaseEmbedding generation should use the LLM abstraction layer, not call embedding APIs directlyIndex storage should support the existing tag-based invalidation system

Add a new package to the monorepo

1
scripts/build-packages.js

Add the new package to the build order array. Place it after its dependencies and before packages that depend on it.

Pattern: See how existing packages like 'packages/config-yaml', 'packages/openai-adapters', 'packages/llm-info' are ordered in the build script based on their dependency relationships.

2
packages/shared-release.config.js

If the package needs publishing, use the shared release config factory to create a release configuration for the new package.

Pattern: See how packages/shared-release.config.js exports a factory function that other packages use to generate their semantic-release config.

3
core/index.d.ts

If the new package exports types used by core, import and re-export them from the central type definitions.

Pattern: See how types from packages/config-types are referenced in core/index.d.ts.

Conventions to follow:

Each package has its own package.json, tsconfig.json, and build configurationPackages use the shared release config from packages/shared-release.config.js for semantic-releaseBuild order in scripts/build-packages.js must respect dependency graph — a package must be built after all its dependenciesShared types should be in packages/config-types or core/index.d.ts, not duplicated across packages

Add or modify GUI styling and design tokens

1
gui/tailwind.config.cjs

Add new design tokens (colors, spacing, breakpoints) to the Tailwind configuration. Extend the theme object with your new values.

Pattern: See how existing custom colors, breakpoints, and design tokens are defined in the theme.extend section of gui/tailwind.config.cjs.

2
gui/postcss.config.cjs

If you need new PostCSS plugins for CSS processing, add them to the PostCSS configuration.

Pattern: See how existing PostCSS plugins (tailwindcss, autoprefixer) are configured in gui/postcss.config.cjs.

Conventions to follow:

Use Tailwind utility classes rather than custom CSS when possibleCustom design tokens go in gui/tailwind.config.cjs under theme.extendColor values should use CSS custom properties for theme support (light/dark mode)Breakpoints should be consistent with the existing responsive design system

Coding Conventions

Standards and patterns used in this codebase

Build & Bundling

Use esbuild for bundling TypeScript into single-file outputs with explicit external dependencies, platform/architecture targeting, and CommonJS format

esbuild.build({ entryPoints: ['src/index.ts'], bundle: true, outfile: 'out/index.cjs', platform: 'node', format: 'cjs', external: ['esbuild', '@esbuild/*', '@lancedb/*', ...] })
binary/build.js
Testing Configuration

Use Jest with ts-jest for TypeScript testing, with explicit transform patterns for ts/tsx/js/jsx files and moduleNameMapper for path aliases or module stubs

module.exports = { transform: { '^.+\\.tsx?$': 'ts-jest', '^.+\\.jsx?$': ['ts-jest', { tsconfig: { allowJs: true } }] }, moduleNameMapper: { 'azure/identity': '<rootDir>/test_util/mock_modules/azure_identity.js' } }
core/jest.config.jsbinary/jest.config.js
TypeScript Type Definitions

Define comprehensive interface hierarchies in .d.ts declaration files with extensive use of union types, optional properties, and discriminated unions for protocol messages and configuration

interface LLMOptions { model: string; title?: string; completionOptions?: CompletionOptions; requestOptions?: RequestOptions; ... } type ChatMessage = { role: MessageRole; content: MessageContent; }
core/index.d.ts
Architecture Pattern

Use a central orchestrator class that wires subsystems together via constructor injection of an IDE abstraction interface, with lazy initialization of services and messenger-based IPC communication

export class Core { constructor(private messenger: IMessenger<...>, private ide: IDE) { this.configHandler = new ConfigHandler(...); this.codebaseIndexer = new CodebaseIndexer(...); this.completionProvider = new CompletionProvider(...); } }
core/core.ts
Message Protocol

Define typed message handlers using string literal message types mapped to handler functions, with request/response patterns communicated over IPC between core, IDE, and webview layers

on('llm/streamChat', (msg) => { ... }); on('config/reload', (msg) => { ... }); on('context/getContextItems', (msg) => { ... });
core/core.ts
Environment & Dev Server

Development entry points set environment variables before importing application code, using process.env flags to toggle development mode and configure paths

process.env.CONTINUE_DEVELOPMENT = 'true'; process.env.CONTINUE_GLOBAL_DIR = path.join(__dirname, '..', '.continue'); require('./out/index.cjs');
binary/core-dev-server.js
Configuration System

Support multiple configuration formats (YAML, JSON, markdown prompt files) with profile management, merging strategies, and schema validation, resolved through a unified ConfigHandler

configHandler.loadConfig() resolves YAML config, JSON config, and prompt files into a unified ContinueConfig object with profile-based overrides
core/core.ts
Async Generators

Use async generator functions (async function*) for streaming LLM responses and incremental results, yielding chunks that consumers can iterate with for-await-of

async *streamChat(messages: ChatMessage[], options: LLMFullCompletionOptions): AsyncGenerator<ChatMessage> { for await (const chunk of this.llm.streamChat(messages)) { yield chunk; } }
core/core.ts
Testing Framework

Support both Jest and Vitest test runners across packages, with Vitest preferred for newer code using defineConfig with explicit include/exclude patterns

export default defineConfig({ test: { include: ['**/*.test.ts'], exclude: ['node_modules', 'dist'] } });
core/vitest.config.tscore/jest.config.js
External Dependencies

Explicitly externalize native modules and platform-specific packages in build configurations to avoid bundling issues with binary addons

external: ['esbuild', '@esbuild/*', '@lancedb/*', 'onnxruntime-node', 'sqlite3', '@vscode/*', 'fsevents']
binary/build.js
Code Style

Use fluent/method-chaining patterns in utility classes, with methods returning 'this' to enable composable API calls

class Calculator { add(a) { this.result += a; return this; } subtract(a) { this.result -= a; return this; } }
manual-testing-sandbox/Calculator.javamanual-testing-sandbox/program.csmanual-testing-sandbox/test.js