Need help with slamhound?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

419 Stars 39 Forks Other 357 Commits 18 Opened issues


Slamhound rips your namespace form apart and reconstructs it.

Services available


Need anything else?

Contributors list


They sent a slamhound on Turner's trail in New Delhi, slotted it
to his pheromones and the color of his hair. It caught up with him
on a street called Chandni Chauk and came scrambling for his
rented BMW through a forest of bare brown legs and pedicab
tires. Its core was a kilogram of recrystallized hexogene and
flaked TNT. He didn't see it coming. The last he saw of India was
the pink stucco facade of a place called the Khush-Oil Hotel.

Because he had a good agent, he had a good contract. Because he had a good contract, he was in Singapore an hour after the explosion. Most of him, anyway. The Dutch surgeon liked to joke about that, how an unspecified percentage of Turner hadn't made it out of Palam International on that first flight and had to spend the night there in a shed, in a support vat.

It took the Dutchman and his team three months to put Turner together again. They cloned a square meter of skin for him, grew it on slabs of collagen and shark-cartilage polysaccharides. They bought eyes and genitals on the open market. The eyes were green.

-- Count Zero, page 1. By William Gibson

Slamhound rips your ns form apart and reconstructs it. No Dutch surgeon required.


[slamhound "1.5.5"]
to the
of your

This project is no longer under active development.


Leiningen Usage

Make an alias for

run -m slam.hound
in your
  :aliases {"slamhound" ["run" "-m" "slam.hound"]}

Take a namespace with a sparse ns form that won't compile:

$ cat src/my/namespace.clj # before: ns form is missing clauses

(ns my.namespace "I have a doc string.")

(defn -main [& args] (pprint args) (io/copy (ByteArrayInputStream. (.getBytes "hello")) (first args)))

Then run slamhound on it:

$ lein slamhound src/my/namespace.clj # [... thinking ...]

$ cat src/my/namespace.clj # after: spits out new ns form (ns my.namespace "I have a doc string." (:require [ :as io] [clojure.pprint :refer [pprint]]) (:import ( ByteArrayInputStream)))

Like magic.

Running on a directory will perform the same operation on every .clj file inside.

Repl Usage

You can reconstruct namespaces from a repl to avoid the slow startup time:

user=> (require '[slam.hound :refer [reconstruct]])
user=> (println (reconstruct "src/my/namespace.clj"))
(ns my.namespace
  "I have a doc string."
  (:require [ :as io]
            [clojure.pprint :refer [pprint]])
  (:import ( ByteArrayInputStream)))

Or to reconstruct files in place:

user=> (slam.hound/swap-in-reconstructed-ns-form "src/my/namespace.clj")
;; Reload the file in your editor to pick up changes

Emacs Usage

The included

allows for convenient access within nREPL or SLIME sessions via
M-x slamhound
. Install manually or via Marmalade.

Vim Usage


for use of the

command within Clojure buffers.

Light Table Usage


from the central plugin repository.


Syntax-quoted references

Slamhound will only find references in a namespace that are consumed within the namespace itself. For example, if you have a macro that refers to a var inside syntax-quote (backtick), but the macro is only called from other namespaces, then Slamhound won't detect the reference and will instead report the failure in the namespace in which the macro is called.

You can work around this problem by attaching dummy metadata to the

form to prevent it from compiling without the necessary references being present:
(defmacro defexample
  "Metadata can be attached to a macro by specifying an `attr-map`
  between the docstring and the params vector."
  {:requires [AClass a-var an/aliased-var #'a-macro]}
  [name & args]
  `(do (def ~(str name \*) (AClass. [email protected]))
       (def ~(str name \-) (a-var [email protected]))
       (def ~(str name \+) (an/aliased-var [email protected]))
       (def ~(str name \!) (a-macro [email protected]))))

Notice that macros must be referenced with

to avoid a
Can't take
the value of a macro

If the syntax quoted references refer to functions, classes, or constant data, unquoting them will work as well:

(defmacro defexample
  {:requires [#'a-macro]}
  [name & args]
  `(do (def ~(str name \*) (new ~AClass [email protected]))
       (def ~(str name \-) (~a-var [email protected]))
       (def ~(str name \+) (~an/aliased-var [email protected]))
       (def ~(str name \!) (a-macro [email protected]))))

In this case

, and
must be resolved at compile time, so Slamhound will successfully find these references.

Note that the shorter reader macro form

(AClass. [email protected])
must be expanded to
(new ~AClass [email protected])
and that macros cannot be unquoted.

Fully qualified and dynamically resolved Vars

Slamhound will also not find references to fully-qualified vars or vars resolved at runtime since it relies on detecting compilation failures to determine when it's done.

PermGen memory pressure

Slamhound aggressively creates and destroys namespaces during reconstruction. This taxes the class loading system, so there is a possibility that the JVM may run out of PermGen space in large projects. If this happens, try running your JVM with the following option to enable garbage collection of discarded classes:


Side effects during namespace evaluation

As namespaces may potentially be reloaded many times during reconstruction, it is important that no side-effects (aside from var definition) occur during namespace evaluation.

Leiningen 1.x


plugin is deprecated, and the
approach above is recommended for users of Leiningen 2. However, if you are still using Leiningen 1.x you can use the
$ lein run -m slam.hound src/foo

Since Leiningen 1.x doesn't support partially-applied aliases, you would have to make a shell alias if you don't want to type the full invocation out every time.


Copyright © 2011-2012 Phil Hagelberg and contributors

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

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.