Skip to main content

Hao Harness

A terminal coding agent powered by DeepSeek models. 中文文档:README.zh-CN.md

Python License

Hao Harness turns the raw DeepSeek Chat API into an agent that can actually get work done: it reads and edits files, searches code, runs commands, and keeps working across multiple tool-calling rounds until the task is done.


Status

v0.1.0 — unreleased, under active development.

Working today:

  • Multi-round agent loop with tool execution and error feedback
  • 7 built-in tools: read / write / edit / list / glob / grep / run command
  • Thinking mode with live reasoning display
  • Dynamic model discovery via GET /models with disk cache and offline fallback
  • Context compaction driven by the model's real context_window
  • Path sandbox, per-action approval, duplicate-call detection
  • Token accounting and time-of-day aware cost estimation
  • 150 unit tests that run without an API key or network access

Not yet implemented: session persistence (--continue), project memory files (HARNESS.md), sub-agents, MCP support.


Requirements

Install

pipx install hao-harness

Or, from a clone (for development):

pip install -e ".[dev]"

Quick start

# 1. Provide your API key
export DEEPSEEK_API_KEY=sk-your-key        # Windows: setx DEEPSEEK_API_KEY sk-...

# 2. Run a one-shot task
harness -p "create hello.py that prints the first 20 Fibonacci numbers, then run it"

# 3. Or start an interactive session
harness

Without installation you can also run it directly from a clone:

python run.py -p "explain what this project does"

Standalone executable

Two build modes, selected by the HARNESS_BUILD_MODE environment variable.

# Build inside a **clean** virtual environment
python -m venv .venv-build
.venv-build\Scripts\python -m pip install -e ".[build]"

# Default: directory layout (fast startup, recommended)
.venv-build\Scripts\python -m PyInstaller harness.spec --noconfirm
# -> dist\harness\   (about 37 MB directory, ship it as a whole)

# Optional: single-file (portable)
$env:HARNESS_BUILD_MODE="onefile"
.venv-build\Scripts\python -m PyInstaller harness.spec --noconfirm
# -> dist\harness.exe   (about 22 MB)

Both bundle Python and every dependency — the target machine needs no Python installation:

$env:DEEPSEEK_API_KEY="sk-..."
.\dist\harness\harness.exe -p "create hello.py and run it"

Which mode to pick

Measured (6 runs each, warmed up, median):

Mode Startup Size Use when
onedir (default) ~0.4 s ~37 MB directory Installer packaging, everyday use
onefile ~1.3 s ~22 MB single file You genuinely need one file to copy around

One-file mode costs roughly 0.9–2 s per launch, for two reasons: it extracts itself to a temp directory on every run, and the extracted files are new, freshly hashed binaries that Windows Defender re-scans each time. Prefer the default onedir unless you really need a single file.

Always build in a clean virtual environment. PyInstaller walks the import graph of your interpreter's site-packages. Building from a polluted environment drags unrelated packages into the binary — we measured 74 MB vs 22 MB for exactly the same code.

Builds are platform-specific. A Windows binary must be built on Windows; macOS and Linux require their own builds.

Desktop app (optional)

The desktop interface is an optional extra: installing it pulls in Qt (PySide6-Essentials) and grows the install from ~19 MB to 100 MB+. Nothing in the terminal path depends on it.

pipx install "hao-harness[gui]"
harness-gui

If the extra is missing, harness-gui prints the exact install command instead of an ImportError traceback — not having it is a normal state, not a failure.

Building a standalone desktop executable:

.venv-build\Scripts\python -m pip install -e ".[build,gui]"
.venv-build\Scripts\python -m PyInstaller harness-gui.spec --noconfirm
# -> dist\harness-gui\   (about 112 MB directory, ship it as a whole)

There is deliberately no one-file desktop build: the artifact is over 100 MB, and one-file mode extracts all of it on every launch into freshly hashed files that Defender re-scans — the startup penalty measured above would be multiplied.

harness-gui.spec is a separate configuration from harness.spec, not a mode of it. The terminal build must exclude Qt (otherwise it grows from 22 MB to 120 MB+); the desktop build must include it. One spec cannot do both.

Building the desktop installer:

.venv-build\Scripts\python -m PyInstaller harness-gui.spec --noconfirm
makensis packaging\installer-gui.nsi
# -> dist\HaoHarness-0.1.0-setup.exe   (38 MB installer for a 112 MB app)

Two installers, two identities — both can be installed side by side. installer.nsi installs Hao Harness CLI into Program Files\Hao Harness CLI and adds it to PATH. installer-gui.nsi installs Hao Harness into Program Files\Hao Harness and does not touch PATH — it is launched from the Start Menu, and this artifact has no command-line entry. Uninstalling either one keeps your configuration (including the API key), so a reinstall needs no re-setup.

