> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/QwenLM/qwen-code/llms.txt
> Use this file to discover all available pages before exploring further.

# File System Tools

> Reference for file system tools (read, write, edit, glob, grep)

# File System Tools

Qwen Code provides a comprehensive suite of tools for interacting with the local file system. All file system tools operate within the workspace directory for security.

## read\_file

**Tool Name:** `read_file`

**Display Name:** ReadFile

**Kind:** Read

**Description:** Reads and returns the content of a specified file. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), and PDF files.

### Parameters

```typescript theme={null}
interface ReadFileParams {
  absolute_path: string;  // Required: Absolute path to file
  offset?: number;        // Optional: Starting line (0-based)
  limit?: number;         // Optional: Number of lines to read
}
```

### Usage

```typescript theme={null}
// Read entire file
read_file({
  absolute_path: '/home/user/project/src/index.ts'
});

// Read specific lines
read_file({
  absolute_path: '/home/user/project/README.md',
  offset: 0,
  limit: 50
});

// Read image
read_file({
  absolute_path: '/home/user/project/logo.png'
});
```

### Behavior

* **Text Files:** Returns content as string with line numbers
* **Images:** Returns base64-encoded data with MIME type
* **PDFs:** Returns base64-encoded data
* **Binary Files:** Returns error message
* **Large Files:** Automatically truncates with indication
* **Missing Files:** Returns error

### Confirmation

No confirmation required (read-only operation).

### Implementation

**Location:** `packages/core/src/tools/read-file.ts`

```typescript theme={null}
export class ReadFileTool extends BaseDeclarativeTool<
  ReadFileToolParams,
  ToolResult
> {
  static readonly Name = ToolNames.READ_FILE;

  constructor(private config: Config) {
    super(
      ReadFileTool.Name,
      ToolDisplayNames.READ_FILE,
      'Reads and returns the content of a specified file...',
      Kind.Read,
      { /* schema */ },
    );
  }

  protected override validateToolParamValues(
    params: ReadFileToolParams,
  ): string | null {
    // Validate absolute path
    if (!path.isAbsolute(params.absolute_path)) {
      return 'Path must be absolute';
    }

    // Validate within workspace
    if (!this.config.getWorkspaceContext()
        .isPathWithinWorkspace(params.absolute_path)) {
      return 'Path must be within workspace';
    }

    // Check .qwenignore
    if (this.config.getFileService()
        .shouldQwenIgnoreFile(params.absolute_path)) {
      return 'File is ignored by .qwenignore';
    }

    return null;
  }
}
```

***

## write\_file

**Tool Name:** `write_file`

**Display Name:** WriteFile

**Kind:** Edit

**Description:** Writes content to a specified file. Creates the file and parent directories if they don't exist. Overwrites existing files.

### Parameters

```typescript theme={null}
interface WriteFileParams {
  file_path: string;  // Required: Absolute path to file
  content: string;    // Required: Content to write
}
```

### Usage

```typescript theme={null}
// Create new file
write_file({
  file_path: '/home/user/project/src/new.ts',
  content: 'export const value = 42;'
});

// Overwrite existing file
write_file({
  file_path: '/home/user/project/README.md',
  content: '# Updated README\n\nNew content...'
});
```

### Behavior

* **New Files:** Creates file and parent directories
* **Existing Files:** Overwrites completely
* **Encoding:** Preserves existing BOM if present
* **Permissions:** Respects file system permissions
* **User Modification:** User can modify content before write

### Confirmation

Yes. Shows a diff of changes and asks for user approval.

### Implementation

**Location:** `packages/core/src/tools/write-file.ts`

```typescript theme={null}
export class WriteFileTool
  extends BaseDeclarativeTool<WriteFileToolParams, ToolResult>
  implements ModifiableDeclarativeTool<WriteFileToolParams>
{
  static readonly Name = ToolNames.WRITE_FILE;

  override async shouldConfirmExecute(
    signal: AbortSignal,
  ): Promise<ToolCallConfirmationDetails | false> {
    if (this.config.getApprovalMode() === ApprovalMode.AUTO_EDIT) {
      return false;
    }

    // Generate diff for confirmation
    const { originalContent, correctedContent } =
      await getCorrectedFileContent(
        this.config,
        this.params.file_path,
        this.params.content,
      );

    const fileDiff = Diff.createPatch(
      fileName,
      originalContent,
      correctedContent,
      'Current',
      'Proposed',
    );

    return {
      type: 'edit',
      title: `Confirm Write: ${fileName}`,
      fileDiff,
      originalContent,
      newContent: correctedContent,
    };
  }
}
```

