@ekairos/changeunit
v0.1.0
Published
ChangeUnit-scoped Git patch application for agents and humans
Maintainers
Readme
changeunit
Scoped Git patch application through UnitChange policy.
changeunit is a native Rust CLI for making repository edits in small, auditable units. It stores ChangeUnit metadata in SQLite and uses standard Git unified diffs as the patch format.
Install
npm install -g @ekairos/changeunit
ecu --helpThe npm package installs a native binary for linux-x64, darwin-x64,
darwin-arm64, and win32-x64.
From source:
git clone https://github.com/ekairos/changeunit
cd changeunit
npm run build:native
node bin/change.js --helpConcept
A ChangeUnit freezes a starting Git point A and controls how patches move toward B.
modify/delete: only registered files in selected groups.add: only registered files or paths under selected group--allow-addprefixes.- Patch input: standard Git unified diff (
diff --git ...). - State:
.change/change.sqlite3in the target worktree. - Stack metadata is provider-neutral. Graphite is an optional adapter, not the source of truth.
Quick Start
ecu init --id ESB-620 --from <commit-sha> --branch release --title "Award reconcile"
ecu group add award-reconcile --title "Award bid item reconciliation" --reason "Owns offer item reconciliation" --allow-add src/lib/domain/award/actions
ecu file add award-reconcile src/lib/domain/award/actions/reconcileSupplierBidItems.execute.ts --reason "Main reconciliation action"
# Edit file, then generate a standard Git patch.
git diff --output .change/work.diff -- src/lib/domain/award/actions/reconcileSupplierBidItems.execute.ts
# Revert/direct-edit as needed, then apply through policy.
ecu apply --group award-reconcile --reason "Implement scoped reconciliation change" .change/work.diff
ecu validateGraphite-Compatible Stacks
changeunit models stacked review separately from ChangeUnit scope:
ChangeUnit = why the change exists and what files it may touch
StackNode = branch/PR review unit
Provider = optional submit adapter such as graphite or githubOne PR can contain several ChangeUnits, and one ChangeUnit can span several PRs.
ecu stack add storage \
--branch change/esb-636-storage \
--base main \
--title "UnitChange storage" \
--unit ESB-636 \
--reason "First review node for storage changes"
ecu stack add apply \
--parent storage \
--branch change/esb-636-apply \
--title "Scoped patch apply" \
--unit ESB-636 \
--reason "Second review node for CLI behavior"
ecu stack status
ecu stack doctor --provider graphite
ecu stack submit --provider graphite --dry-runThe Graphite adapter plans public gt commands:
gt --no-interactive track <branch> --parent <parent-branch>
gt --no-interactive submit --branch <tip-branch> --stack --restack --no-editUse --init to include gt init --trunk <base> in the submitted command plan.
The CLI never writes Graphite internal config as canonical state.
Commands
ecu init --id <id> --from <sha-or-ref> --branch <branch> [--title "..."]
ecu use <id>
ecu group add <group-id> --title "..." --reason "..." [--parent <group-id>] [--allow-add <prefix>]
ecu file add <group-id> <path> --reason "..."
ecu apply --group <group-id> --reason "..." [patch.diff]
ecu validate
ecu status
ecu stack add <node-id> --branch <branch> [--base <branch>] [--parent <node-id>] --title "..." --reason "..."
ecu stack status
ecu stack doctor --provider graphite
ecu stack submit --provider graphite [--tip <node-id>] [--init] [--dry-run]If no patch file is passed to ecu apply, the patch is read from stdin:
git diff -- src/file.ts | ecu apply --group core --reason "Scoped edit"Benchmarks
cargo bench --manifest-path cli/Cargo.tomlCI runs the benchmark harness so performance regressions in patch parsing and policy validation are visible.