The desktop app bundles Qt for Python under LGPL-3.0-only. See NOTICE for the required notice, the bundled license texts, and where to obtain the Qt source.

Usage

harness [task ...] [options]
Option Description
-p, --prompt TEXT Run this task once and exit
--model ID Model to use (default: deepseek-flash)
--effort {low,high,max} Reasoning effort (default: high)
--no-thinking Disable thinking mode (faster, cheaper)
--no-stream Disable streaming output
--list-models List known models and exit
--refresh-models Refresh the model list from the API
-w, --workspace DIR Working directory (default: current directory)
--max-steps N Max tool-calling steps per turn (default: 40)
--yolo Skip all approvals
--allow-outside Allow paths outside the workspace
--lang {zh,en} UI language
--show-config Print the effective configuration and exit

Interactive commands

Command Description
/help Show available commands
/status Show model, context usage and token totals
/models List available models
/model [id] Switch model
/refresh Refresh the model list
/tools List tools
/compact Compact context now
/clear Clear conversation history
/exit Quit

Configuration

Configuration resolves in this order: .env file → environment variables → command-line flags. Copy .env.example to .env to get started.

Variable Default Description
DEEPSEEK_API_KEY — Required
DEEPSEEK_BASE_URL https://api.deepseek.com API endpoint
DEEPSEEK_MODEL deepseek-flash Model id
HARNESS_THINKING true Thinking mode
HARNESS_REASONING_EFFORT high low / high / max
HARNESS_MAX_TOKENS 32000 Max output tokens per reply
HARNESS_MAX_STEPS 40 Max tool-calling steps per turn
HARNESS_MAX_TOOL_OUTPUT 30000 Tool output truncation limit
HARNESS_COMPACT_THRESHOLD 400000 Estimated-token compaction threshold
HARNESS_AUTO_APPROVE false Skip approvals
HARNESS_ALLOW_OUTSIDE false Allow paths outside the workspace
HARNESS_LANG auto zh or en

Project memory

Create HARNESS.md in your project root to give the agent standing context: build commands, code conventions, directory layout, decisions you already made.

# HARNESS.md

- Run tests with `python -m pytest`
- Never edit `migrations/` by hand
- Public API lives in `src/api/`

Two levels are loaded, in this order:

Location Scope
<user config dir>/HARNESS.md Your personal preferences, shared across projects
<workspace>/HARNESS.md This project's conventions

The user config directory is %APPDATA%\harness on Windows, ~/Library/Application Support/harness on macOS, and $XDG_CONFIG_HOME/harness (or ~/.config/harness) on Linux.

Things worth knowing:

  • Only HARNESS.md is read. CLAUDE.md and AGENTS.md are deliberately ignored: they are written against other tools' capabilities and would reference features this harness does not have, which only confuses the model.
  • Memory is appended to the end of the system prompt and cannot override the working rules or the approval mechanism — a repository file is semi-trusted input.
  • Content is capped at 20,000 characters so it can never crowd out the task.
  • Disable with --no-memory; inspect what was loaded with /memory.

Safety

This tool executes commands and modifies files.

  • File operations are confined to the workspace; escaping paths are rejected.
  • Writing files and running commands require explicit confirmation.
  • --yolo disables those confirmations. Only use it in a sandbox or on a throwaway checkout.

Documentation

Document Contents
GOAL.md Scope, architecture, design decisions
PROGRESS.md Development status and roadmap
CONVENTIONS.md Coding standards and toolchain
CHANGELOG.md Release history
NOTICE Third-party software and licenses (includes the Qt LGPL notice)

Development

pip install -e ".[dev]"

python -m ruff check .        # lint
python -m ruff format .       # format
python -m mypy harness        # type check
python -m pytest              # tests (no API key needed)

License

Apache-2.0

The desktop interface bundles Qt for Python, licensed under LGPL-3.0-only. The required notice, the bundled license texts (third_party/LGPL-3.0.txt, third_party/GPL-3.0.txt) and the routes to the Qt source are in NOTICE. Terminal-only usage involves no LGPL components.

Metadata

Release files for hao-harness 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for hao-harness 0.1.0
File Interpreter ABI Platform
hao_harness-0.1.0-py3-none-any.whl Python 3 none any Details

Release files / hao_harness-0.1.0-py3-none-any.whl

Download URL hao_harness-0.1.0-py3-none-any.whl
Size 235.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2eee03ea9d4c2a2915087af8659053a36062059b6fd9282bd3ee79684f76b7e4
BLAKE2b-256 checksum
How to use checksums
2964e5301b37bd39e58c41c4bfb4104495d728023be2a8d0e4cdc42cbbf03c2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page