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 |
| User Commands | None |
| Auto-approved | readFile, undoFileChange |
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 and undo are auto-approved
- 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 |
{
"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"
}