diff --git a/Makefile b/Makefile
index 28f717c00fd745e70123ac7a443dfcb6739314f0..06581376566e417fd551f70a9fdf434bc88826e1 100644
--- a/Makefile
+++ b/Makefile
@@ -59,11 +59,7 @@ mrproper: clean
 	-rm -rf debian/cl-launch .pc/ build-stamp debian/patches/ debian/debhelper.log # debian crap
 
 debian-package: mrproper
-	git clean -xfd
-	RELEASE="$$(git tag -l '[4-.9].[0-9].[0-9]' | tail -n 1)" ; \
-	git-buildpackage --git-debian-branch=master --git-upstream-branch=master --git-upstream-tag=$$RELEASE --git-tag --git-retag --git-ignore-branch
-	lintian -c --fail-on-warnings ../cl-launch_*.changes
-	git clean -xfd
+	./release.lisp debian-package
 
 # This fits my own system. YMMV. Try make install for a more traditional install
 reinstall:
@@ -71,6 +67,7 @@ reinstall:
 
 # This might fit your system, installing from same directory
 reinstall_here:
+	-git clean -xfd
 	make install_source install_binary_standalone INSTALL_SOURCE=$$PWD INSTALL_BIN=$$PWD
 
 test:
@@ -91,25 +88,7 @@ push:
 	git fetch
 	git status
 
-debian-package-all: debian-package
-	./cl-launch.sh --include . -B install_path
-	./cl-launch.sh --no-include -o cl-launch -B install_bin
-	VER=$$(git describe --tags --match '4.*') ; \
-	cd .. && \
-	  tar zcf ~/files/cl-launch/cl-launch-$${VER}.tar.gz --exclude .git cl-launch && \
-	  cp cl-launch/cl-launch.sh ~/files/cl-launch/cl-launch.sh && \
-	  mv cl-launch_$${VER}* ~/files/cl-launch/ && \
-	cd ~/files/cl-launch && \
-	  ln -sf cl-launch-$${VER}.tar.gz cl-launch.tar.gz && \
-	  gpg -b -a cl-launch-$${VER}.tar.gz && \
-	  ln -sf cl-launch-$${VER}.tar.gz cl-launch.tar.gz && \
-	  ln -sf cl-launch-$${VER}.tar.gz.asc cl-launch.tar.gz.asc && \
-	  dput mentors cl-launch_$${VER}-1_amd64.changes
-	rsync -av --delete ~/files/cl-launch/ common-lisp.net:/project/xcvb/public_html/cl-launch/
+debian-package-all:
 
 quickrelease: reinstall_here
-	VER=`./cl-launch.sh --version | ( read a b ; echo $$b )` ; \
-	cd .. && \
-	tar zcf cl-launch-$${VER}.tar.gz --exclude .git cl-launch && \
-	rsync -av cl-launch/cl-launch.sh cl-launch-$${VER}.tar.gz common-lisp.net:/project/xcvb/public_html/cl-launch/ && \
-	ssh common-lisp.net ln -sf cl-launch-$${VER}.tar.gz /project/xcvb/public_html/cl-launch/cl-launch.tar.gz
+	./release.lisp quickrelease
diff --git a/cl-launch.sh b/cl-launch.sh
index ebad9d944d35f252306b5027e1296b6810b4f697..f1114ff078d97afd96416013e3c4aeee2500ba53 100755
--- a/cl-launch.sh
+++ b/cl-launch.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #| cl-launch.sh -- shell wrapper generator for Common Lisp software -*- Lisp -*-
-CL_LAUNCH_VERSION='4.0.0.2'
+CL_LAUNCH_VERSION='4.0.0.3'
 license_information () {
 AUTHOR_NOTE="\
 # Please send your improvements to the author:
@@ -122,7 +122,7 @@ Software specification:
  -e FORM	--eval FORM	     evaluate FORM while building
 		--require MODULE     require MODULE while building
  -r FUNC	--restart FUNC       restart from build by funcalling FUNC
-		--entry	FUNC	     (FUNC argv) after restart (buildapp compat.)
+ -E FUNC	--entry	FUNC	     (FUNC argv) after restart (buildapp compat.)
  -i FORM	--init FORM	     evaluate FORM after restart
  -ip FORM	--print FORM	     evaluate and princ FORM after restart
  -iw FORM	--write FORM	     evaluate and write FORM after restart
@@ -892,7 +892,7 @@ process_options () {
         add_init_form "(uiop:println(progn $1))" ; shift ;;
       -iw|--write)
         add_init_form "(uiop:writeln(progn $1))" ; shift ;;
-      --entry)
+      -E|--entry)
         add_init_form "($1 uiop:*command-line-arguments*)" ; shift ;;
       "("*)
 	add_init_form "(uiop:println(progn $x))" ;;
@@ -1494,7 +1494,7 @@ BEGIN_TESTS='(in-package :cl-user)(defvar *f* ())(defvar *err* 0)(defvar *begin*
 (uiop:implementation-identifier)))
 '
 END_TESTS="$(foo_require t begin)"'
