Skip to main content

Overview

The Write tool creates new files or completely replaces existing file contents. It’s designed for file creation and complete rewrites. For surgical edits to existing files, use the Edit tool instead.

Parameters

file_path
string
required
The path to the file to create or overwrite. Can be absolute or relative to the working directory.
content
string
required
The complete content to write to the file. This replaces any existing content entirely.

Features

Automatic Directory Creation

Write automatically creates parent directories if they don’t exist:
{
  "file_path": "/path/to/new/directory/file.go",
  "content": "package main\n\nfunc main() {}\n"
}
If /path/to/new/directory/ doesn’t exist, it will be created with permissions 0755.

Overwrite Protection

Write checks if a file was modified since last read:
  • Tracks last read time via filetracker
  • Compares modification time with last read time
  • Returns error if file was modified externally
  • Prevents accidental overwrites of manual changes
This ensures you’re not overwriting changes made outside of Crush.

Content Deduplication

Write checks if the new content is identical to existing content:
File /path/to/file.go already contains the exact content. No changes made.
This prevents unnecessary writes and file system notifications.

Diff Generation

Write generates a unified diff showing the changes:
--- /path/to/file.go
+++ /path/to/file.go
@@ -1,3 +1,5 @@
 package main
 
-func main() {}
+func main() {
+    println("Hello")
+}
The diff is included in response metadata.

Usage Examples

Create New File

{
  "file_path": "/path/to/newfile.go",
  "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, World!\")\n}\n"
}

Overwrite Existing File

{
  "file_path": "/path/to/existing.go",
  "content": "package main\n\nfunc main() {}\n"
}
First read the file with View tool to establish read time:
[
  {"tool": "view", "file_path": "/path/to/existing.go"},
  {"tool": "write", "file_path": "/path/to/existing.go", "content": "..."}
]

Create Multiple Files

[
  {
    "tool": "write",
    "file_path": "/path/to/handler.go",
    "content": "package handler\n\nfunc Handle() {}\n"
  },
  {
    "tool": "write",
    "file_path": "/path/to/handler_test.go",
    "content": "package handler\n\nimport \"testing\"\n\nfunc TestHandle(t *testing.T) {}\n"
  }
]

Generate Code

{
  "file_path": "/path/to/generated/models.go",
  "content": "// Code generated by tool. DO NOT EDIT.\n\npackage models\n\ntype User struct {\n\tID string\n\tName string\n}\n"
}

Best Practices

When to Use Write

Use Write for:
  • Creating new files
  • Generating code
  • Complete file rewrites
  • Files where most content changes
  • Template-based file creation
  • Small files that are easy to regenerate
Use Edit for:
  • Surgical changes to existing files
  • Replacing specific functions
  • Modifying configuration values
  • Adding/removing specific sections
  • Files where small portions change

File Creation Workflow

  1. Use LS tool to verify parent directory exists
  2. Prepare complete content including imports, comments, etc.
  3. Use Write tool to create the file
  4. Use View tool to verify the result
  5. Check LSP diagnostics in the response

File Overwrite Workflow

  1. Use View tool to read current content
  2. Prepare new complete content
  3. Use Write tool to overwrite
  4. Check response for errors or diagnostics
  5. Use View tool to verify if needed

Content Preparation

  1. Include all necessary imports at the top
  2. Add file-level comments if appropriate
  3. Use correct indentation (tabs or spaces)
  4. End with newline for compatibility
  5. Follow project conventions for style

Permissions

Write requires permission for all operations. You can pre-approve Write for specific paths:
{
  "allow": {
    "write": ["~/projects/myapp/generated"]
  }
}
This is useful for:
  • Generated code directories
  • Temporary files
  • Output directories
  • Build artifacts

LSP Integration

After writing a file, Crush automatically:
  1. Notifies LSP servers about the file change
  2. Waits for diagnostics (errors, warnings)
  3. Includes diagnostics in the response:
<result>
File successfully written: /path/to/file.go
</result>

<diagnostics file="/path/to/file.go">
  Line 5: undefined: fmt (error)
