Tutorial: an AI engineer for your repository
Etium setup is four questions, the same ones an agent asks on the agent path: which repo; etium only or with the ai-engineer loop library (this tutorial is the library path — Part 0 clones it); GitHub wiring or terminal only (Parts 1–2 are terminal; Part 3 wires GitHub, and you can stop before it); and where throwaway work may go (yours to pick when testing).
From zero to a working AI engineer: first a five-minute token-free dry run in your terminal, then real model runs, then wired to GitHub — where assigning an issue produces a draft PR whose every stage you command with comments and approve through gates.
Nothing here requires a server, a daemon, or an API key handed to
anything: etium supervises, harnesses bring their own auth, gh
brings yours.
0 · Install
npm install -g @etium/core
cd /path/to/your-repo
etium clone-loop ai-engineer
(etium init does Part 0's setup and Part 3's wiring
questions interactively — checks with fix commands first, then the
questions. The manual steps below show exactly what it does.)
The package is a plain folder — a 97-line loop, seven persona prompts, one GitHub surface file, and a README with the exact contract. Cloning it into your repo is the intended move: the templates are yours to edit, and the folder has no dependencies — it runs anywhere.
Prefer to delegate the setup? An AI agent can do this entire part: hand it etium.dev/agent-install.txt with your repo path.
You'll also want at least one coding harness installed and logged in —
pi (pi, then /login),
Claude Code, or Codex. Etium never sees those credentials; see
the model-auth doc in the etium repo.
1 · Dry run: learn the workflow for zero tokens
The loop has a scripting hook: under --harness exec, a
--param cmd.<step>=… shell command stands in for each
persona. Fake personas, real workflow — every gate, option, and artifact
is the real thing:
cd /path/to/your-repo
etium run "Add input validation to the signup form" \
--loop ai-engineer/loop.ts --worktree --harness exec --param rounds=1 \
--param cmd.triage='mkdir -p ai && echo "recommend: plan" > ai/INTAKE.md' \
--param cmd.plan='echo "1. validate email" > ai/PLAN.md' \
--param cmd.plan-review='printf "VERDICT: approve\n" > ai/REVIEW.md' \
--param cmd.implement='echo done > ai/REPORT.md' \
--param cmd.implement-review='printf "VERDICT: approve\n" > ai/REVIEW.md'
The triage persona runs, then the run parks — zero processes — at its first gate:
$ etium gates
2026-…-add-input-validation-… route.0 show: ai/INTAKE.md
→ etium decide 2026-… route <triage|debug|design|plan>
That's the routing gate. Notice what it doesn't offer:
implement. Options appear as stages earn them. Decide, with
guidance:
etium decide <run> route plan --note "email format only, no phone"
Your note is injected into the planner's prompt. The plan stage runs
its builder/reviewer rounds, then the route gate reopens — now offering
implement, showing ai/PLAN.md as evidence.
Route through implement, then wrap-up, and read
the whole story:
$ etium tail <run> --once
gate ? route.0 awaiting decision options=triage|debug|design|plan show=ai/INTAKE.md
gate ◆ route.0 plan by you (cli) — email format only, no phone
gate ? route.1 awaiting decision options=…|plan|implement show=ai/PLAN.md,ai/REVIEW.md
gate ◆ route.1 implement by you (cli)
gate ? route.2 awaiting decision options=…|implement|wrap-up show=ai/REPORT.md,ai/REVIEW.md
gate ◆ route.2 wrap-up by you (cli)
run DONE
Because of --worktree, all of it happened on branch
etium/<run-id> in its own checkout under
.etium/worktrees/ — your working tree was never touched, and
ai/INTAKE.md, ai/PLAN.md, ai/REPORT.md,
ai/REVIEW.md sit on that branch as the audit trail. Every
prompt, stream, and decision is under .etium/runs/<run>/;
grep works on all of it.
2 · Real personas
Drop the cmd.* params and the harness default takes over
(pi; use --harness claude, --harness
codex, or --param model=… as you like):
etium run "Add input validation to the signup form" \
--loop ai-engineer/loop.ts --worktree --param check="npm test"
Now triage actually reads your repo and writes a real recommendation
into ai/INTAKE.md, reviewers actually object
(VERDICT: revise with stable objection keys — the builder
must address them next round), and implement must pass
both its reviewer and your check command.
When a reviewer still objects after rounds rounds (default
2), you get a <stage>-stuck gate:
keep-going, accept, or wrap-up.
Walk away at any gate; kill -9 anything;
etium tick from cron reconciles. That's the operating model:
the AI works, parks, and waits for you.
3 · Wire it to GitHub
Now the same loop, commanded from issues instead of the terminal. On
the machine that will run the work (your laptop is fine), make sure
gh auth status is good for the target repo, then add one
cron line — this is the deployment:
* * * * * cd /path/to/your-repo && \
ETIUM_GH_REPO=you/your-repo ETIUM_GH_TRUSTED=your-login \
ETIUM_GH_LOOP=ai-engineer/loop.ts \
etium tick --surface github >> .etium/tick.log 2>&1
(Just trying it out? Skip cron and run the same thing in the
foreground while you play — etium watch --surface github
with the same variables; Ctrl-C to stop, nothing
installed.)
Then, on GitHub:
- Assign yourself (or the configured agent user) to
an issue. Within a minute, the surface creates a run on branch
etium/issue-N-attempt-0, triage runs, and a status comment appears on the issue telling you exactly what it's waiting for and which commands are valid. - Command with comments.
/et plan start with the retry logic— the word is matched against the open gate's declared options, your text becomes the note, and anyone not inETIUM_GH_TRUSTEDis ignored. - Review the draft PR. As soon as a stage produces
artifacts, the surface pushes the branch and opens one draft PR. The
ai/documents and the commits are the reviewable work. - Finish on GitHub's own terms. Merging the PR ends
the run. Closing the PR or the issue abandons the attempt.
/et stopabandons it with your note as the reason. Re-assigning later starts attempt #1 on a fresh branch — abandoned work never blocks a retry.
The et:working / et:waiting /
et:blocked labels are decoration for your issue list
(label:et:waiting = "waiting on me"); nothing ever reads
them back, so they can't lie for long — the next tick corrects them.
4 · The always-on engineer
Same package, same cron line, different credentials — that's the entire difference. On a spare machine:
- Create a bot GitHub account; give it Write on the repo (never admin), protect your default branch, require reviews. The bot only ever opens draft PRs; merging stays yours.
gh auth loginas the bot; log the harness in (pi→/login) on that machine.- Install etium, clone your repo, add the cron line with
ETIUM_GH_AGENT=<bot-login>andETIUM_GH_TRUSTED=<your-login>.
Now assigning the bot to an issue starts an attempt, and you interact entirely through issue comments and PR reviews from anywhere. If the machine goes offline, nothing lies — runs park, status freezes, and the next tick after it returns reconciles everything.
5 · Make it yours
- Edit the personas.
templates/*.mdare plain markdown — team conventions belong inconventions.md, stage behavior in each persona. Editing a template mid-run fails loudly rather than silently replaying stale work; finish or abandon runs first. - Tune the knobs.
--param rounds=3,--param wall=30m,--param check="make test", per-run--harness/--param model=…. - Change the workflow itself. The loop is 97 lines of ordinary TypeScript — add a stage, change an option set, split a persona. The loop-authoring guide in the repo is the manual; the surface needs no changes, because it matches commands against whatever options your gates declare.
Troubleshooting
- Nothing happens after assigning an issue — cron
isn't running the tick line,
ghisn't authenticated on that machine, or the assigner isn't inETIUM_GH_TRUSTED(assignments by untrusted users are ignored by design). Run the tick command by hand and read its output. - Your
/etcomment did nothing — you're not inETIUM_GH_TRUSTED, or the word isn't among the open gate's options; the status comment always lists the valid set. Decisions fail closed, silently on the invalid side. - The run errored about harness auth — the harness
on the executing machine isn't logged in; the error names the exact
remedy (e.g.
pithen/login). Fix andetium resume <run>— completed steps replay from the ledger, nothing reruns. - You want to see what the model actually did —
etium tail <run>, or open.etium/runs/<run>/steps/*/for the exact prompt and the full raw stream of every step.