diff --git a/.gitignore b/.gitignore
index e565c05a4c6ededbee159a2b347f8519ec475d33..16599c654725a87c9f6418a8115d81db1ad60454 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 *.log
 *.pid
 /install
+.DS_Store
diff --git a/README.md b/README.md
index b945d5c4364734aa0c6e60c2f2d633c707dbf9b5..0a736b6ddfb4f79ed23ebc50793f8aa48685f26a 100644
--- a/README.md
+++ b/README.md
@@ -6,25 +6,21 @@ Fixes <https://tuleap.ring.cx/plugins/tracker/?aid=250>.
 
 I'd rather have a single Git repo, but without official support, maintaining a merged single git repo is useless, so I'll start with submodules which are easier to paste together.
 
-## Ubuntu 15.10
+## Using make-ring.py
 
 Build and install locally under this repository:
 
-    ./ubuntu-15.10-install.sh
+    ./make-ring.py --install
 
-Run daemon and client that were installed locally on the background:
+Run daemon and client that were installed locally.
 
-    ./ubuntu-15.10-run.sh
+    ./make-ring.py --run
 
-Stdout and stderr go to `daemon.log` and `client-gnome.log`.
-
-Stop daemon and client:
-
-    ./ubuntu-15.10-stop.sh
+You can then stop the processes with CTRL-C. You can also run them in the background with the `--background` argument and then use the `--stop` command to stop them. Stdout and stderr go to `daemon.log` and `client-gnome.log`.
 
 Install globally for all users instead:
 
-    ./ubuntu-15.10-install.sh -g
+    ./make-ring.py --install --global-install
 
 Run global install:
 
@@ -34,7 +30,7 @@ This already starts the daemon automatically for us.
 
 Uninstall the global install:
 
-    ./ubuntu-15.10-uninstall.sh
+    ./make-ring.py --uninstall
 
 ## Ubuntu 15.10 host Android device
 
@@ -48,4 +44,4 @@ All executables used must be in your `PATH`, e.g. `adb`.
 
 Then build and install on all connected devices with:
 
