-
-
Notifications
You must be signed in to change notification settings - Fork 60
Add dry_run parameter to file_write tool #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Added optional dry_run parameter to file_write tool with two modes: - dry_run="diff": Returns unified diff without writing to file - dry_run="new-source": Returns complete file content without writing Changes: - Updated tool schema to include dry_run parameter - Modified validate-inputs to extract and pass through dry_run - Updated execute-tool to pass dry_run and skip timestamp update in dry_run mode - Modified format-results to handle new-source output - Updated core.clj write-file, write-clojure-file, and write-text-file functions - Fixed all test calls to pass nil for dry_run parameter All 365 tests pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
The dry_run parameter is for internal use only and should not be exposed in the public schema. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Warning Rate limit exceeded@bhauman has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 45 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe pull request introduces a unified Changes
Sequence DiagramsequenceDiagram
participant Tool as Tool Layer
participant Core as Core Logic
participant FS as File System
Tool->>Tool: validate-inputs (extract dry_run)
Tool->>Core: execute-tool (pass dry_run)
alt dry_run = "new-source"
Core->>Core: compute new_source
Core-->>Tool: return {new-source: ...}
else dry_run = true
Core->>Core: compute diff
Core-->>Tool: return {diff: ...}
else dry_run = nil
Core->>FS: write-file
Core->>FS: update timestamp
Core-->>Tool: return {type: ..., file-path: ...}
end
Tool->>Tool: format-results (check for new-source)
alt new-source present
Tool-->>Client: return new-source directly
else
Tool-->>Client: return formatted result
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes The changes follow a consistent pattern: adding an optional Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/clojure_mcp/tools/file_write/tool.clj (1)
66-92: Clarify dry_run access control and add validation.The PR description states that
dry_runis "for internal use and not exposed in the tool schema." However, the code extractsdry_runfrominputs(line 66), which means external callers can provide it even though it's not in the schema. This creates an undocumented API surface.Additionally, there's no validation that
dry_runcontains valid values ("diff"or"new-source").Consider one of these approaches:
Option 1: Make it truly internal
If dry_run is only for internal tool usage, extract it from a different source (e.g., tool config) rather than from user inputs:(defmethod tool-system/validate-inputs :file-write [{:keys [nrepl-client-atom]} inputs] - (let [{:keys [file_path content dry_run]} inputs + (let [{:keys [file_path content]} inputs nrepl-client (and nrepl-client-atom @nrepl-client-atom)]Option 2: Make it officially supported
If external callers should be able to use dry_run, add it to the schema and validate it:(defmethod tool-system/tool-schema :file-write [_] {:type :object :properties {:file_path {:type :string :description "The absolute path to the file to write (must be absolute, not relative)"} :content {:type :string - :description "The content to write to the file"}} + :description "The content to write to the file"} + :dry_run {:type :string + :enum ["diff" "new-source"] + :description "Preview mode: 'diff' shows changes, 'new-source' shows complete content. Does not write to disk."}} :required [:file_path :content]})And add validation:
+ (when (and dry_run (not (contains? #{"diff" "new-source"} dry_run))) + (throw (ex-info (str "Invalid dry_run value: " dry_run " - must be 'diff' or 'new-source'") + {:dry_run dry_run})))
🧹 Nitpick comments (3)
test/clojure_mcp/tools/file_write/core_test.clj (1)
69-69: Consider adding test coverage for dry_run functionality.All test calls have been updated to pass
nilfor the newdry_runparameter, which correctly maintains existing behavior. However, there's no test coverage for the new dry_run modes ("diff"and"new-source").Consider adding tests to verify:
dry_run="diff"returns diff without writing filedry_run="new-source"returns complete file content without writing- File is not modified when dry_run is set
- File timestamp is not updated when dry_run is set
Do you want me to generate test cases for the dry_run functionality?
Also applies to: 82-82, 96-97, 111-112, 125-126, 138-139, 153-154, 169-170, 185-186, 197-198
src/clojure_mcp/tools/file_write/core.clj (2)
32-75: Consider validating dry_run parameter values.The function correctly threads
dry_runthrough the pipeline and handles both"new-source"and diff modes. However, there's no validation thatdry_runis one of the expected values (nil,"diff", or"new-source"). Invalid values would fall through to the:elsebranch, potentially causing confusion.Consider adding validation at the function entry:
[nrepl-client-atom file-path content dry_run] + (when (and dry_run (not (contains? #{"diff" "new-source"} dry_run))) + (throw (ex-info (str "Invalid dry_run value: " dry_run) + {:dry_run dry_run + :expected #{"diff" "new-source"}}))) (let [file (io/file file-path)
87-112: Same validation consideration applies here.The
write-text-filefunction has the same dry_run handling pattern aswrite-clojure-fileand would benefit from the same parameter validation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/clojure_mcp/tools/file_write/core.clj(4 hunks)src/clojure_mcp/tools/file_write/tool.clj(4 hunks)test/clojure_mcp/tools/file_write/core_test.clj(10 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{clj,cljc}: Use:requirewith ns aliases for imports (e.g.,[clojure.string :as string])
Include clear tool:descriptionfor LLM guidance
Validate inputs and provide helpful error messages in MCP tools
Return structured data with both result and error status in MCP tools
Maintain atom-based state for consistent service access in MCP tools
Files:
src/clojure_mcp/tools/file_write/core.cljsrc/clojure_mcp/tools/file_write/tool.clj
**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{clj,cljc}: Use kebab-case for vars/functions; end predicates with?(e.g.,is-top-level-form?)
Usetry/catchwith specific exception handling; use atom for tracking errors
Use 2-space indentation and maintain whitespace in edited forms
Align namespaces with directory structure (e.g.,clojure-mcp.repl-tools)
Files:
src/clojure_mcp/tools/file_write/core.cljtest/clojure_mcp/tools/file_write/core_test.cljsrc/clojure_mcp/tools/file_write/tool.clj
test/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
deftestwith descriptive names;testingfor subsections;isfor assertions in tests
Files:
test/clojure_mcp/tools/file_write/core_test.clj
🔇 Additional comments (4)
src/clojure_mcp/tools/file_write/core.clj (2)
12-20: LGTM!The
is-clojure-file?predicate correctly follows Clojure naming conventions and provides a clean abstraction for file type detection.
129-132: LGTM!The
write-filedispatcher correctly threads thedry_runparameter to bothwrite-clojure-fileandwrite-text-filepaths.src/clojure_mcp/tools/file_write/tool.clj (2)
94-113: LGTM!The
execute-toolimplementation correctly passesdry_runthrough to the core write function and appropriately skips the timestamp update when in dry-run mode.
115-133: LGTM!The
format-resultsmethod correctly handles the new:new-sourceresult for dry-run mode while preserving the existing diff-based formatting for normal operations.
When dry_run parameter is present, return just the diff or new-source without any preamble (file type, path, or "Changes:" prefix). Changes: - Modified write-clojure-file to return only diff when dry_run="diff" - Modified write-text-file to return only diff when dry_run="diff" - Updated format-results to detect dry_run mode and return raw output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
When dry_run parameter is used, include :dry_run field in the result
containing the mode value ("diff" or "new-source") to make the API
more self-documenting.
Result formats:
- dry_run="new-source": {:error false, :dry_run "new-source", :new-source "..."}
- dry_run="diff": {:error false, :dry_run "diff", :diff "..."}
- Normal operation: {:error false, :type "update", :file-path "...", :diff "..."}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Adds optional
dry_runparameter to thefile_writetool, allowing previewing changes without writing to disk. This brings consistency with the other file editing tools (file_edit,clojure_edit,clojure_edit_replace_sexp) that already support this parameter.Changes
src/clojure_mcp/tools/file_write/tool.clj
validate-inputsto extract and pass throughdry_runexecute-toolto passdry_runand skip timestamp update in dry_run modeformat-resultsto handle new-source outputsrc/clojure_mcp/tools/file_write/core.clj
write-clojure-fileto acceptdry_runparameter and skip file save when setwrite-text-fileto acceptdry_runparameter and conditionally writewrite-filedispatcher to passdry_runthroughtest/clojure_mcp/tools/file_write/core_test.clj
nilfor dry_run parameterDry Run Modes
dry_run="diff"- Returns unified diff without writing to filedry_run="new-source"- Returns complete file content without writingTesting
✅ All 365 tests pass with 0 failures and 0 errors
✅ Verified all three modes work correctly (diff, new-source, and normal write)
Notes
The
dry_runparameter is for internal use only and is not exposed in the tool schema.🤖 Generated with Claude Code
Summary by CodeRabbit