Skip to content

Conversation

@bhauman
Copy link
Owner

@bhauman bhauman commented Jan 2, 2026

Summary

  • Add :config-profile CLI option to load built-in config profiles from classpath resources
  • Profiles are deep-merged on top of base config with highest precedence
  • Include cli-assist profile with clojure_edit_agent, list_nrepl_ports, clojure_eval tools enabled and write-file-guard disabled

Usage

# Apply cli-assist profile
clojure -X:mcp :config-profile :cli-assist

# Combine with custom config file
clojure -X:mcp :config-file '"/tmp/custom.edn"' :config-profile :cli-assist

Merge precedence (highest to lowest)

  1. :config-profile overlay (if provided)
  2. :config-file or project config (.clojure-mcp/config.edn)
  3. home config (~/.clojure-mcp/config.edn)

Test plan

  • Unit tests for load-config-profile (keyword/string/symbol, missing profile, nil)
  • Unit tests for apply-config-profile (merge behavior, nil profile, deep merge)
  • Unit tests for cli-assist profile contents
  • All existing tests pass (281 tests, 0 failures)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added --config-profile CLI option to apply predefined configuration profiles that customize tooling behavior
    • Configuration profiles overlay settings on top of base configuration for flexible customization
  • Tests

    • Added comprehensive test coverage for profile loading and merging functionality

✏️ Tip: You can customize this high-level summary in your review settings.

Allow users to apply built-in config profiles from classpath resources
via CLI argument. Profiles are deep-merged on top of the base config
with highest precedence.

Usage: clojure -X:mcp :config-profile :cli-assist

Includes cli-assist profile with clojure_edit_agent, list_nrepl_ports,
clojure_eval tools enabled and write-file-guard disabled.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

A configuration profile system is introduced, enabling overlay of EDN-based configuration profiles onto base configurations. The system includes a new CLI option, config loading/merging functions, and threaded profile parameter through nREPL initialization.

Changes

Cohort / File(s) Summary
Configuration Infrastructure
resources/clojure_mcp/configs/cli-assist.edn, src/clojure_mcp/config.clj
New EDN config profile enabling CLJ tooling features (clojure_edit_agent, list_nrepl_ports, clojure_eval) and disabling write-file guard. Config module exposes deep-merge (made public), adds load-config-profile and apply-config-profile functions, and extends load-config to support optional profile overlay with updated merge precedence.
Core Initialization
src/clojure_mcp/core.clj
Threads config-profile parameter through configuration loading pipeline: load-config-handling-validation-errors and fetch-config now accept optional profile; create-and-start-nrepl-connection propagates profile through initial-config; adds ::config-profile spec and updates ::nrepl-args to include profile in optional keys.
CLI Interface
src/clojure_mcp/prompt_cli.clj
Adds --config-profile PROFILE CLI option with keyword parsing (handles leading colon); run-prompt destructures config-profile and passes it through config loading.
Test Suite
test/clojure_mcp/config/profile_test.clj
New test module covering profile loading (keyword/string/symbol inputs, missing/nil handling), profile application and override behavior, deep-merge nesting, and cli-assist profile contents validation.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Parser
    participant Core as Core Init
    participant Config as Config Module
    participant Files as Config Files
    participant nREPL as nREPL Client

    CLI->>CLI: Parse --config-profile option
    CLI->>Core: run-prompt with config-profile
    Core->>Config: load-config-handling-validation-errors(file, dir, profile)
    Config->>Files: Load home config
    Files-->>Config: home config
    Config->>Files: Load project config
    Files-->>Config: project config
    Config->>Config: Merge home + project
    Config->>Config: load-config-profile(profile)
    Files-->>Config: profile config
    Config->>Config: apply-config-profile (overlay)
    Config-->>Core: Final merged config
    Core->>nREPL: Create connection with final config
    nREPL-->>Core: nREPL client initialized
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #104: Modifies config.clj load-config and merge behavior with validation schema—overlaps with profile overlay and merge precedence changes.
  • PR #99: Updates config.clj merging logic including deep-merge exposure—directly related to profile merging infrastructure.

Poem