***

## edit

**Tool Name:** `edit`

**Display Name:** Edit

**Kind:** Edit

**Description:** Replaces text within a file. By default requires unique match. Set `replace_all` for multiple replacements.

### Parameters

```typescript theme={null}
interface EditParams {
  file_path: string;      // Required: Absolute path
  old_string: string;     // Required: Text to replace
  new_string: string;     // Required: Replacement text
  replace_all?: boolean;  // Optional: Replace all occurrences
}
```

### Usage

```typescript theme={null}
// Single replacement (default)
edit({
  file_path: '/home/user/project/src/config.ts',
  old_string: `export const API_URL = 'http://localhost:3000';`,
  new_string: `export const API_URL = 'https://api.example.com';`,
});

// Multiple replacements
edit({
  file_path: '/home/user/project/src/utils.ts',
  old_string: 'oldFunction',
  new_string: 'newFunction',
  replace_all: true,
});

// Create new file (empty old_string)
edit({
  file_path: '/home/user/project/src/new.ts',
  old_string: '',
  new_string: 'export const value = 42;',
});
```

### Behavior

* **Unique Match Required:** By default, `old_string` must match exactly once
* **Replace All:** Set `replace_all: true` for multiple matches
* **Context Required:** Include sufficient context (3+ lines before/after)
* **Whitespace Sensitive:** Preserves exact indentation and spacing
* **Line Ending Normalization:** Handles CRLF/LF automatically
* **Self-Correction:** May attempt to fix ambiguous matches

### Confirmation

Yes. Shows a diff of the proposed changes.

### Common Errors

```typescript theme={null}
// Error: old_string not found
edit({
  file_path: '/file.ts',
  old_string: 'function foo() {',  // No match
  new_string: 'function bar() {',
});
// Solution: Read file first to get exact text

// Error: Multiple matches without replace_all
edit({
  file_path: '/file.ts',
  old_string: 'const x = 1;',  // Matches 3 times
  new_string: 'const x = 2;',
});
// Solution: Add more context or use replace_all: true

// Error: File already exists
edit({
  file_path: '/existing.ts',
  old_string: '',  // Trying to create
  new_string: 'content',
});
// Solution: Use write_file or provide old_string
```

### Implementation

**Location:** `packages/core/src/tools/edit.ts`

```typescript theme={null}
export class EditTool
  extends BaseDeclarativeTool<EditToolParams, ToolResult>
  implements ModifiableDeclarativeTool<EditToolParams>
{
  static readonly Name = ToolNames.EDIT;

  async execute(signal: AbortSignal): Promise<ToolResult> {
    const editData = await this.calculateEdit(this.params);

    if (editData.error) {
      return {
        llmContent: editData.error.raw,
        error: {
          message: editData.error.raw,
          type: editData.error.type,
        },
      };
    }

    // Apply replacement
    const newContent = applyReplacement(
      editData.currentContent,
      finalOldString,
      finalNewString,
      editData.isNewFile,
    );

    // Write file
    await this.config
      .getFileSystemService()
      .writeTextFile(this.params.file_path, newContent);

    return {
      llmContent: 'Successfully modified file',
      returnDisplay: { fileDiff, fileName, /* ... */ },
    };
  }
}
```

***

## glob

**Tool Name:** `glob`

**Display Name:** Glob

**Kind:** Read

**Description:** Finds files matching glob patterns, returning paths sorted by modification time (newest first).

### Parameters

```typescript theme={null}
interface GlobParams {
  pattern: string;   // Required: Glob pattern
  path?: string;     // Optional: Directory to search
}
```

### Usage

```typescript theme={null}
// Find all TypeScript files
glob({ pattern: '**/*.ts' });

// Find in specific directory
glob({
  pattern: '*.md',
  path: '/home/user/project/docs'
});

// Complex patterns
glob({ pattern: 'src/**/*.{ts,tsx}' });
glob({ pattern: '**/test/**/*.test.js' });
```

### Patterns

* `*` - Match any characters except `/`
* `**` - Match any characters including `/`
* `?` - Match single character
* `[abc]` - Match any character in set
* `{js,ts}` - Match any pattern in set
* `!pattern` - Exclude pattern

### Behavior

