Useful ToolsFileTools

FileTools

Claude Code-style file operations with read-before-edit tracking and permission control.

Quick Start

main.py
from connectonion import Agent from connectonion.useful_tools import FileTools # Full access (read + write with snapshot tracking) agent = Agent("coder", tools=[FileTools()]) # Read-only mode agent = Agent("reader", tools=[FileTools(permission="read")])

Key Features

1. Read-Before-Edit Validation

FileTools tracks which files have been read and prevents edits without prior reads:

main.py
ft = FileTools() # This will fail - file not read yet ft.edit("app.py", "old", "new") # Error: Read 'app.py' before editing (use read_file first) # Read first, then edit ft.read_file("app.py") ft.edit("app.py", "old", "new") # ✓ Success

2. Stale Read Detection (MD5 Snapshots)

Detects external file changes between read and edit:

main.py
ft = FileTools() ft.read_file("config.json") # ... external process changes config.json ... ft.edit("config.json", "old", "new") # Error: 'config.json' changed since last read - re-read it first

3. write() for NEW Files Only

write() prevents overwriting existing files:

main.py
ft = FileTools() # Create new file - works ft.write("new.py", "print('hello')") # ✓ Success # Try to overwrite - fails with helpful message ft.write("new.py", "print('world')") # Error: File 'new.py' already exists. Use edit() or multi_edit() to modify existing files

4. Permission Modes

main.py
# Write mode (default) - full access ft = FileTools(permission="write") ft.read_file("app.py") # ✓ ft.edit("app.py", ...) # ✓ ft.write("new.py", ...) # ✓ # Read-only mode ft = FileTools(permission="read") ft.read_file("app.py") # ✓ ft.glob("**/*.py") # ✓ ft.grep("pattern") # ✓ ft.edit("app.py", ...) # ✗ Permission denied ft.write("new.py", ...) # ✗ Permission denied

API Reference

read_file(path, offset=None, limit=None)

Read file with line numbers. Automatically tracks MD5 snapshot.

main.py
ft.read_file("app.py") # Returns: "1→import os\n2→from pathlib import Path..." ft.read_file("app.py", offset=10, limit=5) # Returns: "10→def main():\n11→ pass..."

edit(file_path, old_string, new_string, replace_all=False)

Replace string in file. Validates read-before-edit and detects stale reads.

main.py
ft.read_file("app.py") ft.edit("app.py", "old_function", "new_function") # ✓ Success - file edited ft.edit("app.py", "import os", "import sys", replace_all=True) # ✓ Replaces all occurrences

multi_edit(file_path, edits)

Apply multiple edits atomically. All succeed or none applied.

main.py
ft.read_file("app.py") ft.multi_edit("app.py", [ {"old_string": "foo", "new_string": "bar"}, {"old_string": "hello", "new_string": "world", "replace_all": True} ]) # ✓ Both edits applied atomically

write(path, content)

Create NEW files only. Returns error if file exists.

main.py
ft.write("new_module.py", "def hello():\n print('world')") # ✓ Creates parent directories automatically # ✓ Tracks snapshot for subsequent edits # ✗ Fails if file already exists

glob(pattern, path=None)

Search files by glob pattern. Returns max 100 results.

main.py
ft.glob("**/*.py") # All Python files recursively ft.glob("src/**/*.tsx") # All TSX files in src/ ft.glob("*.md", "docs") # Markdown in docs/ directory

grep(pattern, path=None, ...)

Search file contents with regex. Supports multiple output modes.

main.py
# Just file paths (default) ft.grep("TODO", output_mode="files") # Matching lines with context ft.grep("class\s+\w+", output_mode="content", context_lines=2) # Match counts per file ft.grep("import", output_mode="count")

Usage Examples

File editing agent with safety

main.py
from connectonion import Agent from connectonion.useful_tools import FileTools agent = Agent( "code-reviewer", model="co/gemini-2.5-pro", tools=[FileTools()], instructions="Review and fix code. Always read files before editing." ) agent.input("Fix typos in README.md")

Read-only documentation agent

main.py
agent = Agent( "doc-analyzer", tools=[FileTools(permission="read")], instructions="Analyze codebase structure and document findings." )

Code generation agent

main.py
agent = Agent( "code-gen", tools=[FileTools()], instructions="Generate new code files. Use write() for new files, edit() for modifications." ) agent.input("Create a new FastAPI endpoint for user registration")

Backward Compatibility

Individual functions still available without FileTools wrapper:

main.py
from connectonion.useful_tools import read_file, edit, write, glob, grep agent = Agent("custom", tools=[read_file, edit, write]) # No state tracking, no read-before-edit enforcement # write() still prevents overwriting (built into function)

Star us on GitHub

If ConnectOnion saves you time, a ⭐ goes a long way — and earns you a coffee chat with our founder.