-    ./ubuntu-15.10-android-install-all-devices.sh
+    ./scripts/ubuntu-15.10-android-install-all-devices.sh
diff --git a/make-ring.py b/make-ring.py
new file mode 100755
index 0000000000000000000000000000000000000000..98952a0e206ca9cfd8cb6b4fe85cfdc2baba0062
--- /dev/null
+++ b/make-ring.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python3
+#
+# This is the Ring build helper, it can do these things:
+#  - Build Ring
+#  - Install Ring
+#  - Run Ring
+#
+
+import argparse
+import os
+import subprocess
+import sys
+import time
+
+DEBIAN_BASED_DISTROS = [
+    'Debian',
+    'Ubuntu',
+]
+
+APT_INSTALL_SCRIPT = [
+    'apt-get update',
+    'apt-get install -y %(packages)s'
+]
+
+UBUNTU_DEPENDENCIES = [
+    'autoconf', 'autopoint', 'cmake', 'dbus', 'doxygen', 'g++', 'gettext',
+    'gnome-icon-theme-symbolic', 'libasound2-dev', 'libavcodec-dev',
+    'libavcodec-extra', 'libavdevice-dev', 'libavformat-dev', 'libboost-dev',
+    'libclutter-gtk-1.0-dev', 'libcppunit-dev', 'libdbus-1-dev',
+    'libdbus-c++-dev', 'libebook1.2-dev', 'libexpat1-dev', 'libgnutls-dev',
+    'libgsm1-dev', 'libgtk-3-dev', 'libjack-dev', 'libnotify-dev',
+    'libopus-dev', 'libpcre3-dev', 'libpulse-dev', 'libsamplerate0-dev',
+    'libsndfile1-dev', 'libspeex-dev', 'libspeexdsp-dev', 'libsrtp-dev',
+    'libswscale-dev', 'libtool', 'libudev-dev', 'libupnp-dev',
+    'libyaml-cpp-dev', 'openjdk-7-jdk', 'qtbase5-dev', 'sip-tester', 'swig',
+    'uuid-dev', 'yasm'
+]
+
+
+DEBIAN_DEPENDENCIES = [
+    'autoconf', 'autopoint', 'cmake', 'dbus', 'doxygen', 'g++', 'gettext',
+    'gnome-icon-theme-symbolic', 'libasound2-dev', 'libavcodec-dev',
+    'libavcodec-extra', 'libavdevice-dev', 'libavformat-dev', 'libboost-dev',
+    'libclutter-gtk-1.0-dev', 'libcppunit-dev', 'libdbus-1-dev',
+    'libdbus-c++-dev', 'libebook1.2-dev', 'libexpat1-dev', 'libgsm1-dev',
+    'libgtk-3-dev', 'libjack-dev', 'libnotify-dev', 'libopus-dev',
+    'libpcre3-dev', 'libpulse-dev', 'libsamplerate0-dev', 'libsndfile1-dev',
+    'libspeex-dev', 'libspeexdsp-dev', 'libswscale-dev', 'libtool',
+    'libudev-dev', 'libupnp-dev', 'libyaml-cpp-dev', 'openjdk-7-jdk',
+    'qtbase5-dev', 'sip-tester', 'swig',  'uuid-dev', 'yasm'
+]
+
+UNINSTALL_SCRIPT = [
+    'make -C daemon uninstall',
+    'xargs rm < lrc/build-global/install_manifest.txt',
+    'xargs rm < client-gnome/build-global/install_manifest.txt',
+]
+
+STOP_SCRIPT = [
+    'xargs kill < daemon.pid',
+    'xargs kill < gnome-ring.pid',
+]
+
+
+def run_dependencies(args):
+    if args.distribution == "Ubuntu":
+        execute_script(APT_INSTALL_SCRIPT,
+            {"packages": ' '.join(UBUNTU_DEPENDENCIES)}
+        )
+
+    elif args.distribution == "Debian":
+        execute_script(
+            APT_INSTALL_SCRIPT,
+            {"packages": ' '.join(DEBIAN_DEPENDENCIES)}
+        )
+
+    else:
+        print("Not yet implemented for current distribution (%s)" % args.distribution)
+        sys.exit(1)
+
+
+def run_install(args):
+    install_args = ''
+    if args.static:
+        install_args += ' -s'
+    if args.global_install:
+        install_args += ' -g'
+    execute_script(["./scripts/install.sh " + install_args])
+
+
+def run_uninstall(args):
+    execute_script(UNINSTALL_SCRIPT)
+
+
+def run_run(args):
+    run_env = os.environ
+    run_env['LD_LIBRARY_PATH'] = run_env.get('LD_LIBRARY_PATH', '') + ":install/lrc/lib"
+
+    try:
+        dring_log = open("daemon.log", 'a')
+        dring_log.write('=== Starting daemon (%s) ===' % time.strftime("%d/%m/%Y %H:%M:%S"))
+        dring_process = subprocess.Popen(
+            ["./install/daemon/libexec/dring", "-c", "-d"],
+            stdout=dring_log,
+            stderr=dring_log
+        )
+
+        with open('daemon.pid', 'w') as f:
+            f.write(str(dring_process.pid)+'\n')
+
+        client_log = open("gnome-ring.log", 'a')
+        client_log.write('=== Starting client (%s) ===' % time.strftime("%d/%m/%Y %H:%M:%S"))
+        client_process = subprocess.Popen(
+            ["./install/client-gnome/bin/gnome-ring", "-d"],
+            stdout=client_log,
+            stderr=client_log,
+            env=run_env
+        )
+
+        with open('gnome-ring.pid', 'w') as f:
+            f.write(str(client_process.pid)+'\n')
+
+        if args.debug:
+            subprocess.call(
+                ['gdb','-x', 'gdb.gdb', './install/daemon/libexec/dring'],
+            )
+
+        if args.background == False:
+            dring_process.wait()
+            client_process.wait()
+
+    except KeyboardInterrupt:
+        print("\nCaught KeyboardInterrupt...")
+
+    finally:
+        if args.background == False:
+            try:
+                # Only kill the processes if they are running, as they could
+                # have been closed by the user.
+                print("Killing processes...")
+                dring_log.close()
+                if dring_process.poll() is None:
+                    dring_process.kill()
+                client_log.close()
+                if client_process.poll() is None:
+                    client_process.kill()
+            except UnboundLocalError:
+                # Its okay! We crashed before we could start a process or open a
+                # file. All that matters is that we close files and kill processes
+                # in the right order.
+                pass
+
+
+def run_stop(args):
+    execute_script(STOP_SCRIPT)
+
+
+def execute_script(script, settings=None):
+    if settings == None:
+        settings = {}
+    for line in script:
+        line = line % settings
+        rv = os.system(line)
+        if rv != 0:
+            print('Error executing script! Exit code: %s' % rv,
+                  file=sys.stderr)
+            return False
+    return True
+
+
+def validate_args(parsed_args):
+    """Validate the args values, exit if error is found"""
+
+    # Check arg values
+    supported_distros = ['Ubuntu', 'Debian']
+    if parsed_args.distribution not in supported_distros:
+        print('Distribution not supported.\nChoose one of: %s' \
+                  % ', '.join(supported_distros),
+            file=sys.stderr)
+        sys.exit(1)
+
+
+def parse_args():
+    ap = argparse.ArgumentParser(description="Ring build tool")
+
+    ga = ap.add_mutually_exclusive_group(required=True)
+    ga.add_argument(
+        '--dependencies', action='store_true',
+        help='Install ring build dependencies')
+    ga.add_argument(
+        '--install', action='store_true',
+        help='Build and install Ring')
+    ga.add_argument(
+        '--uninstall', action='store_true',
+        help='Uninstall Ring')
+    ga.add_argument(
+        '--run', action='store_true',
+         help='Run the Ring daemon and client')
+    ga.add_argument(
+        '--stop', action='store_true',
+        help='Stop the Ring processes')
+
+    ap.add_argument('--distribution', default='Ubuntu')
+    ap.add_argument('--static', default=False, action='store_true')
+    ap.add_argument('--global-install', default=False, action='store_true')
+    ap.add_argument('--debug', default=False, action='store_true')
+    ap.add_argument('--background', default=False, action='store_true')
+
+    parsed_args = ap.parse_args()
+    validate_args(parsed_args)
+
+    return parsed_args
+
+
+def main():
+    parsed_args = parse_args()
+
+    if parsed_args.dependencies:
+        run_dependencies(parsed_args)
+
+    elif parsed_args.install:
+        run_install(parsed_args)
+
+    elif parsed_args.uninstall:
+        run_uninstall(parsed_args)
+
+    elif parsed_args.run:
+        run_run(parsed_args)
+
+    elif parsed_args.stop:
+        run_stop(parsed_args)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/ubuntu-15.10-install.sh b/scripts/install.sh
similarity index 89%
rename from ubuntu-15.10-install.sh
rename to scripts/install.sh
index 2c6c7e8c05a112ec9ae7b6df3cad51b07333054d..258dd7d7b32bb5f588fe0001cb85185a3d5504b0 100755
--- a/ubuntu-15.10-install.sh
+++ b/scripts/install.sh
@@ -36,12 +36,16 @@ make_install() {
   fi
 }
 
