HandCode 0.3.1 GitHub

HandCode

CI

HandCode keeps a coding agent's work safe across crashes, restarts and provider switches. Its command is agentctl.

When an agent's process dies in the middle of a task and you resume it, the agent framework re-runs whatever was in flight, so a commit can happen twice. agentctl records every action before it runs. A resumed run never repeats one that already happened, and when agentctl cannot tell whether it did, it stops and asks you instead of guessing.

It wraps the OpenHands agent SDK and works with any provider LiteLLM supports, free tiers included.

Documentation: https://csdeepak.github.io/HandCode/

See it in a minute

agentctl demo          # no API key, no network, $0
  1. Plain OpenHands, no agentctl
     the agent committed, then its process was killed ... 1 new commit
     resumed ............................................ 2 new commits   <- the same commit, twice

  2. With agentctl
     the agent committed, then its process was killed ... 1 new commit
     resumed ............................................ 1 new commit    <- once
     the ledger: the commit is OBSERVED (git probe: LANDED) · 0 waiting on you

Real git, real process death and the real SDK. Only the model is scripted, which is what makes it free and identical on every OS.

Quickstart

You need uv, git, and one API key (a free OpenRouter or Gemini key works). uv fetches Python 3.12 itself if you do not have it.

uv tool install "handcode[openhands]"     # from PyPI; seconds with uv

agentctl demo                             # see what it is for
agentctl init                             # one key, one checked default model
cd your-project
agentctl run "fix the failing date test" --accept "python -m pytest -q"

Every run ends with a report of what was checked, what changed, what it cost, and what needs you:

  outcome     PASS   `python -m pytest -q` exited 0 (run by agentctl after the agent finished)
  changed     1 file  +5 -1
  used        9 requests · 43.7K tokens · $0.00 (free-tier model) · 12s
  actions     8 actions: 3 reads, 3 file writes, 2 commands
  needs you   nothing

The user guide covers the quickstart step by step (Windows included), concepts in plain words, troubleshooting by the exact text you see, and an FAQ.

What it protects you from

Without agentctl With it
The process dies mid-action, then you resume The in-flight action runs again It runs at most once. If it already landed, the agent gets its result back
You cannot tell whether something happened It is guessed It is checked (did HEAD move?), or you are asked
Ctrl-C, a closed laptop, a killed terminal Start again agentctl resume
A rate limit mid-task The run dies --wait 30m waits it out and resumes, or --pool routes to another provider
A dangerous command with nobody watching It runs, or the run hangs on a prompt It is queued for agentctl approve / deny
"Done!" from the agent Taken on trust --accept runs your tests and reports PASS or FAIL
Two terminals resuming the same run Both drive it The second is refused and told which process holds it

What it does not do: it is not a sandbox. Commands run on your machine. agentctl stops actions repeating and asks before dangerous ones, but it does not contain what an allowed command does. For a task you would not trust your shell with, run it in the container image, where only the mounted repository is reachable (concepts).

On GitHub. Type a task in your repository's Actions tab and get a pull request back, with the report as its description. Your key stays in your repository's secrets, and the job that runs the agent holds no token that can write (the GitHub Action). It has run on GitHub with a real model and opened a real pull request.

Status. 917 tests, including a chaos suite that kills the process at ten points in the protocol, plus verify.py's end-to-end crash experiments. All run at no cost, on Linux and Windows in CI. Every feature here has also been run at least once against a real provider. The design history, with what was measured and what was found, is the numbered docs/ stream.