# Understanding the Core Config Directory Structure in the Continue IDE

> Explore the core config directory structure in the Continue IDE. Learn how it transforms user-authored files into runtime configurations vital for the project architecture.

- Repository: [Continue/continue](https://github.com/continuedev/continue)
- Tags: architecture
- Published: 2026-06-18

---

**The `core/config` directory serves as the central nervous system of the Continue IDE, transforming static user-authored YAML and Markdown files into strongly-typed runtime configuration objects that power the entire application architecture.**

The `continuedev/continue` repository organizes its configuration logic within the `core/config` package, establishing a clear separation between user-facing configuration files and the internal runtime state. This architectural decision enables multiple IDE extensions—VS Code, JetBrains, and others—to consume a unified configuration API while maintaining consistent behavior across platforms.

## The Architectural Role of `core/config`

The configuration layer acts as a **single source of truth** that bridges the gap between user-editable files and the live application state. When a user modifies [`.continue/config.yaml`](https://github.com/continuedev/continue/blob/main/.continue/config.yaml) or creates a new profile in `.continue/profiles/`, the `core/config` package handles validation, parsing, and distribution of those changes to the LLM orchestration layer, context providers, and web-based UI components.

At the top of this hierarchy sits **[`ConfigHandler.ts`](https://github.com/continuedev/continue/blob/main/ConfigHandler.ts)**, which exposes an async API that the rest of the repository depends on. The handler coordinates multiple specialized loaders to build a complete `ContinueConfig` object defined in [`core/types.ts`](https://github.com/continuedev/continue/blob/main/core/types.ts).

## Directory Layout and Key Responsibilities

The `core/config` package is organized into functional subdirectories, each handling a specific aspect of configuration management:

### YAML Parsing and Validation

The `yaml/` subdirectory contains the low-level parsing logic. The file **[`loadYaml.ts`](https://github.com/continuedev/continue/blob/main/loadYaml.ts)** reads raw YAML content, validates it against the expected schema, and returns a `ConfigResult<ContinueConfig>` type. This is the entry point for converting static text into typed objects.

### Profile Management

The `profile/` directory handles **profiles**—discrete sets of configuration that users can swap at runtime. Key implementations include:

- **[`LocalProfileLoader.ts`](https://github.com/continuedev/continue/blob/main/LocalProfileLoader.ts)** – Reads a single profile from a file or folder and constructs a valid `ContinueConfig` instance
- **[`ProfileLifecycleManager.ts`](https://github.com/continuedev/continue/blob/main/ProfileLifecycleManager.ts)** – Manages creation, selection, and cleanup of profiles (located at the top level of `core/config/`)

### Workspace-Scoped Configuration

The `workspace/` subdirectory contains **[`workspaceBlocks.ts`](https://github.com/continuedev/continue/blob/main/workspaceBlocks.ts)**, which loads configuration specific to individual workspace directories. This includes rule-dot-files that live alongside project code, allowing teams to commit shared configuration into version control.

### Markdown-Based Rules

The `markdown/` directory enables declarative configuration through Markdown files. **[`loadMarkdownRules.ts`](https://github.com/continuedev/continue/blob/main/loadMarkdownRules.ts)** parses these files to extract *skills* and *rules* that surface as quick commands in the UI, bridging documentation and executable configuration.

### Shared and Utility Components

- **[`sharedConfig.ts`](https://github.com/continuedev/continue/blob/main/sharedConfig.ts)** – Stores global values like `allowAnonymousTelemetry` that persist across all profiles
- **[`util/validation.ts`](https://github.com/continuedev/continue/blob/main/util/validation.ts)** – Contains validation helpers used throughout the loading pipeline
- **[`loadLocalAssistants.ts`](https://github.com/continuedev/continue/blob/main/loadLocalAssistants.ts)** – Discovers `.continue/agents`, `.continue/assistants`, and `.continue/configs` files across the workspace

## The Configuration Loading Pipeline

The relationship between `core/config` and the overall architecture follows a clear data flow:

```

+-------------------+          +-------------------+
|   IDE (VS Code,   |  <--->   |   ConfigHandler   |
|   JetBrains, ...) |          |   (core/config)   |
+-------------------+          +-------------------+
         ^                               ^
         |                               |
   UI actions                 loadYaml    loadLocalAssistants
   (refresh, change profile)      |             |
                                  v             v
                         +-----------------------------+
                         |   ContinueConfig (type)     |
                         |   (core/types.ts)           |
                         +-----------------------------+

```

**IDE Integration** – IDE implementations in `extensions/vscode` and `extensions/intellij` instantiate `ConfigHandler`, passing a concrete `IDE` interface implementation. The handler uses this interface to discover workspace directories via `ide.getWorkspaceDirs()` and to read file contents.

**Profile Discovery** – On startup, `ConfigHandler` calls `loadProfiles()`, which invokes [`loadLocalAssistants.ts`](https://github.com/continuedev/continue/blob/main/loadLocalAssistants.ts) to scan for configuration files. Each discovered file receives its own `LocalProfileLoader` instance.

**Serialization for UI** – The web UI consumes configuration through `ConfigHandler.getSerializedConfig()`, which returns a `BrowserSerializedContinueConfig` object safe for transmission over the webview bridge.

## Key Implementation Files

| File | Role |
|------|------|
| [`core/config/ConfigHandler.ts`](https://github.com/continuedev/continue/blob/main/core/config/ConfigHandler.ts) | Central orchestrator that loads profiles, merges configs, and exposes the async API |
| [`core/config/loadLocalAssistants.ts`](https://github.com/continuedev/continue/blob/main/core/config/loadLocalAssistants.ts) | Discovers agent and assistant definitions across the workspace |
| [`core/config/profile/LocalProfileLoader.ts`](https://github.com/continuedev/continue/blob/main/core/config/profile/LocalProfileLoader.ts) | Reads individual profile files and builds typed configuration objects |
| [`core/config/yaml/loadYaml.ts`](https://github.com/continuedev/continue/blob/main/core/config/yaml/loadYaml.ts) | Transforms YAML strings into typed `ContinueConfig` instances |
| [`core/config/workspace/workspaceBlocks.ts`](https://github.com/continuedev/continue/blob/main/core/config/workspace/workspaceBlocks.ts) | Handles per-workspace rule files |
| [`core/config/markdown/loadMarkdownRules.ts`](https://github.com/continuedev/continue/blob/main/core/config/markdown/loadMarkdownRules.ts) | Loads Markdown-based skill definitions |
| [`core/config/ProfileLifecycleManager.ts`](https://github.com/continuedev/continue/blob/main/core/config/ProfileLifecycleManager.ts) | Manages profile state transitions |
| [`core/config/sharedConfig.ts`](https://github.com/continuedev/continue/blob/main/core/config/sharedConfig.ts) | Houses cross-profile global settings |

## Practical Code Examples

### Instantiating the ConfigHandler

IDE extensions initialize the configuration layer by creating a `ConfigHandler` instance with the appropriate dependencies:

```typescript
import { ConfigHandler } from "core/config/ConfigHandler.js";
import { MyIDE } from "./my-ide.js";
import { MyLogger } from "./my-logger.js";

const ide = new MyIDE();               // implements the IDE interface
const llmLogger = new MyLogger();      // implements ILLMLogger

// Construction triggers initial loading
const cfgHandler = new ConfigHandler(ide, llmLogger);

// Wait for initialization before accessing config
await cfgHandler.isInitialized;

// Retrieve the fully-resolved configuration
const configResult = await cfgHandler.loadConfig();
console.log("Loaded models:", configResult.config?.models.map(m => m.model));

```

### Reacting to Configuration Changes

When users edit configuration files, the IDE extension triggers a refresh:

```typescript
// File-watcher handler within the IDE extension
ide.onFileChange(async (filepath) => {
  if (filepath.endsWith("config.yaml")) {
    // Force cascade reload of all profiles
    await cfgHandler.refreshAll("User edited config.yaml");
  }
});

```

### Registering Custom Context Providers at Runtime

Extensions can inject custom functionality by registering context providers directly with the handler:

```typescript
import type { IContextProvider } from "core/index.js";

class PrivateKnowledgeProvider implements IContextProvider {
  get description() {
    return {
      title: "private-knowledge",
      displayTitle: "Private Knowledge Base",
      description: "Queries internal documentation",
      type: "normal",
    };
  }

  async getContextItems(query, extras) {
    // Implementation details...
    return [{ content: "Result", name: "doc", description: "Internal doc" }];
  }

  async loadSubmenuItems() { return []; }
}

// Register after ConfigHandler initialization
cfgHandler.registerCustomContextProvider(new PrivateKnowledgeProvider());

```

## Summary

- The **`core/config`** package translates static YAML and Markdown files into the live `ContinueConfig` objects that drive the application
- **[`ConfigHandler.ts`](https://github.com/continuedev/continue/blob/main/ConfigHandler.ts)** serves as the central coordinator, managing profile loading, shared configuration, and UI serialization
- The directory is organized by function: `yaml/` for parsing, `profile/` for runtime profiles, `workspace/` for project-specific rules, and `markdown/` for skill definitions
- All IDE extensions depend on this layer, consuming configuration through the async API exposed by `ConfigHandler`
- The architecture supports hot-reloading through `refreshAll()` and runtime extensibility via `registerCustomContextProvider()`

## Frequently Asked Questions

### What is the difference between profiles and workspace configuration in Continue?

**Profiles** are complete configuration sets managed by [`LocalProfileLoader.ts`](https://github.com/continuedev/continue/blob/main/LocalProfileLoader.ts) and [`ProfileLifecycleManager.ts`](https://github.com/continuedev/continue/blob/main/ProfileLifecycleManager.ts) that define models, context providers, and commands. **Workspace configuration** refers to rule files specific to a project directory, loaded by [`workspaceBlocks.ts`](https://github.com/continuedev/continue/blob/main/workspaceBlocks.ts), which augment the active profile with project-specific constraints without replacing it.

### How does Continue handle configuration changes while the IDE is running?

The `ConfigHandler` exposes a `refreshAll()` method that re-parses all configuration files and rebuilds the internal state. IDE extensions trigger this method through file watchers when they detect changes to [`.continue/config.yaml`](https://github.com/continuedev/continue/blob/main/.continue/config.yaml) or related files, ensuring the runtime state stays synchronized with disk contents.

### Where are the TypeScript interfaces for Continue's configuration defined?

The primary type definitions reside in **[`core/types.ts`](https://github.com/continuedev/continue/blob/main/core/types.ts)**, which declares the `ContinueConfig` interface and all related types. The [`yaml/loadYaml.ts`](https://github.com/continuedev/continue/blob/main/yaml/loadYaml.ts) module validates raw configuration against these types, returning a `ConfigResult<ContinueConfig>` that guarantees type safety throughout the application.

### How does the ConfigHandler communicate configuration to the web-based UI?

The handler provides `getSerializedConfig()`, which returns a `BrowserSerializedContinueConfig` object. This stripped-down, serializable representation crosses the webview bridge to the React-based UI, allowing the settings panel and chat interface to reflect the current configuration without exposing internal implementation details.