Skip to content

First run

Five minutes. Eight steps. By the end you will have edited an issue, pushed it through git push, and seen the audit row that records the write. Every command is copy-pastable.

The tutorial targets the in-process simulator so you do not need credentials, an internet connection, or any of the real test targets. The same flow works against GitHub, Confluence, and JIRA when you are ready — only the reposix init argument changes.

1. Install reposix

Pick one — all five install both the reposix CLI and the git-remote-reposix helper that git needs to talk to a reposix:: remote.

curl --proto '=https' --tlsv1.2 -LsSf \
    https://github.com/reubenjohn/reposix/releases/latest/download/reposix-installer.sh | sh
powershell -ExecutionPolicy Bypass -c "irm https://github.com/reubenjohn/reposix/releases/latest/download/reposix-installer.ps1 | iex"
brew install reubenjohn/reposix/reposix
cargo binstall reposix-cli reposix-remote
git clone https://github.com/reubenjohn/reposix
cd reposix
cargo install --path crates/reposix-cli --path crates/reposix-remote
# Or for ad-hoc usage without installing:
#   cargo build -p reposix-cli -p reposix-remote
#   export PATH="$PWD/target/debug:$PATH"

After this step, which reposix git-remote-reposix should print two paths.

2. Start the simulator

reposix sim --seed-file crates/reposix-sim/fixtures/seed.json &
# 2026-04-24T12:00:00.000Z  INFO reposix_sim: reposix-sim listening addr=127.0.0.1:7878

Backgrounded so the rest of the steps run in the same shell. The seed loads the canonical demo project — five issues, deterministic IDs.

If you used the Build from source tab above without installing, run target/debug/reposix sim --seed-file crates/reposix-sim/fixtures/seed.json & instead. Every other step assumes reposix is on PATH.

3. Bootstrap the working tree

reposix init sim::demo /tmp/repo
# reposix init: configured `/tmp/repo` with remote.origin.url = reposix::http://127.0.0.1:7878/projects/demo
# Next: cd /tmp/repo && git checkout -B main refs/reposix/origin/main

What that did: git init /tmp/repo, then git config extensions.partialClone origin, set remote.origin.url, and ran git fetch --filter=blob:none origin. /tmp/repo is now a real git working tree — git status, git diff, and git log all work the way they do on any other repo. Cold init runs in 24 ms against the sim (benchmark).

If reposix init fails or you see surprising output, run reposix doctor — it lists each diagnostic with a copy-pastable Fix command. See the doctor reference for the full check catalog.

4. Check out the seeded branch

cd /tmp/repo
git checkout -B main refs/reposix/origin/main

Why refs/reposix/origin/main instead of plain origin/main? The git-remote-reposix helper namespaces fetched refs under refs/reposix/* so that git fast-export correctly emits the deltas on push. See git-layer for the mechanic; the takeaway is one line of friction at clone time, zero friction afterwards.

5. Inspect the project

ls issues/
# 0001.md  0002.md  0003.md  0004.md  0005.md

cat issues/0001.md
# ---
# id: 1
# title: Add user avatar upload
# status: open
# assignee: alice@acme.com
# labels: [backend, needs-review]
# version: 1
# ---
# ## Description
# Avatar uploads are blocked by S3 permissions...

Frontmatter is the schema; the body is plain Markdown. No special tools, no MCP servers — cat, ls, grep -r all behave normally because the working tree IS a git repo. Read Mental model in 60 seconds if this still feels surprising.

6. Edit an issue

Add a comment to issue 1 and flip its status:

cat >> issues/0001.md <<'EOF'

## Comment from tutorial
First-run tutorial — confirmed avatar upload is blocked, escalating.
EOF

sed -i 's/^status: .*/status: in_progress/' issues/0001.md
git diff issues/0001.md

Expected: a diff with two hunks — the status flip on the frontmatter line, and the comment appended at the bottom. No reposix-specific verbs were used to make the edit.

Comments are connector-specific

The simulator and the GitHub backend round-trip a ## Comment section in the issue body verbatim. Other backends differ:

Backend ## Comment block treatment
sim round-tripped verbatim
github round-tripped verbatim
confluence use the dedicated comments API (separate endpoint)
jira not yet supported (tracked as v0.12.0 carry-forward)

See docs/reference/<backend>.md for the per-connector comment shape.

7. Commit and push

git add issues/0001.md
git commit -m "tutorial: add comment, move issue 1 to in_progress"
git push
# To reposix::http://127.0.0.1:7878/projects/demo
#  * [new branch]      main -> main

What just happened: git push handed your commit to the reposix git remote, which parsed the changed file, sanitized the frontmatter (server-controlled fields like id and version are stripped — see trust model), checked the backend version was still 1, and applied the write via REST. The mechanics live in git layer §push round-trip.

If a second writer had mutated issue 1 between your init and your push, the helper would have rejected the push with ! [remote rejected] main -> main (fetch first) and you would have run git pull --rebase && git push to recover. That conflict-rebase loop is the dark-factory teaching mechanism — try it as an exercise.

8. Verify the audit row

sqlite3 ~/.cache/reposix/sim-demo.git/cache.db \
    "SELECT ts, op, decision FROM audit_events_cache \
     WHERE op LIKE 'helper_push_%' ORDER BY ts DESC LIMIT 3"
# 2026-04-24T12:01:32Z|helper_push_accepted|ok
# 2026-04-24T12:01:32Z|helper_push_started|

Two rows: the push opened, the push accepted. No helper_push_rejected_conflict, no helper_push_sanitized_field (you did not try to overwrite a server field). Every push, accept or reject, writes one append-only audit row. git log is the agent's intent; audit_events_cache is the system's outcome.

What did you do?

You used cat, git, sed, git push. No reposix-specific commands except init. That is the dark factory pattern in action — the substrate disappears once it is set up, and the agent works through tools it (and you) already know.

Next