# vscode

> VS Code as an iii worker — vscode::* functions run the VS Code Server through the code CLI per workspace, and a Console page embeds the Workbench for the working directory.

| field | value |
|-------|-------|
| version | 0.1.13 |
| type | bundle |
| license | Apache-2.0 |
| repo | https://github.com/iii-hq/workers |
| author | iii |

## installation

```sh
iii trigger compose::add worker=vscode@0.1.13
```

## configuration

```yaml
- bind_host: 127.0.0.1
  code_executable: 
  data_dir: ~/.iii/vscode
  engine_url: ws://127.0.0.1:49134
  port_max: 18180
  port_min: 18080
  start_timeout_ms: 180000
  stop_grace_ms: 5000
```

## dependencies

- `configuration` @ `latest`

## readme

# vscode

VS Code as an iii worker. The worker runs the VS Code Server through the `code` CLI, one loopback process per workspace directory with its own isolated profile, and ships a **VS Code** page for the Console that embeds the Workbench for the chat's working directory. Nothing is re-implemented: it is the same web Workbench the CLI serves, with your extensions, settings sync, and terminals, beside the conversation.

![The VS Code Workbench open beside a chat in the iii Console](https://raw.githubusercontent.com/iii-hq/workers/main/vscode/assets/vscode-console.png)

## Install

```bash
iii trigger compose::add worker=vscode
```

`iii trigger compose::add` declares the worker in `worker-compose.yaml` and starts it as part of the Compose project. The host needs the VS Code CLI: install VS Code and enable the `code` shell command, or download the [standalone CLI](https://code.visualstudio.com/docs/remote/vscode-server) and point `code_executable` at it. The first start of a workspace downloads the matching VS Code Server build; starting the worker accepts the [VS Code Server license terms](https://aka.ms/vscode-server-license).

## Quickstart

Open **VS Code** from the Console navigation, or press `⌘K` and run `Open VS Code`. The page starts a server for the chat's working directory and shows the Workbench; with no working directory it lists the Console's recent folders. Its `⌘K` rows reload the Workbench, open it in a browser tab, and stop the server.

The same lifecycle is one function call away:

```bash
iii trigger vscode::start workspace=/absolute/path/to/project
```

```json
{
  "id": "ide-19edab41331d",
  "name": "VS Code",
  "workspace": "/absolute/path/to/project",
  "host": "127.0.0.1",
  "port": 18080,
  "pid": 21709,
  "started_at": "2026-08-26T15:28:58.711Z",
  "status": "running",
  "exit_code": null
}
```

Calling `vscode::start` again for the same folder returns the running server. `vscode::instances::list` shows every server the worker owns, `vscode::stop` stops one, and `vscode::delete` also removes its data directory with `delete_profile: true`. Another worker opens a specific folder in the page with `host.panels.open({ pageId: 'vscode', context: { workspace: '/path' } })`.

## Configuration

`config.yaml` seeds the `configuration` worker on first boot; after that the live value under the id `vscode` is authoritative and hot-reloads, so the Console's global Settings modal is the place to change it.

```yaml
code_executable: ""          # path to the VS Code CLI; empty = `code` on PATH
data_dir: ~/.iii/vscode      # one server-data + cli-data folder per workspace
bind_host: 127.0.0.1         # loopback only: 127.0.0.1, localhost, or ::1
port_min: 18080              # one port per running workspace
port_max: 18180
start_timeout_ms: 180000     # first start downloads the server build
stop_grace_ms: 5000          # SIGTERM to SIGKILL
```

`engine_url` (or `--url` / `III_URL`) is bootstrap and never hot-reloads.

## Run from source with compose

Workers in this repository run locally through [`iii compose`](https://github.com/iii-hq/workers/blob/main/harness/DEVELOPMENT.md). Add a container to the compose file next to the workers it should join:

```yaml
containers:
  vscode:
    worker: path://../vscode
    scripts:
      run: pnpm install --ignore-workspace && pnpm build:bundle && node dist/bundle/index.mjs
```

Compose supplies the engine URL and the project namespace to the process, so the page shows up in the Console served by the same compose file. A worker started by hand instead needs `III_NAMESPACE=<compose namespace>` in its environment, or the Console never sees its page. `III_VSCODE_UI_WATCH=1` serves the page from `ui/dist` and hot-reloads it into open Console tabs while `pnpm --dir ui watch` runs.

## Security

Browsers drop the VS Code Server connection-token cookie inside a cross-origin Console iframe, so the worker runs the server in cookie-free mode and refuses to bind anywhere but loopback. The server exposes the host filesystem to the local browser; `vscode::start` and `vscode::instances::list` are allowed for agents by default, `vscode::stop` and `vscode::delete` need approval.

The server is meant for a local single-user Console. Remote or multi-user deployments need a same-origin authenticated proxy in front of it before relaxing this.

## skills

This version ships 1 skill file for agents, also browsable on the worker page:

- [`SKILL.md`](https://workers.iii.dev/workers/vscode?tab=skills&skill=SKILL.md&version=0.1.13)

### SKILL.md

# vscode

The vscode worker runs the VS Code Server through the `code` CLI, one loopback
process per workspace directory with its own isolated profile, and ships a
Console page that embeds the Workbench for the chat's working directory. It
gives people the editor they already use, with their extensions, settings sync,
and terminals, inside the Console beside the conversation. Requires the VS Code
CLI on the host; the first start of a workspace downloads the matching server
build.

The worker owns process lifecycle only. It does not read, write, or search
files on the agent's behalf and it never exposes the server beyond loopback.

## When to Use

- A person asks to open the working directory, a repository, or a folder in
  VS Code, or wants an editor beside the chat.
- A person wants to inspect a change in a real editor before continuing the
  conversation, and `vscode::start` for that folder returns a running server
  the Console page then shows.
- A workspace's server should be reused, listed, stopped, or its profile
  removed after work is done.

## Boundaries

- Not a file API. For reading, searching, or editing files use `shell` or
  `coder::*`; for a shared buffer the agent and person both see, use `editor`.
- Not remote access. The server binds only to loopback and refuses any other
  `bind_host`; a remote or multi-user Console needs its own authenticated
  proxy first.
- Starting a server exposes the host filesystem to the local browser, so
  `vscode::start` is allowed by default while `vscode::stop` and
  `vscode::delete` stay approval-gated.
- The Workbench itself is VS Code Web; the worker adds no editor features of
  its own.

## Functions

- `vscode::start` — start a server for an absolute `workspace` directory, or return the running one; the id defaults to a stable hash of the path.
- `vscode::instances::list` — every server the worker owns with host, port, pid, status, and exit code.
- `vscode::stop` — stop a server's process group by id.
- `vscode::delete` — stop a server, forget it, and optionally remove its data directory with `delete_profile`.

The Console page calls `vscode::start` for the chat's working directory and
opens `http://<host>:<port>/` in a frame; another worker can open a specific
folder with `panels.open({ pageId: 'vscode', context: { workspace } })`.
Configuration (CLI path, data directory, bind host, port range, timeouts) is
managed by the `configuration` worker under the id `vscode`.

## api reference

```json
{
  "functions": [
    {
      "description": "Delete a VS Code Workbench instance and optionally its isolated profile.",
      "metadata": {},
      "name": "vscode::delete",
      "request_schema": {
        "properties": {
          "delete_profile": {
            "type": "boolean"
          },
          "id": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "deleted": {
            "type": "boolean"
          }
        },
        "required": [
          "deleted"
        ],
        "type": "object"
      }
    },
    {
      "description": "List the VS Code Workbench processes this worker owns.",
      "metadata": {},
      "name": "vscode::instances::list",
      "request_schema": {
        "properties": {},
        "required": [],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "instances": {
            "items": {
              "properties": {
                "exit_code": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "host": {
                  "type": "string"
                },
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "pid": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "port": {
                  "type": "integer"
                },
                "started_at": {
                  "type": "string"
                },
                "status": {
                  "enum": [
                    "starting",
                    "running",
                    "stopped",
                    "failed"
                  ],
                  "type": "string"
                },
                "workspace": {
                  "type": "string"
                }
              },
              "required": [],
              "type": "object"
            },
            "type": "array"
          }
        },
        "required": [
          "instances"
        ],
        "type": "object"
      }
    },
    {
      "description": "Internal: reload the vscode configuration when it changes.",
      "metadata": {
        "internal": true
      },
      "name": "vscode::on-config-change",
      "request_schema": {
        "properties": {},
        "type": "object"
      },
      "response_schema": {
        "type": "null"
      }
    },
    {
      "description": "Start (or reuse) a VS Code Workbench for an absolute workspace directory.",
      "metadata": {},
      "name": "vscode::start",
      "request_schema": {
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "workspace": {
            "type": "string"
          }
        },
        "required": [
          "workspace"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "exit_code": {
            "type": [
              "integer",
              "null"
            ]
          },
          "host": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "pid": {
            "type": [
              "integer",
              "null"
            ]
          },
          "port": {
            "type": "integer"
          },
          "started_at": {
            "type": "string"
          },
          "status": {
            "enum": [
              "starting",
              "running",
              "stopped",
              "failed"
            ],
            "type": "string"
          },
          "workspace": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "workspace",
          "host",
          "port",
          "status"
        ],
        "type": "object"
      }
    },
    {
      "description": "Stop a VS Code Workbench process group.",
      "metadata": {},
      "name": "vscode::stop",
      "request_schema": {
        "properties": {
          "id": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "exit_code": {
            "type": [
              "integer",
              "null"
            ]
          },
          "host": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "pid": {
            "type": [
              "integer",
              "null"
            ]
          },
          "port": {
            "type": "integer"
          },
          "started_at": {
            "type": "string"
          },
          "status": {
            "enum": [
              "starting",
              "running",
              "stopped",
              "failed"
            ],
            "type": "string"
          },
          "workspace": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "status"
        ],
        "type": "object"
      }
    },
    {
      "description": "Serve the injectable VS Code Console page assets.",
      "metadata": {
        "internal": true
      },
      "name": "vscode::ui-content",
      "request_schema": {
        "properties": {
          "path": {
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "content": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          }
        },
        "required": [
          "content",
          "content_type"
        ],
        "type": "object"
      }
    }
  ],
  "triggers": []
}
```
