Hey folks. I am tinkering around with using git deps in deps.edn instead of maven. I noticed that if there is a git dep inside of an alias the jack-in will fail saying that the lib needs to be prepared first. Looking into this I found that doing clj -X:deps prepare :aliases '[:dev]' in a terminal before running the jack-in does work. How would I go about doing this from within Calva so that this doesn't need to be a manual step?
Also wouldn't it make sense for Calva to do this automatically given that it's required to use git deps? Various resources are encouraging the use of git deps over maven yet this extra step causes some friction in using them.
Needing to manually run the prep command on the CLI or needing to figure out how to do it in a custom connect sequence seems like unnecessary friction. It seems like it could include any aliases provided by cljAliases and if nothing needs to be prepared at the time it's a no-op.
We should consider supporting this. However, I wonder how big the use case it… I was completely unaware about it and have never had to prepare anything when using git deps. Until we have support (if we go that way) A custom Jack-in command line is probably the best option: > Custom command lines are there to bridge the gap to those situations where standard Jack-in command lines don’t reach But I am not sure, since I don’t know anything about what prepping even means. Where do I read about it?
Unfortunately the official resource is pretty brief about it: https://clojure.org/guides/deps_and_cli#prep_libs
The dep in question is djblue/portal
I've never done a custom jack-in command so not sure what it would look like. The examples on your page don't seem to be relevant to this use case and I don't see what the default command would be
https://github.com/djblue/portal/blob/e376ac4469bded3fb2797b723fb06e9548ccf005/deps.edn#L8 defines what the prep command should target
I’m not sure if it is relevant to the use-case, but a way you can use custom command lines is to first use the Calva: Copy Jack-in command-line to the clipboard and then add the prep stuff to it and use the result as your custom Jack-in command line.
Thanks, I'll check that out
Thanks for the config examples. Clears things up slightly, but there must be somewhere this is elaborated on a tad, 😃
Hmm, so the default command has some hardcoded deps in it. That would mean needing to know if those versions should be updated later on or not. Seems like running the command in the CLI would be more simple.
Luckily it only needs to be run when dependencies are first used or updated and not something needed every time it's run
> Clears things up slightly, but there must be somewhere this is elaborated on a tad, Ah, the classic Clojure issue of being more difficult to find info on specific things 😉
I can definitely still use the maven dep in the meantime since that works out of the box. I was just exploring this since I've seen multiple places encourage using git deps to remove the unnecessary middleman of Maven/Clojars
It's neat to be able to just point to a sha and clone instead of needing to worry about a jar being published for it, especially if you wanted to use a specific commit for a particular reason or if there was a need to fork the original dep and apply something specific without needing to wait on the original source to accept a PR.
> the default command has some hardcoded deps in it There command line can use placeholders for those and get whatever Calva uses injected. FYI, But it would run on every jack-in, so if that is expensive in some ways, it is not the right way to solve the prep.
Totally agree about the neatness of git deps. I use them all the time!
If nothing needs to be prepped or is already prepped it doesn't do anything
djblue/portal was the first dep I was testing out so not sure how many (if any) of my other deps need preparing.
Portal is a whole tool, so may be a special case.
That would make sense
Actually seems like it would be better if it was a Clojure tool so it could be handled differently
Anyway, it looks like we could introduce a setting for gitDepsAlises and if that is set we augment the jack-in command line with that.
Or add a command for it. Issue welcome. We can discuss how to actually solve it there.
Sure
Btw not sure if https://github.com/BetterThanTomorrow/calva/issues/2911 slipped through the cracks from a couple months ago.
Yeah, I remember seeing that on my phone, and then forgot to follow up. I am notoriously bad at keeping track of these things. May need to whip up some Joyride script to help me. 😃
Haha, no worries
> djblue/portal was the first dep I was testing out so not sure how many (if any) of my other deps need preparing. @mike.j.cusack It's pretty rare. I think I've only run across a couple of git deps that need that step -- and it only needs it once for a given version -- you don't need it every time you jack-in -- so this isn't really a Calva issue: you should just do it manually, once (unless you change the Portal dep version).
@seancorfield I already stated that above. It's not a Calva issue, but the mission of Calva, per pez, is to make it simple and easy for people to write Clojure (and flavors of) programs so this is something that Calva could support to that goal. I actually keep my deps updated consistently so depending on how often the particular dep is updated it could be happening often. Also already stated is that the command will be a no-op if there is nothing needed for the current dep versions so it wouldn't cause any extra work when jacking in for that case.
For someone that has worked in Clojure for a long time, such as yourself, it wouldn't be a big deal to do it manually every time the dep(s) is(are) updated, but for many other people it would be helpful to at least have a command in Calva to help with it, as pez mentioned. My interest is for any user of Calva and not just myself.
It’s not clear that support in Calva would make this simpler. Maybe easier, but that’s just a a maybe. You would still need to know that this needs to be done and to configure the prep, now in two places. And we risk misleading people into thinking it is a repl start business (if we implement as a jack-in config, so maybe that tells us that we shouldn’t?). Could be that a way to help with this is to have something in the Calva docs that summarize what we know about it so far. Know that we know that the issue exists.
It is certainly complicated by the use of aliases. The official docs only show the basic prep command -- the use of :aliases isn't shown anywhere in the docs -- hence my blog post going into more details. The prep-lib error message only lists the library (group/artifact), not the alias it came in under. If you're working with Polylith, it will most likely need :aliases '[:dev]' as the OP showed but sometimes it's a test-only deps and then you need the :test alias listed -- so the user has to decide which aliases, if any, are needed for prep.
Even if Calva handled this, configuration of those aliases, if any, would be required in Calva per-project, and then Calva would need to run two commands to jack-in and fail if the prep command fails for any reason (and make all that output easily available for debugging). And that would have to work cross-platform (oh boy, Windows).
(and, as I noted, the use of :deps/prep-lib is fairly rare so this is quite the edge case -- esp. since the usual use of Portal is via Maven coords, on Clojars, rather than git deps)
For a while, LazyTest required prep when used as a git dep -- I had to add this to next.jdbc's CI (GitHub Actions) since that could start with a fresh git dep and there was a Java class that needed compiling -- but if you use LazyTest via :mvn/version you don't need this.
I would say that "most" Calva users will use the Maven coords for libraries that are deployed to Clojars (so prep is not needed), making this even more of an edge case?
need to "prep" cannot be that rare. Every "mixed" Clojure / Java project with "git coordinates" needs this. (as the Java code needed to be compiled)
Mixed Clojure / Java projects that declare :deps/prep-lib are fairly rare. Folks are still compiling the Java as part of their build and deploying JARs to Clojars containing .class files. Certain sectors/verticals might use Java classes more than other and maybe certain subsectors rely more on git deps, but I'll still assert that's pretty rare overall.
Whether prep will become more common over time, I don't know. One of the issues with git deps is they are "infectious" -- a library that uses them cannot publish to Clojars, it can only "publish" as git deps itself -- and there's still pressure to play nice with lein or some other non-`deps.edn` projects which leads to Maven versions on Clojars (see tools.build, for example, which started producing Maven versions because folks wanted to use it with lein etc).
https://github.com/search?q=deps%2Fprep-lib+language%3Aedn&type=code&l=edn shows 179 EDN files containing :deps/prep-lib -- there are close to 20k deps.edn files on GitHub apparently.
I think it's pretty clear why there wouldn't be many with a prep step given that git deps are still relatively "new" and the tendency of veteran Clojure developers to continue using very old things, because "it still works", especially given that Clojure makes a point to maintain backwards compatibility. I think that's an overall good thing and should not change by all means, but it seems to lend itself to issues like this.
There's been a lot of work towards improving the Clojure tooling, but it seems it still remains a major pain point for many people. To me it's awkward to introduce such new features, but then have some not-so-obvious gotchas that are poorly explained in the official docs, as Sean mentioned.
Personally I don't see the issue with adding it to the jack-in, given particular configuration, because the jack-in will absolutely fail if using git deps that require preparing and haven't been prepared yet.
Another potential solution here would be to add a pre-jack-in command configuration that one could then at least add the appropriate prepare command if using those deps. Calva currently has support for post-jack-in, but I don't see anything for pre.
I've been programming for almost 20 years and it took me quite a while digging to figure out what the appropriate command for it being in an alias would be so I can only imagine what a beginner would experience after seeing some resource encourage the use of git deps and then not be able to start a repl.
To me it looks a bit too complicated for Calva to nail it with some config and/or commands. As about 95% of the considerable work with Jack-in has been about Windows quirks, I’m not keen on piling up more of that kind of work. Seems best to try help with understanding the problem, and to quickly find the most probable remedy (`clojure -X:deps prep :aliases '[:dev :test]'`). So a mention in Calva docs, seems like it would help. We can link to the prep section of @seancorfield’s https://corfield.org/blog/2025/08/08/deps/#prep was a great read for me, but was a bit hard to find, from the error message. We could also consider recognizing the error message at jack-in and link to the blog post.
What would be the issue with providing a Calva command that takes an optional list of aliases to run said command?
Or the pre-jack-in command I suggested?
A custom command line could do it, I think. https://calva.io/connect-sequences/#custom-command-line
This is what I have currently. What would need to be added/changed?
"calva.replConnectSequences": [
{
"autoSelectForJackIn": true,
"name": "Auto-connect",
"menuSelections": {
"cljAliases": [
"dev"
]
},
"projectRootPath": [
"."
],
"projectType": "deps.edn"
}
]dev is the alias that would contain the git dep
There is a lot of work with maintaining features. They need to carry their weight for me to be prepared to shoulder the burden they add.
So there are no other use cases of wanting to run a command before jacking in?
Oh, yes, there are lots of use cases. It’s a different question than helping with prep, though.
Ok so what would be the issue with supporting that so one could add the appropriate prep command in that config?
As, I said, it adds maintenance surface. I’m just one person.
I'm not familiar with the inner workings of Calva, but wouldn't this be as simple as prepending the jack-in command with what the user provides, similar to appending for post?
It would be quite helpful, especially in a team environment, to simply have a project config including something like "preJackInCommand": "clojure -X:deps prep :aliases '[:dev :test]'" than requiring everyone on the team to run said command every time a relevant dep is updated.
I’m not arguing it would not be useful. It’s a matter of leverage. So, that particular use case can be covered with a shell script or Babashka task in the project, and requiring people in the team to run that script when a dep is updated. So then to maintain the config and mechanics for it, and burden the users with more config to understand. It may not be worth it.
Sure, you could create a shell script or simply a shell alias with that and ask everyone to run that when a dep is updated, but it's out of process. I can guarantee there would be many times were someone will not think to run it and then try to start a repl and it fail. Then have to run it and try running the repl again. It's disruptive and could be easily solved with what we've discussed, but I understand where you're coming from.
I'm not sure why the Clojure CLI couldn't just detect the situation and run the prep when that happens so it wouldn't fail.
Could be something to suggest at ask.clojure. There’s already this one: https://ask.clojure.org/index.php/14581/improve-clojure-error-following-prepared-include-clojure
Sure, and maybe in a year or two we could see such support 😉
I think there are probably reasons not to auto-prep, but at least we may get to know those reasons, and people wondering about it in the future will be able to find the reasons.
A thing I have been considering is if Calva could integrate with VS Code Tasks. That’s how I often start my repls, and with better integration it could get even more useful. Tasks are a bit like a super general purpose jack-in.
That would be nice if possible
Most of my projects need prep (in a general sense, not git deps prep), and I use Tasks to chain the steps. Like with Calva, the “jack-in” is something like:
1. clean the project
2. npm i
3. compile the ClojureScript parts of Calva
4. start watchers for formatting, TypeScript, ClojureScript, ESLint, tests
5. connect the repl
With VS Code Tasks this is a two step process, 1, Run the build task, 2, Connect Calva. And I get the watchers I want to monitor running in the integrated terminal, in split view:
• https://github.com/BetterThanTomorrow/calva/wiki/Run-Calva-in-Development-Mode#the-dev-process
There are two inconveniences, one bigger then the other:
1. The Calva dependencies need to be maintained in my start Clojure script (an npm script in this case)
2. It is a two-step process instead of just 1, or even fully automatic when opening the project
I don’t know if it is possible, but if Tasks would support some integration with Calva, both problems could be addressed. And git prep would be similarly covered by configuring a build task.
Interesting
As a long-time OSS project maintainer (30+ years), I'll +100 what Pez said here: a feature may look simple to a user, but it may be a lot more work for the maintainer than it looks -- not just code, but cross-platform testing, and documentation, and then supporting it "forever" -- and it may only affect a small number of users, even when it is a "big pain point" for them. In addition, there may be other, more general approaches that solve more than that specifically requested feature -- or perhaps a partially-automated, partially-manual solution that is a lot less work to build and maintain but also addresses a broader problem space.
Part of my argument here is also that if you're dealing with libraries via git deps that need prep, Calva's jack-in is not the only place it impacts. You need to deal with it in CI, you need to deal with it locally when interacting with the project outside of Calva, e.g., running tests, building an application JAR, starting a REPL yourself. And perhaps not all your team mates are using VS Code / Calva (I think my team at one point had four different editor/REPL setups).
As you said @mike.j.cusack perhaps the hardest part of this, as a user, is figuring out that prep is needed in the first place (after your jack-in fails) and then figuring out exactly what that prep command needs to look like. The user has to be able to figure all that out before they can even add the pre-jack-in command, if such a feature existed. I think @pez is right to suggest that this be addressed initially via "just" documentation. When jack-in fails, there's a documented approach to debugging that by taking the jack-in command that Calva would use and running it manually in the terminal yourself (at least, I'm pretty sure that is documented?). So now we're outside Calva/jack-in and just using the CLI/terminal, and still need to go from the (not entirely helpful) "library needs prep" error message to knowing prep is needed to knowing whether to provide aliases -- and only at that point could you configure Calva to automate it just for jack-in for the future.
I think what you said in general is fair, but is adding support for a pre-jack-in command a big ask? There's already support for running a command after. @pez himself said that there are many use cases for such a feature so it wouldn't be just for preparing a git dep and could be used for many things.
I think the discussion is focusing too much on what prompted the discussion rather than a solution that would address much more than it
I'll leave the work/value decision to @pez about adding a preJackInCommand option (the afterCLJJackInCode only runs Clojure code -- is there a general shell command option for post-jack-in work?)
I can see why customJackInCommandLine per https://calva.io/connect-sequences/#custom-command-line is a bit of a painful workaround for this (your point about keeping versions updated) but some folks already use https://calva.io/customizing-jack-in-and-connect/#jack-in-dependency-versions to pick up more recent versions of nREPL/CIDER/etc than Calva ships with. In addition, there's also https://calva.io/connect-sequences/#custom-command-line-substitutionsplaceholdersenvironment-variables which I think would allow you to substitute Calva's versions into your custom jack-in command? @pez am I understanding that correctly? ${JACK-IN-NREPL-VERSION} is that the correct syntax?
Ok so going by that I was able to get it working by setting customJackInCommandLine to "clojure -X:deps prep :aliases '[:dev]';clojure -Sdeps '{:deps {nrepl/nrepl {:mvn/version \"JACK-IN-NREPL-VERSION\"},cider/cider-nrepl {:mvn/version \"JACK-IN-CIDER-NREPL-VERSION\"}}}' -M:dev -m nrepl.cmdline --middleware '[cider.nrepl/cider-middleware]'" , but that's obnoxiously long for a config file and still don't see why having a separate config entry for something to prepend to the existing (or custom) jack in command would be a big ask.
Literally PRE-JACK-IN-COMMAND;JACK-IN-COMMAND
It doesn't really make sense to have such a long JSON config value when the actual jack-in part is not changing from the default
Especially considering that the jack in dep versions can be customized in a separate config
Good to know that it does at least work. Thank you for verifying that.
This monstrosity sprawls out to column 296 instead of neatly fitting within the normal column size of everything else in the config file
While, again, not changing a single thing about the actual jack in
And would be even longer if you need more aliases
Yeah, we get your frustration, dude. You're kind of beating a dead horse at this point. @pez can make a decision about whether to add a pre-jack-in command.
Ah, I see. You can belabor your points, but not anyone else
No need to be snarky.
Consider your comment
The substitution variables are also provided as environment variables, so I would move the commands to a script and then set the custom command line to the path of that script.
Which doesn't address what I said about not actually changing the jack-in part at all and would again rely on something outside of Calva for something very easily implemented in it. Your position on these matters has been made very clear though so I think it's time to look somewhere else.
I didn’t intend to argue anything. I wanted to highlight that Calva provides both substitution and environment variables to facilitate jack-in from a script.