CLI Tool Ergonomics

Recently I’ve been doing some work using node.js and one of the features that I quite like is the ability to install tools. For example, to install live-server I simply type:

npm install -g live-server

To use it, I can call the tool directly:

live-server ./public

And I can remind myself that it exists by checking npm:

npm list --global

I thought it would be nice to have similar functionality using Clojure. I can sort of do it with Babashka using the http-server.clj example. But now I’m copying and pasting a script that I’ll have to put somewhere sensible, I’m not installing a tool that I can keep up to date with a simple command.

The Clojure CLI now has support for installing tools, but I feel like the ergonomics aren’t quite there. For example, if I want to install clj-new the command is:

clojure -Ttools install com.github.seancorfield/clj-new '{:git/tag "v1.2.359"}' :as clj-new

To use it I need to invoke the CLI tools again:

clojure -Tclj-new app :name myname/myapp

What I’d really like to be able to do is just call the tool directly:

clj-new app :name myname/myapp

At this stage there doesn’t seem to be an automated mechanism for updating Clojure CLI tools. It’s a new tool so that’s understandable. But it’s a long way from:

npm update -g

I’m raising this here in the hope that improved ergonomics might be something that other people would like to see too, that they might have some ideas about what that might look like, and how to make it happen.


I kind of feel like that with the cli tooling in general. swtiches and the like. maybe it is what it is. the devs seem to like it that way (I guess you can always just shove stuff into a helper script and invoke it ergonomically that way, to obfuscate the bare interface).


I agree there’s some ergonomics it seems are not there, but at the same time, it is more robust I feel, since it forces you into specific versions immediately, offers namespacing so people can’t name steal and name park, which are common security risk vectors, and it can’t clash with other tools you’ve got installed because you call it through the command line.

What you can do is just add an alias in your shell:

alias clj-new = 'clojure -Tclj-new'

Now you can call it with clj-new directly.

And for tool updates, see:

That’s what I use, it works great.


I use deps.edn and the Clojure CLI for all of my projects. While I like its features, I’ve always found the usability to be quite poor and very idiosyncratic.


If we break this down, what are the missing components?

  • global repository
  • ability to add repositories
  • discoverability
  • adding things to PATH

Who’s going to write clj-toolbox?


You could make a git project out of that script and git clone it on your machine and put that directory on your PATH. It’s a bit of work, I agree, but you can develop the script, have version control and share it.

Having said that, feel free to join the babashka Github Discussions forum to brainstorm about bb install boyer/http-script.

This is also an interesting way to provide a script:

1 Like

Thanks for all the great feedback. I think that using a shim script or an alias is a reasonable way of making installed tools available globally. I quite like the idea that the name you use for a tool is like an alias in a Clojure namespace, a convenience that still points back to the precise definition.

I think @bsless laid it out nicely, though perhaps add alias suggestions and customisation.

I guess a fairly simple stand alone tool that wraps calls to Clojure CLI would do it.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.