Code editing for autonomous agents.
Agents edit code through tools designed for humans — sed, patch, regex-based find-and-replace. These work when a human is watching, but break down in autonomous workflows:
- No structural awareness.
sedtreats code as flat text. An agent can't say "replace function X" — it has to construct fragile regex patterns that break when formatting changes. - No precondition checking.
patchapplies blindly. If another agent (or the same agent in a different step) already modified the file, the edit silently corrupts the codebase. - No diagnosable failures. When edits fail, agents get cryptic error messages instead of structured diagnostics they can act on.
Identedit solves these by treating edits as verified structural operations rather than text substitution.
Three entry points covering different editing needs:
patch — one-shot verified edit (most common):
identedit patch src/example.py --kind function_definition --name process_data --replace 'def f(): ...'
identedit patch src/example.py --at abc123def4567890 --replace 'def f(): ...'
identedit patch src/example.py --at "42:9e0f1a2b3c4d" --set-line " return x + y"
identedit patch config.yaml --config-path server.port --set-value 8080
identedit patch config.json --config-path items --append-value 4read → edit → apply — multi-op or multi-file atomic pipeline:
identedit read --kind function_definition example.py --json # get handles
identedit edit --json < request.json # build changeset (dry-run)
identedit edit --json < request.json | identedit apply # commit to diskread --mode line — line-level precision edits:
identedit read --mode line example.py # display LINE:HASH|content
identedit patch example.py --at "3:a1b2c3d4e5f6" --replace-range "..." --end-anchor "5:7f6e5d4c3b2a"Use the canonical CLI entry points: read, edit, apply, patch, merge, grammar.
- Precondition-verified. Every edit checks that the target hasn't changed since the agent last read it. No silent corruption.
- Transactional. Multi-file edits are all-or-nothing with automatic rollback on failure.
- Diagnosable. Failures return structured JSON with specific error types and recovery suggestions.
- Move and copy. Structural units can be moved or copied within or across files atomically.
- Two granularities. Structure-level for large changes, line-level for small ones. Same safety guarantees for both.
Python, JavaScript/JSX, TypeScript/TSX, Rust, Go, C, C++, Java, Kotlin, Ruby, C#, Swift, PHP, Perl, Lua, Bash, Zsh, Fish, HTML, CSS, SCSS, Markdown, JSON, YAML, TOML, XML, Protobuf, SQL, HCL, Dockerfile
- Open GitHub Releases and pick your tag (for example
v0.2.0). - Download the matching asset:
identedit-<tag>-x86_64-unknown-linux-gnu.tar.gzidentedit-<tag>-aarch64-unknown-linux-gnu.tar.gzidentedit-<tag>-x86_64-apple-darwin.tar.gzidentedit-<tag>-aarch64-apple-darwin.tar.gz
- Extract and place
identediton yourPATH.
cargo install --path .- Core editing commands (
read,edit,apply,patch,merge) are intended to run on macOS, Linux, and Windows. identedit grammar installis currently supported only on macOS and Linux hosts.- On Windows hosts, use bundled grammars for now, or install grammar artifacts on macOS/Linux and copy the compiled library plus manifest entry.
# Replace a function by name (no read step needed)
identedit patch src/example.py --kind function_definition --name process_data \
--replace 'def process_data(x, y):
return x + y'
# Same thing using identity hash (when you already have read output)
identedit patch src/example.py --at <identity-hex16> --replace 'def process_data(x, y):
return x + y'
# Patch a specific line
identedit read --mode line src/example.py
identedit patch src/example.py --at "4:9e0f1a2b3c4d" --set-line " return x + y"
# Update a config key
identedit patch config.yaml --config-path server.port --set-value 8080
# Append to an array-valued config path
identedit patch config.json --config-path items --append-value 4# 1. Read — discover structures
identedit read --kind function_definition src/example.py --json
# 2. Edit — build changeset (dry-run, no file modification)
identedit edit --json < request.json
# 3. Apply — commit to disk (all-or-nothing)
identedit edit --json < request.json | identedit apply# Write replacement body to a temp file, then use --text-file
cat <<'EOF' > /tmp/new_block.py
def process_data(x, y):
return x + y
EOF
identedit patch src/example.py --kind function_definition --name process_data \
--replace --text-file /tmp/new_block.pyOr via the edit pipeline with jq --rawfile:
jq -n --rawfile new_text /tmp/new_block.py '{
command:"edit", file:"src/example.py",
operations:[{
target:{type:"node", identity:"<id>", kind:"function_definition", expected_old_hash:"<hash>"},
op:{type:"replace", new_text:$new_text}
}]
}' | identedit edit --json | identedit applyeditis always a dry-run. No files modified until explicitapply.patch --dry-runvalidates and previews without writing files.- Line-anchored patch defaults to strict mode.
--auto-repairis explicit opt-in. apply --dry-runvalidates and returns a summary without writing.- Config path edits are validated against the target format (JSON/YAML/TOML) before writing.
- Most commands emit JSON;
read --mode linedefaults to plain text unless--jsonis set.
- If
patchfails withprecondition_failedortarget_missing: re-runread, rebuild request, retry once. - If
ambiguous_target: addspan_hintfromreadoutput, retry once. - Maximum 2 attempts per target. If the second attempt fails, fall back to direct file editing.
- Agent workflow guide:
skills/identedit/SKILL.md