The language needs only a JVM, the Clojure jar and a classpath. The tools below build the classpath, fetch libraries, run programs and package them. The viewer shows each of their configuration files by name.
The Clojure CLI and deps.edn
The Clojure CLI is started as clojure or clj (the same, with rlwrap added for editing at the REPL). Each run determines the paths, dependencies and entry point from deps.edn files, then starts the program on the JVM. Any CLI version can run any version of the language.
| Command | Does |
|---|---|
clj [clj-opts] [-Aaliases] | start a REPL (the default) |
clojure [clj-opts] -X[aliases] my/fn? [kpath v ...] kv-map? | execute a function with a map of arguments (:exec-fn, :exec-args) |
clojure [clj-opts] -T[name|aliases] my/fn [kpath v ...] kv-map? | run a tool: a function run with its own classpath, not the project's |
clojure [clj-opts] -M[aliases] [init-opts] [main-opts] [args] | run a main namespace (-m my.ns) or script, via clojure.main |
deps.edn is an edn map. The CLI combines up to four sources into one map, in this order: the root deps (built into the tools.deps library: Clojure as the only dependency, :paths ["src"], the aliases :deps and :test and the repositories Maven Central and Clojars), the user deps.edn in the configuration folder, the project deps.edn in the current folder, and extra deps given with -Sdeps. They are merged as merge-with merge, except that only the last source's :paths is used.
| Key | Meaning |
|---|---|
:paths | the project's source and resource folders (relative) |
:deps | a map of a library name (a symbol such as org.clojure/clojure) to a coordinate map |
:mvn/version | coordinate of a Maven library |
:git/url, :git/tag, :git/sha | coordinate of a library in a Git repository: the sha is required (a full sha, or a prefix together with a tag), the tag is optional and only used with a sha, and the url is optional because it may be inferred from a lib name such as io.github.ORG/PROJECT |
:local/root | coordinate of a library in a local folder or jar |
:exclusions, :deps/root, :deps/manifest | attributes shared by every coordinate: transitive libraries to leave out, the folder in a repository that holds the library, the kind of project file to read |
:aliases | named additions of paths, deps and options, chosen on the command line: :extra-deps, :override-deps, :default-deps, :deps (or :replace-deps), :extra-paths, :paths (or :replace-paths), :classpath-overrides, :ns-default, :ns-aliases, :exec-fn, :exec-args, :jvm-opts, :main-opts |
:mvn/repos, :mvn/local-repo | Maven repositories to use (each with :url, and :releases and :snapshots policies) and the local repository |
:tools/usage, :deps/prep-lib | how a tool is invoked; a library that must be prepared (compiled) before use, with :ensure, :alias and :fn |
tools.build
tools.build is a library of build tasks. A build is a program: a build.clj namespace with functions that call clojure.tools.build.api, run with clj -T:build jar from an alias that adds the library and sets :ns-default build. The tasks include create-basis (the project basis: its paths and downloaded libraries), copy-dir, write-pom, jar and delete; the guide's second example builds a compiled uberjar (a single jar with the application and its libraries) with an uber task.
(ns build
(:require [clojure.tools.build.api :as b]))
(def lib 'my/lib1)
(def version "0.1.0")
(def class-dir "target/classes")
(def jar-file (format "target/%s-%s.jar" (name lib) version))
(def basis (delay (b/create-basis {:project "deps.edn"})))
(defn clean [_]
(b/delete {:path "target"}))
(defn jar [_]
(b/write-pom {:class-dir class-dir :lib lib :version version
:basis @basis :src-dirs ["src"]})
(b/copy-dir {:src-dirs ["src" "resources"] :target-dir class-dir})
(b/jar {:class-dir class-dir :jar-file jar-file}))
build.clj for a library jar, after the tools.build guide.Leiningen: project.clj
Leiningen's project.clj is a Clojure file holding one defproject form: the name (group/artifact), the version string, and then keyword-value pairs. It is code and can be edited with the usual syntax, so the viewer shows it as Clojure.
| Key | Meaning |
|---|---|
:description, :url, :license | information about the project |
:dependencies | a vector of [group/artifact "version" …options] vectors, with :exclusions [lib] |
:plugins, :repositories | Leiningen plugins; where to find and deploy libraries |
:profiles | a map of named alternative settings (:dev, :uberjar, :repl ...) |
:main, :aot | the main namespace for lein run; namespaces to compile ahead of time (:all for all) |
:source-paths, :test-paths, :resource-paths, :target-path | folders |
:jvm-opts, :aliases, :min-lein-version | options for the JVM; task aliases such as "launch" ["run" "-m" "myproject.main"]; the least Leiningen that can build it |
Boot, Babashka and shadow-cljs
- Boot keeps its build in a
build.bootfile: Clojure code that callsset-env!for dependencies and source paths and defines tasks withdeftask. The viewer shows.bootfiles as Clojure. - Babashka (
bb) runs scripts with fast start-up. Itsbb.ednis an edn map, read from the current folder, that can hold:paths,:depsand a:tasksmap of named tasks run asbb task-name. A script file can start with#!/usr/bin/env bb. See Dialects. - shadow-cljs builds ClojureScript. Its
shadow-cljs.ednis an edn map that configures the build and the ClojureScript dependencies; the:buildssection names each build with a:target(such as:esm). Thepackage.jsonnext to it manages JavaScript dependencies with npm. - clj-kondo (a linter) reads
.clj-kondo/config.edn; cljfmt and editor tools read their own edn files.
The REPL and editors
Clojure is developed interactively: forms are sent from the editor to a running REPL (clojure.main, with *1 *2 *3 and *e holding the last results and error) over a socket (the runtime can start a socket server from a JVM property) or over nREPL (which Leiningen starts), which editor plugins such as Calva (VS Code) and CIDER (Emacs) do. clojure.repl supplies doc, find-doc, apropos, source, dir and pst; since Clojure 1.12 add-lib can add a library to a running REPL.
Not described
Known, not yet covered
- Reference: only the headings of the deps.edn reference (about 25 KB), the CLI reference's command list and the tools.build guide's first example were read; the following are not described: the full
deps.ednmerge rules, the-Pprepare and other CLI options, tool installation, the function execution protocol, the Maven pom generation, version finding, Git procurer details,:deps/prep-lib, the runtime basis and the other tools.build tasks. - Reference: Leiningen's full
sample.project.clj(33 KB) was downloaded and its keys sampled; the plugin system, profile merging and every key are not covered. The Babashka book pages onbb.edn, tasks and usage, the Boot README, the Leiningen tutorial, the clj-kondo configuration page and the shadow-cljs README were downloaded and read only for the points above; Babashka task options, Boot tasks and shadow-cljs build options are not described. - Viewer: the keys of
project.cljare coloured as keywords of an ordinary Clojure form; dependency vectors in:dependencies,:pluginsand:managed-dependencieshave their library name coloured as a name.
Unknown
- Reference: checked against downloaded pages:
bb.ednwith:paths,:depsand:tasks(the Babashka book), abuild.bootthat callsset-env!(the Boot README), the project config file.clj-kondo/config.edn(the clj-kondo configuration page) and theproject.cljkeys:dependencies,:main,:profiles,:aot,:jvm-optsand:aliases(the Leiningen tutorial). Not found in any downloaded page: thatdeftaskdefines Boot tasks, the otherproject.cljkeys listed above (they come from the sample project file only in part), and that Calva and CIDER speak nREPL or a socket REPL.
See also
- EDN – the format of deps.edn, bb.edn and shadow-cljs.edn
- File structure – source paths and namespaces
- Versions and history – the language releases