Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
CodinGame Monaco VSCode API
https://github.com/codingame/monaco-vscode-api
Admin
An NPM module that integrates full VSCode functionality, including services and extensions, into the
...
Tokens:
25,962
Snippets:
270
Trust Score:
7.2
Update:
3 weeks ago
Context
Skills
Chat
Benchmark
70.8
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# @codingame/monaco-vscode-api This NPM module allows integrating full VSCode functionality into your Monaco editor. It provides the VSCode API, enabling features like themes, textmate grammars, language servers, extensions, and many other VSCode capabilities in web-based applications. The package works by overriding Monaco's simplified "standalone" services with fully-functional VSCode alternatives. The library is designed as a drop-in enhancement for monaco-editor, allowing developers to progressively add VSCode features as needed. It publishes the VSCode API as `@codingame/monaco-vscode-extension-api` (aliased to `vscode`) and an enhanced Monaco editor as `@codingame/monaco-vscode-editor-api` (aliased to `monaco-editor`), enabling seamless integration with existing Monaco-based applications and VSCode extension development patterns. ## Installation and Basic Setup Install the core packages to get started with monaco-vscode-api. The packages are aliased to allow importing with standard `vscode` and `monaco-editor` module names. ```bash npm install @codingame/monaco-vscode-api npm install vscode@npm:@codingame/monaco-vscode-extension-api npm install monaco-editor@npm:@codingame/monaco-vscode-editor-api npm install -D @types/vscode ``` ## Initialize Services The `initialize` function must be called once before creating any editors. It accepts service overrides that enable specific VSCode functionality. ```typescript import * as monaco from 'monaco-editor' import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' import { initialize } from '@codingame/monaco-vscode-api' import getConfigurationServiceOverride, { updateUserConfiguration } from '@codingame/monaco-vscode-configuration-service-override' // Configure Monaco worker window.MonacoEnvironment = { getWorker: (_moduleId, _label) => new editorWorker() } // Initialize with service overrides (must be called BEFORE creating editors) await initialize({ ...getConfigurationServiceOverride() }) // Now create your editor monaco.editor.create(document.getElementById('editor')!, { value: 'console.log("Hello World")', language: 'javascript' }) // Update configuration programmatically (like vscode settings.json) updateUserConfiguration(`{ "editor.fontSize": 16, "editor.lineHeight": 24, "editor.fontFamily": "Fira Code", "editor.minimap.enabled": false }`) ``` ## Enable Theme and Syntax Highlighting Use the theme and textmate service overrides to enable VSCode themes and TextMate grammar-based syntax highlighting. ```typescript import '@codingame/monaco-vscode-theme-defaults-default-extension' import '@codingame/monaco-vscode-python-default-extension' import * as monaco from 'monaco-editor' import { initialize } from '@codingame/monaco-vscode-api' import getThemeServiceOverride from '@codingame/monaco-vscode-theme-service-override' import getTextmateServiceOverride from '@codingame/monaco-vscode-textmate-service-override' import getLanguagesServiceOverride from '@codingame/monaco-vscode-languages-service-override' // Configure workers const workerLoaders = { TextEditorWorker: () => new Worker( new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url), { type: 'module' } ), TextMateWorker: () => new Worker( new URL('@codingame/monaco-vscode-textmate-service-override/worker', import.meta.url), { type: 'module' } ) } window.MonacoEnvironment = { getWorker(_workerId, label) { const factory = workerLoaders[label] if (factory) return factory() throw new Error(`Worker ${label} not found`) } } // Initialize services for themes and highlighting await initialize({ ...getThemeServiceOverride(), ...getTextmateServiceOverride(), ...getLanguagesServiceOverride() }) // Create editor with Python highlighting monaco.editor.create(document.getElementById('editor')!, { value: `import numpy as np def calculate_mean(data): """Calculate the arithmetic mean.""" return np.mean(data) result = calculate_mean([1, 2, 3, 4, 5]) print(f"Mean: {result}")`, language: 'python' }) ``` ## Register Custom Extensions Register custom VSCode extensions programmatically with the registerExtension function. This enables extension-like functionality without publishing to a marketplace. ```typescript import { registerExtension, ExtensionHostKind } from '@codingame/monaco-vscode-api/extensions' import { initialize } from '@codingame/monaco-vscode-api' import 'vscode/localExtensionHost' await initialize({}) // Register a custom extension const { registerFileUrl, getApi } = registerExtension({ name: 'my-custom-extension', publisher: 'my-company', version: '1.0.0', engines: { vscode: '*' }, contributes: { commands: [{ command: 'myExtension.helloWorld', title: 'Hello World' }] } }, ExtensionHostKind.LocalProcess) // Register extension files (for bundled assets) registerFileUrl('/package.json', new URL('./package.json', import.meta.url).toString()) // Get the VSCode API and use it like a real extension const vscode = await getApi() // Register a command vscode.commands.registerCommand('myExtension.helloWorld', () => { vscode.window.showInformationMessage('Hello from custom extension!') }) // Create diagnostics collection const diagnostics = vscode.languages.createDiagnosticCollection('my-linter') diagnostics.set(vscode.Uri.file('/workspace/test.js'), [ { range: new vscode.Range(0, 0, 0, 10), severity: vscode.DiagnosticSeverity.Warning, message: 'This is a warning from custom extension', source: 'my-linter' } ]) // Register a completion provider vscode.languages.registerCompletionItemProvider('javascript', { provideCompletionItems(document, position) { return [ { label: 'myCustomSnippet', kind: vscode.CompletionItemKind.Snippet, insertText: 'console.log($1);', documentation: 'Custom logging snippet' } ] } }) ``` ## File System Provider Use the files service override to work with virtual file systems. The RegisteredFileSystemProvider allows registering files in memory. ```typescript import * as monaco from 'monaco-editor' import * as vscode from 'vscode' import { RegisteredFileSystemProvider, RegisteredMemoryFile, RegisteredReadOnlyFile, registerFileSystemOverlay } from '@codingame/monaco-vscode-files-service-override' import { initialize } from '@codingame/monaco-vscode-api' await initialize({}) // Create a file system provider const fileSystemProvider = new RegisteredFileSystemProvider(false) // Register writable files fileSystemProvider.registerFile( new RegisteredMemoryFile( vscode.Uri.file('/workspace/index.ts'), `export function greet(name: string): string { return \`Hello, \${name}!\` } console.log(greet('World'))` ) ) // Register a read-only file const readOnlyContent = new TextEncoder().encode('// This file is read-only') fileSystemProvider.registerFile( new RegisteredReadOnlyFile( vscode.Uri.file('/workspace/readonly.ts'), async () => readOnlyContent, readOnlyContent.length ) ) // Register configuration file fileSystemProvider.registerFile( new RegisteredMemoryFile( vscode.Uri.file('/workspace/tsconfig.json'), JSON.stringify({ compilerOptions: { target: 'ES2020', module: 'ESNext', strict: true } }, null, 2) ) ) // Mount the file system with priority 1 (higher than default memory FS at 0) const disposable = registerFileSystemOverlay(1, fileSystemProvider) // Create model reference (preferred over createModel for VSCode integration) const modelRef = await monaco.editor.createModelReference( monaco.Uri.file('/workspace/index.ts') ) const editor = monaco.editor.create(document.getElementById('editor')!, { model: modelRef.object.textEditorModel }) // Save the file await modelRef.object.save() // Cleanup when done modelRef.dispose() editor.dispose() disposable.dispose() ``` ## Configuration and Keybindings Configure user settings and keybindings before initialization using initUserConfiguration and initUserKeybindings. ```typescript import { initialize } from '@codingame/monaco-vscode-api' import getConfigurationServiceOverride, { initUserConfiguration, updateUserConfiguration } from '@codingame/monaco-vscode-configuration-service-override' import getKeybindingsServiceOverride, { initUserKeybindings } from '@codingame/monaco-vscode-keybindings-service-override' // Initialize configuration BEFORE initialize() to prevent flickering await initUserConfiguration(`{ "editor.fontSize": 14, "editor.tabSize": 2, "editor.wordWrap": "on", "editor.formatOnSave": true, "workbench.colorTheme": "Default Dark+" }`) // Initialize custom keybindings await initUserKeybindings(`[ { "key": "ctrl+shift+f", "command": "editor.action.formatDocument" }, { "key": "ctrl+d", "command": "editor.action.addSelectionToNextFindMatch" } ]`) // Now initialize services await initialize({ ...getConfigurationServiceOverride(), ...getKeybindingsServiceOverride() }) // Update configuration at runtime updateUserConfiguration(`{ "editor.fontSize": 16, "editor.minimap.enabled": false }`) ``` ## Remote Agent (VSCode Server) Connect to a remote VSCode server for filesystem access, terminal support, and running non-web extensions. ```typescript import { initialize, LogLevel } from '@codingame/monaco-vscode-api' import * as monaco from 'monaco-editor' import getRemoteAgentServiceOverride from '@codingame/monaco-vscode-remote-agent-service-override' import getTerminalServiceOverride from '@codingame/monaco-vscode-terminal-service-override' // Server must be running: ./bin/code-server --port 8080 --without-connection-token const remoteAuthority = 'localhost:8080' await initialize({ ...getRemoteAgentServiceOverride({ scanRemoteExtensions: true }), ...getTerminalServiceOverride() }, { remoteAuthority, // Optional: connectionToken: 'your-token-here', workspaceProvider: { trusted: true, async open() { return true }, workspace: { folderUri: monaco.Uri.from({ scheme: 'vscode-remote', authority: remoteAuthority, path: '/home/user/project' // Remote path }) } }, developmentOptions: { logLevel: LogLevel.Info } }) ``` ## Load VSIX Extensions Use the rollup/vite plugin to load VSCode extensions from VSIX files. ```typescript // vite.config.ts import vsixPlugin from '@codingame/monaco-vscode-rollup-vsix-plugin' export default { plugins: [ vsixPlugin() ] } ``` ```typescript // In your application code, import vsix files directly import './my-extension.vsix' // Or load extensions from Open VSX / marketplace import { initialize } from '@codingame/monaco-vscode-api' import getExtensionGalleryServiceOverride from '@codingame/monaco-vscode-extension-gallery-service-override' await initialize({ ...getExtensionGalleryServiceOverride({ webOnly: false }) }, { productConfiguration: { extensionsGallery: { serviceUrl: 'https://open-vsx.org/vscode/gallery', resourceUrlTemplate: 'https://open-vsx.org/vscode/unpkg/{publisher}/{name}/{version}/{path}' } } }) ``` ## Localization Enable localized UI by importing language packs. Language packs must be imported before any other monaco-vscode-api imports. ```typescript // MUST be the first import import '@codingame/monaco-vscode-language-pack-fr' // Then import everything else import * as monaco from 'monaco-editor' import { initialize } from '@codingame/monaco-vscode-api' import getLocalizationServiceOverride from '@codingame/monaco-vscode-localization-service-override' await initialize({ ...getLocalizationServiceOverride({ async setLocale(id) { // Handle locale change (e.g., reload page with locale param) const url = new URL(window.location.href) url.searchParams.set('locale', id) window.location.href = url.toString() }, async clearLocale() { const url = new URL(window.location.href) url.searchParams.delete('locale') window.location.href = url.toString() }, availableLanguages: [ { locale: 'en', languageName: 'English' }, { locale: 'fr', languageName: 'French' }, { locale: 'de', languageName: 'German' }, { locale: 'ja', languageName: 'Japanese' }, { locale: 'zh-hans', languageName: 'Chinese (Simplified)' } ] }) }) ``` ## Full Workbench Setup Create a complete VSCode-like workbench with all panels, views, and features. ```typescript import '@codingame/monaco-vscode-theme-defaults-default-extension' import '@codingame/monaco-vscode-javascript-default-extension' import '@codingame/monaco-vscode-typescript-basics-default-extension' import '@codingame/monaco-vscode-json-default-extension' import { initialize, IWorkbenchConstructionOptions } from '@codingame/monaco-vscode-api' import * as monaco from 'monaco-editor' import getWorkbenchServiceOverride from '@codingame/monaco-vscode-workbench-service-override' import getModelServiceOverride from '@codingame/monaco-vscode-model-service-override' import getConfigurationServiceOverride from '@codingame/monaco-vscode-configuration-service-override' import getThemeServiceOverride from '@codingame/monaco-vscode-theme-service-override' import getTextmateServiceOverride from '@codingame/monaco-vscode-textmate-service-override' import getLanguagesServiceOverride from '@codingame/monaco-vscode-languages-service-override' import getSearchServiceOverride from '@codingame/monaco-vscode-search-service-override' import getMarkersServiceOverride from '@codingame/monaco-vscode-markers-service-override' import getExplorerServiceOverride from '@codingame/monaco-vscode-explorer-service-override' import getOutputServiceOverride from '@codingame/monaco-vscode-output-service-override' import getTerminalServiceOverride from '@codingame/monaco-vscode-terminal-service-override' import getDebugServiceOverride from '@codingame/monaco-vscode-debug-service-override' // Configure all workers window.MonacoEnvironment = { getWorker(_workerId, label) { const workers = { TextEditorWorker: () => new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url), { type: 'module' }), TextMateWorker: () => new Worker(new URL('@codingame/monaco-vscode-textmate-service-override/worker', import.meta.url), { type: 'module' }), LocalFileSearchWorker: () => new Worker(new URL('@codingame/monaco-vscode-search-service-override/worker', import.meta.url), { type: 'module' }), OutputLinkDetectionWorker: () => new Worker(new URL('@codingame/monaco-vscode-output-service-override/worker', import.meta.url), { type: 'module' }) } const factory = workers[label] if (factory) return factory() throw new Error(`Unknown worker: ${label}`) } } const constructOptions: IWorkbenchConstructionOptions = { windowIndicator: { label: 'My IDE', tooltip: '', command: '' }, workspaceProvider: { trusted: true, async open() { return true }, workspace: { workspaceUri: monaco.Uri.file('/workspace.code-workspace') } }, defaultLayout: { editors: [ { uri: monaco.Uri.file('/workspace/index.ts'), viewColumn: 1 } ] }, configurationDefaults: { 'window.title': 'My IDE${separator}${dirty}${activeEditorShort}' } } await initialize({ ...getWorkbenchServiceOverride(), ...getModelServiceOverride(), ...getConfigurationServiceOverride(), ...getThemeServiceOverride(), ...getTextmateServiceOverride(), ...getLanguagesServiceOverride(), ...getSearchServiceOverride(), ...getMarkersServiceOverride(), ...getExplorerServiceOverride(), ...getOutputServiceOverride(), ...getTerminalServiceOverride(), ...getDebugServiceOverride() }, constructOptions) ``` ## Shadow DOM Support (Beta) Run VSCode in a shadow DOM to isolate styles between your application and the editor. ```typescript // Vite plugin configuration for shadow DOM CSS loading // vite.config.ts export default { plugins: [ { name: 'load-vscode-css-as-string', enforce: 'pre', async resolveId(source, importer, options) { const resolved = await this.resolve(source, importer, options) if (resolved?.id.match(/node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/)) { return { ...resolved, id: resolved.id + '?inline' } } return undefined } } ] } ``` ```typescript // Application code - container inside shadow DOM is automatically detected import { initialize } from '@codingame/monaco-vscode-api' import * as monaco from 'monaco-editor' await initialize({}) // Create shadow root const host = document.getElementById('editor-host')! const shadowRoot = host.attachShadow({ mode: 'open' }) const container = document.createElement('div') container.style.width = '100%' container.style.height = '100%' shadowRoot.appendChild(container) // Create editor in shadow DOM - styles are automatically injected monaco.editor.create(container, { value: 'console.log("Shadow DOM editor")', language: 'javascript' }) ``` ## Summary The @codingame/monaco-vscode-api library provides a comprehensive solution for integrating VSCode functionality into web applications. Primary use cases include building browser-based IDEs, code editors with advanced features like IntelliSense and debugging, collaborative coding platforms, and educational programming environments. The modular service override architecture allows developers to include only the features they need, from basic syntax highlighting to full workbench experiences with terminals, search, and extension support. Integration patterns typically involve initializing the required service overrides, configuring workers for background processing, and optionally connecting to remote VSCode servers for advanced functionality. The library works seamlessly with modern bundlers like Vite and Webpack, and can be used with frameworks like React, Vue, and Angular. For production deployments, consider the remote agent setup for full VSCode compatibility, proper CORS headers for TypeScript IntelliSense, and the sandbox mode for dynamic reinitialization scenarios.