Skip to content

Technical Selection

1 post with the tag “Technical Selection”

VSCode and code-server: Choosing a Browser-Based Code Editing Solution

VSCode and code-server: Choosing a Browser-Based Code Editing Solution

Section titled “VSCode and code-server: Choosing a Browser-Based Code Editing Solution”

When building browser-based code editing capabilities, developers face a key choice: use VSCode’s official code serve-web feature, or adopt the community-driven code-server solution? This decision affects not only the technical architecture, but also license compliance and deployment flexibility.

Technical selection is a lot like choosing a path in life. Once you pick one, you usually have to keep walking it, and switching later can become very expensive.

In the era of AI-assisted programming, browser-based code editing is becoming increasingly important. Users expect that after an AI assistant finishes analyzing code, they can immediately open an editor in the same browser session and make changes without switching applications. That kind of seamless experience should simply be there when you need it.

However, when implementing this feature, developers face a critical technical choice: should they use VSCode’s official code serve-web feature, or the community-driven code-server solution?

Each option has its own strengths and trade-offs, and choosing poorly can create a lot of trouble later. Licensing is one example: if you only discover after launch that your product is not license-compliant, it is already too late. Deployment is another: a solution might work perfectly in development, then run into all kinds of problems once moved into containers. These are exactly the kinds of pitfalls teams want to avoid.

The approach shared in this article comes from our practical experience in the HagiCode project. HagiCode is an AI-driven coding assistant. While implementing browser-based code editing, we studied both solutions in depth and ultimately designed our architecture to support both, while choosing code-server as the default.

Project repository: github.com/HagiCode-org/site

This is the most fundamental difference between the two solutions, and the first factor we considered during evaluation. When making a technical choice, it is important to understand the legal risks up front.

code-server

  • MIT license, fully open source
  • Maintained by Coder.com with an active community
  • Free to use commercially, modify, and distribute
  • No restrictions on usage scenarios

VSCode code serve-web

  • Part of the Microsoft VSCode product
  • Uses Microsoft’s license (the VS Code license includes restrictions on commercial use)
  • Primarily intended for individual developers
  • Enterprise deployment may require additional commercial licensing review

From a licensing perspective, code-server is more friendly to commercial projects. This is something you need to think through during product planning, because migrating later can become very costly.

Once licensing is settled, the next issue is deployment. That directly affects your operations cost and architectural design.

code-server

  • A standalone Node.js application that can be deployed independently
  • Supports multiple runtime sources:
    • Directly specifying the executable path
    • Looking it up through the system PATH
    • Automatic detection of an NVM Node.js 22.x environment
  • No need to install the VSCode desktop application on the server
  • Easier to deploy in containers

VSCode code serve-web

  • Must depend on a locally installed VSCode CLI
  • Requires an available code command on the host machine
  • The system filters out VS Code Remote CLI wrappers
  • Primarily designed for local development scenarios

code-server is better suited for server and container deployment scenarios. If your product needs to run in Docker, or your users do not have VSCode installed, code-server is usually the right choice.

The two solutions also differ in a few feature parameters. The differences are not huge, but they can create integration friction in real-world usage.

Featurecode-servercode serve-web
Public base path/ (configurable)/vscode-server (fixed)
Authentication--auth parameter with multiple modes--connection-token / --without-connection-token
Data directory{DataDir}/code-server{DataDir}/vscode-serve-web
TelemetryDisabled by default with --disable-telemetryDepends on VSCode settings
Update checksCan be disabled with --disable-update-checkDepends on VSCode settings

These differences need special attention during integration. For example, different URL paths mean your frontend code needs dedicated handling.

When implementing editor switching, the availability detection logic also differs.

code-server

  • Always returned as a visible implementation
  • Still shown even when unavailable, with an install-required status
  • Supports automatic detection of an NVM Node.js 22.x environment

code serve-web

  • Only visible when a local code CLI is detected
  • If unavailable, the frontend automatically hides this option
  • Depends on the local VSCode installation state

