The Hoody Code Orchestrator serves the VS Code web interface, manages password-based authentication, exposes static assets, and provides reverse-proxy routing to local ports. Use these endpoints to embed VS Code in your application, secure access with login, proxy local development servers, or serve PWA/SEO files.
VS Code Web Interface
Section titled “VS Code Web Interface”GET /api/v1/code
Section titled “GET /api/v1/code”Returns the main VS Code web interface as HTML. If authentication is enabled and no session is present, the response is a redirect to /login. The endpoint accepts optional query parameters to open a specific folder or workspace, or to launch VS Code in extension-only mode for embedding a single extension’s UI.
When no folder or workspace is provided, the server uses the last opened workspace (or the CLI argument on first start). Query parameters are stored in settings and applied to the next session.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
folder | query | string | No | Absolute path to folder to open in VS Code. Takes precedence over workspace. Stored in settings for the next session. |
workspace | query | string | No | Absolute path to VS Code workspace file (.code-workspace). Used when folder is not provided. Stored in settings for the next session. |
extension | query | string | No | Extension identifier in the format PUBLISHER.NAME. When set, opens VS Code in extension-only mode. Examples: ms-python.python, ms-toolsai.jupyter, redhat.vscode-yaml. |
ew | query | boolean | No | ”Empty Window” flag. When true, clears the last opened folder or workspace from settings. |
locale | query | string | No | Display language for the VS Code UI as an IETF language tag (e.g., en, fr, de, ja, zh-CN). |
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/api/v1/code?folder=/home/user/project&locale=en"await client.code.vscode.getVSCode({ folder: "/home/user/project", locale: "en"});<!DOCTYPE html><html><head> <title>VS Code</title> <meta charset="utf-8"></head><body> <!-- VS Code web interface mounts here --></body></html>Response headers
| Header | Description |
|---|---|
Content-Type | text/html; charset=utf-8 |
Content-Security-Policy | CSP directives. Automatically updated when --external-js or --external-css is configured. |
curl -i "https://code.example.com/api/v1/code?folder=/home/user/project"await client.code.vscode.getVSCode({ folder: "/home/user/project" });HTTP/1.1 302 FoundLocation: /login?to=%2F%3Ffolder%3D%2Fhome%2Fuser%2FprojectThe client should follow the redirect to the login page. The original target URL is preserved in the to query parameter.
GET /api/v1/code/manifest.json
Section titled “GET /api/v1/code/manifest.json”Returns the Progressive Web App manifest used to install Hoody Code as a desktop-like application. The manifest name is configurable via the --app-name server flag. Icons are served from the same origin and the display mode is fullscreen with window-controls-overlay.
Parameters
Section titled “Parameters”This endpoint takes no parameters.
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/api/v1/code/manifest.json"await client.code.vscode.getManifest();{ "name": "hoody-code", "short_name": "hoody-code", "start_url": ".", "display": "fullscreen", "display_override": ["window-controls-overlay"], "description": "Run Code on a remote server.", "icons": [ { "src": "/_static/out/browser/media/icon-192.png", "type": "image/png", "sizes": "192x192", "purpose": "any" }, { "src": "/_static/out/browser/media/icon-512.png", "type": "image/png", "sizes": "512x512", "purpose": "any" }, { "src": "/_static/out/browser/media/icon-maskable-512.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" } ]}POST /api/v1/code/mint-key
Section titled “POST /api/v1/code/mint-key”Generates or retrieves the server’s 256-bit (32-byte) web key half used by VS Code for secure client–server communication. The key is persisted to user-data-dir/serve-web-key-half and reused across server restarts.
Parameters
Section titled “Parameters”This endpoint takes no parameters.
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl -X POST "https://code.example.com/api/v1/code/mint-key"await client.code.vscode.mintKey();<binary content: 32 bytes of key material>The response is application/octet-stream with exactly 32 bytes.
Authentication
Section titled “Authentication”GET /api/v1/code/login
Section titled “GET /api/v1/code/login”Returns the login page HTML. This endpoint is only available when authentication is set to password. If the user is already authenticated, the response is a 302 redirect to the target page (defaulting to /).
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
to | query | string | No | URL to redirect to after successful login. Defaults to "/". |
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/api/v1/code/login?to=%2Fprojects%2Fhoody"await client.code.auth.getLoginPage({ to: "/projects/hoody" });<!DOCTYPE html><html><head> <title>Login - Hoody Code</title></head><body> <form method="POST" action="/api/v1/code/login?to=%2Fprojects%2Fhoody"> <input type="password" name="password" autofocus required /> <button type="submit">Sign in</button> </form></body></html>curl -i "https://code.example.com/api/v1/code/login"await client.code.auth.getLoginPage();HTTP/1.1 302 FoundLocation: /Issued when the session cookie is valid and the user is already authenticated.
POST /api/v1/code/login
Section titled “POST /api/v1/code/login”Authenticates the user with a password and sets a session cookie on success. Passwords are verified against an argon2 hash (when --hashed-password is used) or a SHA-256 hash (when --password is used). The endpoint is rate-limited to 2 attempts per minute and 12 attempts per hour.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
to | query | string | No | URL to redirect to after successful login. Defaults to "/". |
Request Body
Section titled “Request Body”The body is sent as application/x-www-form-urlencoded.
| Field | Type | Required | Description |
|---|---|---|---|
password | string (password) | Yes | Password to authenticate with. |
Response
Section titled “Response”curl -X POST "https://code.example.com/api/v1/code/login?to=%2Fprojects%2Fhoody" \ -d "password=hunter2"await client.code.auth.login({ to: "/projects/hoody", password: "hunter2"});HTTP/1.1 302 FoundLocation: /projects/hoodySet-Cookie: hoody.session=...; HttpOnly; SameSite=LaxIssued on successful authentication. The session cookie is set and the client is redirected to the to URL (or /).
curl -X POST "https://code.example.com/api/v1/code/login" \ -d "password=wrong"await client.code.auth.login({ password: "wrong" });<!DOCTYPE html><html><head> <title>Login - Hoody Code</title></head><body> <form method="POST" action="/api/v1/code/login"> <p class="error">Invalid password</p> <input type="password" name="password" autofocus required /> <button type="submit">Sign in</button> </form></body></html>| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_PASSWORD | Invalid password | The password provided is incorrect | Check your password and try again |
RATE_LIMITED | Too many login attempts | Rate limit exceeded (2 attempts/min or 12 attempts/hour) | Wait a few minutes before trying again |
GET /api/v1/code/logout
Section titled “GET /api/v1/code/logout”Clears the session cookie and redirects to the home page. Only available when authentication is enabled.
Parameters
Section titled “Parameters”This endpoint takes no parameters.
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl -i "https://code.example.com/api/v1/code/logout"await client.code.auth.logout();HTTP/1.1 302 FoundLocation: /Set-Cookie: hoody.session=; Max-Age=0; Path=/Port Proxying
Section titled “Port Proxying”The proxy endpoints let you expose any service running on a local port of the host running Hoody Code. The two flavors differ in how the URL path is forwarded.
GET /api/v1/code/proxy/{port}/{path}
Section titled “GET /api/v1/code/proxy/{port}/{path}”Proxies a request to a local port, stripping /proxy/:port from the path before forwarding. For example, /proxy/3000/api/users is forwarded to http://localhost:3000/api/users. Supports all HTTP methods, WebSocket upgrades, and requires authentication.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
port | path | integer | Yes | Local port to proxy to. |
path | path | string | Yes | Path to append to the proxied request. |
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/api/v1/code/proxy/3000/api/users"await client.code.proxy.resolve({ port: 3000, path: "api/users" });<proxied response from http://localhost:3000/api/users>curl -i "https://code.example.com/api/v1/code/proxy/3000/api/users"await client.code.proxy.resolve({ port: 3000, path: "api/users" });HTTP/1.1 401 Unauthorized| Error Code | Title | Description | Resolution |
|---|---|---|---|
AUTHENTICATION_REQUIRED | Authentication required | You must be logged in to access proxied ports | Log in with your password first |
curl -i "https://code.example.com/api/v1/code/proxy/3000/api/users"await client.code.proxy.resolve({ port: 3000, path: "api/users" });HTTP/1.1 502 Bad Gateway| Error Code | Title | Description | Resolution |
|---|---|---|---|
PORT_UNREACHABLE | Cannot connect to local port | The specified port is not accessible or no service is running | Verify the application is running on the specified port |
GET /api/v1/code/absproxy/{port}/{path}
Section titled “GET /api/v1/code/absproxy/{port}/{path}”Proxies a request to a local port while preserving the full path, including /absproxy/:port/. Use this when the proxied app must know it is running under a subpath. The base path can be customized via --abs-proxy-base-path.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
port | path | integer | Yes | Local port to proxy to. |
path | path | string | Yes | Path (preserved in the forwarded request). |
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/api/v1/code/absproxy/8080/dashboard"await client.code.proxy.resolveAbsolute({ port: 8080, path: "dashboard" });<proxied response from http://localhost:8080/absproxy/8080/dashboard>curl -i "https://code.example.com/api/v1/code/absproxy/8080/dashboard"await client.code.proxy.resolveAbsolute({ port: 8080, path: "dashboard" });HTTP/1.1 401 Unauthorizedcurl -i "https://code.example.com/api/v1/code/absproxy/8080/dashboard"await client.code.proxy.resolveAbsolute({ port: 8080, path: "dashboard" });HTTP/1.1 502 Bad GatewayStatic Assets
Section titled “Static Assets”GET /_static/{path}
Section titled “GET /_static/{path}”Serves compiled static files from the build directory: JavaScript, CSS, images, icons, and the service worker. Cache headers are tied to the git commit in production and disabled in development mode. The service worker at /_static/out/browser/serviceWorker.js is served with the special Service-Worker-Allowed: / header so it can register at the root scope.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
path | path | string | Yes | Path to static file. |
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl -i "https://code.example.com/_static/out/browser/workbench.html"await client.code.static.get({ path: "out/browser/workbench.html" });HTTP/1.1 200 OKContent-Type: text/htmlCache-Control: public, max-age=31536000, immutableService-Worker-Allowed: /Response headers
| Header | Description |
|---|---|
Cache-Control | Long-lived cache header in production, no cache in development. |
Service-Worker-Allowed | Set to / for service worker files only. |
curl -i "https://code.example.com/_static/missing.js"await client.code.static.get({ path: "missing.js" });HTTP/1.1 404 Not FoundGET /hoody-code/injected/{script}
Section titled “GET /hoody-code/injected/{script}”Serves injected JavaScript files from the extra/injected/ directory. These scripts are loaded sequentially after window load when the --hoody-code flag is enabled, and can be used to customize behavior or branding. Also available under /vscode/hoody-code/injected/{script}.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
script | path | string | Yes | Script filename. |
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/hoody-code/injected/branding.js"await client.code.static.getInjectedScript({ script: "branding.js" });// branding.js — custom branding injected into VS Code(function () { const style = document.createElement("style"); style.textContent = ` .monaco-workbench .titlebar h2 { font-family: "Inter", sans-serif; } `; document.head.appendChild(style);})();curl -i "https://code.example.com/hoody-code/injected/missing.js"await client.code.static.getInjectedScript({ script: "missing.js" });HTTP/1.1 404 Not FoundGET /robots.txt
Section titled “GET /robots.txt”Returns the robots.txt file used by crawlers to discover crawl policies.
Parameters
Section titled “Parameters”This endpoint takes no parameters.
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/robots.txt"await client.code.static.getRobots();User-agent: *Disallow: /
Sitemap: https://code.example.com/sitemap.xmlGET /security.txt
Section titled “GET /security.txt”Returns the security.txt file for responsible vulnerability disclosure. Also served at /.well-known/security.txt.
Parameters
Section titled “Parameters”This endpoint takes no parameters.
Request Body
Section titled “Request Body”This endpoint takes no request body.
Response
Section titled “Response”curl "https://code.example.com/security.txt"await client.code.static.getSecurityPolicy();Contact: mailto:security@example.comExpires: 2026-12-31T23:59:59zPreferred-Languages: enCanonical: https://code.example.com/.well-known/security.txt