Configuration Service
The Configuration Service (IConfigurationService) is a core platform service that manages all configuration settings in Visual Studio Code. It provides access to user, workspace, and folder-specific settings with support for overrides and multiple configuration targets.
Service Overview
The Configuration Service is defined in src/vs/platform/configuration/common/configuration.ts:14 and provides a unified interface for reading and writing configuration values across different scopes.
Service Identifier
export const IConfigurationService = createDecorator < IConfigurationService >( 'configurationService' );
Dependency Injection
The Configuration Service is injected using VS Code’s dependency injection system:
import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
export class MyService {
constructor (
@ IConfigurationService private readonly configurationService : IConfigurationService
) {}
public async initialize () : Promise < void > {
const autoSave = this . configurationService . getValue < string >( 'files.autoSave' );
console . log ( `Auto save mode: ${ autoSave } ` );
}
}
Core Methods
getValue()
Retrieves configuration values with support for sections and overrides.
The configuration section to retrieve (e.g., editor.fontSize)
Overrides for resource or override identifier
// Get entire configuration
const allConfig = configurationService . getValue ();
// Get specific section
const fontSize = configurationService . getValue < number >( 'editor.fontSize' );
// Get with resource override
const config = configurationService . getValue ( 'editor' , {
resource: URI . file ( '/path/to/file.ts' )
});
// Get with language override
const pythonConfig = configurationService . getValue ( 'editor' , {
overrideIdentifier: 'python'
});
updateValue()
Updates configuration values at different targets (user, workspace, folder).
The configuration key to update
The new value (use undefined to remove)
Where to store the setting (USER, WORKSPACE, WORKSPACE_FOLDER, etc.)
Resource or override identifiers for scoped updates
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration' ;
// Update user settings
await configurationService . updateValue (
'editor.fontSize' ,
14 ,
ConfigurationTarget . USER
);
// Update workspace settings
await configurationService . updateValue (
'files.autoSave' ,
'afterDelay' ,
ConfigurationTarget . WORKSPACE
);
// Remove a setting (set to default)
await configurationService . updateValue (
'editor.tabSize' ,
undefined ,
ConfigurationTarget . USER
);
// Update with resource override
await configurationService . updateValue (
'editor.formatOnSave' ,
true ,
{ resource: URI . file ( '/path/to/file.ts' ) },
ConfigurationTarget . WORKSPACE_FOLDER
);
inspect()
Inspects a configuration key to see values at all scopes.
The configuration key to inspect
Resource or override identifier context
const inspected = configurationService . inspect < number >( 'editor.fontSize' );
console . log ( 'Default value:' , inspected . defaultValue );
console . log ( 'User value:' , inspected . userValue );
console . log ( 'Workspace value:' , inspected . workspaceValue );
console . log ( 'Workspace folder value:' , inspected . workspaceFolderValue );
console . log ( 'Effective value:' , inspected . value );
The inspect() method is particularly useful for understanding configuration precedence and debugging why a particular value is active.
reloadConfiguration()
Reloads configuration from disk.
// Reload all configuration
await configurationService . reloadConfiguration ();
// Reload specific target
await configurationService . reloadConfiguration ( ConfigurationTarget . USER );
// Reload workspace folder
await configurationService . reloadConfiguration ( workspaceFolder );
keys()
Retrieves all configuration keys organized by scope.
const keys = configurationService . keys ();
console . log ( 'Default keys:' , keys . default );
console . log ( 'User keys:' , keys . user );
console . log ( 'Workspace keys:' , keys . workspace );
console . log ( 'Workspace folder keys:' , keys . workspaceFolder );
console . log ( 'Policy keys:' , keys . policy );
Configuration Targets
Configuration can be stored at different levels:
export const enum ConfigurationTarget {
APPLICATION = 1 , // Application-wide settings
USER , // User settings (USER_LOCAL or USER_REMOTE)
USER_LOCAL , // Local user settings
USER_REMOTE , // Remote user settings
WORKSPACE , // Workspace settings
WORKSPACE_FOLDER , // Workspace folder settings
DEFAULT , // Default settings (read-only)
MEMORY // In-memory settings (temporary)
}
Settings follow a precedence order (highest to lowest):
WORKSPACE_FOLDER - Folder-specific settings
WORKSPACE - Workspace settings
USER_REMOTE - Remote user settings
USER_LOCAL - Local user settings
APPLICATION - Application settings
DEFAULT - Default values
Configuration Overrides
Overrides allow scoping configuration to specific contexts:
// Get configuration for a specific file
const config = configurationService . getValue ( 'editor' , {
resource: URI . file ( '/workspace/src/main.py' )
});
// This will return workspace folder settings for that file
// Get Python-specific settings
const pythonSettings = configurationService . getValue ( 'editor' , {
overrideIdentifier: 'python'
});
// Settings like [python] in settings.json take precedence
Events
onDidChangeConfiguration
Fired when configuration changes.
import { IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration' ;
const disposable = configurationService . onDidChangeConfiguration (
( event : IConfigurationChangeEvent ) => {
// Check if specific setting changed
if ( event . affectsConfiguration ( 'editor.fontSize' )) {
const newSize = configurationService . getValue < number >( 'editor.fontSize' );
console . log ( 'Font size changed to:' , newSize );
}
// Check with overrides
if ( event . affectsConfiguration ( 'editor.formatOnSave' , {
resource: myFileUri
})) {
console . log ( 'Format on save changed for this file' );
}
// Check what changed
console . log ( 'Changed keys:' , Array . from ( event . affectedKeys ));
console . log ( 'Change source:' , ConfigurationTarget [ event . source ]);
}
);
// Remember to dispose!
disposable . dispose ();
Configuration Data Model
Represents a configuration value at all scopes: interface IConfigurationValue < T > {
readonly defaultValue ?: T ; // Default value
readonly applicationValue ?: T ; // Application scope
readonly userValue ?: T ; // User scope (combined)
readonly userLocalValue ?: T ; // Local user scope
readonly userRemoteValue ?: T ; // Remote user scope
readonly workspaceValue ?: T ; // Workspace scope
readonly workspaceFolderValue ?: T ; // Workspace folder scope
readonly memoryValue ?: T ; // In-memory value
readonly policyValue ?: T ; // Policy value (managed)
readonly value ?: T ; // Effective value (resolved)
readonly overrideIdentifiers ?: string []; // Available overrides
}
Common Use Cases
Reading User Preferences
export class EditorWidget {
constructor (
@ IConfigurationService private configService : IConfigurationService
) {
this . updateFromConfig ();
this . configService . onDidChangeConfiguration ( e => {
if ( e . affectsConfiguration ( 'editor' )) {
this . updateFromConfig ();
}
});
}
private updateFromConfig () : void {
const fontSize = this . configService . getValue < number >( 'editor.fontSize' );
const fontFamily = this . configService . getValue < string >( 'editor.fontFamily' );
const tabSize = this . configService . getValue < number >( 'editor.tabSize' );
this . applySettings ({ fontSize , fontFamily , tabSize });
}
}
Writing Settings Programmatically
import { IConfigurationService , ConfigurationTarget } from 'vs/platform/configuration/common/configuration' ;
export class SettingsManager {
constructor (
@ IConfigurationService private configService : IConfigurationService
) {}
async enableAutoSave () : Promise < void > {
await this . configService . updateValue (
'files.autoSave' ,
'afterDelay' ,
ConfigurationTarget . USER
);
await this . configService . updateValue (
'files.autoSaveDelay' ,
1000 ,
ConfigurationTarget . USER
);
}
async setLanguageSpecific ( language : string , settings : any ) : Promise < void > {
const key = `[ ${ language } ]` ;
await this . configService . updateValue (
key ,
settings ,
ConfigurationTarget . USER
);
}
}
Respecting Workspace Settings
export class FeatureService {
constructor (
@ IConfigurationService private configService : IConfigurationService
) {}
isFeatureEnabled ( feature : string , resource ?: URI ) : boolean {
// Get setting with resource context
const enabled = this . configService . getValue < boolean >(
`features. ${ feature } ` ,
{ resource }
);
return enabled ?? false ;
}
async toggleFeature ( feature : string , enabled : boolean ) : Promise < void > {
// Inspect to see where it's currently set
const inspected = this . configService . inspect < boolean >( `features. ${ feature } ` );
// Update at the most specific scope that's already configured
let target = ConfigurationTarget . USER ;
if ( inspected . workspaceFolderValue !== undefined ) {
target = ConfigurationTarget . WORKSPACE_FOLDER ;
} else if ( inspected . workspaceValue !== undefined ) {
target = ConfigurationTarget . WORKSPACE ;
}
await this . configService . updateValue ( `features. ${ feature } ` , enabled , target );
}
}
Best Practices
Configuration Keys : Use dot-notation for configuration keys (e.g., editor.fontSize, files.autoSave). This creates a logical hierarchy in the settings UI.
Event Listeners : Always dispose of configuration change listeners to prevent memory leaks. Use affectsConfiguration() to filter relevant changes.
Resource Context : When working with file-specific features, always pass the resource URI to getValue() to respect workspace folder settings.
Undefined vs Null : Setting a value to undefined removes it and falls back to defaults. Use null if you need to explicitly store a null value.
IWorkspaceContextService - Provides workspace and folder context
IEnvironmentService - Provides paths to settings files
IFileService - Used internally to read/write settings files
See Also