File
Secure file operations with configurable security boundaries. Read, write, edit, and manage files with path validation against allowed directories.
Short alias: f
Highlights
- Configurable security boundaries with allowed directories
- Automatic backup creation before writes
- Recursive directory operations with pattern filtering
- Line-numbered file reading with pagination
- Text replacement with occurrence control
- Pure-Python content search (no
rg binary required) with .gitignore support
- Section-aware navigation: TOC, slice, and batch slice for markdown files
Read Operations
| Function |
Description |
file.read(path, offset, limit, encoding) |
Read file content with line numbers |
file.read_batch(paths, glob, encoding, max_files) |
Read multiple files in a single call |
file.info(path, follow_symlinks) |
Get file or directory metadata |
Search Operations
| Function |
Description |
file.grep(pattern, path, glob, context, case_sensitive, max_matches, fixed_strings, gitignore) |
Search file contents with regex (pure Python) |
Section Navigation
| Function |
Description |
file.toc(path, encoding) |
Display numbered section index (table of contents) |
file.slice(path, select, encoding) |
Extract content by section number, heading, or line range |
file.slice_batch(items) |
Extract sections from multiple files in a single call |
List Operations
| Function |
Description |
file.list(path, pattern, recursive, include_hidden, sort_by, reverse, follow_symlinks) |
List directory contents |
file.tree(path, max_depth, include_hidden) |
Display directory tree structure |
file.search(path, pattern, glob, file_pattern, case_sensitive, include_hidden, max_results) |
Search for files by name or glob pattern |
Write Operations
| Function |
Description |
file.write(path, content, append, create_dirs, encoding, dry_run) |
Write content to file |
file.edit(path, old_text, new_text, occurrence, encoding, dry_run) |
Edit file by replacing text |
File Management
| Function |
Description |
file.copy(source, dest, follow_symlinks) |
Copy file or directory |
file.move(source, dest) |
Move or rename file or directory |
file.delete(path, backup, recursive, dry_run) |
Delete file or directory |
Key Parameters
| Parameter |
Type |
Description |
path |
str |
File or directory path (relative to cwd or absolute) |
pattern |
str |
Filename pattern for filtering (e.g., *.py, *test*) |
glob |
str |
Glob pattern to filter files, always recursive (e.g., *.py, *.md, src/**/*.py) |
offset |
int |
Line number to start from (1-indexed, default: 1) |
limit |
int |
Maximum lines to return |
occurrence |
int |
Which match to replace (1=first, 0=all) |
encoding |
str |
Character encoding (default: utf-8) |
dry_run |
bool |
Show what would happen without making changes |
recursive |
bool |
Delete non-empty directories |
follow_symlinks |
bool |
Follow symlinks or treat as links |
include_hidden |
bool |
Include hidden files (starting with .) |
context |
int |
Context lines before/after each match in grep (default: 2) |
max_matches |
int |
Max total grep matches before stopping (default: 500) |
fixed_strings |
bool |
Treat grep pattern as a literal string, not regex |
gitignore |
bool |
Honour .gitignore when searching — pass False to include all files (default: True) |
max_files |
int |
Maximum files to read in read_batch (default: 20) |
select |
int|str|list |
Slice selector: section number, heading substring, line range, or list |
items |
list[dict] |
List of {path, select} dicts for slice_batch (max 20) |
Configuration
Required
- No required
tools.file settings.
Optional
| Key |
Type |
Default |
Description |
tools.file.allowed_dirs |
string[] |
[] |
Allowed directories for file operations. Empty means current working directory only. |
tools.file.exclude_patterns |
string[] |
[".git", "node_modules", "__pycache__", ".venv", "venv"] |
Path patterns excluded from operations. |
tools.file.max_file_size |
int |
10000000 |
Max readable/writable file size in bytes. Range: 1000-100000000. |
tools.file.max_list_entries |
int |
1000 |
Max entries returned by list() and tree(). Range: 10-10000. |
tools.file.backup_on_write |
bool |
true |
Create .bak backup files before overwriting. |
tools.file.use_trash |
bool |
true |
Move deleted files to trash when supported. |
tools.file.relative_paths |
bool |
true |
Return relative paths instead of absolute paths. |
tools:
file:
allowed_dirs: ["."]
exclude_patterns: [".git"]
max_file_size: 10000000
max_list_entries: 1000
backup_on_write: true
use_trash: true
relative_paths: true
Defaults
- If
tools.file is omitted, the file pack uses the built-in safety limits and path behavior shown above.
Examples
Reading Files
# Read entire file with line numbers
file.read(path="src/main.py")
# Read with pagination (lines 100-150)
file.read(path="large_file.log", offset=100, limit=50)
# Get file metadata
file.info(path="config.yaml")
Listing Directories
# List current directory
file.list()
# List with pattern filter
file.list(path="src", pattern="*.py")
# Recursive listing sorted by size
file.list(path=".", recursive=True, sort_by="size", reverse=True)
# Display tree structure
file.tree(path="src", max_depth=2)
# Search for files by filename pattern
file.search(pattern="*test*", file_pattern="*.py")
# Search with full path glob (recursive)
file.search(glob="src/**/*.py")
file.search(glob="tests/**/test_*.py")
file.search(glob="**/*.{yaml,yml}")
Reading Multiple Files
# Read specific files
file.read_batch(paths=["src/a.py", "src/b.py"])
# Read by glob pattern
file.read_batch(glob="src/**/*.py", max_files=10) # "*.py" also works
file.read_batch(glob="docs/*.md") # recurses into docs/ subdirs
Searching File Contents
# Search for a regex pattern (glob always recurses — "*.py" == "**/*.py")
file.grep(pattern="LogSpan", path="src/", glob="*.py")
# Case-insensitive with context lines
file.grep(pattern="TODO", path=".", context=3, case_sensitive=False)
# Literal string (no regex)
file.grep(pattern="print(", path="src/", fixed_strings=True)
# Recursive with glob filter
file.grep(pattern="def \\w+\\(", path="src/", glob="**/*.py", context=1)
# Include gitignored files (e.g. search logs or build output)
file.grep(pattern="error", path=".", gitignore=False)
# Explicitly opt in (same as default)
file.grep(pattern="secret", path=".", gitignore=True)
Navigating Sections
# Show table of contents for a markdown file
file.toc(path="README.md")
file.toc(path="docs/spec.md")
# Extract by section number (from toc output)
file.slice(path="README.md", select=2)
# Extract by heading substring (case-insensitive)
file.slice(path="README.md", select="Installation")
# Extract by line range
file.slice(path="README.md", select=":50") # first 50 lines
file.slice(path="README.md", select="100:200") # lines 100–200
file.slice(path="README.md", select="-30:") # last 30 lines
# Mixed selectors
file.slice(path="README.md", select=[1, "Usage", "300:400"])
# Batch slice from multiple files
file.slice_batch(items=[
{"path": "docs/creating-tools.md", "select": "Checklist"},
{"path": "docs/testing.md", "select": "Required Markers"},
{"path": "src/file.py", "select": ":50"},
])
Writing Files
# Write new file
file.write(path="output.txt", content="Hello, World!")
# Append to file
file.write(path="log.txt", content="New entry\n", append=True)
# Create with parent directories
file.write(path="new/dir/file.txt", content="data", create_dirs=True)
Editing Files
# Replace text (errors if multiple occurrences)
file.edit(path="config.py", old_text="DEBUG = False", new_text="DEBUG = True")
# Replace all occurrences
file.edit(path="main.py", old_text="TODO", new_text="DONE", occurrence=0)
# Replace specific occurrence (2nd match)
file.edit(path="data.txt", old_text="foo", new_text="bar", occurrence=2)
File Management
# Copy file
file.copy(source="config.yaml", dest="config.backup.yaml")
# Copy directory
file.copy(source="src/", dest="src_backup/")
# Copy preserving symlinks
file.copy(source="src/", dest="backup/", follow_symlinks=False)
# Move/rename file
file.move(source="old_name.py", dest="new_name.py")
# Delete file (creates backup by default)
file.delete(path="temp.txt")
# Delete without backup
file.delete(path="temp.txt", backup=False)
# Delete non-empty directory
file.delete(path="old_dir/", recursive=True)
Dry Run Mode
# Preview write operation
file.write(path="output.txt", content="data", dry_run=True)
# Preview edit operation
file.edit(path="config.py", old_text="DEBUG = False", new_text="DEBUG = True", dry_run=True)
# Preview delete operation
file.delete(path="temp.txt", dry_run=True)
Symlink Handling
# Get symlink metadata (not target)
file.info(path="link.txt", follow_symlinks=False)
# List showing symlinks as type 'l'
file.list(path=".", follow_symlinks=False)
# Search including hidden files
file.search(pattern="*.conf", include_hidden=True)
Security
All paths are validated against:
- Allowed directories: Paths must be under configured allowed_dirs
- Exclude patterns: Paths matching patterns like .git are blocked
- File size limits: Large files are rejected to prevent memory issues