Skip to content

humanize

humanize runs flows — directories of Python that drive one or more coding agents in a loop and write down everything they did. Most backends drive a coding agent you already have, under its existing login.

Python ≥ 3.12 · reuses the CLI logins you already have

How it fits together

Flows

what the work is: which agents are driven, what each is asked, and when to stop

  • chat
  • ralph_loop
  • stateful_ralph
  • rlar
  • flame_chase
  • and yours

a flow, and one agent for every agent it drives

humanize

the runner: it takes the turns, keeps the sessions, and writes the whole run down

  • the runner
  • sessions and turns
  • agents
  • providers and accounts
  • machines
  • the epic
  • the trace

a turn: a prompt, an effort, and the session to put it on

Agent CLIs

the model, reached through a coding agent you already have and are already logged into

  • claude
  • codex
  • cursor
  • kimi
  • pi
  • grok
  • qwen
  • agy
  • opencode
  • mimo
  • zcode
  • DeepSeek Harness a Python SDK that ships inside humanize — not a CLI you install

edits, commands, and every syscall the agent makes

Environment

where the work actually lands, and what it is allowed to touch there

  • this machine
  • a container of its own
  • a remote target through hmz internal anchor
  • worktrees

The rough shape. Every capability, grouped and linked to its explanation, is on Features; every backend against what a flow may ask of it is Many backends, one agent, which also covers anything that speaks the Agent Client Protocol.

Run a flow

Use a scratch directory

humanize runs every agent with permission prompts disabled: an agent under it edits files without asking. Do this in a throwaway git repository, and read Security before you point it at work you care about.

You need Python 3.12 or newer and one coding agent CLI you have already logged into. humanize holds no API key and talks to no model provider itself, so you log in the way you already log in.

sh
pip install git+https://github.com/humanfia/humanize.git

Then make something for it to fix. calc.py subtracts where it should add, and that bug is the work:

sh
mkdir -p ~/tmp/humanize-demo && cd ~/tmp/humanize-demo && git init -q
printf 'def add(a, b):\n    return a - b\n' > calc.py
git add -A && git commit -qm "a calculator with a bug in it"

Both ways below run the same flow, ralph_loop: it gives the agent the same task over and over in a fresh conversation each time, so it restarts from the task and the repository rather than from a context window full of its own earlier attempts.

At the prompt

sh
hmz

That opens the terminal interface, on nothing in particular. Say which flow and what it is to do, on one line:

$ralph_loop Fix the bug in calc.py.

$ names a flow, and this directory has never run that one, so /flow opens inside it with your line held. Two questions answer what runs it: which flow — which the line already named — and then what its one agent is: the CLI you are already logged into, which of its models, and how hard it should think. The models offered are the ones your account may name, asked of the CLI itself rather than written into humanize. save, the row below the agents, starts the flow on the line you typed — as shift+enter or ctrl+j does from anywhere on the menu.

You answer that once. What you chose is remembered for this directory, so the next hmz here opens on it and Fix the bug in calc.py. is the whole of what you type.

The agent takes a turn — one exchange with the model, which may run tools and may take minutes — and then the loop gives it the same task again. Type another line while it is working and it goes into the running turn rather than starting a new one. / lists every command, ctrl+c twice stops the loop, and /exit leaves.

Or without the interface

The same flow, the same agent, with the task on the line instead. ralph_loop is one of humanize's own flows, which live in a flowverse fetched the first time the flow menu opens — so if you have come straight here, open hmz once first and press /flow.

sh
hmz exec -f ralph_loop -a claude/claude-opus-4-8:high "Fix the bug in calc.py."
sh
hmz exec -f ralph_loop -a codex/gpt-5.6-sol:high "Fix the bug in calc.py."
sh
hmz exec -f ralph_loop -a agy/gemini-3.7-flash-high:high "Fix the bug in calc.py."
sh
hmz exec -f ralph_loop -a qwen/qwen3-coder-plus:high "Fix the bug in calc.py."
sh
hmz exec -f ralph_loop -a kimi/kimi-code/k3:high "Fix the bug in calc.py."
sh
hmz exec -f ralph_loop -a grok/grok-4.6:high "Fix the bug in calc.py."
sh
hmz exec -f ralph_loop -a zcode/zai/glm-5.3:high "Fix the bug in calc.py."