🐰 A config profile hops in, bringing tools and tweaks,
Overlaying gently on the base that's sought for weeks,
Merge paths deep and true, from home to proj to profile's grace,
CLI flags now parse the way, threading through the place! ✨

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a :config-profile CLI option that loads resource-based configuration overlays, which is the primary feature introduced across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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 (2)
resources/clojure_mcp/configs/cli-assist.edn (1)

1-6: LGTM — consider adding a brief comment.

The profile structure is correct and aligns with the PR objectives. The tool names use the expected underscore convention for MCP tools.

Consider adding a comment at the top explaining the profile's purpose for future maintainers:

💡 Optional: Add documentation comment
+;; CLI-assist profile: Enables tools for command-line agent workflows.
+;; Disables write-file-guard to allow unrestricted file writes.
 {:enable-tools
  [:clojure_edit_agent
   :list_nrepl_ports
   :clojure_eval]

  :write-file-guard false}
src/clojure_mcp/prompt_cli.clj (1)

40-44: Consider extracting the keyword parse function to reduce duplication.

The parse-fn logic for converting strings to keywords (lines 41-44) is identical to the model option's parse-fn (lines 29-32). Consider extracting a shared helper.

💡 Optional refactor
;; Define once near the top of cli-options
(defn- parse-keyword [s]
  (if (str/starts-with? s ":")
    (keyword (subs s 1))
    (keyword s)))

;; Then use in both places:
;; :parse-fn parse-keyword
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5810ff6 and df798d4.

📒 Files selected for processing (5)
  • resources/clojure_mcp/configs/cli-assist.edn
  • src/clojure_mcp/config.clj
  • src/clojure_mcp/core.clj
  • src/clojure_mcp/prompt_cli.clj
  • test/clojure_mcp/config/profile_test.clj
🧰 Additional context used
📓 Path-based instructions (2)
**/*.clj

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.clj: Use :require with ns aliases in Clojure imports (e.g., [clojure.string :as string])
Use kebab-case for variable and function names in Clojure
End Clojure predicate functions with ? (e.g., is-top-level-form?)
Use try/catch with specific exception handling in Clojure; use atom for tracking errors
Use 2-space indentation in Clojure code and maintain whitespace in edited forms
Align Clojure namespaces with directory structure (e.g., clojure-mcp.repl-tools)
Include clear tool :description in MCP tools for LLM guidance
Validate inputs and provide helpful error messages in MCP tool implementations
Return structured data with both result and error status in MCP tool responses
Maintain atom-based state for consistent service access in MCP tool implementations

Files:

  • test/clojure_mcp/config/profile_test.clj
  • src/clojure_mcp/config.clj
  • src/clojure_mcp/prompt_cli.clj
  • src/clojure_mcp/core.clj
**/*test*.clj

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • test/clojure_mcp/config/profile_test.clj
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*.clj : Include clear tool `:description` in MCP tools for LLM guidance
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*.clj : Align Clojure namespaces with directory structure (e.g., `clojure-mcp.repl-tools`)
📚 Learning: 2026-01-02T16:18:02.394Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*.clj : Include clear tool `:description` in MCP tools for LLM guidance

Applied to files:

  • resources/clojure_mcp/configs/cli-assist.edn
  • src/clojure_mcp/config.clj
  • src/clojure_mcp/prompt_cli.clj
  • src/clojure_mcp/core.clj
📚 Learning: 2026-01-02T16:18:02.394Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*.clj : Align Clojure namespaces with directory structure (e.g., `clojure-mcp.repl-tools`)

Applied to files:

  • resources/clojure_mcp/configs/cli-assist.edn
  • test/clojure_mcp/config/profile_test.clj
  • src/clojure_mcp/config.clj
  • src/clojure_mcp/core.clj
📚 Learning: 2026-01-02T16:18:02.394Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*.clj : Validate inputs and provide helpful error messages in MCP tool implementations

Applied to files:

  • resources/clojure_mcp/configs/cli-assist.edn
📚 Learning: 2026-01-02T16:18:02.394Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*.clj : Maintain atom-based state for consistent service access in MCP tool implementations

Applied to files:

  • resources/clojure_mcp/configs/cli-assist.edn
