Top-level object editor for Clojure source files.
The tool is designed for AI agents. It exposes each file as an ordered list of top-level objects and supports two mutations:
insert: insert zero or more top-level objects before or after an existing object, or at the head/tail of the filereplace: replace one or more contiguous top-level objects with zero or more new objectsThe runtime path is babashka, so normal CLI usage does not pay JVM startup cost. rewrite-clj is used for parsing and validation.
Each top-level object has:
oid: stable file-local object identity encoded as a 6-character base62 tokenrev: short hash of the current full object textfile_rev: short hash of the whole fileThe default workflow is:
oid to address an object@rev to guard against overwriting a changed object--file-rev for strict whole-file optimistic lockingThis means one list can usually support multiple follow-up edits without re-listing, as long as the target object itself has not changed.
The project is packaged as a bbin-installable Babashka tool via bb.edn.
Install from a local checkout:
bbin install . --as formpatch
After publishing the repository, install from git:
bbin install io.github.mikewong23571/formpatch --as formpatch
The tool entrypoint is declared in :bbin/bin and resolves to:
bb -m formpatch.cli/-main
Show usage:
./bin/formpatch --help
List top-level objects in a file:
./bin/formpatch list --file src/formpatch.clj
Fetch one or more full objects by handle:
./bin/formpatch get \
--file src/formpatch.clj \
--objects 00000a,00000b@19ab7def
Insert objects after an anchor:
./bin/formpatch insert \
--file src/formpatch.clj \
--after 00000a@19ab7def <<'EOF'
(defn helper-a
[]
:a)
(defn helper-b
[]
:b)
EOF
Insert at the head of the file (no anchor needed):
./bin/formpatch insert \
--file src/formpatch.clj \
--head <<'EOF'
(ns foo.core)
EOF
Use --tail to append at the end of the file. Both work on empty files.
Replace one object with multiple objects:
./bin/formpatch replace \
--file src/formpatch.clj \
--targets 00000a@19ab7def <<'EOF'
(defn helper
[x]
(inc x))
(defn updated
[x]
(helper x))
EOF
Delete objects without stdin:
./bin/formpatch replace \
--file src/formpatch.clj \
--targets 00000a@19ab7def \
--empty
Preview a mutation without writing:
./bin/formpatch replace \
--file src/formpatch.clj \
--targets 00000a@19ab7def \
--dry-run \
--diff <<'EOF'
(defn preview []
:ok)
EOF
Enable strict whole-file locking when needed:
./bin/formpatch replace \
--file src/formpatch.clj \
--file-rev abc12345 \
--targets 00000a@19ab7def \
--empty
list emits JSON on stdout, but each object's text is truncated by default to reduce token usage.
get emits JSON on stdout with the full object text for one or more objects.
insert and replace emit a minimal mutation delta JSON on stdout. The response includes:
file_rev: the new file versiontouched: the objects created or updated by the mutationdeleted: removed oidsbefore / after: stable neighbor anchors around the changed spanUse --diff when you also want a unified diff string embedded in the same JSON response.
formpatch persists object identities in a small EDN sidecar store. By default it lives under:
~/.cache/formpatch/state
You can override it with:
FORMPATCH_STATE_DIRformpatch.state-dirThe wrapper applies a small deterministic formatting policy:
Run the JVM test suite:
clojure -T:build test
Run the Babashka task wrapper:
bb formpatch --help
Run the tool entrypoint exactly as bbin will invoke it:
bb -m formpatch.cli/-main --help
The design document is in rewrite-clj-object-editing-design.md.
Own this plugin?
Verify ownership to unlock analytics, metadata editing, and a verified badge. GitHub access is read-only (username + org membership).
Sign in to claimOwn this plugin?
Verify ownership to unlock analytics, metadata editing, and a verified badge. GitHub access is read-only (username + org membership).
Sign in to claimBased on adoption, maintenance, documentation, and repository signals. Not a security audit or endorsement.
npx claudepluginhub mikewong23571/formpatch --plugin formpatchClojure language server
Truth-verified file editing for AI coding agents via MCP
Tools for managing CLAUDE.md memory files
Record Claude Code Write/Edit/MultiEdit calls into deltoids traces, grouped by Claude session.
Git diff review integration for Claude Code with VSCode extension. Provides inline diff view, browser diff editor, and auto-open files.
Ultra-compressed communication mode. Cuts ~75% of tokens while keeping full technical accuracy by speaking like a caveman.