--- name: filesystem description: 'File and directory operations via Claude Code built-in tools, replacing the Filesystem MCP server. Triggers on: "read this file", "write to file", "edit file", "find files matching", "search for text in files", "list directory", "show directory tree", "rename file".' metadata: version: 1.1.1 category: content tags: [files, directories, search, navigation] difficulty: beginner --- # Filesystem All file and directory operations use Claude Code's built-in tools. No MCP server needed — native tools are faster, more capable, and cost zero context tokens when idle. ## Quick Reference | Filesystem MCP Tool | Replacement | Notes | | ----------------------------- | ------------------------------ | ---------------------------------------------------------------------- | | `read_file(path)` | `Read` tool | Supports line offset and limit | | `read_multiple_files(paths)` | Multiple parallel `Read` calls | Faster than sequential MCP calls | | `write_file(path, content)` | `Write` tool | Overwrites entire file | | `edit_file(path, edits)` | `Edit` tool | Exact string replacement; surgical edits | | `list_directory(path)` | `Glob` or `Bash ls` | Glob for patterns, ls for simple listing | | `directory_tree(path)` | `Bash fd` or `Glob **/*` | fd is fastest; Glob for pattern filtering | | `search_files(pattern, path)` | `Grep` tool | Full regex, file type filters, context lines | | `create_directory(path)` | `Bash mkdir -p` | `-p` creates intermediate directories | | `move_file(src, dst)` | `Bash mv` | Also handles renames | | `get_file_info(path)` | `Bash stat` or `Bash ls -la` | Size, permissions, timestamps | | `list_allowed_directories` | N/A | Claude Code operates in the working directory; no sandbox restrictions | --- ## Reading Files ### Read a Single File Use the `Read` tool with an absolute path: ```text Read: /path/to/file.py ``` For large files, use offset and limit to read specific sections: ```text Read: /path/to/file.py (offset: 100, limit: 50) ``` This reads 50 lines starting from line 100. Use this for files with thousands of lines to avoid flooding context. ### Read Multiple Files in Parallel Issue multiple `Read` calls in a single response. Claude Code executes them concurrently: ```text Read: /path/to/file1.py Read: /path/to/file2.py Read: /path/to/file3.py ``` Parallel reads are faster than the MCP's `read_multiple_files` which serialized internally. ### Read Images and PDFs The `Read` tool handles binary formats: - **Images** (PNG, JPG, SVG): displayed visually - **PDFs**: extracted text; use `pages: "1-5"` for large documents (max 20 pages per call) --- ## Writing and Editing Files ### Write a New File Use the `Write` tool to create a file or overwrite an existing one: ```text Write: /path/to/new-file.py Content: ``` The `Write` tool requires reading the file first if it already exists. For new files, write directly. ### Edit an Existing File Use the `Edit` tool for surgical modifications — replace exact string matches: ```text Edit: /path/to/file.py old_string: "def old_function():" new_string: "def new_function():" ``` The `Edit` tool fails if `old_string` is not unique in the file. Provide enough surrounding context to make the match unique, or use `replace_all: true` for find-and-replace across the entire file. **Prefer Edit over Write** for existing files. Edit preserves everything outside the changed region and shows a clear diff. Write replaces the entire file. --- ## Finding Files ### By Name Pattern (Glob) ```text Glob: **/*.py → all Python files recursively Glob: src/**/*.ts → TypeScript files under src/ Glob: *.md → Markdown files in current directory Glob: **/test_*.py → test files anywhere in the tree ``` Results are sorted by modification time (most recent first). ### By Content (Grep) ```text Grep: pattern="def process_data" type="py" Grep: pattern="TODO|FIXME" glob="*.py" Grep: pattern="class.*Controller" output_mode="content" -C=2 ``` | Grep Parameter | Purpose | | ---------------- | -------------------------------------------------- | | `pattern` | Regex pattern to match | | `type` | File type filter (py, js, ts, rust, go, etc.) | | `glob` | Glob pattern filter (`*.tsx`, `src/**/*.py`) | | `output_mode` | `files_with_matches` (default), `content`, `count` | | `-C`, `-A`, `-B` | Context lines: around, after, before matches | | `-i` | Case-insensitive search | ### Directory Listing Simple listing: ```bash ls -la /path/to/directory ``` Recursive tree with `fd`: ```bash fd . /path/to/directory --type f ``` Tree with depth limit: ```bash fd . /path/to/directory --type f --max-depth 2 ``` Filter by extension: ```bash fd -e py /path/to/directory ``` --- ## File Operations ### Create Directory ```bash mkdir -p /path/to/new/directory ``` The `-p` flag creates all intermediate directories. Always verify the parent path exists first with `ls`. ### Move / Rename ```bash mv /path/to/source.py /path/to/destination.py ``` Rename a file (same directory): ```bash mv /path/to/old-name.py /path/to/new-name.py ``` Move a directory: ```bash mv /path/to/source-dir /path/to/destination-dir ``` ### Copy ```bash cp /path/to/source.py /path/to/destination.py cp -r /path/to/source-dir /path/to/destination-dir ``` ### Delete ```bash rm /path/to/file.py rm -r /path/to/directory ``` Always confirm with the user before deleting files or directories. ### File Metadata ```bash stat /path/to/file.py ls -la /path/to/file.py wc -l /path/to/file.py ``` | Command | Returns | | -------- | ------------------------------------------- | | `stat` | Size, permissions, timestamps, inode | | `ls -la` | Permissions, owner, size, modification date | | `wc -l` | Line count | | `file` | MIME type detection | --- ## Common Workflows ### Find and Replace Across Files ```bash # Find all files containing the old string Grep: pattern="old_function_name" type="py" output_mode="files_with_matches" # Then Edit each file Edit: /path/to/file1.py (old_string → new_string, replace_all: true) Edit: /path/to/file2.py (old_string → new_string, replace_all: true) ``` ### Explore an Unfamiliar Codebase 1. Check project structure: `fd . --type f --max-depth 2` 2. Read configuration: `Read: package.json` or `Read: pyproject.toml` 3. Find entry points: `Grep: pattern="def main|if __name__" type="py"` 4. Read key files identified above ### Find Large Files ```bash fd --type f --exec stat -f '%z %N' {} \; | sort -rn | head -20 ``` --- ## Error Handling | Error | Cause | Resolution | | --------------------------- | --------------------------------------- | ------------------------------------------------- | | Read: file not found | Path incorrect or file deleted | Verify with `ls` or `Glob` | | Edit: old_string not unique | Multiple matches in the file | Add more surrounding context to make it unique | | Edit: old_string not found | Content changed since last read | Re-read the file, then retry with current content | | Write: file not read first | Attempting to overwrite without reading | Read the file first, then Write | | Permission denied | Insufficient OS permissions | Check with `ls -la`; use `chmod` if appropriate | | Glob: no files found | Pattern too restrictive | Broaden the pattern; check path spelling | --- ## Limitations - **Read** returns up to 2000 lines by default. Use offset/limit for larger files. - **Read** truncates lines longer than 2000 characters. - **Edit** requires exact string matching — whitespace and indentation must match precisely. - **Write** overwrites the entire file. No append mode. To append, read first, then write the combined content. - **Glob** only matches files, not directories. Use `Bash ls` or `fd` to list directories. - **PDF reading** is limited to 20 pages per call. Specify page ranges for large documents. --- ## Calibration Rules 1. **Read before Edit.** Always read a file before editing it. The Edit tool enforces this. 2. **Edit over Write for existing files.** Edit is surgical and shows diffs. Write is a full replacement — use it only for new files or complete rewrites. 3. **Glob over Bash for file search.** Glob is optimized for pattern matching. Only fall back to `fd` or `find` for queries Glob cannot express (size filters, date filters). 4. **Grep over Bash for content search.** Grep is optimized for ripgrep-based search with proper permissions. Never use `grep` or `rg` via Bash. 5. **Parallel reads for multiple files.** Issue all Read calls in a single response for concurrent execution. 6. **Always use absolute paths.** Claude Code tools require absolute paths. Never pass relative paths to Read, Write, or Edit.