File Edit Plugin
Safe file operations with diff preview, automatic backups, and undo capability. Shows unified diffs in permission prompts for clear visibility of changes.
| Name | file_edit |
| Type | Tool Plugin (Registry-managed) |
| Tools Provided |
readFile, updateFile, writeNewFile, removeFile, moveFile, renameFile, undoFileChange,
multiFileEdit, findAndReplace, restoreFile, listBackups
Total: 11 tools |
| User Commands | None |
| Auto-approved | readFile, undoFileChange, restoreFile, listBackups |
Features
- Diff Preview: Shows unified diff in permission prompts
- Automatic Backups: Creates backups before any modification
- Undo Support: Restore any file from its most recent backup
- Safe Defaults: Only read-only operations are auto-approved:
readFile,undoFileChange,restoreFile,listBackups - Gitignore Integration: Automatically adds
.jaatoto.gitignore
from jaato import PluginRegistry
registry = PluginRegistry()
registry.discover()
# Expose file_edit plugin
registry.expose_tool('file_edit')
# Or with custom backup directory
registry.expose_tool('file_edit', config={
'backup_dir': '/custom/backup/path'
})
# Read a file (auto-approved)
readFile(path="src/main.py")
# Update existing file (shows diff)
updateFile(
path="src/main.py",
new_content="import sys\n\ndef main():\n..."
)
# Create new file (shows content)
writeNewFile(
path="src/utils.py",
content="def helper():\n return 42"
)
# Move/rename a file (shows confirmation)
moveFile(
source_path="src/old.py",
destination_path="src/new.py"
)
# Undo last change (auto-approved)
undoFileChange(path="src/main.py")
Configuration Parameters
backup_dir
Directory where backups are stored. Backups are organized by original file path within this directory.
| Type | str |
| Default | .jaato/backups |
Gitignore Integration
On initialization, the plugin automatically adds .jaato
to your .gitignore if it exists and the entry is missing.
This prevents backup files from being committed.
.jaato/backups/src/main.py/2024-01-15_14-30-00.bak
This allows multiple backups per file and easy manual recovery.
.jaato/
backups/
src/
main.py/
2024-01-15_14-30-00.bak
2024-01-15_15-45-22.bak
utils.py/
2024-01-15_14-35-10.bak
config/
settings.json/
2024-01-14_09-00-00.bak
# Use a shared backup location
registry.expose_tool('file_edit', config={
'backup_dir': '/var/backups/jaato'
})
# Or per-project location
registry.expose_tool('file_edit', config={
'backup_dir': '.backups'
})
Tool Reference
readFile
Read the contents of a file. This is a safe, read-only operation and is auto-approved.
| Parameter | Type | Description |
|---|---|---|
path | string | Path to file |
updateFile
Update an existing file with new content. Shows a unified diff for approval and creates a backup before modifying.
| Parameter | Type | Description |
|---|---|---|
path | string | Path to existing file |
new_content | string | Complete new file content |
writeNewFile
Create a new file. Fails if the file already exists (use updateFile instead).
| Parameter | Type | Description |
|---|---|---|
path | string | Path for new file |
content | string | File content to write |
removeFile
Delete a file. Creates a backup before deletion so it can be restored.
| Parameter | Type | Description |
|---|---|---|
path | string | Path to file to delete |
moveFile
Move or rename a file. Creates destination directories if needed. Creates a backup before moving. Fails if destination exists unless overwrite=True.
| Parameter | Type | Description |
|---|---|---|
source_path | string | Path to source file |
destination_path | string | Path to move file to |
overwrite | boolean | If true, overwrite existing destination (default: false) |
renameFile
Alias for moveFile. Use for renaming files (same parameters and behavior).
undoFileChange
Restore a file from its most recent backup. Auto-approved since it's a recovery operation.
| Parameter | Type | Description |
|---|---|---|
path | string | Path to file to restore |
multiFileEdit
Execute multiple file operations atomically. Either ALL changes succeed
or NONE are applied (automatic rollback on failure). Supports mixed
operations: edit, create, delete, rename.
Use this for refactoring operations that must succeed together (e.g., renaming
a symbol across multiple files).
| Parameter | Type | Description |
|---|---|---|
operations | array | Array of operations, each with an action field ("edit"/"create"/"delete"/"rename") plus action-specific fields (path, old, new, content, from, to, prologue, epilogue) |
findAndReplace
Find and replace text across multiple files using regex patterns.
Supports glob patterns for file selection and respects .gitignore
by default. Use dry_run=true to preview changes without applying them.
| Parameter | Type | Description |
|---|---|---|
pattern | string | Regex pattern to search for |
replacement | string | Replacement string (supports backreferences like \1) |
paths | string | Glob pattern for files to search (e.g., "src/**/*.py") |
dry_run | boolean | Preview changes without applying (default: false) |
include_ignored | boolean | Include .gitignore-excluded files (default: false) |
restoreFile
Restore a file from a specific backup or the most recent backup.
More targeted than undoFileChange: lets you choose which
backup to restore from. Auto-approved since it's a recovery operation.
| Parameter | Type | Description |
|---|---|---|
path | string | Path to file to restore |
backup_path | string | Specific backup file to restore from (optional; uses latest if omitted) |
listBackups
List all available file backups. Can filter by file path or list all backups in the session backup directory. Auto-approved since it is read-only.
| Parameter | Type | Description |
|---|---|---|
path | string | Optional file path to filter backups. If omitted, lists all backups. |
{
"path": "src/main.py",
"content": "import sys\n\ndef main():\n...",
"size": 1234,
"lines": 45
}
{
"success": true,
"path": "src/main.py",
"size": 1456,
"lines": 52,
"backup": ".jaato/backups/src/main.py/2024-01-15_14-30-00.bak"
}
{
"success": true,
"source": "src/old.py",
"destination": "src/new.py",
"source_backup": ".jaato/backups/src/old.py/2024-01-15_14-30-00.bak"
}
{
"success": true,
"path": "src/main.py",
"restored_from": ".jaato/backups/src/main.py/2024-01-15_14-30-00.bak",
"message": "File restored from backup"
}
Permission Display
The file_edit plugin provides custom formatting for permission prompts, showing unified diffs for file modifications.
Update File Display
Shows a unified diff highlighting additions (green +)
and deletions (red -).
New File Display
Shows all lines as additions since the file doesn't exist yet.
Delete File Display
Shows all lines as deletions, making it clear what will be removed.
Truncation
Large diffs are automatically truncated to prevent overwhelming the permission display. The summary indicates if truncation occurred.
Tool: updateFile
Summary: Update file: src/main.py (+5/-2 lines)
--- src/main.py (original)
+++ src/main.py (modified)
@@ -1,5 +1,8 @@
import sys
+import os
+from pathlib import Path
def main():
- print("hello")
+ print("Hello, World!")
+ return 0
if __name__ == "__main__":
main()
[y]es / [n]o / [a]lways / [never]
Tool: writeNewFile
Summary: Create new file: src/utils.py (15 lines)
--- /dev/null
+++ src/utils.py
@@ -0,0 +1,15 @@
+"""Utility functions."""
+
+def helper():
+ """Return a helpful value."""
+ return 42
+
+def format_name(first, last):
+ """Format a full name."""
+ return f"{first} {last}"
...
[y]es / [n]o / [a]lways / [never]
Best Practices
Content Formatting
When using updateFile or writeNewFile,
provide raw file content directly. Do not wrap in quotes or
triple-quotes.
Use the Right Tool
updateFile: For existing files onlywriteNewFile: For new files only- Using the wrong one returns a helpful error
Recovery Workflow
If a modification goes wrong:
- Use
undoFileChange(path)to restore - Review the original content with
readFile(path) - Make the correct modification
# CORRECT: Raw content
writeNewFile(
path="example.py",
content="import sys\n\ndef main():\n pass"
)
# WRONG: Quoted content
writeNewFile(
path="example.py",
content='''"""
import sys
def main():
pass
"""''' # This writes the quotes too!
)
// Using updateFile on non-existent file
{
"error": "File not found: new.py. Use writeNewFile for new files."
}
// Using writeNewFile on existing file
{
"error": "File already exists: main.py. Use updateFile to modify existing files."
}
// No backup available
{
"error": "No backup found for: src/main.py"
}