After reading about the rise and fall of Lisp at the Jet Propulsion Lab JPL I refresh my Lisp experience. Now I can hack on a Lisp web service hosted on a remote server from within Emacs from my laptop.

Setting up a Lisp dev environment is easy: the instructions at Common Lisp Wiki will give you a GNU/Emacs with SLIME mode package installed. For a remote development setup, both the remote server and local dev machine should have Steel Bank Common Lisp along with the QuickLisp package manager installed.

The SLIME package provides an Emacs major-mode for Common Lisp development. Similar to the Sam text editor, the SLIME uses a seperate backend server that it communicates with over a network port. It is that server, named Swank, that is loaded into the Lisp interpreter. This means that on the target box we can just install the Swank backend and then communicate with it over SSH.

Add the following to the .sbclrc on the remote box to load Swank when SBCL is started:

; Setup Swank
(ql:quickload "swank")
(require 'asdf)
(asdf:oos 'asdf:load-op 'swank)
(setf swank:*communication-style* :fd-handler)
(swank:create-server :dont-close t)

Now in a seperate terminal window start a new instance of SSH to the remote machine, and forward the local port 4007 to the remote port 4005 which is used by Swank:

ssh -C -L4007:127.0.0.1:4005 $USER@$REMOTEIP

Now tell SLIME to connect to the remote machine. In Emacs type M-x slime-connect and choose 127.0.0.1 and port 4007.

And that’s it! You will now be interacting with the REPL of the remote machine. For bonus points we can start a simple web server on the remote box just to prove we’ve done it. If you type this into the REPL it will load the Clack web framwork and serve up a simple Hello, World on port 5000:

(ql:quickload :clack)
(clack:clackup
  (lambda (env)
    (declare (ignore env))
    '(200 (:content-type "text/plain")(break) ("Hello, Clack!"))))

Use Curl on the development machine and you should see:

curl http://$REMOTEIP:5000
Hello, Clack!

To change the server text to Hello, World!:

(clack:stop *)
(clack:clackup
  (lambda (env)
  (declare (ignore env))
  '(200 (:content-type "text/plain")(break) ("Hello, World!"))))

Enjoy!