Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Build configurations for Leiningen + runtime project.clj access
branch: master

This branch is 8 commits ahead of ninjudd:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.


"Because I just... don't feel like managing two config files... *sigh*..."


slothcfg for Leiningen 2 fills in the missing features in Leiningen 2's profile support:

  • Makes the project.clj file available to your code at runtime so that you can use it as a config file!
  • Build profiles for Leiningen that can be set and remain in effect until unset.
  • Built-in templates to create .cljs, .cljx or .cljs config files.


To install slothcfg, add the following to your project map as a plugin:

[slothcfg "1.0.1"]

That is all you need. But you will probably also want to add two directories to your .gitignore file. The first is the directory .slothcfg, which will be in the same directory as your project.clj. This directory holds the currently active profile. The second is the namespace that is automatically generated by slothcfg with your profile values. In most of the examples above, you'd want to add "src/cfg/current.clj" or possibly "src/cfg" to your .gitignore, if there are no other files you will have in src/cfg that you wish to check into git.


The first step is learning about Leiningen's profiles, in the "Profiles" section. slothcfg only provides user interface to turn profiles on and off, and to make them available to the code in the project itself, so you need to understand how they work.

Sticky profiles

The only user-operable way of controlling profiles in use is using Leiningen's built-in with-profile task, which requires you to list all the profiles you'd like to have in effect for the task that is given as its argument.

When slothcfg is installed, you can get a list of the currently active profiles by doing lein profiles:

[prompt]$ lein profiles

Current sticky profiles:

Here, slothcfg has modified the built in profiles task to also print out the currently active sticky profiles. In this case, since none have been set, there are no current sticky profiles. We can set a few profiles using slothcfg set:

[prompt]$ lein slothcfg set test stage
Warning: Unknown profile :stage is being set active.
Current sticky profiles: #{:test :stage}

Now two profiles have been set to active, :test and :stage. slothcfg has warned that it cannot find any profile called :stage, as it isn't present in the project map. But it has still set the profile to stick.

If we set :stage by mistake, we can unset that profile using the slothcfg unset command:

[prompt]$ lein slothcfg unset stage
Current sticky profiles: #{:test}

If we wish to remove all sticky profiles at once, we can simply call slothcfg unset with the --all flag:

[prompt]$ lein slothcfg unset --all
All profiles unset.
[prompt]$ lein profiles

Current sticky profiles:

