# The OpenHands repository now ships Agent Canvas, and its Docker example binds to loopback

> The repository is still OpenHands/OpenHands and the description still says AI-Driven Development, but the README's own heading is Agent Canvas and the npm package is @openhands/agent-canvas. Its three install options differ mainly in how much of your filesystem the agent gets, and the README says so in a warning attached to the shortest one.

**OpenHands/OpenHands** — OpenHands is a self-hosted control center for coding agents, running Claude Code, Codex, or any ACP-compatible agent across local, remote, and cloud backends.

- Repository: https://github.com/OpenHands/OpenHands
- Website: https://openhands.dev
- Stars: 89,526 · Forks: 11,808
- Language: Python
- License: not declared
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/openhands-openhands

## The repository, the description and the README now name three different things

Start with the naming, because it will otherwise waste your afternoon. The repository is OpenHands/OpenHands. The repository description still reads OpenHands: AI-Driven Development. The first heading in the README is Agent Canvas, subtitled as the self-hosted developer control center for coding agents and automations. The published package is @openhands/agent-canvas, and the console command it installs is agent-canvas.

So the artifact you get is not named after the repository. What it does is described as turning your coding agents into a self-hosted, always-on engineering team: a control center for starting conversations and automating everyday tasks, with generating reports that publish to Slack and decomposing GitHub issues into tasks given as the examples.

The consequence is a search and install mismatch. Someone who arrives looking for OpenHands and types the repository name finds a product called Agent Canvas, and someone who runs a global npm install gets a binary called agent-canvas. The documentation is filed under the new name, at docs.openhands.dev on an agent-canvas path, while the project URL and the Slack channel keep the old one. Verify which artifact you want before installing: the primary language recorded for the repository is Python, and the package you install from npm is a TypeScript module.

## Option 1 hands the agent your filesystem, and the warning sits directly above it

The first install option is the shortest, and it carries a callout that says more than the rest of the section: this runs the agent-server directly on the machine you are installing on, and the agent will have full access to your filesystem.

The prerequisites are Node.js 24 or later and uv. The commands are two lines:

```sh
npm install -g @openhands/agent-canvas
agent-canvas
```

The agent-canvas command starts the full local stack by default, and the same command can be split so you run the pieces apart: --frontend-only gives a static frontend plus ingress, --backend-only gives the agent server plus the automation backend plus ingress.

That split is the useful part of this section and also its limit. It gives you a way to run the interface on one machine and the agent server on another, which is how the README describes sharing an Agent Server with your team for code review and dependency updates while personal agents run on your laptop. It does not give you a sandbox. On Option 1 there is no boundary between what the agent can read and what you can read, so the safe version of this install is on a machine whose filesystem you would not mind losing. Containment requires the next option, which is a different command rather than a different flag on this one.

## The Docker run binds 127.0.0.1 and still sets AGENT_CANVAS_ALLOW_LAN_SESSION_KEY

Option 2 adds a sandbox, and its command is where the detail worth reading lives:

```sh
export PROJECTS_PATH="$HOME/projects"  # directory containing your project folders
mkdir -p "$PROJECTS_PATH" "$HOME/.openhands"

docker run -it --rm \
  -p 127.0.0.1:8000:8000 \
  -e AGENT_CANVAS_ALLOW_LAN_SESSION_KEY=true \
  -v "$HOME/.openhands:/home/openhands/.openhands" \
  -v "${PROJECTS_PATH}:/projects" \
  ghcr.io/openhands/agent-canvas:1.24.0 # x-release-please-version
```

Two things sit in tension in those lines. The port mapping publishes on 127.0.0.1, so nothing on your network can reach the container. The environment variable in the next line enables LAN session keys. As written, the second setting has nothing to expose, which is the safe combination. Change the mapping to 0.0.0.0 to reach the canvas from another machine, the obvious edit when a colleague or a webhook needs to connect, and you have enabled LAN session keys in the same breath. Those are two separate decisions sharing one command, and the coupling is not flagged.