-(tst t(if (equal "won" (first uiop::*command-line-arguments*))
+(tst t(if (equal "won" (first uiop:*command-line-arguments*))
 (format t "argument passing worked, ")
 (progn (incf *err*) (format t "argument passing failed (got ~S), " (cl-launch::raw-command-line-arguments))))
 (if (equal "doh" (cl-launch::getenv "DOH"))
@@ -2535,7 +2535,7 @@ Returns two values: the fasl path, and T if the file was (re)compiled"
 #-ecl
 (defun build-and-dump (dump build restart final init quit)
   (build-and-load build restart final init quit)
-  (remove :cl-launched *features*)
+  (setf *features* (remove :cl-launched *features*))
   (dump-image dump :executable (getenvp "CL_LAUNCH_STANDALONE"))
   (quit 0))
 
diff --git a/release.lisp b/release.lisp
new file mode 100755
index 0000000000000000000000000000000000000000..2e5fdf4aaa17c890957bc7ae6ce7c25675470b7a
--- /dev/null
+++ b/release.lisp
@@ -0,0 +1,103 @@
+#!/bin/sh
+#| -*- Lisp -*-
+exec "$(dirname $0)/cl-launch.sh" \
+  --system inferior-shell --system optima.ppcre --load "$0" \
+  --init '(in-package :cl-launch-release)' --entry cl-launch-release::main \
+  -- "$@" ; exit
+|#
+(defpackage :cl-launch-release
+  (:use :cl :uiop :inferior-shell :optima :optima.ppcre)
+  (:export #:rep #:clean
+           #:debian-package #:debian-package-all #:quickrelease))
+
+(in-package :cl-launch-release)
+
+(defun run* (command &rest keys &key (output t op) (error-output t eop))
+  (declare (ignore output error-output))
+  (apply 'run command (append (unless op '(:output t)) (unless eop '(:error-output t)) keys)))
+
+(defun run/interactive (command &rest keys)
+  (apply 'run command :output :interactive :input :interactive :error-output :interactive keys))
+
+(defun rep (argument) (eval-input argument)) ;; read-eval-print, no loop.
+
+(defun debian-version ()
+  (match (read-file-line "debian/changelog" :at 0)
+    ((ppcre "^[^(]*\\(([-0-9.]+)\\)" x) x)))
+
+(defun debian-version-tag (&optional (version (debian-version)))
+  (first (split-string version :separator "-")))
+
+(defun debian-arch ()
+  "amd64")
+
+(defun git-tag (&optional (pattern "4.*"))
+  (run/ss `(git describe --tags --match ,pattern)))
+
+(defun clean ()
+  (run* '(git clean -xfd))
+  (values))
+
+(defun debian-package ()
+  (clean)
+  (let* ((version (debian-version))
+         (tag (debian-version-tag version))
+         (up (pathname-parent-directory-pathname (getcwd)))
+         (origtarball (subpathname up (strcat "cl-launch_" tag ".orig.tar.gz"))))
+    (delete-file-if-exists origtarball)
+    (run* `(git-buildpackage --git-debian-branch=master --git-upstream-branch=master (--git-upstream-tag= ,tag) --git-tag --git-retag --git-ignore-branch))
+    (run* `(lintian -c --fail-on-warnings (../cl-launch_ ,version _ ,(debian-arch) .changes))))
+  (clean))
+
+(defun debian-package-all ()
+  (let* ((version (debian-version))
+         (tag (debian-version-tag version))
+         (up (pathname-parent-directory-pathname (getcwd)))
+         (home (user-homedir-pathname))
+         (cl-launch-tag (strcat "cl-launch-" tag))
+         (cldir (subpathname home "files/cl-launch/")))
+    (debian-package)
+    (run* `(./cl-launch.sh --include "." -B install_path))
+    (run* `(./cl-launch.sh --no-include -o cl-launch -B install_bin))
+    (with-current-directory (up)
+      (run* `(rm -f ,cl-launch-tag))
+      (run* `(ln -s cl-launch ,cl-launch-tag))
+      (run* `(tar zcfh (,cldir ,cl-launch-tag .tar.gz)
+                  --exclude .git ,cl-launch-tag))
+      (run* `(cp cl-launch/cl-launch.sh (,cldir cl-launch.sh)))
+      (run* (format nil "mv cl-launch_~A* ~A" tag cldir))
+      (run* `(rm -f ,cl-launch-tag)))
+    (with-current-directory (cldir)
+      (run* `(ln -sf (cl-launch ,tag .tar.gz) cl-launch.tar.gz))
+      (run/interactive `(gpg -b -a (cl-launch- ,tag .tar.gz)))
+      (run* `(ln -sf (cl-launch- ,tag .tar.gz) cl-launch.tar.gz))
+      (run* `(ln -sf (cl-launch- ,tag .tar.gz.asc) cl-launch.tar.gz.asc))
+      (run* `(dput mentors (cl-launch_ ,version _ ,(debian-arch) .changes)))
+      (run* `(rsync -av --delete ,cldir "common-lisp.net:/project/xcvb/public_html/cl-launch/")))
+    (values)))
+
+(defun cl-launch-version ()
+  (match (read-file-line "cl-launch.sh" :at 2)
+    ((ppcre "^CL_LAUNCH_VERSION='([0-9]+([.][0-9]+)+)'$" version) version)))
+
+(defun quickrelease ()
+  (let* ((version (cl-launch-version))
+         (link (strcat "cl-launch-" version))
+         (tarball (strcat link ".tar.gz")))
+    (with-current-directory ("../")
+      (run* `(rm -f ,link))
+      (run* `(ln -s cl-launch ,link))
+      (run* `(tar zcfh ,tarball --exclude .git ,link))
+      (run* `(rsync -av cl-launch/cl-launch.sh ,tarball
+                    "common-lisp.net:/project/xcvb/public_html/cl-launch/"))
+      (run* `(ssh common-lisp.net ln -sf ,tarball /project/xcvb/public_html/cl-launch/cl-launch.tar.gz))
+      (run* `(rm -f ,link ,tarball))))
+  (values))
+
+(defun main (argv)
+  (if argv
+      (multiple-value-bind (command status)
+          (find-symbol (string-upcase (first argv)) :cl-launch-release)
+        (if (eq status :external)
+            (format t "~@[~{~S~^ ~}~%~]" (multiple-value-list (apply command (rest argv))))
+            (error "Unknown command ~A" (first argv))))))