Back to All Cheatsheet Libraries cheatsheets

OpenHands

The open-source, self-hosted AI software engineer: Docker and CLI quickstarts, LLM config, the skills/microagents system, and a safety guide for autonomous coding in a sandbox.

An open-source AI software engineer that runs on your own machine

OpenHands (the project, formerly under the All-Hands-AI org name — GitHub org is now OpenHands) is a self-hosted autonomous coding agent: point it at a repo, describe the task, and it plans, edits files, runs commands, and iterates in a sandboxed container until the job is done. Same category as Claude Code and OpenAI Codex, but open source and bring-your-own LLM — Anthropic, OpenAI, Google, a local model, or anything OpenAI-API-compatible.

The same org also ships Agent Canvas, a newer, broader "developer control center" for running OpenHands, Claude Code, Codex, or any Agent-Client-Protocol agent across local/remote/cloud backends with Slack/GitHub/Linear automations. This page covers the core OpenHands coding agent — what almost everyone means by "OpenHands" — not Agent Canvas.

1

Docker quickstart — the standard way to run it

This single container is both the web UI and the orchestrator; it spins up a separate sandbox container per session to actually execute the agent's commands, which is why it needs the Docker socket mounted.

docker run -it --rm --pull=always \ -e AGENT_SERVER_IMAGE_REPOSITORY=ghcr.io/openhands/agent-server \ -e AGENT_SERVER_IMAGE_TAG=1.26.0-python \ -e LOG_ALL_EVENTS=true \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.openhands:/.openhands \ -p 3000:3000 \ --add-host host.docker.internal:host-gateway \ --name openhands-app \ docker.openhands.dev/openhands/openhands:1.8

Open http://localhost:3000, pick an LLM provider and paste an API key, then open or clone a repo from the UI.

2

CLI quickstart — no Docker, runs in your terminal

The CLI installs via uv (the fast Python package manager) and talks to the same agent-server underneath, but without the web UI — good for scripting, CI, or working entirely in a terminal.

uv tool install openhands --python 3.12 openhands # launches the interactive CLI openhands -t "Add input validation to the signup form" openhands --gpu --mount-cwd # mount the current directory, pass through a GPU
3

System requirements

A modern processor with at least 4 GB RAM. Docker Desktop on macOS/Windows, Docker Engine on Linux, or WSL2 + Docker Desktop on Windows.

4

Getting an LLM API key

Any provider works. Anthropic (Claude) and OpenAI keys are the most common; OpenHands also has its own hosted credits if you'd rather not manage a separate provider account. A local model via Ollama or LM Studio works too, just point the base URL at it.

Task description → Plan → Edit files / run shell commands in a sandboxed container → Observe output → Iterate → Done

The sandbox container

A separate, disposable container per session where the agent actually executes code — never your host shell directly. This is the entire safety boundary; see the Safety tab.

PROJECTS_PATH

The one host directory mounted into the agent's reach. Nothing outside it is visible to the sandbox, which is why scoping it matters more than any other setting.

Confirmation modes

Default asks before every action; --always-approve runs unattended; --llm-approve has a second, cheaper model gate risky actions. Covered in the CLI tab.

Skills / microagents

Markdown files that teach the agent repo-specific context, loaded automatically or triggered by keyword. Covered in its own tab.

The CLI is the fastest way to work with OpenHands day to day

Running openhands alone launches the default interactive mode, which asks for confirmation before each action. Everything below layers on top of that base command.

