Skip to content

Conversation

bhauman
Copy link
Owner

@bhauman bhauman commented Aug 18, 2025

Summary

  • handle Babashka bb shebangs in clojure-file?
  • reuse new detection in file-write and unified-read tools
  • cover babashka scripts in unit tests

Testing

  • clojure -X:test (fails: command not found)

https://chatgpt.com/codex/tasks/task_b_68a0c1b3724c83308265bb45eee7fe34

Summary by CodeRabbit

  • New Features
    • Clojure file detection now recognizes Babashka shebang scripts, even without Clojure-like extensions.
    • Expanded recognition to include .lpy files.
    • Improved “collapsible” Clojure file detection for unified read, excluding .edn from collapsing.
  • Documentation
    • Updated descriptions to reflect shebang-based detection and supported extensions.
  • Tests
    • Added tests validating Babashka shebang recognition and ensuring non-Babashka scripts are not treated as Clojure files.

Copy link

coderabbitai bot commented Aug 18, 2025

Walkthrough

Expanded Clojure file detection centralizes in utils/valid_paths.clj, adding Babashka shebang support and .lpy recognition. File write and unified read tools now delegate to this helper. Unified read additionally excludes .edn. Tests added for shebang detection across write, read, and utility layers. Minor docstring/require adjustments.

Changes

Cohort / File(s) Summary of edits
Clojure file detection utility
src/clojure_mcp/utils/valid_paths.clj
Added private babashka-shebang? with safe IO; extended clojure-file? to use shebang or extensions (.clj/.cljs/.cljc/.bb/.edn/.lpy); updated docstring; guarded reads with path-exists? and try/catch.
File write tool uses centralized detection
src/clojure_mcp/tools/file_write/core.clj
Replaced string/extension checks with valid-paths/clojure-file?; updated requires; refreshed is-clojure-file? docstring; no other logic changes.
Unified read tool tightens collapsible check
src/clojure_mcp/tools/unified_read_file/tool.clj
collapsible-clojure-file? now uses valid-paths/clojure-file? but rejects .edn; docstring simplified; removed inline docstring from tool-name defmethod; signatures unchanged.
Tests for Babashka shebang detection
test/clojure_mcp/tools/file_write/core_test.clj, test/clojure_mcp/tools/unified_read_file/tool_test.clj, test/clojure_mcp/utils/valid_paths_test.clj
Added tests creating temp files with "#!/usr/bin/env bb" to assert detection; negative test for regular bash shebang; cleanup of temp files; minor parentheses adjustments.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant FileWrite as file_write/core
  participant ValidPaths as utils/valid_paths
  participant FS as Filesystem

  Caller->>FileWrite: write-file(path, content)
  FileWrite->>ValidPaths: clojure-file?(path)
  ValidPaths->>FS: path-exists?(path)
  alt exists
    ValidPaths->>FS: read first line
    ValidPaths-->>ValidPaths: check ext or Babashka shebang
  end
  ValidPaths-->>FileWrite: true/false
  FileWrite-->>Caller: proceed per detection (unchanged flow)
Loading
sequenceDiagram
  participant Caller
  participant UnifiedRead as unified_read_file/tool
  participant ValidPaths as utils/valid_paths
  participant FS as Filesystem

  Caller->>UnifiedRead: collapsible-clojure-file?(path)
  UnifiedRead->>ValidPaths: clojure-file?(path)
  ValidPaths->>FS: optional read first line
  ValidPaths-->>UnifiedRead: true/false
  UnifiedRead-->>Caller: true if clojure-file? and not .edn
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit taps the path with gentle paw,
Sniffs a shebang, “bb!”—aha, I saw!
Scripts now hop into the Clojure fold,
Unified trails, both bright and bold.
With ears up high and tests that sing,
We bless each file—thump-thump—spring! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/detect-babashka-files-as-clojure-files

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (7)
src/clojure_mcp/utils/valid_paths.clj (2)

85-96: Broaden Babashka shebang detection to cover env -S and /usr/local installs.

Many bb scripts use #!/usr/bin/env -S bb (to allow args), and bb may live under /usr/local/bin/bb. A small regex will reduce false negatives and allow trailing args.

Apply this diff to the detection block:

