
How do I install and use the OpenHands CLI to make a change, run tests, and open a PR?
Most engineering teams want to see OpenHands in action as fast as possible: install the CLI, point it at a repo, have an agent make a scoped change, run tests, and open a pull request you can review. This guide walks through that exact workflow end to end, so you can treat OpenHands like real infrastructure in your stack—not a toy copilot.
Quick Answer: Install the OpenHands CLI, authenticate it, and point it at your repository. Then use CLI commands to define a task, let an agent make changes inside a sandbox, run your test suite, and automatically open a PR with diffs you can review. You get autonomous execution plus full visibility into what ran, where it ran, and what changed.
Why This Matters
If an agent can’t take a ticket from “please fix X” to “here’s a PR with passing tests,” it’s just another assistant sitting next to your IDE. OpenHands is designed to run as a cloud coding agent platform you operate: model-agnostic, sandboxed, and wired into your Git workflows.
Being able to install the OpenHands CLI and run a change–test–PR loop matters because it:
- Proves the agent can handle real SDLC work, not just snippets.
- Shows you how autonomy and governance work together (sandbox runtime, logs, and reviewable diffs).
- Lets you scale from one-off experiments to thousands of agents running headlessly in CI/CD once you trust the runtime.
Key Benefits:
- End-to-end automation: Offload full tasks—code edits, tests, and PR creation—instead of micro-suggestions in your editor.
- Visibility and control: Every command, file change, and test run is logged and auditable; nothing happens as a black box.
- Scales like infrastructure: The same CLI you use interactively can run headlessly in pipelines for repo-wide upgrades, refactors, and fixes.
Core Concepts & Key Points
| Concept | Definition | Why it's important |
|---|---|---|
| OpenHands CLI | A command-line interface to run, inspect, and automate OpenHands agents from your terminal or pipelines. | Lets you treat agents like infrastructure: scriptable, debuggable, and CI/CD-friendly instead of tied to a chat UI. |
| Sandboxed runtime | A secure, containerized environment where agents execute, with scoped access to code, tools, and credentials. | Keeps agent work safe and auditable; you control what the agent can touch and can replay runs deterministically. |
| Change–Test–PR loop | A repeatable workflow where an agent makes code changes, runs tests, and opens a pull request for review. | Gives you a production-grade pattern to convert tickets into reviewable artifacts, not just suggestions. |
How It Works (Step-by-Step)
At a high level, you’ll:
- Install and configure the OpenHands CLI.
- Run an agent against a local or remote repository.
- Let the agent implement a change, run tests, and open a PR.
Details will vary depending on your environment (local vs. CI, GitHub vs. GitLab, specific test runner), but the pattern stays the same: you describe the task, the CLI orchestrates the agent in a sandbox, and you review the resulting branch and PR.
1. Install the OpenHands CLI
The CLI is how you control cloud coding agents from your own environments—terminal, Docker, or CI. Exact commands may differ slightly by platform, but a typical flow looks like this:
a. Prerequisites
- Git installed and configured (
git --version). - Docker or Kubernetes available if you’re running fully sandboxed self-hosted runtimes.
- Access to an LLM provider (OpenAI, Anthropic, Bedrock, or your own deployment) and credentials.
- For GitHub/GitLab PR automation: a PAT (personal access token) with repo permissions.
b. Install via package manager (example layout)
On macOS (Homebrew-style installation):
brew tap openhands/cli
brew install openhands
On Linux (curl + install pattern):
curl -fsSL https://openhands.dev/install.sh | bash
On Windows (scoop-style):
scoop bucket add openhands https://github.com/openhands/scoop-bucket
scoop install openhands
Verify installation:
openhands --version
You should see a version string confirming the CLI is available.
2. Configure OpenHands CLI and Authentication
The CLI needs to know which models and services it can use, and how to talk to your Git host.
Run the initial setup:
openhands configure
Typical configuration inputs:
-
Model settings
- Choose your provider:
openai,anthropic,bedrock, or a self-hosted endpoint. - Provide the API key or endpoint token.
- Optionally specify a default model (you can override per run).
- Choose your provider:
-
Runtime / sandbox settings
- Configure whether to use a local Docker runtime or a remote sandbox.
- Set resource limits if needed (CPU, memory, timeout).
-
Git integration
- Add your GitHub/GitLab token and default host (e.g.,
github.com). - Set a default Git user/email for agent-created commits.
- Configure SSH vs HTTPS as appropriate for your environment.
- Add your GitHub/GitLab token and default host (e.g.,
The CLI will typically write these settings to a config file such as:
~/.config/openhands/config.yaml
You can edit this file directly to tune defaults (e.g., default branch naming convention, default test command, etc.).
3. Connect the CLI to Your Repository
You can run OpenHands against a local checkout or have it clone from a remote URL.
a. Local repository
From the root of your project:
cd /path/to/your-repo
git status # ensure your working tree is clean
You’ll want an up-to-date main branch:
git checkout main
git pull origin main
The CLI will operate within this repo, using the sandbox runtime to modify files and run tests.
b. Remote repository (optional pattern)
If you prefer to let the CLI handle cloning:
openhands init \
--repo https://github.com/your-org/your-repo.git \
--branch main \
--checkout-path /tmp/openhands-your-repo
Then:
cd /tmp/openhands-your-repo
From here, the steps are the same as with a local repo.
4. Describe the Change You Want
OpenHands works best when you describe the task in SDLC terms. Examples:
- “Refactor the authentication middleware to extract logging into a separate module and add unit tests for the new module.”
- “Fix the failing Jest tests in
user-profile.test.tsand update any impacted React components.” - “Upgrade
lodashto the latest compatible major version and update any breaking usages.”
You can supply this as a command-line argument or via a task file.
Option A: Inline task
openhands run \
--task "Fix the failing unit tests for the payment service and ensure all tests pass." \
--run-tests "npm test" \
--open-pr
Option B: Task file
Create openhands-task.yaml:
task: >
Implement pagination for the /api/users endpoint,
update any affected frontend components, and add tests
covering page boundaries and invalid page parameters.
run_tests: "npm test"
open_pr: true
base_branch: "main"
Run:
openhands run --config openhands-task.yaml
5. Let the Agent Make a Change
When you invoke openhands run, the CLI:
- Spins up a sandboxed runtime (container/isolated environment).
- Loads your repository into that runtime.
- Uses your chosen model to plan the change.
- Applies edits to the codebase (adding/modifying files as needed).
- Writes a log of all operations.
You’ll typically see:
- A summary of the task.
- A stream of actions (files opened, diffs proposed).
- A preview of changes before they’re finalized, depending on your settings.
You can configure the degree of autonomy:
- Fully autonomous: The agent applies changes directly in the sandbox, then syncs to your branch.
- Confirm before apply: The CLI pauses to show you diffs and asks for confirmation.
Example with a confirm step:
openhands run \
--task "Add input validation to the user registration endpoint and tests for invalid inputs." \
--run-tests "pytest" \
--review-before-apply
The CLI will print diffs and prompt:
Review the proposed changes above.
Apply these changes? (y/N):
6. Run Tests from the CLI
You can let OpenHands run tests as part of the same command, or run them separately first.
a. Let OpenHands run tests
If you specify --run-tests, the agent will:
- Run the given test command inside the sandbox.
- Parse failures and iterate if needed (e.g., fix failing tests, rerun).
Example:
openhands run \
--task "Fix any failing tests in the orders service and clean up unused mocks." \
--run-tests "pytest tests/orders" \
--open-pr
You’ll see:
Running tests: pytest tests/orders
Tests failed: 3
Attempting to fix failures...
Re-running tests...
All tests passed.
b. Manually run tests
If you prefer to keep test control explicit:
openhands run \
--task "Implement the new discount calculation rules in discount_service.py." \
--no-tests
Then:
pytest
Once tests are green, you can still use the CLI to open a PR:
openhands pr open --base main --title "Implement new discount calculation rules"
7. Open a Pull Request from the CLI
The final step of the change–test–PR loop is to push a branch and open a PR you can review.
If you used --open-pr, OpenHands will:
- Create a new branch (e.g.,
openhands/task-1234). - Commit the changes with a generated commit message.
- Push the branch to your remote.
- Open a PR via GitHub/GitLab API, including:
- Title and description summarizing the task.
- Bullet list of changes and tests run.
- Links to logs or runtime artifacts, if configured.
You’ll see something like:
Branch created: openhands/add-registration-validation
Pushed to origin.
Pull request created: https://github.com/your-org/your-repo/pull/1234
You can customize:
openhands run \
--task "Add rate limiting to the public API and document the new limits in README." \
--run-tests "npm test" \
--open-pr \
--pr-title "Add rate limiting to public API" \
--pr-base "main" \
--pr-label "openhands"
Or, if you’ve already made the change and just want PR creation:
git checkout -b openhands-rate-limiting
# ...your own edits/tests...
git commit -am "Add API rate limiting and docs"
openhands pr open \
--base main \
--title "Add API rate limiting" \
--label "openhands"
Common Mistakes to Avoid
-
Letting agents run without guardrails:
Don’t give an agent unrestricted access to production or broad credentials. Use the sandbox runtime, scoped tokens, and repo-level access. Configure the CLI so agents work within isolated Docker/Kubernetes environments you control. -
Being vague about the task:
“Make the code better” is not a task. Specify files, behaviors, and test expectations. Tie your instructions to artifacts: failing tests, endpoints, specific services, or libraries. Clear tasks produce focused diffs and faster approvals. -
Skipping test configuration:
If your repo needs environment variables, databases, or special commands for tests, codify that in your CLI config or task file. Otherwise, tests will fail for environmental reasons and the agent will chase noise. -
Running against a dirty working tree:
Always start from a cleangit status. Uncommitted local changes confuse the agent and can produce tangled diffs.
Real-World Example
Here’s how I’d wire this up in a real service repo.
You’ve got a Python microservice billing-service with flaky tests around invoice generation. There’s already a GitHub issue: “Fix flaky invoice tests and document expected rounding behavior.”
From your terminal:
cd ~/src/billing-service
git checkout main
git pull origin main
openhands run \
--task "Fix flaky invoice generation tests in tests/test_invoice.py, ensure deterministic rounding behavior in invoice.py, and update docs/invoices.md to describe the new rules. All tests must pass." \
--run-tests "pytest" \
--open-pr \
--pr-title "Fix flaky invoice tests and document rounding behavior"
OpenHands will:
- Clone or use your local repo in a sandbox.
- Analyze
tests/test_invoice.pyandinvoice.py. - Update the implementation to remove nondeterministic behavior.
- Update
docs/invoices.mdwith a concise explanation of rounding rules. - Run
pytestuntil everything passes. - Create a branch, commit, push, and open a PR on GitHub with:
- A summary of what changed.
- A note that
pytestwas run successfully. - Links to artifacts/logs, depending on your setup.
Your reviewers see a standard PR: changes scoped to the invoice logic and tests, plus docs, with a clear story. No babysitting, no mystery; just a clean diff and a repeatable process.
Pro Tip: Start by constraining early tasks to small, well-bounded changes (one service, one test suite, one feature). Once you’ve validated the change–test–PR loop in this narrow scope, you can confidently scale OpenHands to larger refactors and parallel agent runs in CI.
Summary
Installing and using the OpenHands CLI to make a change, run tests, and open a PR is about treating agents like part of your infrastructure, not as a sidecar in your IDE. You install the CLI, configure your model and sandbox runtime, scope a task against a clean repository, and let the agent execute a complete change–test–PR loop with full visibility.
Because OpenHands is model-agnostic, sandboxed, and open by design, you get autonomy without black boxes: you can inspect every diff, trace every run, and replay tasks deterministically—whether it’s a single bugfix or thousands of concurrent dependency upgrades.