Local-first repository workflow for coding agents

Turn parallel agent sessions into verified, traceable Tasks.

AIT is a CLI that gives every coding request an isolated worktree, the exact revision that passed your checks, and a repository-owned record that survives the agent session. Use it with Codex, Claude, or another coding agent.

  • Local first
  • No server required
  • Agent neutral
  • Git interoperability

Illustrated outcomes · explore each step in the demo

Three cards → three isolated workstreams local · main · ait 1.1.1

One worktree per card Conflicts are never silently overwritten

  1. Card 01 · Accessible password controlworktree 1 · agent A · 3 tests passed · clean rebase
    finished
  2. Card 02 · Extract session validatorworktree 2 · agent B · 8 tests passed · target advanced, rebased cleanly
    rebased → finished
  3. Card 03 · Rename auth config keysworktree 3 · agent C · substantively overlaps the changes in Card 02
    stopped · conflict
Card 03 stops instead of overwriting Card 02.

Compatible work is cleanly rebased at closeout. Incompatible overlap stops in explicit conflict state for you to judge. Mechanical rebase does not prove semantic compatibility, so repository checks and human review remain necessary.

ait queue summarywhich cards can move, which wait on you →

Follow an AIT Task

One request. A working change. A finished Task.

Watch AIT open an isolated worktree, verify a small change, and finish it back into the original project.

Actual AIT command output recorded on 2026-09-07 and edited for readability. Paths are shortened; playback time is not an execution benchmark.
Read the command transcript
AIT first-task command recording — 2026-09-07
Actual command output. Absolute example roots are shortened to ~/ait-first-task.
The replay is edited for readability; playback is not an execution-time measurement.

Working directory: ~/ait-first-task
$ ait --version
ait 1.1.2
Exit code: 0

Working directory: ~/ait-first-task
$ node --test tests/baseline.test.mjs
✔ task titles preserve the input order and data (1.168458ms)
✔ the existing board title is unchanged (0.063583ms)
✔ the existing priorities are unchanged (0.046333ms)
ℹ tests 3
ℹ suites 0
ℹ pass 3
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 63.568458
Exit code: 0

Working directory: ~/ait-first-task
$ ait init
Initialized empty AIT repository in ~/ait-first-task/.ait (plan=zh-Hant-TW/concise)
Exit code: 0

Working directory: ~/ait-first-task
$ ait config set --user-name 'AIT Demo'
ait config set
user-name: AIT Demo
Exit code: 0

Working directory: ~/ait-first-task
$ cat docs/sprints/open-tasks.md
# Open tasks [plan-ref: example/open-tasks]

## Intent
Add openTasks(tasks) to src/tasks.mjs. Return a new array of tasks whose done property is not true, preserving order and object references without mutating the input. Keep taskTitles unchanged.

## Constraints
Only edit this Task worktree. Do not edit checks/, remove tests, or add packages. The root agent executes this task without subagents.

