Skip to content
Hoody.com

Hoody Code spawns isolated VS Code instances on demand through HTTP requests. You can embed a single extension in your own application, password-protect an environment, and manage several development workspaces from one orchestrator.

  • Spawn instances - Create a VS Code environment with one HTTP request
  • Extension embedding - Open a single already-installed extension in an isolated view
  • Password protection - Require a password before an instance is reachable
  • Multi-workspace - Independent settings and extensions per instance
  • Instance isolation - Separate data directories per instance
  • Health monitoring - Track orchestrator status and running instances
  • Custom configuration - Pass CLI flags via query parameters
  • Instance reuse - Existing instances are reused instead of re-spawned

Hoody Code is two processes, and knowing which one answers a request saves a lot of confusion.

The orchestrator answers on the container’s code URL. It spawns and reuses instances, and that is nearly all it does:

https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.com

Each spawned VS Code instance is its own server on its own port, reached through the container’s HTTP proxy hostname for that port:

https://PROJECT-CONTAINER-http-PORT.SERVER.containers.hoody.com

Spawning returns a page whose iframe points at that second hostname. Everything inside the editor, including login and the web key, belongs to the instance rather than the orchestrator.

On the orchestrator (...-code-1...):

On a spawned instance (...-http-PORT...):

  • POST /api/v1/code/mint-key - Generate or retrieve the server’s web key half
  • GET /login, POST /login, GET /logout - Only when the service was launched in password mode

Spawn VS Code for a folder:

Terminal window
# Spawn or reuse instance 0 for a folder. Returns the wrapper HTML page,
# whose iframe points at the instance's own hostname.
curl "https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.com/?folder=/home/user/my-project&id=0"
# Check orchestrator health
curl "https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.com/api/v1/code/health"

Spawning is HTTP only: it is a page request, not an API call, so the CLI and SDK have no equivalent. id is required alongside folder, and omitting it returns a 400.

Add extension to a spawn request and VS Code hides the file explorer, leaving only that extension’s UI. The value is the PUBLISHER.NAME id, so ms-azuretools.vscode-docker works the same way:

Terminal window
# Spawn instance 0 in extension-only mode
curl "https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.com/?folder=/workspace&id=0&extension=ms-python.python"

Set password authentication with a CLI flag when the Code service is launched. Login belongs to the spawned instance, not the orchestrator, and lives at the host root:

Terminal window
# Submit login credentials to the instance
curl -X POST "https://PROJECT-CONTAINER-http-PORT.SERVER.containers.hoody.com/login" \
-d 'password=my-password'

GET /login returns the form and GET /logout clears the session. All three exist only when the service was launched in password mode.

The mint-key endpoint is separate. It generates or retrieves the server’s 32-byte web key half used for secure communications, and is not a password API. It is also served by the instance:

Terminal window
# Generate/retrieve server web key (binary response)
curl -X POST "https://PROJECT-CONTAINER-http-PORT.SERVER.containers.hoody.com/api/v1/code/mint-key"

Each instance keeps its own state:

  • Installed extensions live in that instance’s own directory, under <data-dir>/<id>/extensions
  • User settings and keybindings are stored separately
  • The last opened folder or workspace is saved in settings for the next session

First request - Fresh spawn:

  • Shows a loading overlay
  • Spawns the VS Code process
  • Configures it from the request parameters
  • Returns the iframe once it is ready

Subsequent requests - Reuse:

  • No loading overlay
  • Reuses the existing instance rather than re-spawning it
  • Keeps the same state

Use the supported query parameters to configure an instance:

Terminal window
# Spawn instance 0 with the French UI locale
curl "https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.com/?folder=/workspace&id=0&locale=fr"

Supported parameters:

  • folder - What to open. Required. The value is stored in settings for the next session.
  • id - Which instance to spawn or reuse. Required; without it the request is a 400.
  • extension - Open in extension-only mode, given as PUBLISHER.NAME
  • restart - true, 1, yes or on kills the existing instance and spawns a fresh one
  • locale - Display language, as an IETF language tag such as fr

The orchestrator passes flags through an allowlist. Anything outside it is dropped without an error, so a parameter that looks accepted may simply have been ignored.

The health check is shown in Basic instance above. Its response:

{
"status": "ok",
"service": "hoody-code",
"started": "2024-01-15T10:30:00.000Z",
"built": "2024-01-10T09:00:00.000Z",
"pid": 1234,
"ip": "10.0.0.12",
"memory": { "rss": 44145050, "heap": 29884416 },
"fds": 42,
"userAgent": "HoodyMonitor/1.0"
}

Give each user their own instance. Settings and installed extensions stay separate, so one user’s changes do not reach another’s environment.

Embed a single extension in your own application with extension-only mode, which hides the file explorer and leaves just that extension’s UI.

Run sandboxed coding environments: password-protect student instances, pre-configure extensions, monitor health, and clean up instances between sessions.

Automate code edits by spawning a temporary instance, driving it through extensions, cleaning up when the job finishes, and integrating the whole run with your build pipeline.

Demonstrate a VS Code extension by embedding an instance in documentation. Readers get an interactive demo of what the extension does and install nothing.

Use a separate folder per project for isolation, and plan capacity for the load you expect.

Always use absolute paths such as /home/user/project. Do not use relative paths or .., validate paths to prevent traversal, and make sure the folder exists before spawning.

Set the password with a CLI flag when launching the Code service, rotate it regularly, and remember that URLs can leak through logs and browser history.

Monitor health via /api/v1/code/health, clean up old instances, and track disk usage in the data directories.

Validate extension IDs against the PUBLISHER.NAME format, test compatibility before embedding, document system dependencies, and pin versions for consistency.

Q: How many instances can I run? The practical limit is the container’s memory and CPU.

Q: Do instances persist after restart? Data directories persist, including extensions and settings. Running processes do not, so you re-spawn them.

Q: Can I customize VS Code appearance? Use the locale query parameter for the display language, load custom CSS/JS via the --external-js/--external-css server flags, and configure further through extension settings.

Q: How do I update extensions? Extensions are installed per instance directory. Update them from the VS Code UI inside the instance, or restart with a fresh data directory.

Q: What happens on first request vs. a reused instance? A fresh spawn starts a new VS Code process and (when --page-loader is enabled) shows a branded loading overlay during initialization; a reused instance loads its existing process without re-spawning.

Q: Can I run multiple Code services? Yes. Use different instance numbers such as code-1 and code-2. Each one has its own orchestrator, port range, and data directory.

Q: How do I embed in my app? Request the URL with the extension parameter, embed the returned page in an iframe, handle authentication if the instance needs it, and monitor the health endpoint.

Cause: Folder not found, invalid parameters. Solution: Verify the folder exists and is an absolute path, confirm the folder parameter (if used) is passed correctly, and check the orchestrator logs.

Cause: Invalid extension ID or web-incompatible extension. Solution: Verify the ID format PUBLISHER.NAME, check that the extension supports the web version, test without extension-only mode first, and confirm the ID on the marketplace.

Cause: Incorrect password or login endpoint misuse. Solution: Verify the password matches the one configured via CLI flag, check the URL encoding of the form body, and confirm the service was started with password authentication enabled.

Cause: Too many instances running. Solution: Check health with /api/v1/code/health, adopt an instance cleanup policy, and increase server resources.

Cause: Data directory cleared. Solution: Do not delete the data directories of active instances, and back up critical instance data.

Cause: Orchestrator down or network issue. Solution: Verify the orchestrator process is running, check network connectivity to the Code Orchestrator URL, and review orchestrator logs for errors.