Agent skill
clojure-edit
ALWAYS use this skill when reading or editing Clojure, ClojureScript, CLJC, EDN, Babashka (.bb), or ClojureDart (.cljd) files. Clojure code is structurally sensitive — unbalanced parentheses, brackets, or braces produce broken files. This skill provides form-aware editing scripts, automatic syntax validation via a PostToolUse hook, and structural editing patterns that prevent the most common class of errors. Trigger for any operation on .clj, .cljs, .cljc, .edn, .bb, or .cljd files.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/clojure-edit
SKILL.md
Clojure Edit
Guidance for reading and editing Clojure code with attention to structural correctness, idiomatic patterns, and proper handling of s-expressions.
Clojure LSP Integration
The clojure-lsp plugin provides real-time diagnostics for Clojure files. Use mcp__ide__getDiagnostics to check for syntax errors, unresolved symbols, and other issues after editing.
Supported file types: .clj, .cljs, .cljc, .edn, .bb, .cljd
Workflow:
- Make edits using the patterns in this skill
- Call
mcp__ide__getDiagnosticsto verify no errors were introduced - Fix any issues before proceeding
Devbox note: For projects using devbox, prefix Babashka commands with devbox run -- (e.g., devbox run -- bb scripts/...).
Reading Clojure Files
Pattern-Based Reading Strategy
When reading Clojure files, use focused exploration rather than reading entire files:
- Read by namespace pattern: Target specific namespaces or symbols
- Read by content pattern: Search for specific forms or expressions
- Read strategically: Focus on relevant sections to minimize context usage
Using the read_clojure_file Script
This skill includes a Babashka script for pattern-based, structure-aware file reading. The script requires bb (Babashka) to be installed globally on your system:
# Find all defn forms, showing only signatures (collapsed view)
scripts/read_clojure_file.clj src/my/namespace.clj --form-type defn --collapsed
# Find functions by name pattern
scripts/read_clojure_file.clj src/my/namespace.clj --name-pattern "^process-"
# Search for content within forms
scripts/read_clojure_file.clj src/my/namespace.clj --content-pattern "http-request"
# Combine filters
scripts/read_clojure_file.clj src/my/namespace.clj --form-type defn --name-pattern "user" --collapsed
Benefits:
- Shows only function signatures when using
--collapsed, not full bodies - Filters by form type (defn, defmethod, def, etc.)
- Pattern matching on names and content
- Reduces context usage by focusing on relevant code
Before Editing
Always read the file before editing IF:
- You haven't read it yet in this session
- External modifications might have occurred
- You need current context about the code structure
Skip reading ONLY if:
- You just wrote the file in the previous tool call
- You have current context from earlier in the session
Editing Clojure Code Correctly
Core Principle: Respect the Structure
Clojure code is built from s-expressions (forms). Always edit at the form level, not the character level.
Editing Strategy
1. Read First (if needed)
Use Read tool to understand current structure
2. Identify the Form to Edit
- Locate the specific
defn,def,let, or other form - Understand its boundaries (opening and closing parens)
- Note indentation and surrounding context
3. Use Edit Tool with Complete Forms
- Provide complete, balanced s-expressions
- Match exact indentation from the source
- Include ALL parens in both old_string and new_string
4. Verify Syntax
- Ensure all opening parens have closing parens
- Check that brackets
[]and braces{}are balanced - Verify string quotes are closed
Using the edit_clojure_form Script
This skill includes a Babashka script for form-aware editing that targets functions by name rather than text matching. The script requires bb (Babashka) to be installed globally on your system and resolves file paths relative to your current working directory.
Basic Usage
# Replace an entire function by name
scripts/edit_clojure_form.clj --file src/my/namespace.clj \
--name my-function \
--operation replace \
--new-form "(defn my-function [x y]\n (+ x y 10))"
# Insert a new function before an existing one
scripts/edit_clojure_form.clj --file src/my/namespace.clj \
--name existing-function \
--operation insert-before \
--new-form "(defn helper [x]\n (* x 2))"
# Insert after a function
scripts/edit_clojure_form.clj --file src/my/namespace.clj \
--name my-function \
--operation insert-after \
--new-form "(defn related-function [x]\n (my-function x x))"
# Target specific form types (useful for defmethod, etc.)
scripts/edit_clojure_form.clj --file src/my/namespace.clj \
--name area \
--form-type defmethod \
--operation replace \
--new-form "(defmethod area :circle [shape]\n (* Math/PI (:radius shape) (:radius shape)))"
Working with Complex Multi-line Forms
For large or complex forms, use a heredoc with command substitution to avoid shell escaping issues:
# Use heredoc directly - no temp file needed!
scripts/edit_clojure_form.clj --file src/my/file.clj \
--name old-function \
--operation replace \
--new-form "$(cat <<'EOF'
(defn my-complex-function
"A complex function with lots of lines"
{:malli/schema [:=> [:catn
[:name :string]
[:count :int]]
:string]}
[name count]
(let [result (complex-calculation name)]
(process-with count result)))
EOF
)"
Key points:
- Use
$(cat <<'EOF' ... EOF)- heredoc wrapped in command substitution - Single quotes around
'EOF'prevent variable expansion inside the heredoc - No temp files needed - everything is inline and self-contained
Alternative: Temp files (if heredocs don't work in your shell)
cat > /tmp/my-form.clj << 'FORM_EOF'
(defn my-complex-function ...)
FORM_EOF
scripts/edit_clojure_form.clj --file src/my/file.clj \
--name old-function \
--operation replace \
--new-form "$(cat /tmp/my-form.clj)"
Handling Function Names with Special Characters
Function names containing arrows (->, ->>) or other shell-special characters must be quoted:
# CORRECT - quotes protect the arrow from shell interpretation
scripts/edit_clojure_form.clj --file src/my/file.clj \
--name 'uri->endpoint-fn' \
--operation replace \
--new-form "..."
# WRONG - shell will interpret -> as redirection
scripts/edit_clojure_form.clj --file src/my/file.clj \
--name uri->endpoint-fn \
--operation replace \
--new-form "..."
Preview Changes with Dry Run
Always preview complex edits before applying them:
scripts/edit_clojure_form.clj --file src/my/file.clj \
--name my-function \
--operation replace \
--new-form "$(cat /tmp/new-form.clj)" \
--dry-run | head -50
Understanding Error Messages
- "Form not found:
<name>" - The target form doesn't exist, or the name is misspelled. - "Exception during edit:
<details>" - A parsing or manipulation error. Common causes: unbalanced parentheses, invalid syntax, file path issues.
Self-Editing Precautions
When editing the script itself:
- Always use
--dry-runfirst - Keep a backup or rely on git to restore if needed
- Test the script immediately after editing
Common Editing Patterns
Adding a New Function
;; Use Edit to add after existing function
;; old_string: (end of previous function)
;; new_string: (end of previous function)\n\n(defn new-function [...] ...whole form...)
;; OR use the form-editing script:
;; scripts/edit_clojure_form.clj --file <file> --name <existing-fn> --operation insert-after --new-form "<new-defn>"
Modifying Function Body
;; Replace entire defn form
;; old_string: (defn old-impl [args]\n old-body)
;; new_string: (defn old-impl [args]\n new-body)
;; OR use the form-editing script:
;; scripts/edit_clojure_form.clj --file <file> --name old-impl --operation replace --new-form "<new-defn>"
Adding to Let Bindings
;; Replace entire let form
;; old_string: (let [existing bindings]\n body)
;; new_string: (let [existing bindings\n new-binding value]\n body)
Clojure Best Practices
For idiomatic Clojure patterns (conditionals, destructuring, control flow, function design, library usage), see references/clojure_best_practices.md.
For documentation practices (docstrings, Codox setup, cross-cutting concerns), see references/documentation-practices.md.
Parenthesis Management
Golden Rules
- Never edit partial forms - Always include complete s-expressions
- Count your parens - Opening parens must equal closing parens
- Match indentation - Preserve the source's indentation style
- Edit structurally - Think in forms, not lines
Common Paren Errors to Avoid
;; Missing closing paren:
(defn foo [x]
(+ x 1) ;; Missing closing paren for defn!
;; Correct:
(defn foo [x]
(+ x 1)) ;; All parens balanced
;; Mismatched brackets:
(defn foo [x} ;; [ paired with }
(+ x 1))
;; Correct:
(defn foo [x] ;; [ paired with ]
(+ x 1))
Self-Checking Strategy
Before submitting an edit:
- Count opening parens in new_string
- Count closing parens in new_string
- Verify they match
- Check bracket [] and brace {} pairs
- Verify string quotes are paired
Editing Decision Tree
Need to modify Clojure file?
│
├─ Adding new top-level form (defn, def, etc.)?
│ └─ Use Edit: old_string = end of file or previous form
│ new_string = previous context + new complete form
│
├─ Modifying existing function?
│ ├─ Small change (rename, add param)?
│ │ └─ Use Edit: Replace entire defn form
│ │
│ └─ Complete rewrite?
│ └─ Use Edit: Replace entire defn form
│
├─ Adding to existing form (let, cond, etc.)?
│ └─ Use Edit: Replace entire parent form
│
└─ Renaming symbol across file?
└─ Use Edit with replace_all: true
(Be careful with common names!)
Reference Materials
references/clojure_best_practices.md- Comprehensive coding guidelinesreferences/documentation-practices.md- Docstrings, Codox, and documentation conventions
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?