Detailed guidance for contributors working on the OpenHands CLI.
This repo includes both pyproject sections for hatch/uv and Poetry for compatibility.
- Add a runtime dependency (using uv):
uv add <package>
- Add a dev dependency (linters, build tools, etc.):
uv add --dev <package>
- Sync environment:
uv sync --extra dev
If you use Poetry instead of uv:
poetry add <package>
poetry add --group dev <package>
poetry installCommit the updated pyproject.toml (and lockfile if applicable) with your change.
PyInstaller uses a spec file (openhands-cli.spec) to describe what to include in the binary. Two common knobs when something is missing in the built executable:
-
hiddenimports: Python modules that PyInstaller fails to detect automatically. Use when imports are dynamic or optional. Example in spec:
hiddenimports=[ 'openhands_cli.tui', 'openhands_cli.pt_style', *collect_submodules('prompt_toolkit'), *collect_submodules('openhands.core'), *collect_submodules('openhands.tools'), ]
-
datas (a.k.a. data files): Non-Python files required at runtime (templates, config, etc.). Use collect_data_files to include them. Example in spec:
datas=[ *collect_data_files('tiktoken'), *collect_data_files('openhands.core.agent.codeact_agent', includes=['prompts/*.j2']), ]
Differences:
- hiddenimports is for modules to be packaged as bytecode.
- datas is for external resource files copied into the bundle.
If a library fails at runtime with "ModuleNotFoundError" inside the binary, add it to hiddenimports. If a library complains about missing template/config/resource files, add those paths to datas.
-
Quick build (recommended):
./build.sh --install-pyinstaller
This ensures PyInstaller is present via uv and then runs build.py.
-
Manual build:
uv add --dev pyinstaller uv run pyinstaller openhands-cli.spec --clean
-
Test the binary:
./dist/openhands-cli # macOS/Linux # or dist/openhands-cli.exe # Windows
If the binary fails to start:
- Run the Python entrypoint to confirm the app itself works:
uv run openhands-cli
- Re-run build with --no-clean to inspect build artifacts, or add more hiddenimports/datas.
- Run all pre-commit hooks:
make lint
- Format code:
make format
To actually converse with a model, export one of the supported keys before running the CLI/binary:
export OPENAI_API_KEY=... # or
export LITELLM_API_KEY=...