</diagnostics>
This helps catch errors immediately after file creation.

Error Handling

File Modified Since Last Read

File /path/to/file.go has been modified since it was last read.
Last modification: 2024-01-01T12:00:00Z
Last read: 2024-01-01T11:00:00Z

Please read the file again before modifying it.
Solution: Read the file with View tool, then retry Write.

Path is a Directory

Path is a directory, not a file: /path/to/directory
Solution: Provide a complete file path including filename.

Permission Denied

Permission denied
Solution:
  • Approve the permission prompt
  • Add path to allow list in crush.json
  • Check file system permissions

Parent Directory Doesn’t Exist

This shouldn’t happen as Write creates parent directories automatically, but if it does: Solution: Check file system permissions and disk space.

Platform Notes

Line Endings

  • Unix/Linux/macOS: LF (\n)
  • Windows: CRLF (\r\n)
Write handles line endings automatically:
  • Use \n in your content string
  • Write converts to appropriate line ending for the platform

File Permissions

  • Unix/Linux/macOS: Files created with 0644 (rw-r—r—)
  • Windows: Default Windows permissions

Path Separators

Use forward slashes / on all platforms:
  • C:/Users/name/file.txt
  • C:\\Users\\name\\file.txt

Advanced Usage

Template-Based Generation

Generate files from templates:
{
  "file_path": "/path/to/handler.go",
  "content": "package handler\n\nimport (\n\t\"net/http\"\n)\n\nfunc HandleUser(w http.ResponseWriter, r *http.Request) {\n\t// TODO: Implement\n}\n"
}

Batch File Creation

Create multiple related files in parallel:
[
  {
    "tool": "write",
    "file_path": "src/models/user.go",
    "content": "package models\n\ntype User struct {}\n"
  },
  {
    "tool": "write",
    "file_path": "src/handlers/user.go",
    "content": "package handlers\n\nfunc GetUser() {}\n"
  },
  {
    "tool": "write",
    "file_path": "tests/user_test.go",
    "content": "package tests\n\nimport \"testing\"\n\nfunc TestUser(t *testing.T) {}\n"
  }
]

Code Generation

Generate code from existing files:
  1. Read source files with View
  2. Parse or analyze content
  3. Generate new code based on analysis
  4. Write generated files with Write tool

Write vs Edit vs MultiEdit

Use Write When:

  • ✅ Creating new files
  • ✅ Complete file rewrites
  • ✅ Generated code
  • ✅ Most of the file is changing
  • ✅ Small files easy to regenerate

Use Edit When:

  • ✅ Targeted changes to existing files
  • ✅ Replacing specific functions
  • ✅ Modifying one section
  • ✅ Need precise control
  • ✅ File is large or complex

Use MultiEdit When:

  • ✅ Multiple changes to same file
  • ✅ Several edits in sequence
  • ✅ Each edit is surgical
  • ✅ Want atomic operation
  • ✅ Changes are independent

Common Workflows

Create New Feature

[
  // 1. Check structure
  {"tool": "ls", "path": "src"},
  
  // 2. Create main file
  {"tool": "write", "file_path": "src/feature.go", "content": "..."},
  
  // 3. Create test file
  {"tool": "write", "file_path": "src/feature_test.go", "content": "..."},
  
  // 4. Verify creation
  {"tool": "view", "file_path": "src/feature.go"}
]

Generate Documentation

[
  // 1. Read source files
  {"tool": "view", "file_path": "src/handler.go"},
  
  // 2. Generate docs
  {"tool": "write", "file_path": "docs/handler.md", "content": "..."},
  
  // 3. Verify output
  {"tool": "view", "file_path": "docs/handler.md"}
]

Scaffold Project

[
  {"tool": "write", "file_path": "cmd/main.go", "content": "..."},
  {"tool": "write", "file_path": "internal/server.go", "content": "..."},
  {"tool": "write", "file_path": "internal/handler.go", "content": "..."},
  {"tool": "write", "file_path": "go.mod", "content": "..."},
  {"tool": "write", "file_path": "README.md", "content": "..."}
]

Build docs developers (and LLMs) love