Skip to content

Latest commit

 

History

History
110 lines (89 loc) · 2.79 KB

File metadata and controls

110 lines (89 loc) · 2.79 KB

Development Guide

Detailed guidance for contributors working on the OpenHands CLI.

1) Managing dependencies with Poetry/uv

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 install

Commit the updated pyproject.toml (and lockfile if applicable) with your change.

2) Packaging with PyInstaller: spec file tips

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.

3) Build locally and test

  • 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.

4) Linting and formatting

  • Run all pre-commit hooks:
    make lint
  • Format code:
    make format

5) Notes on agent credentials

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=...