The other thing to notice is PROJECTS_PATH. It is mounted at /projects, the README says to create it before starting the container, and the agent will be able to access any project under it. The example sets it to $HOME/projects, so the blast radius is whatever you keep in a projects folder. Choose that path as carefully as you would choose a permission, because it is the permission. A second volume mounts $HOME/.openhands for state, which is the directory worth backing up and inspecting before you trust a new install.

## One manifest carries two version lines: agent-canvas 1.24.0 and extensions 0.24.0

The package manifest is named @openhands/agent-canvas at version 1.24.0, published rather than private, of type module, with a single bin entry mapping the command agent-canvas to bin/agent-canvas.mjs. Engines require node >=24, which is the hard floor for the whole install story.

Inside the dependencies, the version lines split. @openhands/extensions sits at 0.24.0 while the package itself is at 1.24.0, and @openhands/typescript-client is at 1.49.6. Every other dependency is pinned to an exact version rather than a range, from react and react-dom at 19.3.0 through @react-router at 7.18.2, monaco-editor at 0.56.0, @xterm/xterm at 6.0.0, i18next at 26.4.2 and axios at 1.18.0.

The consequence is that you cannot read your OpenHands dependency versions off the top-level version. 1.24.0 tells you about the canvas, and the numbers that decide what your agent server does are two others. For an automated install, pin all three. The exact pinning of the rest of the tree is what makes an install reproducible, and it is also why a fix in a transitive dependency waits for a canvas release rather than arriving on its own.

The image tag in the Docker command carries the same lesson differently: 1.24.0 followed by a trailing comment marking it as the line release automation rewrites. Do not hand-edit it.

## Five playwright configs separate mock-model runs from live ones, and you have to pick

The repository root is where the test strategy shows itself. There are five Playwright configurations, not one: playwright.config.ts, playwright.live.config.ts, playwright.mock-llm.config.ts, playwright.mock-llm-docker.config.ts and playwright.bind-policy.config.ts. Alongside them sit vitest.setup.ts, test-utils.tsx, __mocks__/, __tests__/, stryker.config.mjs for mutation testing, and a react-router.config.ts.

The names describe the axes. One config is the default, one is explicitly live, two are about a mocked model with and without Docker, and one is about bind policy. The suite is split along whether a real model is allowed to answer and whether the run needs a container, and the split is expressed in filenames rather than toggles in one config.

The consequence for a contributor is that a green run tells you which world you were in. Under a mock-llm config you have verified wiring, routing and rendering without spending a token, which is the right default for most changes. You have verified nothing about model behaviour, and the live config is the one that costs money and talks to a provider. Know which file you invoked before you read a pass as evidence. The presence of a mutation-testing config says the project treats coverage numbers as a starting point rather than a target.

The desktop shell is visible too, with electron/ and electron-builder.config.mjs next to vercel.json and helm/, so one frontend is built for a packaged app, a static web deploy and a Kubernetes install.

## The frontend resolves a backend twice, through a proxy and through the browser

The .env.sample file is short and unusually well commented, and it explains a split that will otherwise confuse you. Two variables point at the same backend for different consumers:

```
VITE_BACKEND_HOST="127.0.0.1:8000"
VITE_BACKEND_BASE_URL="http://127.0.0.1:8000"
VITE_FRONTEND_PORT="3001"
VITE_USE_TLS="false"
VITE_INSECURE_SKIP_VERIFY="false"
VITE_ENABLE_BROWSER_TOOLS="true"
```

VITE_BACKEND_HOST is the host and port the Vite dev proxy uses. VITE_BACKEND_BASE_URL is the base URL used by browser-side direct requests. One is consumed by the dev server, the other is baked into code the browser runs, and they are configured separately. The file also says the defaults assume you are manually pointing the frontend at a backend on 127.0.0.1:8000, that the recommended local workflow is npm run dev because it starts an isolated local backend for the checkout, and that npm run dev:frontend is for when you intentionally want a separately managed backend.

Here is the trap. To drive a containerized ACP agent server, the comment tells you to point VITE_BACKEND_BASE_URL at the published port, giving http://localhost:8010 as the example, and points at examples/acp-docker/ and docs/ACP_AGENTS.md. Nothing tells you to change VITE_BACKEND_HOST with it. Leave the first variable at 127.0.0.1:8000 and the proxy and the browser are talking to two different backends, which produces failures that look like the agent is unreachable rather than like a config mismatch.