-          (let [line (-> r line-seq first)]
-            (and line
-                 (or (str/starts-with? line "#!/usr/bin/env bb")
-                     (str/starts-with? line "#!/usr/bin/bb")
-                     (str/starts-with? line "#!/bin/bb")))))
+          (let [line (-> r line-seq first)]
+            (boolean
+              (and line
+                   (re-matches
+                     #"^#!\s*(/usr/bin/env(\s+-S)?\s+bb|.*/bb)(\s|$).*"
+                     line)))))

This matches:

  • #!/usr/bin/env bb
  • #!/usr/bin/env -S bb
  • Any shebang pointing to a .../bb executable (e.g., /usr/local/bin/bb, /usr/bin/bb, /bin/bb)
  • Optional trailing arguments after bb

97-117: LGTM: Centralized, extension-first detection with bb shebang fallback.

  • Extension checks are case-insensitive and short-circuit before file IO.
  • Predicate naming and docstring are clear.
  • Inclusion of .lpy is a useful addition.

Minor docstring polish to reflect the broader shebang support would help future readers.

Apply this small docstring update:

-     Also detects files starting with a Babashka shebang (`bb`)."
+     Also detects files starting with a Babashka shebang (e.g., `#!/usr/bin/env bb`,
+     `#!/usr/bin/env -S bb`, or any shebang pointing to a `.../bb` executable)."
test/clojure_mcp/utils/valid_paths_test.clj (1)

105-116: Solid coverage; make cleanup resilient with try/finally.

If an assertion or write fails mid-block, the temp file delete might be skipped. Wrap in try/finally to guarantee cleanup.

Apply this diff:

   (testing "Detect Babashka shebang"
     (let [tmp (io/file (System/getProperty "java.io.tmpdir") "bb-script.sh")]
-      (spit tmp "#!/usr/bin/env bb\n(println :hi)")
-      (is (valid-paths/clojure-file? (.getPath tmp)))
-      (.delete tmp)))
+      (try
+        (spit tmp "#!/usr/bin/env bb\n(println :hi)")
+        (is (valid-paths/clojure-file? (.getPath tmp)))
+        (finally
+          (.delete tmp)))))
   (testing "Regular bash script not detected"
     (let [tmp (io/file (System/getProperty "java.io.tmpdir") "bash-script.sh")]
-      (spit tmp "#!/bin/bash\necho hi")
-      (is (not (valid-paths/clojure-file? (.getPath tmp))))
-      (.delete tmp))))
+      (try
+        (spit tmp "#!/bin/bash\necho hi")
+        (is (not (valid-paths/clojure-file? (.getPath tmp))))
+        (finally
+          (.delete tmp))))))

Optional: add cases for #!/usr/bin/env -S bb and /usr/local/bin/bb once the regex change lands.

test/clojure_mcp/tools/file_write/core_test.clj (1)

57-63: Good behavior test; ensure temp file cleanup with try/finally.

This makes the test robust against mid-block failures.

Apply this diff:

   (testing "Detecting Babashka shebang"
     (let [tmp (io/file *test-dir* "script.sh")]
-      (spit tmp "#!/usr/bin/env bb\n(println :hi)")
-      (is (file-write-core/is-clojure-file? (.getPath tmp)))
-      (.delete tmp))))
+      (try
+        (spit tmp "#!/usr/bin/env bb\n(println :hi)")
+        (is (file-write-core/is-clojure-file? (.getPath tmp)))
+        (finally
+          (.delete tmp))))))

Optional: consider adding a .lpy extension case in this test block to exercise the new extension support as well.

test/clojure_mcp/tools/unified_read_file/tool_test.clj (1)

64-67: LGTM; add try/finally for temp file deletion.

Keeps the test directory tidy even on failures.

Apply this diff:

-    (let [tmp (io/file *test-dir* "script.sh")]
-      (spit tmp "#!/usr/bin/env bb\n(println :hi)")
-      (is (unified-read-file-tool/collapsible-clojure-file? (.getPath tmp)))
-      (.delete tmp))
+    (let [tmp (io/file *test-dir* "script.sh")]
+      (try
+        (spit tmp "#!/usr/bin/env bb\n(println :hi)")
+        (is (unified-read-file-tool/collapsible-clojure-file? (.getPath tmp)))
+        (finally
+          (.delete tmp))))
src/clojure_mcp/tools/file_write/core.clj (1)