Note that none of this is modifying the project map. It is simply stashing a bit of state that will be automatically applied when you run Leiningen tasks. This state is stored in the file .slothcfg/current in your project root. This file can be deleted at any time with no ill effect (other than unsticking all the profiles that were set.

Finally, note that the built-in with-profile task still works the same as it ever did. Any profiles it sets are added to the set of sticky profiles already in effect, as sticky profiles are as if there is an implicit with-profile with those tasks.

Project map access

The second half of slothcfg is making the project map, with all active profiles merged in, available to the project itself, in addition to within leiningen's own process. It does this in part by outputting a Clojure source file into a location of your choice (by default {first of :source-paths project key}/cfg/current.clj) that contains the project map. Any code that is interested in the project map, whether it is running in Leiningen, in your project, or in a JAR built by Leiningen with slothcfg installed, can access it by loading that namespace and accessing the project variable in it.

As an example, suppose you run the repl task:

[prompt]$ lein repl
Connection opened on localhost port 4005.

Then within the repl, you can do the following:

user> (use 'cfg.current)
user> (prn project)
{:compile-path "/path/to/my-great-project/target/classes", :group "slothcfg", ...}

So we can see that we were able to use the cfg.current namespace and find the entire project map in the project var from that namespace. As you would expect, you can now write code that requires the cfg.current namespace and changes its behavior based on its contents. This code will continue to work even when a JAR is built from this project. The project map available in the JAR will be based on the configurations that were included when the JAR was built (either through sticky profiles or the with-profile task or none, depending on which is the case).


You can change the behavior of slothcfg by setting some values in the project map. slothcfg's configuration goes in the :slothcfg key, which should contain a map of option names to their values. Here are the current keys:

So for example, if the project map has the following map in the :slothcfg key:

:slothcfg {:config-source-path "src/main/clojure"
             :namespace myproject.config
             :var config
             :keyseq [:config]
             :verbose true}

Then the project map will be at myproject.config/project, which is in the file src/main/clojure/myproject/config.clj. When you run the command:

[prompt]$ lein with-profile test profiles
Performing task with-profile with profiles (:dev :user :default)
Performing task 'profiles' with profile(s): 'test'
Performing task profiles with profiles (:test)

Current sticky profiles:

Here you can see the verbose statements of slothcfg mixed in with the statement output by the with-profile task. First the with-profile task has its profiles output by slothcfg, before it runs. Only the default Leiningen profiles are in effect when it runs. Then it prints out its statement that it is running the profiles task with the test profile. Then slothcfg prints out the profiles in effect when the profiles task runs; just the test profile. At the end, you can see that there were no sticky profiles in effect. If we add the prod profile as a sticky profile:

[prompt]$ lein slothcfg set prod
Performing task slothcfg with profiles (:dev :user :default)
Current sticky profiles: #{:prod}
[prompt]$ lein with-profile test profiles
Performing task with-profile with profiles (:dev :user :default)
Performing task 'profiles' with profile(s): 'test'
Performing task profiles with profiles (:test :prod)

Current sticky profiles: #{:prod}

Here we can see that the prod profile was added to the running of the profiles task because it was set sticky, and the test profile was added by the with-profile task.

Since all of this extra output is controled by the :verbose key in the :slothcfg configuration map, you can actually make yourself a profile that has the :verbose key to true in a :slothcfg map, and then set that profile to by sticky:

;; In project.clj...
:profiles {:verbose-slothcfg {:slothcfg {:verbose true}}}


[prompt]$ lein slothcfg set verbose-slothcfg

will make it so that you can switch slothcfg from verbose output to quiet output by setting or unsetting the verbose-slothcfg profile.

[prompt]$ lein slothcfg set verbose-slothcfg
Current sticky profiles: #{:prod :verbose-slothcfg}
[prompt]$ lein jar
Performing task jar with profiles (:dev :user :default :prod :verbose-slothcfg)
Created /path/to/my-great-project/target/my-great-project.jar

Forked version of configleaf

slothcfg was forked from Configleaf because it appeared to be inactive (it hadn't been updated in over a year). I decided to fork this project and give it a new name so that folks can include new updates via Leiningen. I decided to go this route instead of submitting a pull request because the configleaf project has two outstanding pull requests already (one of them over a year old). The changes in those pull requests have been incorperated into slothcfg (in fact, slothcfg is actually a fork of Justin's pull request).

Upgrading from configleaf

  1. In your project.clj, remove configleaf.hooks from :hooks and change the configleaf entry in your :plugins to match what's listed in the Installation section.
  2. Search your entire project and replace ever occurrence of "configleaf" with "slothcfg".
  3. Rename the invisible .configleaf directory at the root of your project to .slothcfg

Remember that the set-profile and unset-profile tasks are now replaced by slothcfg set and slothcfg unset. This was done to future-proof slothcfg in case another plugin (or leiningen itself) wants to use those task names.


  • Version 1.0.1 (By: Greg Slepak / @taoeffect)

    • Renamed project to slothcfg so that users can pull new features from Clojars.
    • Removed all use of :use (it's bad, mmm'k?)
    • Removed robert-hooke dependency because it comes with leiningen 2.
    • Consolidated the set-profile and unset-profile tasks under a generic slothcfg task to future-proof slothcfg.
    • Added :file-ext option to specify config file extension.
    • Added :template option to allow the option of providing your own mustache template.
    • Added :middleware option to optionally transform the project map.
    • Added templates for .cljx and .cljs :file-ext.
    • Updated .clj template to use 'defonce' now.
    • Templates now store config map in an atom to allow for updates within the project.
    • dissoc :checkout-deps-shares from the project map to fix an incompatibility with Leiningen 2.3.0 that caused an "Unreadable form" RuntimeException.
    • Included @ninjudd's PR to configleaf to add :keyseq and :var options
    • Restructured and updated text in
  • Version 0.4.7 (By: Justin Balthrop / @ninjudd)

    • remove unused v1 legacy methods
    • Add support for outputting a subset of the project map via :keyseq option
    • Added :var option
  • Version 0.4.6

    • Implement the :never-sticky configuration key.
  • Version 0.4.5

    • Bug fixes; remove one of the hooks which is no longer necessary in lein2. Don't use earlier 0.4 series versions (harm is bounded to extra files being added to JARs or lein tasks failing).
  • Version 0.4.3

    • Minor update to also add slothcfg itself to dependencies, fixes similar bugs.
  • Version 0.4.2

    • Minor update to automatically add leiningen-core to dependencies, fixes certain tasks were hooked but ran in project.
  • Version 0.4.1

    • Minor update to ensure that project map metadata is baked along with the project map.
  • Version 0.4.0

    • Extensive rewrite to work with Leiningen 2.
  • Version 0.3.0

    • Renamed and reorganized the project map. Should be easier to explain and use now.
  • Version 0.2.0 (By: David Santiago / @davidsantiago)

    • Addition of Java system properties to configurations.
    • Changes to configuration map format to allow system properties.


Copyright (C) 2011 - 2013

Distributed under the Eclipse Public License, the same as Clojure.

Something went wrong with that request. Please try again.