Edit tool: applying a file change
Overview
This flow runs when the main loop dispatches a tool_use for the FileEdit tool, ending with the patched content flushed to disk . The entry point is the tool's call method in tools/FileEditTool/FileEditTool.ts .
Steps
- The tool destructures
file_path,old_string,new_string, andreplace_allfrom the validated input and expands the path to an absolute path viaexpandPath. - It fires off skill discovery for the path and activates conditional skills, not awaiting skill loading so the edit is not blocked .
- It notifies the diagnostics tracker that the file is about to change via
diagnosticTracker.beforeFileEdited. - It ensures the parent directory exists by calling
fs.mkdir(dirname(absoluteFilePath))before entering the atomic read-modify-write section . - When file history is enabled, it snapshots pre-edit content via
fileHistoryTrackEditkeyed on the parent message uuid . - It reads current contents with
readFileForEdit, capturingoriginalFileContents,fileExists,encoding, and line endings . - It validates freshness: if the on-disk mtime is newer than the last tracked read, it compares content against the cached full read and throws
FILE_UNEXPECTEDLY_MODIFIED_ERRORon divergence . - It normalizes quote characters by calling
findActualStringto find the real old string in the file andpreserveQuoteStyleto keep curly quotes innew_stringmatching the file's style . - It generates the patch and updated file buffer via
getPatchForEdit, honoring thereplace_allflag . - It writes the updated buffer to disk with
writeTextContent, preserving the original encoding and line endings . - It notifies the LSP manager of the change via
changeFileandsaveFile, and clears previously delivered diagnostics for that URI . - It calls
notifyVscodeFileUpdatedwith old and new content so the editor's diff view updates . - It updates
readFileStatewith the new content and fresh modification time so subsequent edits see a consistent snapshot and stale writes are invalidated . - It emits telemetry:
tengu_write_claudemdwhen editing CLAUDE.md,countLinesChanged(patch)for line deltas, andtengu_edit_string_lengthswith byte sizes and the replaceAll flag . - When
CLAUDE_CODE_REMOTEis truthy and the GrowthBooktengu_quartz_lanternflag is enabled, it computes a single-file git diff viafetchSingleFileGitDiffand logstengu_tool_use_diff_computed. - Finally it returns a
dataobject carryingfilePath,oldString,newString,originalFile,structuredPatch,userModified,replaceAll, and the optionalgitDiff.
State touched
- — LSP failure paths log via
logForDebugging
(The primary mutable state for the edit — readFileState — is a per-context map passed in as a parameter to call, not a module-level state token in the whitelist .)
Decisions
No [decision:...] tokens are available in the whitelist for this flow .