This difference directly affects the user experience. code-server is more transparent: users can see the option and understand that installation is still required. code serve-web is more hidden: users may not even realize the option exists. Which approach is better depends on the product positioning.

HagiCode’s Dual-Implementation Architecture

Section titled “HagiCode’s Dual-Implementation Architecture”

After in-depth analysis, the HagiCode project adopted a dual-implementation architecture that supports both solutions at the architectural level.

// The default active implementation is code-server
// If an explicit activeImplementation is saved, try that implementation first
// If the requested implementation is unavailable, the resolver tries the other one
// If a fallback occurs, return fallbackReason

We default to code-server mainly because of licensing and deployment flexibility. However, for users who already have a local VSCode environment, code serve-web is also a solid option.

CodeServerImplementationResolver is responsible for unifying:

  • Implementation selection during startup warm-up
  • Implementation selection when reading status
  • Implementation selection when opening projects
  • Implementation selection when opening Vaults

This design allows the system to respond flexibly to different scenarios, and users can choose the implementation that best matches their environment.

// When localCodeAvailable=false, do not show code serve-web
// When localCodeAvailable=true, show the code serve-web configuration

The frontend automatically shows available options based on the environment, so users are not confused by features they cannot use.

After all that theory, what should you pay attention to during actual deployment? In the end, implementation is what matters.

For containerized deployment, code-server is the better choice:

# Use the official code-server image directly
FROM codercom/code-server:latest
# Or install through npm
RUN npm install -g code-server

This solves the problem in a single layer without requiring an additional VSCode installation.

code-server configuration

{
"vscodeServer": {
"enabled": true,
"activeImplementation": "code-server",
"codeServer": {
"host": "0.0.0.0",
"port": 8080,
"executablePath": "",
"authMode": "none"
}
}
}

code serve-web configuration

{
"vscodeServer": {
"enabled": true,
"activeImplementation": "serve-web",
"serveWeb": {
"host": "0.0.0.0",
"port": 8080,
"executablePath": "/usr/local/bin/code"
}
}
}

Configuration can be a bit tedious the first time, but once it is in place, things become much easier to maintain.

code-server

http://localhost:8080/?folder=/path/to/project&vscode-lang=zh-CN

code serve-web

http://localhost:8080/vscode-server/?folder=/path/to/project&tkn=xxx&vscode-lang=zh-CN

Pay attention to the differences in paths and parameters. You need to handle them separately during integration.

The system supports runtime switching and automatically stops the previous implementation when switching:

// VsCodeServerManager automatically handles mutual exclusion
// When switching activeImplementation, the old implementation will not keep running in the background

This design lets users try different implementations at any time and find the option that works best for them.

const { settings, runtime } = await getVsCodeServerSettings();
// runtime.activeImplementation: "code-server" | "serve-web"
// runtime.fallbackReason: reason for switching
// runtime.status: "running" | "starting" | "stopped" | "unhealthy"

When status is visible, users can quickly determine whether a problem comes from the server side or from their own operation.

Comparison Dimensioncode-servercode serve-webRecommendation
LicenseMIT (commercial-friendly)Microsoft (restricted)code-server
Deployment flexibilityIndependent deploymentDepends on local VSCodecode-server
Server suitabilityDesigned for serversMainly for local developmentcode-server
ContainerizationNative supportRequires VSCode installationcode-server
Feature completenessClose to desktop editionOfficial complete versioncode serve-web
Maintenance activityActive communityOfficially maintained by MicrosoftBoth have strengths

Recommended strategy: Use code-server first, and consider code serve-web when you need full official functionality and already have a local VSCode environment.

The approach shared in this article is distilled from HagiCode’s real development experience. If you find this solution valuable, that is also a good sign that HagiCode itself is worth paying attention to.


If this article helped you:

Thank you for reading. If you found this article useful, feel free to like, bookmark, and share it. This content was created with AI-assisted collaboration, with the final version reviewed and approved by the author.