## Acceptance
Add a focused regression test for done true, false, missing, empty input, preserved order and identity. Run node --test tests/*.test.mjs and node checks/first-task.mjs before Task finish; verify acceptance again in the original directory afterward.

- [ ] Add non-mutating openTasks and focused tests. [ref: open-tasks]
Exit code: 0

Working directory: ~/ait-first-task
$ ait task start --from 'docs/sprints/open-tasks.md#open-tasks' --intent 'Add openTasks without mutating input'
ait task start
task: LT-0001
title: Add non-mutating openTasks and focused tests
next: cd ~/ait-first-task/.ait-worktree-links/lt-0001
Exit code: 0

Working directory: ~/ait-first-task/.ait-worktree-links/lt-0001
$ node --test tests/baseline.test.mjs tests/open-tasks.test.mjs
✔ task titles preserve the input order and data (1.041042ms)
✔ the existing board title is unchanged (0.053041ms)
✔ the existing priorities are unchanged (0.048583ms)
✔ openTasks returns unfinished tasks without changing input or objects (1.224417ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 63.11
Exit code: 0

Working directory: ~/ait-first-task/.ait-worktree-links/lt-0001
$ node checks/first-task.mjs
FIRST_TASK_ACCEPTED
Exit code: 0

Working directory: ~/ait-first-task/.ait-worktree-links/lt-0001
$ ait snapshot create LT-0001 --message 'Add non-mutating openTasks'
ait snapshot create
snapshot_id: SNP-0B558114ECDB
task_id: LT-0001
line_name: feature/lt-0001
parent_snapshot_id: SNP-2B43A5F97E11
message: Add non-mutating openTasks
Exit code: 0

Working directory: ~/ait-first-task/.ait-worktree-links/lt-0001
$ ait task finish LT-0001 --local
finished: LT-0001 -> main @ SNP-0B558114ECDB
closed: task, worktree, line, sprint
title: Add non-mutating openTasks and focused tests
Exit code: 0

Working directory: ~/ait-first-task
$ node --test tests/baseline.test.mjs tests/open-tasks.test.mjs
✔ task titles preserve the input order and data (0.987959ms)
✔ the existing board title is unchanged (0.050417ms)
✔ the existing priorities are unchanged (0.042292ms)
✔ openTasks returns unfinished tasks without changing input or objects (0.963875ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 61.445542
Exit code: 0

Working directory: ~/ait-first-task
$ node checks/first-task.mjs
FIRST_TASK_ACCEPTED
Exit code: 0

Working directory: ~/ait-first-task
$ ait blame src/tasks.mjs --line 7
target: current line main
resolved snapshot: SNP-0B558114ECDB
path: src/tasks.mjs
blame parent: SNP-2B43A5F97E11
range: 7-7

7         SNP-0B558114ECDB task=LT-0001 confidence=durable_snapshot_binding
Exit code: 0

Implementation recorded in the completed Task:
// Small, existing behavior to preserve while adding your first feature.
export function taskTitles(tasks) {
  return tasks.map((task) => task.title);
}

export function openTasks(tasks) {
  return tasks.filter((task) => task.done !== true);
}

Bound sprint after Task finish:
# Open tasks [plan-ref: example/open-tasks]

## Intent
Add openTasks(tasks) to src/tasks.mjs. Return a new array of tasks whose done property is not true, preserving order and object references without mutating the input. Keep taskTitles unchanged.

## Constraints
Only edit this Task worktree. Do not edit checks/, remove tests, or add packages. The root agent executes this task without subagents.

## Acceptance
Add a focused regression test for done true, false, missing, empty input, preserved order and identity. Run node --test tests/*.test.mjs and node checks/first-task.mjs before Task finish; verify acceptance again in the original directory afterward.

- [x] Add non-mutating openTasks and focused tests. [ref: open-tasks]
34.95% / 36.28% fewer provider tokens than the Git linked-worktree workflow

Two separate 200-session GPT-5.6 Sol campaigns · 100/100 accepted in each treatment · Read the scope and evidence

Why not just use a worktree?

A worktree isolates files. AIT owns the work from request to regression.

Parallel execution is already common. The missing layer is a durable definition of what each agent was asked to do, which result passed, and how it joined newer work.

Worktree alone

Useful isolation, unfinished coordination

  • Creates a separate checkout.
  • Leaves task identity, checks, rebase, and cleanup to surrounding tools.
  • Later attribution usually ends at a commit.

AIT Task

One governed result with a full lifecycle

  • Binds the request, isolated worktree, checks, and accepted revision.
  • Rechecks the target, rebases clean work, or stops on a real conflict.
  • ait blame connects a regressed line to its revision and recorded intent.

One request. One governed result.

The agent runs the workflow. You keep the outcome and the record.

  1. 01Ask

    State the outcome and constraints in plain language.

  2. 02Isolate

    The Task receives one dedicated writable worktree.

  3. 03Verify

    Your checks stay attached to the exact revision that passed.

  4. 04Finish safely

    AIT updates clean work or stops without hiding a conflict.

  5. 05Trace later

    The responsible revision and recorded intent remain connected.

Start with one repository

Install 1.1.1, run ait init, then ask your agent normally.

The default workflow stays local and starts no server.

What happens when several Tasks run at once?

Each Task keeps its own intent, worktree and checks. Compatible work can finish; a conflicting change stops with its work retained. Recorded versions make later investigation possible.

Open the workflow diagram (Traditional Chinese) →