Showing 0 commands
Command What it does
openhandsInteractive default mode — asks for confirmation before every action the agent takes.
openhands -t "task description"Start immediately with a task instead of typing it into the prompt.
openhands -f requirements.txtRead the task description from a file — useful for a long spec or a task generated by another tool.
openhands --always-approveNever pause for confirmation. Fast, but the agent can run any command in the sandbox unattended — scope PROJECTS_PATH tightly first (Safety tab).
openhands --llm-approveA second, usually cheaper LLM call reviews each action for risk before it runs — a middle ground between manual approval and full autonomy.
openhands --resumeLists previous conversations to pick up where you left off.
openhands --resume --lastResumes the most recent conversation with no picker.
openhands --resume abc123def456Resumes a specific conversation by its ID.
openhands --gpu --mount-cwdPasses a GPU through to the sandbox and mounts the current working directory — for local-model inference or GPU-dependent build steps.
uv tool upgrade openhands --python 3.12Updates the CLI to the latest release. Run this before filing a bug — many "broken" reports turn out to be an old build.
Key Function
Ctrl+POpens the command palette — settings, MCP server status, and other in-session controls.
EscPauses the agent mid-task. Useful the moment you see it heading somewhere you didn't intend.
Ctrl+Q / /exitExits the CLI cleanly.
Showing 0 variables
Variable / setting Example Notes
LLM_MODEL-e LLM_MODEL=claude-sonnet-5-20260929The model string your provider expects. Set from the UI's Settings panel on first launch, or as an env var for headless/CI use.
LLM_API_KEY-e LLM_API_KEY=sk-…Your provider's API key. Never bake this into a committed Dockerfile or script — pass it at runtime.
SANDBOX_VOLUMES-e SANDBOX_VOLUMES=/Users/tyler/acme:/workspace:rwReplaces the older, now-deprecated WORKSPACE_* path options. Format is host_path:container_path[:mode]; comma-separate multiple mounts. This is the actual boundary of what the agent can touch — see the Safety tab.
SANDBOX_RUNTIME_CONTAINER_IMAGE-e SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.38-nikolaikThe image used for the per-session sandbox container — separate from the main app image. Pin a version if you need reproducible sandbox behavior across runs.
LOG_ALL_EVENTS-e LOG_ALL_EVENTS=trueVerbose event logging — the first thing to enable when a run behaves unexpectedly and you need to see every step the agent took.
AGENT_SERVER_IMAGE_TAG-e AGENT_SERVER_IMAGE_TAG=1.26.0-pythonPins the agent-server image version independently of the main app tag — useful when a release note calls out a specific server fix.
Tavily API key (web search)Settings → LLM tab → Search API KeyOptional. Without it the agent can't search the web for up-to-date library docs or error messages — worth adding for anything touching a fast-moving dependency.
--add-host host.docker.internal:host-gatewaydocker run … --add-host host.docker.internal:host-gatewayLets the container reach services running on your host machine (a local dev server, a database) by that hostname.
~/.openhands mount-v ~/.openhands:/.openhandsPersists settings, conversation history, and credentials across container restarts — without it, every docker run starts from a blank slate.
Model choice matters more here than in a chat app
An autonomous agent taking dozens of tool-calling steps per task needs a model good at long-horizon planning and reliable tool use, not just conversational quality. Anthropic's Claude and OpenAI's frontier models are the most commonly reported to work well end-to-end.
Token usage adds up fast
A single non-trivial task can involve dozens of read/edit/run cycles, each resending accumulated context. Watch usage on your provider's dashboard the first few times, especially with --always-approve running unattended.
A local model works, but expect a capability gap
Point the LLM base URL at Ollama or LM Studio for a fully local setup. Smaller local models struggle with the longer planning chains autonomous coding needs — a frontier hosted model is still the more reliable choice for anything beyond simple edits.

Teach the agent your repo's own conventions

Markdown files under a hidden folder at the repo root give the agent context it would otherwise have to rediscover every session — the equivalent of a CLAUDE.md or AGENTS.md for OpenHands. The system was called microagents in the original (V0) product and renamed skills in the current (V1) generation; both terms still show up across docs and issue threads for the same underlying mechanism.

1

Where they live

.openhands/skills/ # current (V1) location .openhands/microagents/ # older (V0) location — both still recognized
2

repo.md — loaded on every task

The main agent reads this automatically at the start of a session. Put here anything that's true for every task in the repo: how to run tests, the build command, coding conventions, which directories are generated and shouldn't be hand-edited.

.openhands/skills/repo.md .openhands/skills/frontend.md .openhands/skills/migrations.md
3

Triggered skills — loaded only when relevant

A skill other than repo.md can declare trigger keywords in its frontmatter; the agent only loads it when those words show up in the conversation. This keeps narrow domain knowledge (a specific migration tool, a legacy subsystem) out of every prompt's context until it's actually needed.

The sandbox is the whole safety model — respect it
  • Running the agent-server directly (no Docker sandbox) gives it full filesystem access on your machine. That's an explicit, documented mode for advanced use — not the default, and not what you want for a first run.
  • The Docker-sandboxed path restricts the agent to SANDBOX_VOLUMES/PROJECTS_PATH and nothing else — scope that mount to exactly the project you're working on, not your entire home directory.
  • Never point it at a repo with production credentials in plaintext (a checked-in .env, cloud CLI credentials cached in the mounted path) — the agent can read anything inside the mount and may include it in tool calls sent to the LLM provider.
  • Treat --always-approve as a deliberate choice, not a default habit. Confirmation mode exists specifically to catch a plan going sideways before it runs a destructive command.
  • Give it a scratch branch, not main. Autonomous multi-step edits are exactly the case where an easy revert matters most.
  • The Docker socket mount (/var/run/docker.sock) is powerful. It lets the main container spin up sandbox containers, but it also means that container effectively has Docker-level access to the host — standard for this architecture, still worth knowing rather than assuming it's fully contained.
Symptom Likely cause / fix
"Cannot connect to the Docker daemon"Docker Desktop (or Engine) isn't running, or the socket path differs on your OS/setup — confirm docker ps works outside OpenHands first.
Agent can't see files you expect it toSANDBOX_VOLUMES doesn't include that path. It only sees what's explicitly mounted — this is a feature, not a bug, see the Safety notes above.
Agent stalls or loops on the same failing stepPause with Esc, add a note to repo.md about the specific gotcha it's hitting, and resume — this is exactly what the skills system is for.
Old/unexpected behavior after an updateRun with --pull=always on the Docker command, or uv tool upgrade openhands for the CLI, before assuming it's a real bug.
Confusing "OpenHands" search resultsThe org renamed and also ships Agent Canvas, a separate broader product. If a result mentions Slack/Linear automations or "agent-canvas," it's describing that product, not the coding agent this page covers.