-./ubuntu-15.10-dependencies.sh
-
 TOP="$(pwd)"
 INSTALL="${TOP}/install"
 
-cd daemon
+if $global; then
+    BUILDDIR="build-global"
+else
+    BUILDDIR="build-local"
+fi
+
+cd "${TOP}/daemon"
 DAEMON="$(pwd)"
 cd contrib
 mkdir -p native
@@ -59,8 +63,8 @@ make -j$(nproc)
 make_install $global
 
 cd "${TOP}/lrc"
-mkdir -p build
-cd build
+mkdir -p ${BUILDDIR}
+cd ${BUILDDIR}
 if $global; then
   cmake .. -DCMAKE_BUILD_TYPE=Debug $static
 else
@@ -70,8 +74,8 @@ make
 make_install $global
 
 cd "${TOP}/client-gnome"
-mkdir -p build
-cd build
+mkdir -p ${BUILDDIR}
+cd ${BUILDDIR}
 if $global; then
   cmake .. $static
 else
diff --git a/ubuntu-15.10-android-install-all-devices.sh b/scripts/ubuntu-15.10-android-install-all-devices.sh
similarity index 100%
rename from ubuntu-15.10-android-install-all-devices.sh
rename to scripts/ubuntu-15.10-android-install-all-devices.sh
diff --git a/ubuntu-15.10-dependencies.sh b/ubuntu-15.10-dependencies.sh
deleted file mode 100755
index 1bf18f3f1859342fed57eed0140223e4eac13063..0000000000000000000000000000000000000000
--- a/ubuntu-15.10-dependencies.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env bash
-
-# All dependencies and development dependencies for all repositories.
-
-sudo apt-get install \
-    autoconf \
-    automake \
-    autopoint \
-    cmake \
-    dbus \
-    doxygen \
-    g++ \
-    gettext \
-    gnome-icon-theme-symbolic \
-    libasound2-dev \
-    libavcodec-dev \
-    libavcodec-extra \
-    libavdevice-dev \
-    libavformat-dev \
-    libboost-dev \
-    libclutter-gtk-1.0-dev \
-    libcppunit-dev \
-    libdbus-1-dev \
-    libdbus-c++-dev \
-    libebook1.2-dev \
-    libexpat1-dev \
-    libgnutls-dev \
-    libgsm1-dev \
-    libgtk-3-dev \
-    libjack-dev \
-    libnotify-dev \
-    libopus-dev \
-    libpcre3-dev \
-    libpulse-dev \
-    libsamplerate0-dev \
-    libsndfile1-dev \
-    libspeex-dev \
-    libspeexdsp-dev \
-    libsrtp-dev \
-    libswscale-dev \
-    libtool \
-    libudev-dev \
-    libupnp-dev \
-    libyaml-cpp-dev \
-    openjdk-7-jdk \
-    qtbase5-dev \
-    sip-tester \
-    swig \
-    uuid-dev \
-    yasm
diff --git a/ubuntu-15.10-run.sh b/ubuntu-15.10-run.sh
deleted file mode 100755
index 04a303324b7f58005259b02ad12214b9de7ec0f8..0000000000000000000000000000000000000000
--- a/ubuntu-15.10-run.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-# Run local install daemon and client that have
-# been installed with the install script on the background.
-cd "$(dirname "${BASH_SOURCE[0]}")"
-./install/daemon/libexec/dring -c -d >>daemon.log 2>&1 &
-echo $! >daemon.pid
-LD_LIBRARY_PATH="$LD_LIBRARY_PATH:install/lrc/lib" ./install/client-gnome/bin/gnome-ring -d >>client-gnome.log 2>&1 &
-echo $! >client-gnome.pid
diff --git a/ubuntu-15.10-stop.sh b/ubuntu-15.10-stop.sh
deleted file mode 100755
index 688794e9386596901177a79a4e840f5c7f7fdf12..0000000000000000000000000000000000000000
--- a/ubuntu-15.10-stop.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-# Stop local install daemon and client that have been installed with the install script.
-cd "$(dirname "${BASH_SOURCE[0]}")"
-kill "$(cat client-gnome.pid)"
-kill "$(cat daemon.pid)"
diff --git a/ubuntu-15.10-uninstall.sh b/ubuntu-15.10-uninstall.sh
deleted file mode 100755
index 6a87cc288182735d19179c4d5f4b137940b9f1a9..0000000000000000000000000000000000000000
--- a/ubuntu-15.10-uninstall.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-# Uninstall a global install.
-sudo make -C daemon uninstall
-sudo xargs rm < lrc/build/install_manifest.txt
-sudo xargs rm < client-gnome/build/install_manifest.txt