📚 Learning: 2026-01-02T16:18:02.394Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Prefer REPL-driven development for rapid iteration and feedback in Clojure

Applied to files:

  • resources/clojure_mcp/configs/cli-assist.edn
📚 Learning: 2026-01-02T16:18:02.394Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.394Z
Learning: Applies to **/*test*.clj : Use `deftest` with descriptive names in Clojure tests; use `testing` for subsections and `is` for assertions

Applied to files:

  • test/clojure_mcp/config/profile_test.clj
📚 Learning: 2025-12-27T06:54:07.157Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain/model.clj:91-97
Timestamp: 2025-12-27T06:54:07.157Z
Learning: When reviewing Clojure code (e.g., in src/clojure_mcp/... ), verify calls to presets/get-preset follow the two arities: [preset-key] and [preset-key overrides]. The 2-arg version should merge the provided overrides map with the preset defaults and return the resulting configuration. Check for correct map merging, preservation of immutability, and validation of overrides keys to ensure predictable configuration outcomes.

Applied to files:

  • test/clojure_mcp/config/profile_test.clj
  • src/clojure_mcp/config.clj
  • src/clojure_mcp/prompt_cli.clj
  • src/clojure_mcp/core.clj
📚 Learning: 2025-08-18T00:39:24.837Z
Learnt from: hugoduncan
Repo: bhauman/clojure-mcp PR: 86
File: src/clojure_mcp/subprocess.clj:0-0
Timestamp: 2025-08-18T00:39:24.837Z
Learning: In the clojure-mcp project, the user prefers to only parse stdout for nREPL port discovery in the subprocess.clj module, and explicitly does not want to parse stderr for port information.

Applied to files:

  • src/clojure_mcp/core.clj
🔇 Additional comments (13)
src/clojure_mcp/prompt_cli.clj (2)

229-229: LGTM!

The destructuring correctly includes config-profile alongside other options.


251-255: LGTM!

The config profile is correctly passed to config/load-config, and the logging provides helpful visibility when a profile is applied.

test/clojure_mcp/config/profile_test.clj (3)

7-36: LGTM — good coverage of input variants and edge cases.

The test correctly validates all input types (keyword, string, symbol) and edge cases (missing profile, nil). The use of testing blocks with descriptive names follows guidelines.


38-73: LGTM — thorough testing of merge semantics.

Good coverage of:

  • Profile override behavior
  • Preservation of non-overlapping keys
  • Nil/missing profile handling
  • Deep merge for nested maps

75-85: LGTM!

The test validates the cli-assist profile contents match expectations from the PR objectives.

src/clojure_mcp/config.clj (4)

44-52: LGTM!

Making deep-merge public enables direct testing. The implementation correctly handles recursive map merging.


54-76: LGTM — good error handling and documentation.

The function handles all input types (keyword, symbol, string) and provides helpful warnings when profiles are missing or fail to parse.

Minor note: Line 69 uses slurp instead of file-utils/slurp-utf8. This is fine for classpath resources which are typically UTF-8, but consider using file-utils/slurp-utf8 for consistency with other config loading code (line 26).


78-92: LGTM!

The function correctly applies the profile overlay with proper precedence (profile values win).


168-216: LGTM — correct merge precedence and clean implementation.

The 3-arity version properly threads the config-profile through the loading process with the documented precedence (profile > project > home).

Note: The profile config is not validated with validate-configs before merging. This may be intentional since profiles are built-in resources (trusted), but consider adding validation if user-defined profiles are supported in the future.

src/clojure_mcp/core.clj (4)

236-257: LGTM!

The multi-arity implementation correctly forwards config-profile to config/load-config while preserving the existing error handling behavior.


259-271: LGTM!

The fetch-config function correctly threads config-profile to the config loading layer.


284-316: LGTM!

The function correctly:

  1. Destructures config-profile from initial-config
  2. Excludes it from nrepl/create via dissoc
  3. Forwards it to config loading in both project-dir and REPL-query paths

371-374: LGTM!

The spec correctly defines ::config-profile accepting keyword, symbol, or string, and properly includes it as optional in ::nrepl-args.

@bhauman bhauman merged commit e13fbec into main Jan 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants