关于 clojure-eval
clojure-eval 是通过 nREPL 服务执行 Clojure 代码的技能,适用于需要测试函数、检查会话或确认命名空间可加载的开发者。它支持发现端口并在多次求值间保留会话状态。
主要功能
- 01发现 nREPL 服务
- 02求值 Clojure 表达式
- 03在求值间保留状态
- 04重新加载命名空间以测试
- 05重置会话并设置超时
适用场景
- 01检查修改后的命名空间能否编译
- 02交互式试运行函数调用
- 03查看运行中及已连接的 nREPL 会话
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bhauman/ clojure-mcp-light --skill clojure-eval安装后在 Claude Code 中输入/clojure-eval确认已加载。
附带文件examples.md
详细介绍
Clojure REPL 求值
何时使用此技能
在以下情况下使用此技能:
- 验证编辑后的 Clojure 文件能否正确编译和加载
- 交互式测试函数行为
- 检查 REPL 的当前状态
- 通过求值表达式调试代码
- 为测试引入或加载命名空间
- 在提交前验证代码更改是否有效
工作原理
clj-nrepl-eval 命令会针对 nREPL 服务求值 Clojure 代码。会话状态会在各次求值之间保留,因此你可以在一次求值中引入命名空间,并在后续调用中使用它。每个 host:port 组合都有自己的会话文件。
说明
0. 发现并选择 nREPL 服务
首先,发现当前目录中正在运行的 nREPL 服务:
clj-nrepl-eval --discover-ports
这会显示当前项目目录中正在运行的所有 nREPL 服务(Clojure、Babashka、shadow-cljs 等)。
然后使用 AskUserQuestion 工具:
-
如果发现了端口: 提示用户选择要使用的 nREPL 端口:
- question:“要使用哪个 nREPL 端口?”
- header:“nREPL 端口”
- options: 将每个发现的端口作为一个选项列出,其中包含:
- label: 端口号
- description: 服务类型和状态(例如,“当前目录中的 Clojure nREPL 服务”)
- 最多列出 4 个发现的端口作为选项
- 用户可以选择“Other”来输入自定义端口号
-
如果未发现端口: 提示用户如何启动 nREPL 服务:
- question:“未找到 nREPL 服务。要如何启动一个?”
- header:“启动 nREPL”
- options:
- label:“deps.edn 别名”,description:“在 deps.edn 中查找并使用 nREPL 别名”
- label:“Leiningen”,description:“使用 'lein repl' 启动 nREPL”
- 用户可以选择“Other”以使用其他方法,或在特定端口上已有服务运行时选择该项
重要:如果启动 REPL,不要指定端口;让 nREPL 启动并返回其使用的端口。
1. 求值 Clojure 代码
求值时会自动连接到指定端口
使用 -p 标志指定端口,并传入 Clojure 代码。
建议:通过 stdin 使用 heredoc,以避免 shell 转义问题。单引号分隔符(<<'EOF')会原样传递所有字符。
clj-nrepl-eval -p <PORT> <<'EOF'
(+ 1 2 3)
EOF
多个表达式:
clj-nrepl-eval -p <PORT> <<'EOF'
(def x 10)
(+ x 20)
EOF
2. 显示 nREPL 会话
发现当前目录中的所有 nREPL 服务:
clj-nrepl-eval --discover-ports
显示当前项目目录中正在运行的所有 nREPL 服务,包括其类型(clj/bb/basilisp)以及它们是否与当前工作目录匹配。
检查之前连接过的会话:
clj-nrepl-eval --connected-ports
仅显示你之前建立的连接(在首次通过某个端口求值后显示)。
3. 常见用法
引入命名空间(始终使用 :reload 以获取更改):
clj-nrepl-eval -p <PORT> "(require '[my.namespace :as ns] :reload)"
引入命名空间后测试函数:
clj-nrepl-eval -p <PORT> "(ns/my-function arg1 arg2)"
检查文件是否能编译:
clj-nrepl-eval -p <PORT> "(require 'my.namespace :reload)"
多个表达式:
clj-nrepl-eval -p <PORT> "(def x 10) (* x 2) (+ x 5)"
复杂的多行代码:
clj-nrepl-eval -p <PORT> <<'EOF'
(def x 10)
(* x 2)
(+ x 5)
EOF
自定义超时时间(毫秒):
clj-nrepl-eval -p <PORT> --timeout 5000 "(long-running-fn)"
重置会话(清除所有状态):
clj-nrepl-eval -p <PORT> --reset-session
clj-nrepl-eval -p <PORT> --reset-session "(def x 1)"
可用选项
-p, --port PORT- nREPL 端口(必填)-H, --host HOST- nREPL 主机(默认值:127.0.0.1)-t, --timeout MILLISECONDS- 超时时间(默认值:120000 = 2 分钟)-r, --reset-session- 重置持久化的 nREPL 会话-c, --connected-ports- 列出之前连接过的 nREPL 会话-d, --discover-ports- 发现当前目录中的 nREPL 服务-h, --help- 显示帮助信息
重要提示
- 优先通过标准输入使用 heredoc: 使用
clj-nrepl-eval -p <PORT> <<'EOF' ... EOF,避免 shell 转义问题 - 会话会持续保留: 状态(变量、命名空间、已加载的库)会在多次调用之间持续保留,直到 nREPL 服务器重启。
--reset-session只会重置 nREPL 会话(清除*e、*1等动态变量),不会清除通过def定义的变量或已加载的命名空间 - 自动修复分隔符: 工具会自动修复缺失或不匹配的括号
- 始终使用 :reload: 引入命名空间时,使用
:reload以获取最新更改 - 默认超时: 2 分钟(120000ms)——长时间运行的操作请增大超时时间
- 输入优先级: 命令行参数优先于标准输入
典型工作流
- 发现 nREPL 服务器:
clj-nrepl-eval --discover-ports - 使用 AskUserQuestion 工具提示用户选择端口
- 引入命名空间:
clj-nrepl-eval -p <PORT> "(require '[my.ns :as ns] :reload)" - 测试函数:
clj-nrepl-eval -p <PORT> "(ns/my-fn ...)" - 迭代:进行更改,使用
:reload重新引入,再次测试