diff --git a/.gitignore b/.gitignore
index 28f6fc3c6d4bb00ef70e307cc0881125aa69a133..7db39efacf307e933c928e07484d92558301ca46 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,4 @@
 /nginx/uwsgi_temp
 /.gitlab-shell-bundle
 /.gitlab-bundle
+/*.gem
diff --git a/.koding.yml b/.koding.yml
index 2aa6bc252d3f2cbd37e9b9fcb932aa62816c8be1..72f67f7b27e37deac81cda569b74f1328f14e8ba 100644
--- a/.koding.yml
+++ b/.koding.yml
@@ -51,14 +51,15 @@ resource:
 
         echo _KD_NOTIFY_@Cloning GitLab repository...@
         # clone and run gitlab
-        git clone https://gitlab.com/gitlab-org/gitlab-development-kit.git
+        gem install gitlab-development-kit
+        gdk init
 
         # force to use 0.0.0.0 for localhost
         echo "0.0.0.0" > gitlab-development-kit/host
 
         echo _KD_NOTIFY_@Compiling GitLab...@
         cd gitlab-development-kit
-        make
+        gdk install
 
         EOF
 
@@ -70,7 +71,7 @@ resource:
         echo ""
         echo "Now launch a new terminal and do;"
         echo "  $ cd gitlab-development-kit"
-        echo "  $ ./run"
+        echo "  $ gdk run"
         echo ""
 
         echo _KD_DONE_
diff --git a/GDK_ROOT b/GDK_ROOT
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/HELP b/HELP
index ca4583edae047772f92ee3ce52eef018d74c9dcd..dcc5774c3dd6277d9cb8364cb554370cfc0ed17d 100644
--- a/HELP
+++ b/HELP
@@ -1,11 +1,11 @@
 # GitLab Development Kit cheat sheet
 
-./run            # Start everything
-./run db         # Start enough to run tests
-./run app        # Start GitLab, need './run db'
+gdk run            # Start everything
+gdk run db         # Start enough to run tests
+gdk run app        # Start GitLab, needs 'gdk run db'
 
-make gitlab_repo=https://my-fork   # Install everything
-make update                        # Pull application changes from Git
-make clean-config all              # Delete and regenerate all config files created by GDK
+gdk install gitlab_repo=https://my-fork   # Install everything
+gdk update                                # Pull application changes from Git
+gdk reconfigure                           # Delete and regenerate all config files created by GDK
 
 # Development admin account: root / 5iveL!fe
diff --git a/bin/gdk b/bin/gdk
new file mode 100755
index 0000000000000000000000000000000000000000..d556d46808e3a1238b4bcdbd3b1be916e552073e
--- /dev/null
+++ b/bin/gdk
@@ -0,0 +1,43 @@
+#!/usr/bin/env ruby
+require 'fileutils'
+
+# Gitlab Development Kit CLI launcher
+#
+# Note to contributors: this script must not change (much) because it is
+# installed outside the gitlab-development-kit repository with 'gem
+# install'. Edit lib/gdk.rb to define new commands.
+
+def main
+  case ARGV.first
+  when 'init'
+    if ARGV.count > 2
+      puts "Usage: gdk init [DIR]"
+      return false
+    end
+
+    cmd = %W(git clone https://gitlab.com/gitlab-org/gitlab-development-kit.git)
+    cmd << ARGV[1] if ARGV.count == 2
+    system(*cmd)
+  else
+    $gdk_root = find_root(Dir.pwd)
+    if $gdk_root.nil?
+      puts "Could not find GDK_ROOT in the current directory or any of its parents."
+      return false
+    end
+    puts "(in #{$gdk_root})"
+    load(File.join($gdk_root, 'lib/gdk.rb'))
+    GDK::main
+  end
+end
+
+def find_root(current)
+  if File.exist?(File.join(current, 'GDK_ROOT'))
+    File.realpath(current)
+  elsif File.realpath(current) == '/'
+    nil
+  else
+    find_root(File.join(current, '..'))
+  end
+end
+
+exit(main)
diff --git a/doc/howto/browse.md b/doc/howto/browse.md
index 6b417d96f108c271d82481f944b2d0708e949a4a..217dd50d528f0ee8e18b542654fc39c5f7b90c92 100644
--- a/doc/howto/browse.md
+++ b/doc/howto/browse.md
@@ -5,7 +5,7 @@ quickest way to do it.
 
 ```
 cd gitlab-development-kit
-./run
+gdk run
 ```
 
 Open [localhost:3000](http://localhost:3000) in your web browser. It
diff --git a/doc/howto/https.md b/doc/howto/https.md
index 0a3c803494bd735ed985d3c447fa293e0b6e2374..7198caf10a47e2eedbaa09007af3c18c5b81246a 100644
--- a/doc/howto/https.md
+++ b/doc/howto/https.md
@@ -15,8 +15,8 @@ On OS X you can add this certificate to the trust store with:
 Next make sure that HTTPS is enabled in gitlab/config/gitlab.yml: look
 for the `https:` and `port:` settings.
 
-Uncomment the `nginx` line in your Procfile. Now `./run app`
-(and `./run`) will start NGINX listening on https://localhost:3443.
+Uncomment the `nginx` line in your Procfile. Now `gdk run app`
+(and `gdk run`) will start NGINX listening on https://localhost:3443.
 
 If you are using a port other than localhost:3000 for
 gitlab-workhorse, or if you want to use a port other than
diff --git a/doc/howto/local_network.md b/doc/howto/local_network.md
index f4f40677116861fdaa9a4e11716cfcd98efb33bf..0f1c4f45ebea832308596935c5b3eccaafc3e6cb 100644
--- a/doc/howto/local_network.md
+++ b/doc/howto/local_network.md
@@ -6,12 +6,12 @@ application then run:
 
 ```
 echo 0.0.0.0 > host
-./run
+gdk run
 ```
 
 If you would like to revert back to the `localhost` network then run:
 
 ```
 rm host
-./run
+gdk run
 ```
diff --git a/doc/howto/performance_metrics.md b/doc/howto/performance_metrics.md
index 1612a2b32c696ab8958787b6e43a5f45d8885a4b..bce054264ddd3fe9d3b5a8913399779a1973aa9f 100644
--- a/doc/howto/performance_metrics.md
+++ b/doc/howto/performance_metrics.md
@@ -10,7 +10,7 @@ Golang compiler and NPM installed. InfluxDB and Grafana consume about
 You need to have a working GDK installation before you install InfluxDB
 and Grafana.
 
-First make sure you do not have `./run` active anywhere. Then run:
+First make sure you do not have `gdk run` active anywhere. Then run:
 
     rm Procfile
     make performance-metrics-setup
diff --git a/doc/howto/pry.md b/doc/howto/pry.md
index 5d7500f0a425ac45d49ed61474c214a4f2b853a3..38b1fb4b8cd0b8180bb779e74f883257aee80784 100644
--- a/doc/howto/pry.md
+++ b/doc/howto/pry.md
@@ -12,6 +12,6 @@ development server (localhost:3000) you need to comment out the
 `rails-web:` line in the Procfile in your GDK root directory because
 Unicorn is not compatible with Pry.
 
-Then launch GDK as usual (e.g. with `./run`) and in a separate
-terminal run: `./run thin`. Your Pry prompts will appear in the window
+Then launch GDK as usual (e.g. with `gdk run`) and in a separate
+terminal run: `gdk run thin`. Your Pry prompts will appear in the window
 that runs Thin.
diff --git a/doc/set-up-gdk.md b/doc/set-up-gdk.md
index e5bee872eb8c7e466511a7ff80bd618f166d1e2f..058131546ec6487bca34b2e30e1750ff4a61523b 100644
--- a/doc/set-up-gdk.md
+++ b/doc/set-up-gdk.md
@@ -8,11 +8,12 @@ contain 'problematic' characters such as ` ` and `(`. For example,
 cause problems.
 
 ```
-git clone https://gitlab.com/gitlab-org/gitlab-development-kit.git
+gem install gitlab-development-kit
+gdk init
 cd gitlab-development-kit
 ```
 
-The `Makefile` will clone the repositories, install the Gem bundles and set up
+The `gdk install` command will clone the repositories, install the Gem bundles and set up
 basic configuration files. Pick one:
 
 ## Develop in a fork
@@ -20,19 +21,19 @@ basic configuration files. Pick one:
 ```
 # Set up GDK with 'origin' pointing to your gitlab-ce fork.
 # Replace MY-FORK with your namespace
-make gitlab_repo=https://gitlab.com/MY-FORK/gitlab-ce.git
+gdk install gitlab_repo=https://gitlab.com/MY-FORK/gitlab-ce.git
 support/set-gitlab-upstream
 ```
 
 The set-gitlab-upstream script creates a remote named `upstream` for
 [the canonical GitLab CE
 repository](https://gitlab.com/gitlab-org/gitlab-ce). It also modifies
-`make update` (See [Update gitlab and gitlab-shell
+`gdk update` (See [Update gitlab and gitlab-shell
 repositories](Update gitlab and gitlab-shell repositories)) to pull
 down from the upstream repository instead of your fork, making it
 easier to keep up-to-date with the project.
 
-If you want to push changes from upstream to your fork, run `make
+If you want to push changes from upstream to your fork, run `gdk
 update` and then `git push origin` from the `gitlab` directory.
 
 ## Develop in the main repo
@@ -41,7 +42,7 @@ Alternatively, you can clone all components from their official source.
 
 ```
 # Clone your own forked repositories
-make
+gdk install
 ```
 
 
@@ -56,13 +57,14 @@ instead of 3000 so that you can run GDK EE next to CE without port
 conflicts.
 
 ```
-git clone https://gitlab.com/gitlab-org/gitlab-development-kit.git gdk-ee
+gem install gdk
+gdk init gdk-ee
 cd gdk-ee
 echo 3001 > port
-make gitlab_repo=https://gitlab.com/gitlab-org/gitlab-ee.git
+gdk install gitlab_repo=https://gitlab.com/gitlab-org/gitlab-ee.git
 ```
 
-Now you can start GitLab EE with `./run` in the `gdk-ee` directory and you
+Now you can start GitLab EE with `gdk run` in the `gdk-ee` directory and you
 will not have port conflicts with a separate GDK instance for CE that
 might still be running.
 
@@ -73,15 +75,15 @@ onboarding document: https://about.gitlab.com/handbook/developer-onboarding/#git
 
 Start GitLab and all required services:
 
-    ./run
+    gdk run
 
 To start only the databases use:
 
-    ./run db
+    gdk run db
 
 To start only the app (assuming the DBs are already running):
 
-    ./run app
+    gdk run app
 
 To access GitLab you may now go to http://localhost:3000 in your
 browser. The development login credentials are `root` and `5iveL!fe`.
diff --git a/gitlab-development-kit.gemspec b/gitlab-development-kit.gemspec
new file mode 100644
index 0000000000000000000000000000000000000000..8a551970a27f8b3c7652b05c407992ab095a80ad
--- /dev/null
+++ b/gitlab-development-kit.gemspec
@@ -0,0 +1,15 @@
+# coding: utf-8
+
+Gem::Specification.new do |spec|
+  spec.name          = "gitlab-development-kit"
+  spec.version       = '0.1.1'
+  spec.authors       = ["Jacob Vosmaer"]
+  spec.email         = ["jacob@gitlab.com"]
+
+  spec.summary       = %q{CLI for GitLab Development Kit}
+  spec.description   = %q{CLI for GitLab Development Kit.}
+  spec.homepage      = "https://gitlab.com/gitlab-org/gitlab-development-kit"
+  spec.license       = "MIT"
+  spec.files         = []
+  spec.executables   = ['gdk']
+end
diff --git a/lib/gdk.rb b/lib/gdk.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e17811def2777d69b3eafe6f2a2b8a63f54027ad
--- /dev/null
+++ b/lib/gdk.rb
@@ -0,0 +1,26 @@
+# GitLab Development Kit CLI parser / executor
+
+module GDK
+  PROGNAME = 'gdk'
+
+  # This function is called from bin/gdk. It must return true/false or
+  # an exit code.
+  def self.main
+    case ARGV.shift
+    when 'run'
+      system('./run', *ARGV, chdir: $gdk_root)
+    when 'install'
+      system('make', *ARGV, chdir: $gdk_root)
+    when 'update'
+      system('make', 'update', chdir: $gdk_root)
+    when 'reconfigure'
+      system('make', 'clean-config', 'all', chdir: $gdk_root)
+    when 'help'
+      puts File.read(File.join($gdk_root, 'HELP'))
+      true
+    else
+      puts "Usage: #{PROGNAME} run|init|install|update|reconfigure|help [ARGS...]"
+      false
+    end
+  end
+end