ConnectOnionConnectOnion

FileTools

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

Quick Start

main.py
1from connectonion import Agent 2from connectonion.useful_tools import FileTools 3 4# Full access (read + write with snapshot tracking) 5agent = Agent("coder", tools=[FileTools()]) 6 7# Read-only mode 8agent = 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
1ft = FileTools() 2 3# This will fail - file not read yet 4ft.edit("app.py", "old", "new") 5# Error: Read 'app.py' before editing (use read_file first) 6 7# Read first, then edit 8ft.read_file("app.py") 9ft.edit("app.py", "old", "new") # ✓ Success

2. Stale Read Detection (MD5 Snapshots)

Detects external file changes between read and edit:

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

3. write() for NEW Files Only

write() prevents overwriting existing files:

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

4. Permission Modes

main.py
1# Write mode (default) - full access 2ft = FileTools(permission="write") 3ft.read_file("app.py") # ✓ 4ft.edit("app.py", ...) # ✓ 5ft.write("new.py", ...) # ✓ 6 7# Read-only mode 8ft = FileTools(permission="read") 9ft.read_file("app.py") # ✓ 10ft.glob("**/*.py") # ✓ 11ft.grep("pattern") # ✓ 12ft.edit("app.py", ...) # ✗ Permission denied 13ft.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
1ft.read_file("app.py") 2# Returns: "1→import os\n2→from pathlib import Path..." 3 4ft.read_file("app.py", offset=10, limit=5) 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
1ft.read_file("app.py") 2ft.edit("app.py", "old_function", "new_function") 3# ✓ Success - file edited 4 5ft.edit("app.py", "import os", "import sys", replace_all=True) 6# ✓ Replaces all occurrences

multi_edit(file_path, edits)

Apply multiple edits atomically. All succeed or none applied.

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

write(path, content)

Create NEW files only. Returns error if file exists.

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

glob(pattern, path=None)

Search files by glob pattern. Returns max 100 results.

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

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

Search file contents with regex. Supports multiple output modes.

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

Usage Examples

File editing agent with safety

main.py
1from connectonion import Agent 2from connectonion.useful_tools import FileTools 3 4agent = Agent( 5 "code-reviewer", 6 model="co/gemini-2.5-pro", 7 tools=[FileTools()], 8 instructions="Review and fix code. Always read files before editing." 9) 10 11agent.input("Fix typos in README.md")

Read-only documentation agent

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

Code generation agent

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

Backward Compatibility

Individual functions still available without FileTools wrapper:

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

Enjoying ConnectOnion?

⭐ Star us on GitHub = ☕ Coffee chat with our founder. We love meeting builders.