12-21: Predicate delegation is correct; sync write-file docstring for .bb/shebang.

boolean coercion avoids leaking nils; delegating to utils keeps behavior consistent across tools.

The write-file docstring still lists only .clj/.cljs/.cljc/.edn. Since .bb and bb-shebangs are now handled as Clojure files here, update the docstring accordingly.

Proposed docstring tweak (outside this hunk):

;; In write-file docstring, replace:
;; "For Clojure files (.clj, .cljs, .cljc, .edn), applies linting and formatting."
;; with:
;; "For Clojure files (.clj, .cljs, .cljc, .edn, .bb) or files with a Babashka shebang, applies linting and formatting."
src/clojure_mcp/tools/unified_read_file/tool.clj (1)

33-37: Optional: Centralize the “collapsible” predicate in utils.valid-paths

Tests in tool_test.clj already cover the EDN exclusion (see line 68), so no extra tests are needed.

  • Move the inline logic into clojure_mcp.utils.valid-paths/collapsible-clojure-file?
  • Delegate from unified_read_file/tool.clj to keep a single source of truth.

Proposed diff in src/clojure_mcp/tools/unified_read_file/tool.clj:

 (defn collapsible-clojure-file?
   "Determines if a file is a collapsible Clojure source file."
   [file-path]
   (when file-path
-    (and (valid-paths/clojure-file? file-path)
-         (not (str/ends-with? (str/lower-case file-path) ".edn")))))
+    (valid-paths/collapsible-clojure-file? file-path)))

Add helper in src/clojure_mcp/utils/valid_paths.clj:

(ns clojure_mcp.utils.valid-paths
  (:require [clojure.string :as str]))

(defn collapsible-clojure-file? [path]
  (and (clojure-file? path)
       (not (str/ends-with? (str/lower-case (str path)) ".edn"))))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1088242 and e49642b.

📒 Files selected for processing (6)
  • src/clojure_mcp/tools/file_write/core.clj (1 hunks)
  • src/clojure_mcp/tools/unified_read_file/tool.clj (1 hunks)
  • src/clojure_mcp/utils/valid_paths.clj (1 hunks)
  • test/clojure_mcp/tools/file_write/core_test.clj (1 hunks)
  • test/clojure_mcp/tools/unified_read_file/tool_test.clj (1 hunks)
  • test/clojure_mcp/utils/valid_paths_test.clj (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{clj,cljc}

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.{clj,cljc}: Use kebab-case for vars/functions; end predicates with ? (e.g., is-top-level-form?)
Use try/catch with 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:

  • test/clojure_mcp/tools/unified_read_file/tool_test.clj
  • test/clojure_mcp/utils/valid_paths_test.clj
  • test/clojure_mcp/tools/file_write/core_test.clj
  • src/clojure_mcp/tools/file_write/core.clj
  • src/clojure_mcp/tools/unified_read_file/tool.clj
  • src/clojure_mcp/utils/valid_paths.clj
test/**/*.{clj,cljc}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use deftest with descriptive names; testing for subsections; is for assertions in tests

Files:

  • test/clojure_mcp/tools/unified_read_file/tool_test.clj
  • test/clojure_mcp/utils/valid_paths_test.clj
  • test/clojure_mcp/tools/file_write/core_test.clj
src/**/*.{clj,cljc}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/**/*.{clj,cljc}: Use :require with ns aliases for imports (e.g., [clojure.string :as string])
Include clear tool :description for 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.clj
  • src/clojure_mcp/tools/unified_read_file/tool.clj
  • src/clojure_mcp/utils/valid_paths.clj
🔇 Additional comments (2)
src/clojure_mcp/utils/valid_paths.clj (1)

85-96: Safe and focused shebang read — nice guardrails.

Good use of path-exists? and with-open with a try/catch to safely read just the first line. This keeps the check lightweight and failure-safe.

src/clojure_mcp/tools/file_write/core.clj (1)

5-11: Consolidating detection via valid-paths is the right move.

The alias-based require is clean, and reusing a single source of truth for file-type detection reduces drift between tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant