Clojure Command Line Interface (CLI) tools provide a fast way for developers to get started with Clojure and simplify an already pretty simple experience. With tools.deps it also provides a more flexible approach to including libraries, including the use of code from a specific commit in a Git repository.
Practicalli Clojure 35 - Clojure CLI tools - an introduction is a video of a live broadcast of this content (inclucing typos)
Clojure CLI tools provide:
- Running an interactive REPL (Read-Eval-Print Loop)
- Running Clojure programs
- Evaluating Clojure expressions
- Managing dependencies via tools.deps
Clojure CLI tools allow you to use other libraries to, referred to as dependencies or ‘deps’. These may be libraries you are writing locally, projects in git (e.g. on GitHub) or libraries published to Maven Central or Clojars.
The Clojure CLI tools can cover the essential features of Clojure Build tools Leiningen and Boot, but are not designed as a complete replacement. Both these build tools are mature and may have features you would otherwise need to script in Clojure CLI tools.
This article is a follow on from new Clojure REPL Experience With Clojure CLI Tools and Rebel Readline
Clojure is packaged as a complete library, a JVM JAR file, that is simply included in the project like any other library you would use. You could just use the Java command line, but then you would need to pass in quite a few arguments as your project added other libraries.
Clojure is a hosted language, so you need to have a Java runtime environment (Java JRE or SDK) and I recommend installing this from Adopt OpenJDK. Installation guides for Java are covered on the ClojureBridge London website
The Clojure.org getting started guide covers instructions for Linux and MacOXS operating systems. There is also an early access release of clj for windows
The installation provides the command called
clojure and a wrapper called
clj that provides a readline program called rlwrap that adds completion and history once the Clojure REPL is running.
clj when you want to run a repl (unless you are using rebel readline instead) and
clojure for everything else.
Start a Clojure REPL using the
clj command in a terminal window. This does not need to be in a directory containing a Clojure project for a simple REPL.
A Clojure REPL will now run. Type in a Clojure expression and press
Return to see the result
Exit the REPL by typing
Ctrl+D (pressing the
D keys at the same time).
Run a Clojure program in a the given file. This would be useful if you wanted to run a script or batch jobs.
Aliases can be added that define configurations for a specific build task:
You can use and legal Clojure keyword name for an alias and include multiple aliases with the
clojurecommand. For example in this command we are combining three aliases:
deps.edn file allows you to specify a particular version of the Clojure language the REPL and project use. You can also evaluate
*clojue-version* in a REPL to see which version of the Clojure language is being used.
clj -Sdescribe will show you the version of the Clojure CLI tools that is currently installed.
clj -Sverbosewill also show the version of Clojure CLI tools used before it runs a REPL.
deps.edn is a configuration file using extensible data notation (edn), the language that is used to define the structure of Clojure itself.
Configuration is defined using a map with top-level keys for
:aliases and any provider-specific keys for configuring dependency sources (e.g. GitHub, GitLab, Bitbucket).
~/.clojure/deps.edn for global configurations that you wish to apply to all the projects you work with
project-directory/deps.edn for project specific settings
The installation directory may also contain a
deps.edn file. On my Ubuntu Linux system this location is
/usr/local/lib/clojure/deps.edn and contains the following configuration.
Note: the install
deps.ednis now depreciated and will not be included in a future version of the Clojure CLI tools.
The deps.edn files in each of these locations (if they exist) are merged to form one combined dependency configuration. The merge is done in the order above install/config/local, last one wins. The operation is essentially merge-with merge, except for the :paths key, where only the last one found is used (they are not combined).
You can use the
-Sverbose option to see all of the actual directory locations.
Much more detail is covered in the Clojure.org article - deps and cli
deps.edn file in the top level of your project can be used to include libraries in your project. These may be libraries you are writing locally, projects in git (e.g. on GitHub) or libraries published to Maven Central or Clojars.
Include a library by providing its name and other aspects like version. This information can be found on Clojars if the library is published there.
Libraries as JAR files will be cached in the
clojure.java-time as a dependency in the
deps.edn file, so Clojure CLI tools can downloaded the library and add it to the classpath.
For larger projects you should definately find an editor you find productive and has great CLojure support. You can write code in the REPL and you can just run a specific file of code, if you dont want to set up a full project.
Create a directory
deps.edn file in this directory with the following code:
src directory and the source code file
src/practicalli/what_time_is_it.clj which contains the following code:
The code has a static entry point named
-main that can be called from Clojure CLI tools. The
-m option defines the main namespace and by default the
-main function is called from that namespace. So the Clojure CLI tools provide program launcher for a specific namespace:
deps.edn you are not limited to using just dependencies from JAR files, its much easier to pull code from anywhere.
TODO: Expand on this section in another article with some useful examples
Rebel readline enhances the REPL experience by providing multi-line editing with auto-indenting, language completions, syntax highlighting and function argument hints as you code.
clj-new is a tool to generate new projects from its own small set of templates. You can also create your own clj-new templates. It is also possible to generate projects from Leiningen or Boot templates, however, this does not create a
deps.edn file for Clojure CLI tools, it just creates the project as it would from either Leiningen or Boot.
clj-new as an alias in your
~/.clojure/deps.edn like this:
Create a Clojure CLI tools project using the
clj-new app template
app template creates a couple of tests to go along with the sample code. We can use the cognitec test runner to run these tests using the
clj-new currently has the following built-in templates:
app – a
deps.edn project with sample code, tests and the congnitect test runner, clj -A:test:runner. This project includes
:gensys directive, so can be run as an application on the command line via
lib – the same as the
app template, but without the
:gensys directive as this is mean to be a library.
template – the basis for creating your own templates.
Use the figwheel-main template to create a project for a simple Clojurescript project, optionally with one or reagent, rum or om libraries.
An alias is a way to add optional configuration to your project which is included when you use the alias name when running
We will cover examples of using aliases as we discover more about Clojure CLI tools. For now, take a look at Clojure CLI and deps.edn - video by Sean Corfield
Installing CLI tools downloads a tar file that contains the installation files, the executables, man pages, a default
deps.edn file, an
example-deps.edn and a Jar file.
The jar file is installed in a directory called
libexec is not removed when installing newer versions of the Clojure CLI tools, so you may find multiple versions inside the
Despite the seemingly stripped-down set of options available in deps.edn (just :paths, :deps, and :aliases), it turns out that the
:aliases feature really provides all you need to bootstrap a wide variety of build tasks directly into the clojure command. The Clojure community is building lots of tools on top of Clojure CLI tools to provide richer features that can simply be added as an alias.
What I really like best about this approach is that I can now introduce new programmers to Clojure using command line conventions that they are likely already familiar with coming from many other popular languages like perl, python, ruby, or node.
- Clojure CLI webapp template - @lambdatronic
- A sample full stack Clojure CLI project - @oakes
- JUXT Edge - a clojure application foundation - @juxt
This work is licensed under a Creative Commons Attribution 4.0 ShareAlike License, including custom images & stylesheets. Permissions beyond the scope of this license may be available at @jr0cket