* **Sorting:** Most recently modified first
* **Limit:** Returns max 100 files
* **Respects Ignores:** Follows `.gitignore` and `.qwenignore`
* **Absolute Paths:** Always returns absolute paths

### Confirmation

No confirmation required.

### Implementation

**Location:** `packages/core/src/tools/glob.ts`

***

## grep\_search

**Tool Name:** `grep_search`

**Display Name:** Grep

**Kind:** Read

**Description:** Searches for regex patterns within file contents. Returns matching lines with file paths and line numbers.

### Parameters

```typescript theme={null}
interface GrepParams {
  pattern: string;   // Required: Regex pattern
  path?: string;     // Optional: File or directory
  glob?: string;     // Optional: File filter pattern
  limit?: number;    // Optional: Max results
}
```

### Usage

```typescript theme={null}
// Search for pattern
grep_search({
  pattern: 'function\\s+\\w+',
});

// Search in directory with filter
grep_search({
  pattern: 'TODO',
  path: 'src',
  glob: '*.ts',
});

// Limit results
grep_search({
  pattern: 'import',
  limit: 50,
});

// Complex regex
grep_search({
  pattern: 'class\\s+(\\w+)\\s+extends',
  glob: '**/*.{ts,tsx}',
});
```

### Behavior

* **Engine:** Uses ripgrep if available, falls back to JS implementation
* **Case Insensitive:** By default
* **Respects Ignores:** Follows `.gitignore` and `.qwenignore`
* **Line Context:** Returns full matching lines
* **Performance:** Very fast with ripgrep

### Confirmation

No confirmation required.

### Implementation

**Location:** `packages/core/src/tools/grep.ts` and `ripGrep.ts`

***

## list\_directory

**Tool Name:** `list_directory`

**Display Name:** ListFiles

**Kind:** Read

**Description:** Lists files and subdirectories in a specified directory.

### Parameters

```typescript theme={null}
interface ListDirectoryParams {
  path: string;                    // Required: Directory path
  ignore?: string[];               // Optional: Patterns to ignore
  respect_git_ignore?: boolean;    // Optional: Respect .gitignore
}
```

### Usage

```typescript theme={null}
// List directory
list_directory({
  path: '/home/user/project/src'
});

// With ignore patterns
list_directory({
  path: '/home/user/project',
  ignore: ['*.log', 'node_modules', '.git'],
});

// Ignore .gitignore
list_directory({
  path: '/home/user/project',
  respect_git_ignore: false,
});
```

### Behavior

* **Sorting:** Directories first, then alphabetically
* **Type Indication:** Shows `[DIR]` for directories
* **Respects Ignores:** Follows ignore patterns by default

### Confirmation

No confirmation required.

### Implementation

**Location:** `packages/core/src/tools/ls.ts`

***

## Security

All file system tools enforce security measures:

### Path Validation

1. **Absolute Paths Required:** All paths must be absolute
2. **Workspace Boundary:** Paths must be within workspace
3. **Ignore Patterns:** Respects `.qwenignore` and `.gitignore`
4. **Temp Directory Access:** Limited temp directory access

### Example Validation

```typescript theme={null}
protected override validateToolParamValues(
  params: FileToolParams,
): string | null {
  const filePath = params.path;

  // Check absolute
  if (!path.isAbsolute(filePath)) {
    return `Path must be absolute: ${filePath}`;
  }

  // Check workspace
  const workspaceContext = this.config.getWorkspaceContext();
  if (!workspaceContext.isPathWithinWorkspace(filePath)) {
    return `Path must be within workspace: ${filePath}`;
  }

  // Check ignore
  if (this.config.getFileService().shouldQwenIgnoreFile(filePath)) {
    return `Path is ignored: ${filePath}`;
  }

  return null;
}
```

## Best Practices

1. **Read Before Edit:** Always read files before editing
2. **Sufficient Context:** Include 3+ lines of context in `old_string`
3. **Use Glob First:** Use glob to find files before reading
4. **Limit Results:** Use limits to prevent overwhelming context
5. **Validate Paths:** Always use absolute paths
6. **Handle Errors:** Check for error results

## Next Steps

* [Shell Tool](./shell.mdx) - Execute shell commands
* [Task Tool](./task.mdx) - Delegate to subagents
* [Memory Tool](./memory.mdx) - Save long-term memories
* [Tools System](../tools-system.mdx) - Understanding the tools architecture