The remaining two flags are worth knowing. VITE_USE_TLS false means proxied backend connections are plain HTTP by default, and VITE_INSECURE_SKIP_VERIFY false is the separate switch that skips certificate verification, a debugging aid that should stay off outside a lab.

## The session key is off by default and named two different ways on the two sides

Authentication is a single line in .env.sample, and it is commented out:

```
# VITE_SESSION_API_KEY="" # Set to the same value as backend SESSION_API_KEY or OH_SESSION_API_KEYS_0 when auth is enabled
```

Read what that requires. The frontend variable and the backend variable are not the same name, and the backend side has two shapes, SESSION_API_KEY for a single key and an indexed plural form for a list. So getting auth right is a two-sided edit with three names involved, and nothing in the repository validates that the two sides agree.

The default is off, which is defensible on loopback and wrong everywhere else. On the Docker option the canvas is published on 127.0.0.1:8000, and while it stays there an empty session key costs you nothing. The moment you widen the port mapping, put it behind the ingress, or use --backend-only on a shared host, the empty key is the front door. Set it before you expose anything, and set the backend side to the same string.

One more default deserves a decision rather than an inheritance. VITE_ENABLE_BROWSER_TOOLS is true, and the comment says to set it to false to omit BrowserToolSet from new conversations. So the agent arrives with a browser tool, and removing it is a frontend variable that only affects conversations started afterwards. Existing conversations keep the toolset they were created with, which is the kind of detail that matters when you are working out why a running session can still open pages.

## Conclusion

Take Agent Canvas if you want one control plane over several coding agents, including third-party ones, and you are willing to decide deliberately how much of your filesystem each agent can reach. Two things to settle before the first conversation. Choose the backend layout from the blast radius, not from convenience: Option 1 gives the agent full access to the machine it is installed on, while the Docker options bound the agent to PROJECTS_PATH, so pointing that at $HOME/projects hands over everything under your home directory. And keep the published port on 127.0.0.1, because the example already sets AGENT_CANVAS_ALLOW_LAN_SESSION_KEY, and widening the port mapping is the same edit as exposing session keys. Set VITE_SESSION_API_KEY to match the backend before you put it behind an ingress.

## FAQ

### What is OpenHands used for?

Agent Canvas is described as a self-hosted developer control center for coding agents and automations. It starts conversations with agents and automates everyday tasks such as generating reports that publish to Slack or automatically decomposing GitHub issues into tasks, running locally by default and optionally on OpenHands Cloud or Enterprise infrastructure.

### How do I install OpenHands?

The prerequisites are Node.js 24 or later and uv. The documented path is npm install -g @openhands/agent-canvas followed by agent-canvas, which starts the full local stack. Two Docker options follow, one sandboxing the agent and one giving every conversation its own container.

### how to install openhands on windows

There is a separate README.windows.md for Windows carrying the equivalent commands, since the macOS and Linux versions use export and a multi-line docker run. The Docker prerequisite is Docker Desktop on macOS or Windows, and Docker Engine or Docker Desktop on Linux.

### What are the key differences between OpenHands and Claude Code?

Agent Canvas runs the open source OpenHands agent out of the box, but can also use third-party agents such as Claude Code and Codex, and anything speaking the Agent-Client Protocol. The difference the README draws is the control plane around them: local, Docker, VM, company infrastructure, or OpenHands Cloud and Enterprise backends you can switch between.

### how to use openhands

The agent-canvas command starts the full local stack by default and can be split into --frontend-only for a static frontend plus ingress, or --backend-only for the agent server, automation backend and ingress. The frontend can be pointed at different backends, and you can switch between local, remote and cloud agents.

## Sources

- [Official documentation](https://openhands.dev)
- [Official README](https://github.com/OpenHands/OpenHands#readme)
- [Project repository](https://github.com/OpenHands/OpenHands)
- [Release notes](https://github.com/OpenHands/OpenHands/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/openhands-openhands