-f names the flow and -a names one agent, written cli/model:effort — the CLI that runs the turn, the model it asks for, and how hard that model should think. A flow that drives several takes several, separated by commas or given an -a apiece; the fuller spelling, which also says which account and which of the flow's places an agent fills, is [name=]cli[@account]/model:effort. A Ralph loop does not stop on its own, which is what it is for: ctrl+c at the command line when you have seen enough. Every round is written down, so stopping loses nothing.

Either way, check the work:

sh
git diff
diff
 def add(a, b):
-    return a - b
+    return a + b

It made that edit with no permission prompt, and there is no setting that turns them back on. That is the one thing to have understood before pointing this at a real repository.

The model id is wrong, or your CLI is not above

A model id is whatever that CLI shipped this week, and which ones you may name depends on the account you are logged in as. Open /flow in the interface and turn to its agents: humanize asks each CLI once and keeps the answer. Every backend it drives, including the ones not in those tabs, is in Many backends, one agent; Installation is how to sign each one in.

Next. /epics lists the runs of this directory and turns any one of them into a timeline you can open in Perfetto. The User Guide has a page per thing humanize does, and its tutorials each take a real piece of work start to finish: Beat a benchmark, Port a project, and Build a coding agent. For the words above, properly defined, read Concepts.

Weave a flow

A weaver is whoever writes a flow. A flow is a directory whose __init__.py holds a function marked @flow, and that function drives the agents. Write one when you want the same agents run the same way again and again, rather than typed out afresh each time.

sh
mkdir -p .humanize/flows/twice
python
# .humanize/flows/twice/__init__.py
"""Two passes: do the work, then read it back and fix what is wrong."""

from hmz.flows import Agent, flow


@flow
def run(agents: tuple[Agent], task: str) -> None:
    (agent,) = agents
    session = agent.new()
    session(task)
    session("Now review what you just did, and fix anything that is wrong.")

Run it by name. humanize also offers it in the interface: /flow lists the flows it ships, every flowverse fetched here, and your own — the ones in .humanize/flows as local, the ones in ~/.humanize/flows as user.

sh
hmz exec -f twice -a claude/claude-opus-4-8:high "add a --dry-run flag to calc.py"

Three rules are the whole contract:

The @flow mark makes it a flowNot the function's name, which is yours to choose
The annotation on agents says how many it drivestuple[Agent], tuple[Agent, Agent]tuple[Agent, ...] is refused
That annotation must be readable at runtimeImport Agent normally, never under if TYPE_CHECKING

The command line cannot know the count any other way, so humanize checks it before the first turn — and an annotation nothing can read back is not one it can hold you to.

Whether the second turn remembers the first is the other choice you are making:

python
agent("do the task")     # a session of its own, dropped straight after: nothing carries over
session = agent.new()    # a session you hold
session("do the task")   # opens it
session("keep going")    # resumes it, the first turn still in context

Read a flow for what will not run, before anything runs it:

python
from hmz.sdk import Hmz

for found in Hmz().flows.check("local/twice"):
    print(f"{found.severity}: {found.code}: {found.said}")

Nothing printed is a flow with nothing wrong with it. local/ is this project's own flows, which is where .humanize/flows/twice is offered from. See Checking a flow.

Next. The Weaver Guide is what a flow may do and how to write one — loops, settings, goals, shapes, hooks, worktrees. Build under test is the shortest useful flow there is, start to finish.

Work on humanize

sh
git clone https://github.com/humanfia/humanize.git
cd humanize
uv sync
uv run pre-commit install

Installing the hooks once means every commit is checked before it is made. There are two gates and both have to pass:

sh
uv run pre-commit run --all-files   # the formatter, the linter and the type checker
uv run pytest                       # everything that does not need a real agent
uv run pytest --run-agents          # also drives the real CLIs, and spends real tokens

What the code is held to: pyright in strict mode over src and tests, with # type: ignore switched off — a suppression names a rule; ruff with every rule on, less the ones annotated in pyproject.toml; Google-style docstrings; and a popular, well-maintained library in preference to a custom implementation.

Each package depends only downwards, and a test checks the layering — Architecture has the layers and the rules that keep them. Most packages have a SPEC under specs/, in a file named for the package. Do not modify a SPEC unless you were asked to: it is the contract, and the code is what has to move.

Next. Contributing is the whole of it, and Your first patch takes one change from clone to pull request.

Where to go next

humanize runs every agent with permission prompts disabled, and no setting turns them back on — an agent under a flow edits files, runs commands and makes commits without asking. Read Security before you point one at a repository you care about.

Released under the Apache-2.0 licence.