There is one downside however. I had tunneled into the box to check something out, and then forgot about. I went back to developing. I was ready to test my changes, and I ran (run-all-tests). Normally this would be fine, except my slime buffer was still connected to the production box, and run-all-tests does more than just unit tests, it does things like insert (fake) data into the database and makes sure it comes back out correctly. And I was still connected to the production box, so now that fake data is in my production DB.
After deleting all the crap data out of the DB, I thought of Eric Ries' 5 Whys, and set about trying to make sure this never happens again.
Step 1: Don't allow tests in production
(defn no-tests-for-you 
(println "You're in production, dumbass. No tests for you!"))
(defn prevent-tests 
(def run-all-tests user/no-tests-for-you)
(def test-ns user/no-tests-for-you)
(def test-var user/no-tests-for-you))
(when (= winston.env/environment :production)
Here, I have a dummy function that reminds the user we're talking to the production box. I also have a function that redefines most of the ways to run clojure tests. with-ns is from clojure.contrib.with-ns, which evaluates body in the specified namespace. Thankfully, (run-all-tests) is the most common way for me to start tests, and the remaining ways all take more effort to run, so this net will likely catch most of my goofs. I also have a var, winston.env/environment which specifies if we're in production or development. If we're in production, we obviously don't want to run tests.
Step 2: Fix the prompt
A big part of my confusion was because I wasn't sure which box I was connected to. Let's fix that by modifying the repl prompt to print the hostname. I already had code that started a repl manually, rather than using the default one in clojure.main. All I had to do was supply a new definition for the repl-prompt
(def hostname (.trim (sh "hostname")))
(defn repl-prompt 
(printf "%s:%s=> " winston.env/hostname *ns*))
(defn start-repl 
(binding [clojure.main/repl-prompt winston.repl/repl-prompt]
I used the sh function from clojure.contrib.shell-out to determine the hostname, and store that in a variable. Then I modified the repl prompt to print hostname:namespace=> rather than just "namespace=>". binding is clojure's way to safely monkey patch. Inside the scope of binding, all calls to clojure.main/repl-prompt will be replaced with calls to winston.repl/repl-prompt.
Step 3: Fix Slime?
I sort of cheated on step 2. Everything I wrote works great, but it doesn't fix Slime. Apparently slime hardcodes the definition of the prompt. You'll see the modified prompt when using the repl at the console, but not via slime. And I don't know of a good way to fix the slime prompt. Anyone out there have ideas?