Jig
Jig is an application harness providing a beautifully interactive development experience for Clojure projects.
Install / Use
/learn @juxt/JigREADME
Jig
“Programming should be interactive, as beautiful as possible, modular, and it should generate assets that are easy to use and learn.” – Michael O. Church

Jig is an application harness providing a beautifully interactive development experience for Clojure projects.
Releases and Dependency Information
Features and benefits
Feedback is at the heart of all agile software development processes. If you can reduce the time between making a change and seeing the result, you can proceed faster, with more confidence and accuracy.
For the majority of developers, the impact of changing code cannot be determined until the entire system has been re-built and re-tested. While there are many advantages to frequent and thorough testing, for developers the wait is long enough for us to lose our concentration and focus.

Unless you have experienced a development environment that offers instant feedback upon change it is difficult to describe the impact it can have on your ability to solve difficult problems, produce reliable code quickly and make programming more enjoyable.
Addressing Clojure's code reloading quirks
Clojure, in the tradition of dynamic languages, comes very close to providing this kind of experience right out-of-the-box. In LISP, functions are bound to vars, which can be rebound, and when functions are applied, the latest binding of the function is used.
In practice, however, there are some minor quirks that impair the
dependability of the code reloading : adding a new library dependency,
redeclaring a defmulti or Clojure protocol, stale state referenced
in defs and defonces are some examples. One of Jig's aims is
to handle these incidentals for you, letting you concentrate more fully
on your programming.
Jig builds upon Stuart Sierra's excellent reloaded workflow pattern. Therefore it's important that you're familiar with the general idea of this pattern: the developer invokes a 'reset' function at various intervals which causes a minimalist reloading of just the code that has changed since the last reset, and anything else that needs reloading as a result (Due to the intricacies of Clojure and the JVM, this is a non-trivial problem that Stuart has solved). Typically, the reset function is bound to a hotkey, Emacs keybinding (I use "C-c r") or something more exotic. The price of entry is that a developer has to ensure all application state is held in a single map (or record) called the system. Otherwise the pattern doesn't work but in practice this is a good architectural policy to establish regardless.
Jig extends Stuart's work by providing some optional extra features that can help in the development of large Clojure systems:
- modularity through componentisation
- configuration
- support for multiple projects
- a growing set of common re-usable infrastructure components.
Modularity
Stuart describes the System Constructor which creates the initial
state of a system. Jig provides an implementation of the System
Constructor that delegates the job of creating the system to components,
each component having the same lifecycle interface as Stuart describes:
init, start and stop. The System is created by
threading it through all the components.
A reset stops and restarts all components. Components are initialized and started (in dependency order) and stopped (in reverse dependency order) allowing for a clean shutdown of resources.
Why?
There are many good reasons for dividing your System into separate components. One is that it gives you looser coupling between your components, which can make it easier to re-use them (among other benefits). Another is that it allows you flexibility and architectural options at deploy time.
For example, you can deploy all your components in a single JVM for a test environment, while in production you could distribute components across multiple JVMs, for scaleability. If you are forced to deploy lots of small JVMs, in all environments, this can be an inefficient use of precious memory. I prefer to run a smaller number of JVMs, each with more memory. Developing Clojure applications as monolithic systems works well to begin with but can reduce flexibility down the road.
I want the option of deploying early versions of new projects quickly, without the hassle of setting up a new server or incurring the cost of a dedicated JVM (200Mb is not an insignificant overhead when you have dozens of Clojure-based web applications). Jig lets me quickly hook up new web applications and services onto an existing Clojure deployment.
Here's an example of one of my component graphs.

Separation of dev-workflow from application code
Rather than using a lein template to generate the project and the corresponding dev System, Jig separates these concerns. You can use Jig's workflow to develop on existing projects that don't have a built-in dev workflow.
You can also fork and improve Jig to your own requirements. The aim is to retain internal re-prgrammability to your development tooling.
One Jig project can be used against many different projects, even simultaneously (see Components)
I wrote Jig because I wanted to create new Clojure projects quickly without having to maintain the development harness for each one. As I make a small improvement to one development harness, I don't want the hassle of going through all my other projects to update them in the same way, but neither do I want dozens of development harnesses that differ from each other. I want one development harness, re-usable 'jig' that I can use against multiple Leiningen-based projects.
Configuration
Jig lets you specify configuration for your components in a single configuration file. However, components can source their own configuration if desired.
Injection of the System into the web request context.
Jig does not have opinions as to how you should build your applications. However, if does provide good support for writing Ring and Pedestal services should you wish to keep using Jig in your deployment. More details can be found below.
Automatic provision of url-for for URI generation
Pedestal boasts bidirectional routes, so that URIs can be generated from
route definitions rather than determined some other way. Jig provides a
url-for function in the Pedestal context, and defaults the
app-name and request to make it easy to generate paths that
make sense in the context of the page on which the link is placed.
Portable web applications
It can be cost-effective for multiple web applications to share the same
JVM. Jig allows you to host web applications under contextual URI
prefixes. This is a feature made possible by the provision of the
url-for function, since 'portable' web applications can use this
to generate URIs for web links in their content, without resorting to
hard-coding URI paths.
Component failure recovery
Errors thrown from components that fail during initialization or start-up do not cause the entire system to fail. This reduces the number of times that you have to reboot the JVM. Only components that are successfully initialized are started, and only those that are successfully started are stopped. Any failures are indicated in the REPL, with full details and stack traces written to the log file..
Usage
Normally you'll be used to creating with a project with lein new,
cd'ing to the newly created directory, perhaps adding some plugins to
its project.clj file, and running lein. Working with Jig is
different, in that you run lein from the Jig project directory and
'point' the configuration at one (or more) of your existing Leiningen
projects.
Clone the Jig repository as you would any other Clojure project.
$ git clone https://github.com/juxt/jig
Configure Jig by copying in a config file into the
config/config.edn. You can skip this step if you want to see Jig
running in its default configuration which includes examples.
If you're using Emacs, load up Jig's project.clj and
M-x nrepl-jack-in
(that's usually bound to 'Control-c, Meta-j')
In the *nrepl* buffer that (eventually) appears, type
user> (go)
Alternatively, on the command line, type
lein repl
and then
user> (go)
Sync the application by calling reset
user> (reset)
Resetting the application will cause namespaces to reload (thanks to
Stuart's work in org.clojure/tools.namespace) such that the
application will be back in sync with the code-base. This is the feature
that makes development fast and interactive, and it's all thanks to
Stuart's hard work.
You should find yourself typing (reset) rather a lot, and soon
even that becomes burdensome. Here's some Emacs code you can paste into
your $HOME/.emacs.d/init.el to provide a shortcut.
(defun nrepl-reset ()
(interactive)
(save-some-buffers)
(set-buffer "*nrepl*")
(goto-char (point-max))
(insert "(user/reset)")
(nrepl-return))
(global-set-key (kbd "C-c r") 'nrepl-reset)
or, if you are using cider:
(defun cider-repl-reset ()
(interactive)
(save-some-buffers)
(with-current-buffer (cider-current-r
