calva

Jon Hancock 2025-05-29T02:08:32.422929Z

Two amazing MCP servers in one week. Would appreciate tips from others. For clojure-mcp with Claude Desktop, should I attempt to configure it to use the same nREPL running in Calva or have two separates JVMs running...possibly editing the same code base?

pez 2025-05-29T04:37:49.695929Z

I’ve only tried using the same nrepl server.

Jon Hancock 2025-05-29T07:24:52.041929Z

care to share the deps config? ..when I start Calva it show the localhost:port in the output (I always select deps.edn and don't choose any custom names configs in the check box list). I always assumed this was the nREPL listener address used by Calva. As the port changes each time I start the REPL, I'm a bit confused as to how this should be setup.

pez 2025-05-29T07:41:17.746599Z

It sounds like you have the correct mental model. I haven’t played with it much and don’t really have a setup. I tested it with CoPilot and my .vscode/mcp.json looked like so:

{
  "servers": {
    "clojure-mcp": {
      "type": "stdio",
      "command": "sh",
      "args": [
        "-c",
        "cd ${workspaceFolder} && clojure -X:mcp :port 54501"
      ]
    }
  }
}
As you can see I would have to update the nrepl port every time if I did it like this. But you can create an :nrepl alias in deps.edn (if that’s what you are using) that starts the nrepl server on a known port. Use the Copy Jack-in Command Line command to get the dependencies and middleware that Calva wants. Or, hack clojure-mcp to use the nrepl-port file in lieu of the :port arg. That kind of change is worthy of a PR to the clojure-mcp project, I think.

kenny 2025-05-29T13:55:27.544739Z

Hi. I followed the https://calva.io/formatting/#indentation-rules section in the docs, pasting the config and test-code into a .cljfmt.edn file, and the code is formatted as such. I’ve tried manually running the format document command & no changes. How might I go about debugging why the formatting settings are not applying?

{:remove-surrounding-whitespace? true
 :remove-trailing-whitespace? true
 :remove-consecutive-blank-lines? false
 :insert-missing-whitespace? false
 :indent-line-comments? true
 :indents {#re "^\w" [[:inner 0]]}
 :test-code
 (concat [2]
         (map #(inc (* % 2))
              (filter #(aget sieved %)
                      (range 1 hn))))}

kenny 2025-05-30T13:38:23.914349Z

Ugh, sorry, got pulled away yesterday. Restarting the editor does not work. Renaming to cljfmt.edn also does not work.

kenny 2025-05-30T13:39:17.315329Z

Is there a place where Calva logs info? Looking at the “Output” panel under “Calva says”, I don’t get much info — it doesn’t appear to be a place where logs are sent.

kenny 2025-05-30T13:41:56.263479Z

I have opened a code workspace that currently looks like the below. I’ve tried removing the calva.fmt.configPath key. Still no dice.

{
  "folders": [
    {
      "path": "."
    },
    {
      "path": "code",
      "name": "Code"
    }
  ],
  "settings": {
    "editor.formatOnSave": true,
    "editor.formatOnPaste": true,
    "editor.defaultFormatter": null,
    "calva.fmt.configPath": "cljfmt.edn"
  }
}

kenny 2025-05-30T13:44:33.840439Z

Out of curiosity, I just tried opening another project without the code-workspace. e.g., just a regular, flat Clojure project. I added a cljfmt.edn and ran format document. Nothing. It’s like some knob somewhere is turned off.

pez 2025-05-30T13:47:11.912779Z

@phill suggested checking the developer tools. Which you do from the Help menu of VS Code.

pez 2025-05-30T13:47:43.674499Z

Iiuc, Calva could handle that much better.

kenny 2025-05-30T13:50:21.226529Z

Oh, yeah - great idea! Do I need clojure-lsp?

kenny 2025-05-30T13:52:12.761509Z

Seems expected

Overwriting grammar scope name to file mapping for scope source.clojure.
Old grammar file: file:///Applications/Cursor.app/Contents/Resources/app/extensions/clojure/syntaxes/clojure.tmLanguage.json.
New grammar file: file:///Users/kenny/.cursor/extensions/betterthantomorrow.calva-2.0.516/clojure.tmLanguage.json

pez 2025-05-30T13:57:52.518409Z

All red herrings. 😃

pez 2025-05-30T13:59:24.667629Z

@phill says that the error message was about \w not being a valid escape character. Since the regex there is actually a string you need to escape the escape: \\w.

kenny 2025-05-30T14:02:07.987029Z

For some reason my console does not have that error though. Tried, nonetheless. Same - no format change. Did reload window. Also restarted.

{:remove-surrounding-whitespace? true
 :remove-trailing-whitespace? true
 :remove-consecutive-blank-lines? false
 :insert-missing-whitespace? false
 :indent-line-comments? true
 :indents {#re "^\\w" [[:inner 0]]}
 :test-code
 (concat [2]
         (map #(inc (* % 2))
              (filter #(aget sieved %)
                      (range 1 hn))))}

kenny 2025-05-30T14:03:09.919189Z

Wait - that is kind of interesting though. Is Calva ignoring my cljfmt.edn file? Perhaps it should have printed the error and it didn’t because it isn’t finding the cljfmt.edn file for some reason.

kenny 2025-05-30T14:05:00.520199Z

clj-kondo complains about #() not being allowed in edn. Perhaps reading this file is failing because of this test, haha

pez 2025-05-30T14:26:11.323559Z

Could be. I don’t recall what we use for parsing, right now.

kenny 2025-05-30T14:26:35.127589Z

Another update: if I run clj -Tcljfmt check on the CLI it will report everything is formatted correctly. If I go into the file and run the format document command, numerous changes will be made.

kenny 2025-05-30T14:27:06.340789Z

It’s really like the cljfmt.edn file is ignored.

pez 2025-05-30T14:32:52.370719Z

When I try it (and I now realize it is I who have written the example … facepalm ) I need to fix both the regular expression and the #(). Then it works. Probably cljfmt is less picky than Calva.

😅 1
kenny 2025-05-30T14:33:43.706049Z

{:remove-surrounding-whitespace? true
 :remove-trailing-whitespace? true
 :remove-consecutive-blank-lines? false
 :insert-missing-whitespace? false
 :indent-line-comments? true
 :function-arguments-indentation :cursive
 :indents {#re "^\\w" [[:inner 0]]}}
running with this rn

pez 2025-05-30T14:33:55.941099Z

The reason here is that at some point we changed it so that Calva is using clojure.edn/read-string instead of clojure.core/read-string. So we broke the example.

👌 1
pez 2025-05-30T14:35:12.569599Z

If you have the time , you are welcome to PR a working example and a note about the discrepancy between Calva’s and cljfmt’s treating of the file.

👍 1
kenny 2025-05-30T14:36:09.318909Z

It still does not seem to follow the rules when formatting the doc, tho.

kenny 2025-05-30T14:38:43.938399Z

The setup looks like this. I wonder if it has to do with the monorepo setup here.

.
├── bb.edn
├── cljfmt.edn
├── code
│   ├── apache-math
│   ├── date
│   ├── distributions
│   ├── math
│   ├── mcp
│   ├── models
│   ├── neanderthal-matrix
│   ├── solvers
│   ├── test
│   ├── tree-ui
│   └── utility-belt
├── Provisdom.code-workspace
└── repos.edn

kenny 2025-05-30T14:41:40.353079Z

Running cljfmt check in one of the libraries, say utility-belt, states the code is formatted correctly. Opening a file in VSCode, in again say utility-belt, and running format document will change the formatting. Does Calva stop checking for cljfmt.edn once it hits any workspace root? e.g., we first check utility-belt (none found), then code (none found), and stop since it’s a workspace root.

kenny 2025-05-30T14:43:10.136769Z

Ah, that seems to be it! If I place the cljfmt.edn file inside of the code directory, it works!

kenny 2025-05-30T14:53:53.460599Z

Think I’m getting closer! If I explicitly set the configPath, it will work.

"settings": {
    "editor.formatOnSave": true,
    "editor.formatOnPaste": true,
    "editor.defaultFormatter": null,
    "calva.fmt.configPath": "/Users/kenny/github/provisdom/all-repos/cljfmt.edn"
  }
However, if I switch to use VSCode’s workspaceFolder variable reference, it does not work — back to ignoring cljfmt.edn.
{
  "folders": [
    {
      "path": ".",
      "name": "all-repos"
    },
    {
      "path": "code",
      "name": "Code"
    }
  ],
  "settings": {
    ...
    "calva.fmt.configPath": "${workspaceFolder:all-repos}/cljfmt.edn"
  }
}
I can confirm ${workspaceFolder:all-repos} expands to the correct value by creating a https://code.visualstudio.com/docs/reference/variables-reference#_how-can-i-know-a-variables-actual-value.

pez 2025-05-30T14:54:19.577079Z

I’ve run across that too. Calva only looks in one place, and cljfmt looks recursively somehow.

kenny 2025-05-30T14:56:16.999599Z

I see. Does Calva support VSCode variable references?

pez 2025-05-30T14:58:15.319339Z

Not if they arrive unresolved.

kenny 2025-05-30T14:59:08.718449Z

That must be what’s happening. Why would a variable arrive unresolved?

pez 2025-05-30T15:02:13.486889Z

I don’t know how this is supposed to be resolved. But seems like we can’t expect it to work when used in a Calva setting like that. In tasks.json it is resolved, and the setting is then not using it.

pez 2025-05-30T15:03:31.764079Z

So, an absolute path is probably what is needed.

2025-05-30T22:39:29.185259Z

I am unaware of the setting for the location of cljfmt.edn. I just put cljfmt.edn in the project root, I mean right beside project.clj.

pez 2025-05-29T13:58:29.606069Z

See if it helps naming it cljfmt.edn. I doubt this is the problem, but anyway, let’s confirm.

michaelwhitford 2025-05-29T16:02:05.182739Z

If it's not in the workspace you have to restart calva to get it to read the cljfmt.edn file, and restart if you make any changes. The automatic re-read and reload only happens if the cljfmt.edn file is in the workspace.

michaelwhitford 2025-05-29T16:02:33.089089Z

That tripped me up when I first configured it and put the file in ~/.cljfmt.edn

2025-05-29T23:09:09.772649Z

I opened Developer Tools (Help -> toggle developer tools) and saw the following message: " ERR Unsupported escape character: \w.: Error: Unsupported escape character: \w."

michaelwhitford 2025-05-29T23:11:16.691469Z

I have it like this:

:indents {#re ".*" [[:inner 0]]

michaelwhitford 2025-05-29T23:15:25.861269Z

Here is my entire config:

{:remove-surrounding-whitespace? false
 :remove-trailing-whitespace? true
 :remove-consecutive-blank-lines? false
 :insert-missing-whitespace? false
 :sort-ns-references? true
 :function-arguments-indentation :cursive
 :indents {#re ".*" [[:inner 0]]}
 :extra-indents {->         [[:default 1]]
                 ->>        [[:default 1]]
                 cond->     [[:default 1]]
                 cond->>    [[:default 1]]
                 some->     [[:default 1]]
                 some->>    [[:default 1]]
                 as->       [[:default 1]]
                 str        [[:default 1]]
                 or         [[:default 1]]
                 and        [[:default 1]]
                 not        [[:default 1]]
                 do         [[:default 1]]
                 doall      [[:default 1]]
                 dorun      [[:default 1]]
                 doseq      [[:default 1]]
                 dosync     [[:default 1]]
                 dotimes    [[:default 1]]
                 doto       [[:default 1]]
                 =          [[:default 1]]
                 when       [[:default 1]]}}