Hand tasks to agents
Hand a task to Claude Code, Codex, or Hermes with hi agent. The agent works without permission prompts in a box, on its own branch, and you get back one report, the same for every agent.
hi agent hands a task to a coding agent and waits for it. The agent works
in a box: a rootless container with the project and nothing
else from your home folder, a network that reaches only what is allowed,
and its own git branch. When it is done, you get one report: what it said,
whether it worked, and which files changed. The report has the same shape
whichever agent did the work.
hi agent "make the flaky test in tests/test_sync.py reliable"
Box myproject-1: claude in ~/.local/state/hi/box/myproject-1/work (branch hi-box/myproject-1), network dev.
Claude Code is working in myproject-1. hi box attach myproject-1 follows it; Ctrl+C stops waiting, not the agent.
The test waited a fixed 100 ms for the sync thread. It now waits on the
thread's event, and passes 50 times in a row. Committed as 3f2a91c.
Changed on hi-box/myproject-1:
tests/test_sync.py
Review with hi box diff myproject-1, keep with git merge hi-box/myproject-1, then hi box rm myproject-1.
Run a task
hi agent "<task>" # the first agent installed and signed in
hi agent claude "<task>" # Claude Code
hi agent codex "<task>" # Codex
hi agent hermes "<task>" # Hermes Agent
Without an agent’s name, hi agent takes Claude Code if it is installed and
signed in on this machine, then Codex, then Hermes. The agent starts from your
last commit, on a new worktree and the branch hi-box/<name>; uncommitted
changes in the project aren’t in it, and hi says so when there are some.
Hermes
Hermes Agent from Nous
Research (hi install hermes) runs on OpenRouter with your key in
~/.hermes/.env. The key stays outside the box, like Claude Code’s
sign-in: the box’s Hermes gets a placeholder and hi’s proxy as its
endpoint, and only the proxy reads the key, and only that key, from
~/.hermes/.env. Hermes itself and its Python are mounted read-only from
your install, so the box runs the version you have.
- Only OpenRouter for now; with another provider
hi agent hermessays so. - The box gets a small Hermes config of its own: your model, the terminal in the box, and none of your gateways, MCP servers, or other keys.
- Hermes doesn’t know OpenRouter’s prices through hi’s proxy, so its report has no cost.
The model
--model picks the agent’s model, for example --model sonnet or
--model gpt-6.1-sol. Without it, the box uses the model in your own
settings (model in ~/.claude/settings.json, in ~/.codex/config.toml,
or Hermes’ model.default in ~/.hermes/config.yaml), so it behaves like
the agent on this machine. If
your settings don’t name one, Claude Code gets opus: in the box it only
holds a placeholder token, so it can’t see your plan and would otherwise
choose its plan-less default, Sonnet. Codex keeps its own default. The box’s
first line says which model it runs, and the report’s closing line says
which one did the work.
In a folder without git
Not every task is code. In a folder that isn’t a git repository, even an empty one, the agent works in the folder itself:
mkdir gpu-prices && cd gpu-prices
hi agent "collect this year's GPU rental prices from RunPod and Shadeform into prices.csv"
Box gpu-prices-1: claude in ~/gpu-prices (not a git repository: it works in place), network dev.
…
Changed in ~/gpu-prices:
prices.csv
hi lists the folder’s files before the run and again after, so the report
names every file added, changed, or removed, and hi box diff says which.
There’s no branch to throw away: what the agent writes or deletes is in
the folder at once. hi warns when the folder has more than 1,000 files or
1 GB, and refuses to work in your home folder or above it, since the box
gets the whole folder. --here works in place in a git repository too.
A task from a file
Write a long task, a brief, as a markdown file and give its name instead of the task:
hi agent briefs/gpu-prices.md
hi agent codex review.md
./make-brief.sh | hi agent claude - # - reads the task from stdin
hi agent --task-file brief.txt # a file whose name doesn't end in .md
A single word ending in .md is a file: its contents are the task. Two or
more words are always the task itself, so
hi agent "fix the typo in README.md" works as before. hi reads the file
before it makes the box, so a brief you haven’t committed works too. A name
that doesn’t exist stops hi with an error, instead of being sent to the
agent as the task. A task file can be at most 1 MB, and the report’s
task_file says which file it was.
Options in the brief
A brief can start with the options it needs, between two --- lines:
---
agent: claude
bundles: [web, office]
network: open
---
# Nordic GPU providers
Find the five largest GPU cloud providers in the Nordics…
It can set agent, model, bundles, network, allow, data, and
gpu.
Flags on the command line win. A brief can come from anyone, another agent
too, so what would widen the box (network, allow, data, gpu) is
asked about first; without a terminal it’s left out, and hi says which
flag allows it.
Bundles: skills and the tools they need
For work that isn’t code, such as browsing or writing documents, attach a bundle: a set of skills and the tools they need.
mkdir gpu-prices && cd gpu-prices
hi agent --bundle web,office "find the five largest Nordic GPU cloud providers and write a comparison as a Word document"
Bundles: web, office
Skills: agent-browser, docx, hi, pdf, pptx, xlsx
Image: localhost/hi-agent:7f3a91c2b0d4 (cached)
Network: open (agent-browser (open): visits whatever sites the task needs)
| Bundle | Skills | Tools in the image |
|---|---|---|
web |
agent-browser |
agent-browser and its Chrome |
office |
Anthropic’s docx, xlsx, pptx, pdf (proprietary) |
LibreOffice, pandoc, Poppler, qpdf, Tesseract, and their Python and npm packages |
data |
DuckDB’s query, read-file, convert-file; data-visualization |
the DuckDB CLI, matplotlib, seaborn, plotly, pandas |
- The image is built once for each set of skills, on the box’s own
image, and reused; the first build of
officetakes several minutes.hi bundle pruneremoves images not used for 30 days. - The skills go in the box’s home folder, with the
hiskill, never into your folder, so they leave nothing behind in the results. Each is pinned to a commit. - The network.
webneeds an open network. hi shows why and asks before it widens the box; without a terminal, add--network open. An open network and--datadon’t go together, since an agent reading untrusted pages could be told to pass your team’s data on. -
More bundles come from your team’s template sources on a hi server, and your own, in
~/.local/share/hi/bundles/bundles/<name>.json(orHI_BUNDLES_DIR).hi bundle lslists them all, andhi bundle show <name>what one installs. A bundle file is described in Skills. - A project can ask for bundles in its
devcontainer.json, undercustomizations.hi:"bundles": ["data"]. Every box and agent in that project then gets them, and--bundleadds more. Their network is asked about as above; the repository can’t grant it.
hi box shell --bundle data gives you the same box to try things in.
While it works
hi agent waits until the agent is done. While it works, one line under
the command shows that it is: a red scanner going back and forth, the time
so far, the tokens in and out, the steps taken, and the latest one.
▬▬▬▬▬▬▬▬▬▬▬▬ 4m12s · 1.2M in · 18k out · 12 steps · Bash: .venv/bin/python backtest.py
hi reads it from the agent’s own session log in the box’s home folder, so
it works the same for Claude Code and Codex. Tokens in include cached
ones. The line shows only in a terminal; hi agent wait shows it too.
When the agent is done, the report gives the same numbers for the whole run, above the changed files:
Took 6m41s · 14 steps · 1.2M tokens in (1.1M cached) · 18k out · claude-sonnet-5-5 · $2.10 at API prices
The cost is Claude Code’s own figure at API prices; on a Claude subscription nothing is charged per run. Codex gives no cost.
hi box attach <name> in another terminal follows the agent. Codex shows its
progress; Claude Code prints only its final answer. Ctrl+C stops waiting,
not the agent:
hi agent wait myproject-1 # wait again and print the report
The box options from hi box work here too: --name, --network,
--allow, --gpu, --data, --here, --image, --memory, and
--bundle. See
Run code in a box.
In the background
hi agent codex --detach "upgrade FastAPI and fix what breaks"
# … later
hi agent wait myproject-2
--detach starts the agent and returns at once. hi agent wait waits for
it, if it’s still working, and prints the report.
Several attempts, and rounds
hi agent best-of runs one task in several boxes at once, checks each
result itself, and ranks them; with a score, it runs rounds that keep only
gains, in the style of autoresearch. See
Autoresearch.
hi agent best-of 3 --agents claude,codex "make the backtest loader 2x faster"
hi agent best-of 4 --rounds 50 --score "make score" --lower --edit train.py program.md
The report as JSON
--json prints the report on stdout and everything else on stderr, for
scripts and for agents that hand work to other agents:
hi agent codex --json "review the change on this branch; don't edit files"
{
"name": "myproject-3",
"agent": "codex",
"status": "done",
"exit_code": 0,
"session_id": "019a…",
"text": "The change looks right, but parse_date drops the time zone…",
"report": {"status": "complete", "summary": "…", "tests": "pass", "follow_ups": ["…"]},
"branch": "hi-box/myproject-3",
"changed_files": [],
"warnings": []
}
| Field | What it is |
|---|---|
status |
done, failed, or running (from --detach) |
exit_code |
The agent’s exit status |
text |
The agent’s final message |
report |
The agent’s own summary: status (complete, partial, blocked), summary, tests, follow_ups; null if it didn’t give one |
changed_files |
Every file changed since the start, committed or not, from git; outside git, from the folder’s files before and after |
folder |
The folder the agent worked in, when it worked in place |
session_id |
The agent’s session, when it reports one |
task_file |
The file the task came from, when it came from one |
bundles, skills, image |
With --bundle: the bundles, the skills in the box, and the image it ran on |
tokens |
input (with cached input), cached, and output tokens |
seconds, steps, model |
How long the run took, the agent’s tool calls, and the model it used |
cost_usd |
Claude Code’s figure for the run at API prices; on a subscription nothing is charged |
warnings |
Anything hi noticed, such as a missing summary |
hi asks every agent to end with a short summary block, and takes it out of
text into report. The changed files come from git, not from the agent,
so they are right even when the agent is wrong about what it did.
hi agent exits with 0 when the agent is done, and 1 when it failed: a
non-zero exit, an error from the agent, or no answer at all.
Work with an agent yourself
hi agent claude
hi agent codex
Without a task, the agent opens in your terminal, in a box, without
permission prompts. When you quit, hi box diff shows what it did.
Sign-ins
Claude Code never sees your token. The box gets a placeholder, and hi’s proxy outside the box swaps in your Claude sign-in for requests to Anthropic. The proxy reads the sign-in from Claude Code on your machine, so it stays fresh while you use Claude there. For long unattended runs, store a token that lasts a year:
claude setup-token # prints a token
hi agent token claude # paste it; kept in ~/.config/hi, never in a box
Codex gets a copy of its sign-in (~/.codex/auth.json) in the box’s
home folder for now, and its own hosts (chatgpt.com and OpenAI’s) on top
of the box’s network preset. A refresh token works only once, so when
Codex refreshes its sign-in in the box, hi copies the new one back to
~/.codex/auth.json when the run ends or the box is removed. Otherwise
Codex on your machine would stop working.
Review and clean up
Every agent run is a box, so the hi box commands work on it:
hi box ls # every box, its agent, state, branch, and changes
hi box diff myproject-1 # commits and files; --full for the whole diff
git merge hi-box/myproject-1 # keep the work
hi box rm myproject-1 # keeps the branch if it has commits
diff marks files that run on your machine later, such as a Makefile,
package.json, .envrc, CI workflows, and editor tasks. Read those before
you run anything from the branch.
Giving it a good task
The agent works unattended, so give it a task it can finish and check on
its own: “make make check pass”, “add tests for parse_config and fix
what they find”, or “upgrade FastAPI and fix what breaks”. A vague task
such as “fix something” gives a vague result.
Hand a task to another agent when it helps: a second opinion from another vendor (Codex reviewing what Claude Code wrote), a long or risky task that should run in a box while you carry on, or one agent out of quota. Don’t use it to split one task into pieces: the agents’ own subagents do that better, because they share what they already know.
How it works, step by step
cd ~/projects/myproject
hi agent claude "make the flaky test in tests/test_sync.py reliable"
- It checks the agent. Claude Code must be installed and signed in on this machine; hi says what is missing before it makes anything.
- It makes a box, as
hi boxdoes: it picks rootless Podman (or Docker, with a warning), readsdevcontainer.json, names the boxmyproject-1, and checks out your last commit into a new worktree on the branchhi-box/myproject-1. - It writes the allowlist from the network preset, the agent’s own
hosts,
--allow, and the project’s domains if you allowed them. - It starts the proxy, the box’s only way out, on a private network with no route out. It is the only container that can read your Claude sign-in.
- It starts the agent in the box, in the background:
- It sees the worktree, your repository’s
.gitwithhooksandconfigread-only, an empty home folder of its own, and theclaudebinary from your machine, read-only. Nothing else from your home folder. - The Claude token in the box is the word
hi-box-placeholder, andANTHROPIC_BASE_URLpoints at the proxy, which puts your real token in its place on the way to Anthropic. - The task and the summary request go in a file in the box’s home
folder, and from there to the agent on stdin, so a task of any length
fits. The command is
claude -p --output-format json --dangerously-skip-permissions; the result goes to a file in the box’s home folder, and the final text to the box’s log. Codex runs ascodex exec --dangerously-bypass-approvals-and-sandbox -o <file> -.
- It sees the worktree, your repository’s
- It waits for the box to stop, then stops the proxy.
- It writes the report from the agent’s result file, the box’s exit
status, and
git diffagainst the commit it started from.