Python API
Supported root exports
The root contract is axm_edit.__all__: batch_apply, rollback,
Edit, ReplaceOp, CreateOp, DeleteOp, Operation,
BatchResult, RollbackResult, ValidationError, and __version__.
ValidationError is a result-detail model, not the Pydantic exception.
Operation is the union of replace/create/delete/rewrite models.
RewriteOp participates in that union but is not re-exported at the root:
import it from axm_edit.models.operations.
Other public-looking core helpers are internal implementation modules,
not additional root contracts.
The README example uses the root API; the tutorial uses tool classes. Review the recovery limits alongside the generated docstrings: restoration is best-effort and metadata is not snapshotted.
axm_edit
axm-edit — Atomic batch file editing for AI agents.
Replace, create, and delete files in a single atomic operation.
Operation = Annotated[ReplaceOp | CreateOp | DeleteOp | RewriteOp, Field(discriminator='op')]
module-attribute
Discriminated union of all operation types.
Edit
Bases: BaseModel
A single line-level edit within a replace operation.
Attributes:
| Name | Type | Description |
|---|---|---|
line |
int | None
|
Optional 1-indexed line hint in the original file.
If provided, used as a starting point for searching |
old |
str
|
Expected content to find and replace (validation anchor).
May contain |
new |
str
|
Replacement content. |
ReplaceOp
Bases: BaseModel
Modify lines in an existing file.
All line numbers reference the file as originally read, before any edits are applied. The engine sorts edits bottom-to-top to avoid line-shift problems.
CreateOp
Bases: BaseModel
Create a new file.
Fails if the file already exists unless overwrite is True.
DeleteOp
Bases: BaseModel
Delete an existing file.
Fails if the file does not exist.
BatchResult
Bases: BaseModel
Result of a batch edit operation.
Atomicity contract (see :func:axm_edit.core.engine.batch_apply):
atomicity is guaranteed at validation (all-or-nothing — a validation
error rejects the whole batch before any write); the apply phase is
best-effort with automatic rollback-to-checkpoint, so on any mid-apply
exception success is False, error is populated, checkpoint
holds the targeted snapshot, and every touched path has been restored to
its pre-batch state.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether all operations were applied ( |
checkpoint |
str | None
|
Targeted-path snapshot captured before apply, usable for rollback; present whenever the apply phase was entered. |
applied |
int
|
Total number of individual edits applied. |
summary |
dict[str, int]
|
Counts of modified, created, and deleted files. |
error |
str | None
|
Human-readable error message on failure. |
details |
list[ValidationError]
|
Detailed validation errors on failure. |
RollbackResult
Bases: BaseModel
Outcome of a best-effort rollback.
Rollback is a strict inverse: it only undoes what the batch did. It is
also best-effort — every captured path is attempted even if an earlier one
fails, so a partial rollback is fully observable instead of aborting
mid-loop. ok is True only when the snapshot was well-formed and
every captured path was restored.
Attributes:
| Name | Type | Description |
|---|---|---|
restored |
list[str]
|
Relative paths successfully restored to their pre-batch state. |
unrestored |
list[str]
|
Relative paths that could not be restored (a filesystem error was raised while undoing them). |
valid |
bool
|
Whether the snapshot was well-formed and parseable. |
ok
property
True iff the snapshot was valid and nothing failed to restore.
ValidationError
Bases: BaseModel
A single validation failure.
batch_apply(root, operations)
Validate and apply a batch of file operations.
Atomicity contract:
- Validation is the gate. All operations are validated first; if any
fails the batch is rejected wholesale (
success=False) before a single byte is written — a true all-or-nothing guarantee. Validation includes the syntax gate: a batch that would leave a parseable Python, TOML or JSON file unparseable is refused (:mod:axm_edit.core.syntax_gate). JSON comments and trailing commas are tolerated; new JSON files are unchecked. - Apply is best-effort with automatic rollback. Once validation
passes, a targeted checkpoint of every touched path is captured and the
operations are applied. If any exception occurs mid-apply (anchor
drift, a
write_text/unlink/mkdirfailure, a permission error, …) the partial work is rolled back to that checkpoint — touched files are restored to their pre-batch bytes and batch-created files (and the empty directories created for them) are removed — and a failingBatchResultis returned. The filesystem is not made transactional at the OS level; the rollback restores only the snapshotted paths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
Project root directory (all paths are relative to this). |
required |
operations
|
Sequence[Operation]
|
List of replace, create, rewrite and delete operations. |
required |
Returns:
| Type | Description |
|---|---|
BatchResult
|
BatchResult with success status, a targeted-path snapshot |
BatchResult
|
( |
rollback(root, checkpoint)
Restore exactly the paths captured by checkpoint to their prior state.
Rollback is a strict inverse of the batch and best-effort: for each snapshotted path a file that existed is rewritten with its original bytes, a file that did not exist before is removed, and only the directories the batch itself created (recorded in the snapshot) are pruned — a pre-existing directory is never removed. Every captured path is attempted even if an earlier one fails, so a partial rollback is fully reported. No git command is run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
Project root directory. |
required |
checkpoint
|
str
|
The JSON snapshot returned by :func: |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
RollbackResult
|
class: |
RollbackResult
|
paths restored and those that could not be restored. |
|
RollbackResult
|
is |
|
RollbackResult
|
a malformed snapshot yields |
RewriteOp(file: str, content: str, expected_checksum: str) adds the
op="rewrite" discriminator. The checksum is required; see the
rewrite guide.
Tool integrations
These module classes are the installed axm.tools entry points.
Their execute methods return axm.tools.base.ToolResult.
Their docstrings are generated from the checkout; where a docstring overstates
a guarantee, the batch and
filesystem contracts describe the implementation:
in particular, process execution uses no implicit shell.
BatchEditTool
Atomic batch file editing for AI agents.
Replaces, rewrites, creates, and deletes files in a single atomic
operation.
Registered as batch_edit via axm.tools entry point.
execute(*, path='.', operations=None, lint=True, lint_diff=True, lint_diff_max_ratio=0.5, **kwargs)
Execute a batch of file operations atomically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Project root directory. |
'.'
|
operations
|
list[dict[str, object]] | None
|
List of operation dicts with |
None
|
lint
|
bool
|
Run ruff --fix on changed Python files after apply. |
True
|
lint_diff
|
bool
|
Surface per-file diffs of post-lint mutations. |
True
|
lint_diff_max_ratio
|
float
|
Fallback threshold (diff / file size). |
0.5
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with applied counts, the |
ToolResult
|
payload (a JSON string, not a SHA) to pass back to |
ToolResult
|
|
ToolResult
|
warnings and blocking verdict). A blocking preflight refuses the |
ToolResult
|
batch before any checkpoint or write, so the payload then |
ToolResult
|
carries no checkpoint at all. |
BatchRollbackTool
Restore project state to a previous checkpoint.
Registered as batch_rollback via axm.tools entry point.
Not to be confused with the atomicity of batch_edit. A batch that
fails mid-apply restores every file it touched by itself, through the
same :func:axm_edit.core.checkpoint.rollback primitive and without
anyone calling this tool. What this tool undoes is a batch that
succeeded.
That case is reachable only by a caller holding the checkpoint payload
from batch_edit's structured data. An MCP agent sees the text
view, which omits the payload on purpose (it is the base64 of every
touched file), so in practice a successful batch is undone with git.
execute(**kwargs)
Rollback to a checkpoint created by batch_edit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
object
|
Keyword arguments. path: Project root directory. checkpoint: The snapshot payload from batch_edit's response. |
{}
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult indicating whether the rollback succeeded. |
ReadFileTool
Read file content with optional line-range support.
Returns file content with line numbers. Supports partial reads
via start_line / end_line (1-indexed, inclusive).
Registered as read_file via axm.tools entry point.
execute(*, path='.', file=None, start_line=None, end_line=None, **kwargs)
Read a file, optionally restricting to a line range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Project root directory. |
'.'
|
file
|
str | None
|
Relative path to the file to read. |
None
|
start_line
|
int | None
|
Optional 1-indexed start line (inclusive). |
None
|
end_line
|
int | None
|
Optional 1-indexed end line (inclusive). |
None
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with file content, line numbers, and metadata. |
WriteFileTool
Write content to a file, creating parent directories.
Simple single-file write for AI agents. For atomic multi-file
operations, use :class:BatchEditTool instead.
Registered as write_file via axm.tools entry point.
execute(*, path='.', file=None, content=None, **kwargs)
Write content to a file, confined under a project root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Project root directory (default "."). |
'.'
|
file
|
str | None
|
Path to the file to write, relative to |
None
|
content
|
str | None
|
Text content to write. |
None
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with written file path and byte count. A |
ToolResult
|
that escapes |
ToolResult
|
traversal) is refused with |
EditFileTool
Find and replace text in a single file.
Performs a single-occurrence replacement by default. Errors if
the target text is not found or appears multiple times (unless
count is specified).
Registered as edit_file via axm.tools entry point.
execute(*, path='.', file=None, old=None, new=None, count=1, **kwargs)
Find and replace text in a file, confined under a project root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Project root directory (default "."). |
'.'
|
file
|
str | None
|
Path to the file to edit, relative to |
None
|
old
|
str | None
|
Text to find (exact match). |
None
|
new
|
str | None
|
Replacement text. |
None
|
count
|
int
|
Max replacements (default 1). Use -1 for all. |
1
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with replacement details. A |
ToolResult
|
|
ToolResult
|
refused with |
SearchFilesTool
Grep-like search across project files.
Searches for literal strings or regex patterns across files within a
sandboxed project root. Supports glob-based file filtering.
Registered as search_files via axm.tools entry point.
execute(*, path='.', pattern=None, is_regex=False, include=None, **kwargs)
Search for a pattern across project files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Project root directory (default "."). |
'.'
|
pattern
|
str | None
|
Search string or regex (required). |
None
|
is_regex
|
bool
|
Treat pattern as regex (default False). |
False
|
include
|
list[str] | None
|
Glob patterns to filter files (e.g. ["*.py"]). |
None
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with matches list (file, line, content), count, and |
ToolResult
|
truncated flag. The text view groups by content when at most half |
ToolResult
|
of the matches have distinct content, while preserving every site. |
ListDirTool
Directory listing with file metadata for AI agents.
Lists files and directories within a sandboxed root directory.
Supports recursive listing via max_depth. Hidden entries and
build artefacts (__pycache__, node_modules, etc.) are
skipped automatically.
Registered as list_dir via axm.tools entry point.
execute(*, path='.', max_depth=1, **kwargs)
List files and directories in a project directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Root directory to list (default "."). |
'.'
|
max_depth
|
int
|
Recursion depth — 1 for immediate children only, >1 for nested listing (default 1). |
1
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with entries list (name, path, type, |
ToolResult
|
size_bytes), count, and truncated flag. |
FileBytesTool
Bases: AXMTool
Report what a file really contains, byte for byte, without writing.
Orchestration and shaping layer only: every rule lives in
:mod:axm_edit.core.byte_report. No code path opens the file for
writing, so calling this tool can never change the target.
execute(*, path=None, expected=None, expect_escaped=False, encoding=_SUPPORTED_ENCODING, **kwargs)
Inspect the bytes of one file, without ever touching the disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | None
|
Absolute path to the file to inspect. |
None
|
expected
|
str | None
|
Content the caller believes it wrote, when known. |
None
|
expect_escaped
|
bool
|
Whether escape sequences are expected verbatim on disk rather than the literal characters they denote. |
False
|
encoding
|
str
|
Decoding used to read the report; only |
_SUPPORTED_ENCODING
|
kwargs
|
object
|
Ignored extra arguments (MCP forward-compatibility). |
{}
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
|
ToolResult
|
|
ToolResult
|
diagnostic and not an execution failure; ``ToolResult( |
ToolResult
|
success=False, error=...)`` when the file could not be read. |
ToolResult
|
Never raises. |
RunCommandTool
Execute arbitrary shell commands with timeout and output truncation.
Runs the given command via subprocess.run in the resolved working
directory, with configurable timeout and output size caps. The command
string is executed verbatim by the shell, so this tool can run any
shell command the calling process is permitted to run.
.. warning::
The _BLOCKED_PATTERNS denylist is a best-effort guardrail
against obvious footguns (e.g. rm -rf /), not a security
sandbox. It matches substrings and is bypassable by design
(encoding, indirection, equivalent commands). Do not rely on it for
isolation or to contain untrusted input — treat any command passed
here as executing with the full privileges of the host process.
Registered as run_command via axm.tools entry point.
execute(*, command=None, path='.', cwd=None, timeout=_DEFAULT_TIMEOUT, **kwargs)
Execute a shell command.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command
|
str | None
|
Shell command string (required). |
None
|
path
|
str
|
Project root directory (default "."). |
'.'
|
cwd
|
str | None
|
Working directory, relative to root (optional). |
None
|
timeout
|
int
|
Timeout in seconds (default 30). |
_DEFAULT_TIMEOUT
|
Returns:
| Type | Description |
|---|---|
ToolResult
|
ToolResult with stdout, stderr, exit_code, and timed_out. |