The sorrel CLI
A persistent, single-user local VCS over the real engine. Every command reads and
writes content-addressed objects under .sorrel/; state survives process
restarts; everything supports --json for tools and agents.
The core loop
$ sorrel init # .sorrel/: object store + manifest + HEAD
$ echo "hello" > a.txt
$ sorrel status # dirty: added a.txt (real diff vs HEAD)
$ sorrel change create -m "add a" # snapshot, diff, Change object, advance HEAD
$ echo "world" >> a.txt
$ sorrel diff # line-level unified hunks vs HEAD
$ sorrel change create -m "edit a"
$ sorrel log # snapshot DAG walk with change ids,
# authors, and messages
status and change create use the engine's stat cache, so
unchanged files are never re-hashed. log resolves each snapshot to the
Change that produced it through a small index in .sorrel/changes.index.
Lanes: parallel work without branch noise
$ sorrel lane create --name agent/feature
$ sorrel lane list # every lane, its head, the active one marked
$ sorrel lane switch <lane-id> # restores that lane's tree (refuses if dirty)
Each lane has its own head under .sorrel/heads/. Two lanes advance
independently — exactly what parallel agents need to work without stepping on each
other.
Merge: fast-forward or real three-way
$ sorrel merge <lane-id>
# fast-forward when the active lane has not diverged
# otherwise: engine three-way merge (merge base + line merge)
# on conflicts:
# - conflicted files get <<<<<<< ours / ======= / >>>>>>> theirs markers
# - .sorrel/MERGE_STATE records the stored MergeResult object
# - HEAD does not move
$ sorrel merge --abort # restore the pre-merge tree
Clean merges write a merged snapshot with both parents and record a merge Change. Conflicted merges leave inspectable state: marker-annotated files in the tree and first-class Conflict objects in the store.
Sync: push and pull against a Hub
$ sorrel remote add origin http://127.0.0.1:3000
$ sorrel push # negotiate missing objects, upload, advance ref
$ sorrel pull # fetch refs, download closure, verify ids
Push seeds the local snapshot closure, asks the Hub which objects are missing, uploads only those, and advances the remote ref with fast-forward and closure checks. Pull verifies every downloaded object's content id before trusting it.
Workflows, policy, slices
$ sorrel workflow validate # parse + check sorrel.workflow.yml
$ sorrel workflow run <job> # execute locally, gated by Core policy
$ sorrel policy evaluate ... # Core policy decision for an action
$ sorrel grant create ... # record a real Core grant decision
$ sorrel slice create ... # slice manifest for a subproject