diff --git a/ansible-script.py b/ansible-script.py
index c8915b714abadc9d945c94e29de02685064fe009..c1e5d3c3ac7eb866884af80ceec822191a6f67f3 100755
--- a/ansible-script.py
+++ b/ansible-script.py
@@ -11,19 +11,24 @@ to be executed as the first argument.
 import argparse
 import sys
 import os
-import importlib
+import yaml
 from tabulate import tabulate
 from lib import general
 
+path = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + 'scripts' + os.path.sep
+
 
 def list():
     scripts = []
-    for file in sorted(os.listdir(os.path.dirname(os.path.realpath(__file__)) + os.path.sep + 'scripts')):
-        if file != '__init__.py' and '.pyc' not in file:
-            scriptname = file.split('.')[0]
-            script = importlib.import_module('.' + scriptname, package='scripts')
-            scripts.append([scriptname, script.__doc__.splitlines()[0]])
-
+    for file in sorted(os.listdir(path)):
+        name, ext = os.path.splitext(file)
+        if ext == '.yml':
+            with open(path + file, 'r') as config:
+                try:
+                    script = yaml.load(config)
+                    scripts.append([name, script['description']])
+                except yaml.YAMLError:
+                    pass
     print(tabulate(scripts, headers=['Script', 'Description']))
     exit(0)
 
@@ -40,12 +45,12 @@ def script():
     if arg == 'list':
         list()
 
-    try:
-        script = importlib.import_module('.' + arg, package='scripts')
-    except Exception:
-        raise Exception('Script %s does not exist.' % (arg))
-
-    return script
+    with open(path + arg + '.yml', 'r') as config:
+        try:
+            return yaml.load(config)
+        except Exception:
+            pass
+    raise Exception('Script %s does not exist.' % (arg))
 
 
 parser = argparse.ArgumentParser(description='Ansible script by Paragon',
diff --git a/lib/general.py b/lib/general.py
index 88fc7d2cb82d681c412aefbba06cf137631adb5b..58eeda63a50e462f21652fb85884134a12de42b4 100644
--- a/lib/general.py
+++ b/lib/general.py
@@ -4,6 +4,7 @@ import yaml
 import uservars
 import threading
 import Queue
+import types
 import window
 from subprocess import Popen, PIPE, STDOUT
 
@@ -25,16 +26,24 @@ def run(parser, script=None):
                             help='Disable GUI')
     if not os.path.exists(path + 'inventory/group_vars'):
         parser.add_argument('--company', default=os.environ.get('ANSIBLE_COMPANY', None),
-                            required=(not isGitlabUser(env)),
+                            required=companyRequired(env),
                             help='Only useful if inventories from multiple companies are installed')
         parser.add_argument('--include-local', action='store_true', default=False,
                             help='If company=all, this would also include the local inventory, default to False')
 
     if script:
-        parser.description = script.__doc__
+        parser.description = script['description']
         parser.add_argument('--custom', action='store_true', default=False,
                             help='Only run a custom playbook and ignore the global one')
-        script.extend(parser)
+        if 'cli' in script:
+            for type in ['arguments', 'options']:
+                prefix = '--' if type == 'options' else ''
+                if type in script['cli']:
+                    for item in script['cli'][type]:
+                        parser.add_argument(prefix + item, **script['cli'][type][item])
+            if 'defaults' in script['cli']:
+                for item in script['cli']['defaults']:
+                    parser.set_defaults(**{item: script['cli']['defaults'][item]})
 
     args, extras = parser.parse_known_args()
 
@@ -42,7 +51,12 @@ def run(parser, script=None):
         window.guiAvailable = False
 
     if script:
-        script.append(args)
+        if 'arguments' in script:
+            for item in script['arguments']:
+                value = script['arguments'][item]
+                if not isinstance(value, types.StringTypes):
+                    value = ','.join(value)
+                setattr(args, item, value)
 
     if 'playbook' in args and 'limit' in args:
         extras.append('--limit=' + args.limit)
@@ -110,8 +124,8 @@ def followUp(script, args):
     if error_seen:
         exit(1)
 
-    if script and hasattr(script, 'follower'):
-        cmd = ['ascr', script.follower(), '--limit=' + args.limit]
+    if 'follower' in script:
+        cmd = ['ascr', script['follower'], '--limit=' + args.limit]
         if hasattr(args, 'company'):
             cmd.append('--company=' + args.company)
         if not window.guiAvailable:
@@ -144,6 +158,12 @@ def startThreads(company, args, files, path, extras, pathSecrets, script):
             thread.join()
 
 
+def companyRequired(env):
+    if 'ANSIBLE_COMPANY' in env:
+        return False
+    return not isGitlabUser(env)
+
+
 def isGitlabUser(env):
     return ('USER' in env and env['USER'] == 'gitlab-runner')
 
@@ -209,7 +229,21 @@ def main(args, extras, path, pathSecrets, company = None, script = None):
     cmd.append('--extra-vars={excluded_roles: ' + json.dumps(excluded_roles) + '}')
 
     if script:
-        script.build(cmd, args)
+        if 'command' in script:
+            for item in script['command']:
+                condition = True
+                if 'condition' in item:
+                    condition = bool(getattr(args, item['condition']))
+                if condition:
+                    value = item['value']
+                    if not isinstance(value, types.StringTypes):
+                        value = ','.join(value)
+                    if 'args' in item:
+                        commandargs = []
+                        for commandarg in item['args']:
+                            commandargs.append(getattr(args, commandarg))
+                        value = value % tuple(commandargs)
+                    cmd.append('--' + item['name'] + '=' + value)
 
     # Append more CLI options
     for extra in extras:
diff --git a/scripts/__init__.py b/scripts/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/scripts/apache-config.yml b/scripts/apache-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b5be99d2fad6dd3450ab33181bc07708d737acb2
--- /dev/null
+++ b/scripts/apache-config.yml
@@ -0,0 +1,22 @@
+description: 'Quickly configure Apache'
+cli:
+  options:
+    application:
+      default: 'apache'
+      help: 'The application to configure Apache for, e.g. apache, drupal, piwk, nextcloud'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'commonauth'
+    - 'commonconnect'
+    - 'common'
+    - 'php'
+    - 'jailkit'
+command:
+  - name: 'tags'
+    value: 'ApacheConfig'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=%s'
+    args:
+      - 'limit'
+      - 'application'
diff --git a/scripts/apacheconfig.py b/scripts/apacheconfig.py
deleted file mode 100755
index aed02752c49b854f7c529dfe71d66ee145f25710..0000000000000000000000000000000000000000
--- a/scripts/apacheconfig.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Quickly configure Apache"""
-
-def extend(parser):
-    parser.add_argument('--application', default='apache',
-                        help='The application to configure Apache for, e.g. apache, drupal, piwk, nextcloud')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'commonauth,commonconnect,common,php,jailkit'
-
-
-def build(cmd, args):
-    cmd.append('--tags=ApacheConfig')
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=' + args.application)
diff --git a/scripts/bigfiles.py b/scripts/bigfiles.py
deleted file mode 100755
index 7da93e7beb3eebb8b228aec9c3968c8da6f1eb38..0000000000000000000000000000000000000000
--- a/scripts/bigfiles.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Find big files / directories"""
-
-def extend(parser):
-    parser.add_argument('--depth', default=5,
-                        help='How many directories deep this should parse')
-    parser.add_argument('--threshold', default='1G',
-                        help='Only show directories bigger than this')
-
-
-def append(args):
-    pass
-
-
-def build(cmd, args):
-    cmd.append('-m')
-    cmd.append('command')
-    cmd.append('-a')
-    cmd.append('du -xchd ' + str(args.depth) + ' --threshold=' + args.threshold + ' /')
diff --git a/scripts/bigfiles.yml b/scripts/bigfiles.yml
new file mode 100644
index 0000000000000000000000000000000000000000..68b8886fdd5ee8a6a48dadb2d8d1acfcfd5f8011
--- /dev/null
+++ b/scripts/bigfiles.yml
@@ -0,0 +1,17 @@
+description: 'Find big files / directories'
+cli:
+  options:
+    depth:
+      default: 5
+      help: 'How many directories deep this should parse'
+    threshold:
+      default: '1G'
+      help: 'Only show directories bigger than this'
+command:
+  - name: 'module-name'
+    value: 'command'
+  - name: 'args'
+    value: 'du -xchd %s --threshold=%s /'
+    args:
+      - 'depth'
+      - 'threshold'
diff --git a/scripts/composer-update.py b/scripts/composer-update.py
deleted file mode 100755
index 2f676b946b72ca009dbca31116e6bb6326f3499b..0000000000000000000000000000000000000000
--- a/scripts/composer-update.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""Update Composer itself and global packages"""
-
-def extend(parser):
-    parser.set_defaults(limit='webserver')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=composer')
-    cmd.append('--tags=update')
-
-def follower():
-    return 'jailkitupgrade'
diff --git a/scripts/composer-update.yml b/scripts/composer-update.yml
new file mode 100644
index 0000000000000000000000000000000000000000..501c6eaf178ce8d434707c4a1e1eb91cf1661de6
--- /dev/null
+++ b/scripts/composer-update.yml
@@ -0,0 +1,14 @@
+description: 'Update Composer itself and global packages'
+cli:
+  defaults:
+    limit: 'webserver'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=composer'
+    args:
+      - 'limit'
+  - name: 'tags'
+    value: 'update'
+follower: 'jailkitupgrade'
diff --git a/scripts/connectivity.py b/scripts/connectivity.py
deleted file mode 100755
index fe004e87f5ed9c2280cb5952d0220fbd2279aea6..0000000000000000000000000000000000000000
--- a/scripts/connectivity.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Update hosts and ssh config"""
-
-def extend(parser):
-    parser.set_defaults(limit='all')
-    parser.set_defaults(include_local=True)
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=commonconnect')
diff --git a/scripts/connectivity.yml b/scripts/connectivity.yml
new file mode 100644
index 0000000000000000000000000000000000000000..30284ec064e82824236fef49e71c1df0a33c3611
--- /dev/null
+++ b/scripts/connectivity.yml
@@ -0,0 +1,12 @@
+description: 'Update hosts and ssh config'
+cli:
+  defaults:
+    limit: 'all'
+    include_local: True
+arguments:
+  playbook: 'role'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=commonconnect'
+    args:
+      - 'limit'
diff --git a/scripts/cronjobs.py b/scripts/cronjobs.py
deleted file mode 100755
index 8c6aa00935ae3cea603557271de74a9962b6fd64..0000000000000000000000000000000000000000
--- a/scripts/cronjobs.py
+++ /dev/null
@@ -1,12 +0,0 @@
-"""Update Cron Jobs"""
-
-def extend(parser):
-    pass
-
-
-def append(args):
-    args.playbook = 'farm'
-
-
-def build(cmd, args):
-    cmd.append('--tags=cron')
diff --git a/scripts/cronjobs.yml b/scripts/cronjobs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..93d7973bf608b711c5c00caba1c66078b7a4cbe0
--- /dev/null
+++ b/scripts/cronjobs.yml
@@ -0,0 +1,6 @@
+description: 'Update Cron Jobs'
+arguments:
+  playbook: 'farm'
+command:
+  - name: 'tags'
+    value: 'cron'
diff --git a/scripts/drupal-config.yml b/scripts/drupal-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8f180637f4ca0ba0b1df24fadc8d9dcdb6f8e911
--- /dev/null
+++ b/scripts/drupal-config.yml
@@ -0,0 +1,33 @@
+description: 'Quickly configure Drupal sites'
+cli:
+  options:
+    site:
+      default: None
+      help: 'The id of a site if only one of the defined sites should be updated'
+    quick:
+      action: 'store_true'
+      default: False
+      help: 'Only Drupal itself, not the CLI or JailKit'
+  defaults:
+    limit: 'webserver-drupal'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'commonauth'
+    - 'commonconnect'
+    - 'common'
+    - 'php'
+    - 'apache'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=drupal'
+    args:
+      - 'limit'
+  - name: 'extra-vars'
+    condition: 'site'
+    value: 'limit_drupal_site=%s'
+    args:
+      - 'site'
+  - name: 'start-at-task'
+    condition: 'quick'
+    value: 'Drupal Role'
diff --git a/scripts/drupal-deploy.yml b/scripts/drupal-deploy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..51a93092388d3294ac5127841bfe6a6d6840d3bc
--- /dev/null
+++ b/scripts/drupal-deploy.yml
@@ -0,0 +1,31 @@
+description: 'Quickly re-deploy a Drupal site'
+cli:
+  arguments:
+    host:
+      default: None
+      help: 'The hostname on which to re-reploy Drupal'
+    site:
+      default: None
+      help: 'The id of a site'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'commonauth'
+    - 'commonconnect'
+    - 'common'
+    - 'php'
+    - 'apache'
+    - 'jailkit'
+command:
+  - name: 'tags'
+    value: 'deploy'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=drupal'
+    args:
+      - 'host'
+  - name: 'extra-vars'
+    value: 'limit_drupal_site=%s'
+    args:
+      - 'site'
+  - name: 'start-at-task'
+    value: 'Install Drupal'
diff --git a/scripts/drupal.py b/scripts/drupal.py
deleted file mode 100755
index 7e861b90fcbef30f0113987c5b8c5fff5a7ab6f2..0000000000000000000000000000000000000000
--- a/scripts/drupal.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""Quickly configure Drupal sites"""
-
-def extend(parser):
-    parser.add_argument('--site', default=None,
-                        help='The id of a site if only one of the defined sites should be updated')
-    parser.add_argument('--quick', action='store_true', default=False,
-                        help='Only Drupal itself, not the CLI or JailKit')
-    parser.set_defaults(limit='webserver-drupal')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'commonauth,commonconnect,common,php,apache'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=drupal')
-    if args.site:
-        cmd.append('--extra-vars=limit_drupal_site=' + args.site)
-    if args.quick:
-        cmd.append('--start-at-task=Drupal Role')
diff --git a/scripts/drupaldeploy.py b/scripts/drupaldeploy.py
deleted file mode 100755
index 12536b4b5e628abe5d6b251c8d3a27559d9d096f..0000000000000000000000000000000000000000
--- a/scripts/drupaldeploy.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""Quickly re-deploy a Drupal site"""
-
-def extend(parser):
-    parser.add_argument('host', default=None,
-                        help='The hostname on which to re-reploy Drupal')
-    parser.add_argument('site', default=None,
-                        help='The id of a site')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'commonauth,commonconnect,common,php,apache,jailkit'
-
-
-def build(cmd, args):
-    cmd.append('--tags=deploy')
-    cmd.append('--extra-vars=hosts=' + args.host + ' role=drupal')
-    cmd.append('--extra-vars=limit_drupal_site=' + args.site)
-    cmd.append('--start-at-task=Install Drupal')
diff --git a/scripts/drush-aliases.yml b/scripts/drush-aliases.yml
new file mode 100644
index 0000000000000000000000000000000000000000..74ccea8dd6bee5bd64b321fdf2e0ed1bf7bafe5d
--- /dev/null
+++ b/scripts/drush-aliases.yml
@@ -0,0 +1,13 @@
+description: 'Retrieve and adjust Drush aliases from remote host(s)'
+cli:
+  defaults:
+    limit: 'webserver-drupal'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'tags'
+    value: 'DrushUpdateAliases'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=drush'
+    args:
+      - 'limit'
diff --git a/scripts/elastalert.py b/scripts/elastalert.py
deleted file mode 100755
index 0365a84f87391bf46528bc5349c58fa739af0a07..0000000000000000000000000000000000000000
--- a/scripts/elastalert.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Update rules on ElastAlert hosts"""
-
-def extend(parser):
-    parser.set_defaults(limit='logserver')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--tags=Rules')
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=elasticsearch')
diff --git a/scripts/elastalert.yml b/scripts/elastalert.yml
new file mode 100644
index 0000000000000000000000000000000000000000..186356206012f2205f65e426ba38794eb1a79178
--- /dev/null
+++ b/scripts/elastalert.yml
@@ -0,0 +1,13 @@
+description: 'Update rules on ElastAlert hosts'
+cli:
+  defaults:
+    limit: 'logserver'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'tags'
+    value: 'Rules'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=elasticsearch'
+    args:
+      - 'limit'
diff --git a/scripts/firewall-config.py b/scripts/firewall-config.py
deleted file mode 100755
index 056cea96dcf6fd1bbf66e31298dfc447d817b759..0000000000000000000000000000000000000000
--- a/scripts/firewall-config.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Rebuild Firewall Configuration"""
-
-def extend(parser):
-    pass
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'commonauth,commonconnect'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=common')
-    cmd.append('--tags=firewall')
diff --git a/scripts/firewall-config.yml b/scripts/firewall-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bf561eae213a4b840928bcad39f9ddf220fb0632
--- /dev/null
+++ b/scripts/firewall-config.yml
@@ -0,0 +1,13 @@
+description: 'Rebuild Firewall Configuration'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'commonauth'
+    - 'commonconnect'
+command:
+  - name: 'tags'
+    value: 'firewall'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=common'
+    args:
+      - 'limit'
diff --git a/scripts/firewall-unprotect.py b/scripts/firewall-unprotect.py
deleted file mode 100755
index 31bbf1f8fc2036e069c57347f8052b35e9d3af67..0000000000000000000000000000000000000000
--- a/scripts/firewall-unprotect.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Switch Firewall to unprotected mode for a period of time"""
-
-def extend(parser):
-    parser.add_argument('--unprotect-period', default=None,
-                        help='Number of minutes before the firewall goes into protected mode again')
-
-
-def append(args):
-    args.playbook = 'firewall'
-
-
-def build(cmd, args):
-    cmd.append('--tags=unprotect')
-    if args.unprotect_period:
-        cmd.append('--extra-vars=unprotect_period=' + args.unprotect_period)
diff --git a/scripts/firewall-unprotect.yml b/scripts/firewall-unprotect.yml
new file mode 100644
index 0000000000000000000000000000000000000000..895e7eb45b887eb2d92ae1fe8f241c33d0988e32
--- /dev/null
+++ b/scripts/firewall-unprotect.yml
@@ -0,0 +1,16 @@
+description: 'Switch Firewall to unprotected mode for a period of time'
+cli:
+  options:
+    unprotect-period:
+      default: None
+      help: 'Number of minutes before the firewall goes into protected mode again'
+arguments:
+  playbook: 'firewall'
+command:
+  - name: 'tags'
+    value: 'unprotect'
+  - name: 'extra-vars'
+    condition: 'unprotect_period'
+    value: 'unprotect_period=%s'
+    args:
+      - 'unprotect_period'
diff --git a/scripts/getdrushaliases.py b/scripts/getdrushaliases.py
deleted file mode 100755
index 99e958fb4ec9896ed0db51f10a42d9f353382ac9..0000000000000000000000000000000000000000
--- a/scripts/getdrushaliases.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Retrieve and adjust Drush aliases from remote host(s)"""
-
-def extend(parser):
-    parser.set_defaults(limit='webserver-drupal')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--tags=DrushUpdateAliases')
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=drush')
diff --git a/scripts/haproxy-certs.yml b/scripts/haproxy-certs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..42e8a59193e23a331f8a0724eef42f04490f16d2
--- /dev/null
+++ b/scripts/haproxy-certs.yml
@@ -0,0 +1,17 @@
+description: 'Build SSL Certs for HaProxy'
+cli:
+  defaults:
+    limit: 'proxyserver'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'commonauth'
+    - 'commonconnect'
+    - 'common'
+command:
+  - name: 'tags'
+    value: 'Certs'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=haproxy'
+    args:
+      - 'limit'
diff --git a/scripts/haproxy-config.yml b/scripts/haproxy-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ca5ecb676e38dd811e87edcd513b618debd94f80
--- /dev/null
+++ b/scripts/haproxy-config.yml
@@ -0,0 +1,17 @@
+description: 'Quickly configure HaProxy'
+cli:
+  defaults:
+    limit: 'proxyserver'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'commonauth'
+    - 'commonconnect'
+    - 'common'
+command:
+  - name: 'tags'
+    value: 'Config'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=haproxy'
+    args:
+      - 'limit'
diff --git a/scripts/haproxycerts.py b/scripts/haproxycerts.py
deleted file mode 100755
index 5e3d87c39e0fbf78b8377dd8e2d1eb7b7a8b1126..0000000000000000000000000000000000000000
--- a/scripts/haproxycerts.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Build SSL Certs for HaProxy"""
-
-def extend(parser):
-    parser.set_defaults(limit='proxyserver')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'commonauth,commonconnect,common'
-
-
-def build(cmd, args):
-    cmd.append('--tags=Certs')
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=haproxy')
diff --git a/scripts/haproxyconfig.py b/scripts/haproxyconfig.py
deleted file mode 100755
index 75b669100206f557958bedec1ad579b4d5bba2df..0000000000000000000000000000000000000000
--- a/scripts/haproxyconfig.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Quickly configure HaProxy"""
-
-def extend(parser):
-    parser.set_defaults(limit='proxyserver')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'commonauth,commonconnect,common'
-
-
-def build(cmd, args):
-    cmd.append('--tags=Config')
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=haproxy')
diff --git a/scripts/hosts.py b/scripts/hosts.py
deleted file mode 100755
index 1de50d3c86ae17f22f9814f8e4f86b7dc7cfa7c9..0000000000000000000000000000000000000000
--- a/scripts/hosts.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Locally update host information for all inventories"""
-
-def extend(parser):
-    parser.set_defaults(company='all')
-    parser.set_defaults(limit='all')
-
-
-def append(args):
-    args.playbook = 'hosts'
-
-
-def build(cmd, args):
-    pass
diff --git a/scripts/hosts.yml b/scripts/hosts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0fb82e804c5f9ebe464c9ff8142c763c6c758826
--- /dev/null
+++ b/scripts/hosts.yml
@@ -0,0 +1,7 @@
+description: 'Locally update host information for all inventories'
+cli:
+  defaults:
+    company: 'all'
+    limit: 'all'
+arguments:
+  playbook: 'hosts'
diff --git a/scripts/jailkit-update.yml b/scripts/jailkit-update.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fecf1872ac1f8c6567eb152f6b64e2e70c538041
--- /dev/null
+++ b/scripts/jailkit-update.yml
@@ -0,0 +1,22 @@
+description: 'Force updating all Jails'
+cli:
+  options:
+    site:
+      default: None
+      help: 'The id of a site if only one of the defined sites should be updated'
+  defaults:
+    limit: 'webserver-drupal'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=jailkit jailsite_init_force=True'
+    args:
+      - 'limit'
+  - name: 'start-at-task'
+    value: 'JailKit Role'
+  - name: 'extra-vars'
+    condition: 'site'
+    value: 'limit_drupal_site=%s'
+    args:
+      - 'site'
diff --git a/scripts/jailkit-upgrade.yml b/scripts/jailkit-upgrade.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3956aa5c39c25533a8c8cb19dac4bb072130fbf6
--- /dev/null
+++ b/scripts/jailkit-upgrade.yml
@@ -0,0 +1,15 @@
+description: 'Update OS components in all Jails'
+cli:
+  defaults:
+    limit: 'webserver-drupal'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=jailkit'
+    args:
+      - 'limit'
+  - name: 'start-at-task'
+    value: 'JailKit Role'
+  - name: 'tags'
+    value: 'UpdateJails'
diff --git a/scripts/jailkit-user.yml b/scripts/jailkit-user.yml
new file mode 100644
index 0000000000000000000000000000000000000000..42cae502407c97f623efeb7f12e52bea194855a7
--- /dev/null
+++ b/scripts/jailkit-user.yml
@@ -0,0 +1,20 @@
+description: 'Init and update users in Jails'
+cli:
+  options:
+    site:
+      default: None
+      help: 'The id of a site if only one of the defined sites should be updated'
+  defaults:
+    limit: 'webserver-drupal'
+arguments:
+  playbook: 'user'
+command:
+  - name: 'tags'
+    value:
+      - 'JailUserInit'
+      - 'SetPermissions'
+  - name: 'extra-vars'
+    condition: 'site'
+    value: 'limit_drupal_site=%s'
+    args:
+      - 'site'
diff --git a/scripts/jailkitupdate.py b/scripts/jailkitupdate.py
deleted file mode 100755
index 28c5ee7a93e68224bf5cef5f032e7eb62620916c..0000000000000000000000000000000000000000
--- a/scripts/jailkitupdate.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""Force updating all Jails"""
-
-def extend(parser):
-    parser.add_argument('--site', default=None,
-                        help='The id of a site if only one of the defined sites should be updated')
-    parser.set_defaults(limit='webserver-drupal')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=jailkit jailsite_init_force=True')
-    cmd.append('--start-at-task=JailKit Role')
-    if args.site:
-        cmd.append('--extra-vars=limit_drupal_site=' + args.site)
diff --git a/scripts/jailkitupgrade.py b/scripts/jailkitupgrade.py
deleted file mode 100755
index 0e06590e96795010ae9a73626c12e474d0314621..0000000000000000000000000000000000000000
--- a/scripts/jailkitupgrade.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Update OS components in all Jails"""
-
-def extend(parser):
-    parser.set_defaults(limit='webserver-drupal')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=jailkit')
-    cmd.append('--start-at-task=JailKit Role')
-    cmd.append('--tags=UpdateJails')
diff --git a/scripts/jailkituser.py b/scripts/jailkituser.py
deleted file mode 100755
index c0600937ae16fa632d21b5469b5208b322c59f36..0000000000000000000000000000000000000000
--- a/scripts/jailkituser.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""Init and update users in Jails"""
-
-def extend(parser):
-    parser.add_argument('--site', default=None,
-                        help='The id of a site if only one of the defined sites should be updated')
-    parser.set_defaults(limit='webserver-drupal')
-
-
-def append(args):
-    args.playbook = 'user'
-
-
-def build(cmd, args):
-    cmd.append('--tags=JailUserInit,SetPermissions')
-    if args.site:
-        cmd.append('--extra-vars=limit_drupal_site=' + args.site)
diff --git a/scripts/nextcloud.py b/scripts/nextcloud.py
deleted file mode 100755
index 120b7d66188d0d0f51b4b5044b07731addd0d7af..0000000000000000000000000000000000000000
--- a/scripts/nextcloud.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Quickly update NextCloud sites"""
-
-def extend(parser):
-    parser.set_defaults(limit='webserver')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'common,commonauth,commonconnect,commonkeys,apache,php,letsencrypt'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=nextcloud')
-    cmd.append('--tags=deploy')
diff --git a/scripts/nextcloud.yml b/scripts/nextcloud.yml
new file mode 100644
index 0000000000000000000000000000000000000000..38beff1dc46c872b7fb6876fe070ddba8754f1cd
--- /dev/null
+++ b/scripts/nextcloud.yml
@@ -0,0 +1,21 @@
+description: 'Quickly update NextCloud sites'
+cli:
+  defaults:
+    limit: 'webserver'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'common'
+    - 'commonauth'
+    - 'commonconnect'
+    - 'commonkeys'
+    - 'apache'
+    - 'php'
+    - 'letsencrypt'
+command:
+  - name: 'tags'
+    value: 'deploy'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=nextcloud'
+    args:
+      - 'limit'
diff --git a/scripts/piwik.py b/scripts/piwik.py
deleted file mode 100755
index 60c9ec7ae0348c26eabc5cdecfe644f9cfd73944..0000000000000000000000000000000000000000
--- a/scripts/piwik.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""Quickly update Piwik sites"""
-
-def extend(parser):
-    parser.set_defaults(limit='piwikserver')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'common,commonauth,commonconnect,commonkeys,apache,php,letsencrypt'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=piwik')
-    cmd.append('--tags=deploy')
diff --git a/scripts/piwik.yml b/scripts/piwik.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e31ef6a31ebc01701fe185d7aa94597b328b0ff6
--- /dev/null
+++ b/scripts/piwik.yml
@@ -0,0 +1,21 @@
+description: 'Quickly update Piwik sites'
+cli:
+  defaults:
+    limit: 'piwikserver'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'common'
+    - 'commonauth'
+    - 'commonconnect'
+    - 'commonkeys'
+    - 'apache'
+    - 'php'
+    - 'letsencrypt'
+command:
+  - name: 'tags'
+    value: 'deploy'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=piwik'
+    args:
+      - 'limit'
diff --git a/scripts/role.py b/scripts/role.py
deleted file mode 100755
index 328dd5d5638487ae35bb77705cca61c4e472815f..0000000000000000000000000000000000000000
--- a/scripts/role.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Run a specific role only"""
-
-def extend(parser):
-    parser.add_argument('role',
-                        help='Role to execute')
-    parser.add_argument('hosts',
-                        help='Host name or pattern')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.hosts + ' role=' + args.role)
diff --git a/scripts/role.yml b/scripts/role.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ba955281b0b8978e6e03b0f1363759a9dcefa854
--- /dev/null
+++ b/scripts/role.yml
@@ -0,0 +1,15 @@
+description: 'Run a specific role only'
+cli:
+  arguments:
+    role:
+      help: 'Role to execute'
+    hosts:
+      help: 'Host name or pattern'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=%s'
+    args:
+      - 'hosts'
+      - 'role'
diff --git a/scripts/sanity.py b/scripts/sanity.py
deleted file mode 100755
index 5fadbc99d412f59d53a4481b08f6ae7fa766949d..0000000000000000000000000000000000000000
--- a/scripts/sanity.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""Check for updates, upgrade and reboot hosts"""
-
-def extend(parser):
-    parser.add_argument('mode', choices=['check', 'upgrade', 'reboot'],
-                        help='Mode for the sanity play')
-    parser.add_argument('--force', action='store_true', default=False,
-                        help='Force to also reboot proxy servers')
-
-
-def append(args):
-    args.playbook = 'sanity'
-
-
-def build(cmd, args):
-    cmd.append('--tags=' + args.mode)
-    if args.force:
-        cmd.append('--extra-vars=force=true')
diff --git a/scripts/sanity.yml b/scripts/sanity.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2e1a51eab8933059ff9a7371be9154186b6dfc1e
--- /dev/null
+++ b/scripts/sanity.yml
@@ -0,0 +1,24 @@
+description: 'Check for updates, upgrade and reboot hosts'
+cli:
+  arguments:
+    mode:
+      choices:
+        - 'check'
+        - 'upgrade'
+        - 'reboot'
+      help: 'Mode for the sanity play'
+  options:
+    force:
+      action: 'store_true'
+      default: False
+      help: 'Force to also reboot proxy servers'
+arguments:
+  playbook: 'sanity'
+command:
+  - name: 'tags'
+    value: '%s'
+    args:
+      - 'mode'
+  - name: 'extra-vars'
+    condition: 'force'
+    value: 'force=true'
diff --git a/scripts/shells.py b/scripts/shells.py
deleted file mode 100755
index 961505c15b94f44ea07e60df73cb0758ccb9fda4..0000000000000000000000000000000000000000
--- a/scripts/shells.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Build SSL Certs for HaProxy"""
-
-def extend(parser):
-    pass
-
-
-def append(args):
-    args.playbook = 'farm'
-    args.roles_exclude = 'drupal,drupal-cli,drupalconsole,drush,composer,apache,php,redis,memcache,letsencrypt'
-
-
-def build(cmd, args):
-    cmd.append('--tags=shells')
diff --git a/scripts/shells.yml b/scripts/shells.yml
new file mode 100644
index 0000000000000000000000000000000000000000..534f8a786c88fa57f466b36ff5435950e2204893
--- /dev/null
+++ b/scripts/shells.yml
@@ -0,0 +1,17 @@
+description: 'Build SSL Certs for HaProxy'
+arguments:
+  playbook: 'farm'
+  roles_exclude:
+    - 'drupal'
+    - 'drupal-cli'
+    - 'drupalconsole'
+    - 'drush'
+    - 'composer'
+    - 'apache'
+    - 'php'
+    - 'redis'
+    - 'memcache'
+    - 'letsencrypt'
+command:
+  - name: 'tags'
+    value: 'shells'
diff --git a/scripts/users.py b/scripts/users.py
deleted file mode 100755
index f3b994757941e31cd9e6e233c5be76aab4befa77..0000000000000000000000000000000000000000
--- a/scripts/users.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Create and configure all users
-
-Notice: this is NOT going through jails and other roles, just the users themselves
-"""
-
-def extend(parser):
-    parser.set_defaults(limit='all')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=commonauth')
diff --git a/scripts/users.yml b/scripts/users.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f56df15ddbc9ed362033e5b8f3a7269c65928365
--- /dev/null
+++ b/scripts/users.yml
@@ -0,0 +1,12 @@
+description: 'Create and configure all users'
+note: 'this is NOT going through jails and other roles, just the users themselves'
+cli:
+  defaults:
+    limit: 'all'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=commonauth'
+    args:
+      - 'limit'
diff --git a/scripts/varnish-config.yml b/scripts/varnish-config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a2160f43ecb45c44045d34d3065b5309b6178137
--- /dev/null
+++ b/scripts/varnish-config.yml
@@ -0,0 +1,13 @@
+description: 'Quickly configure Varnish'
+cli:
+  defaults:
+    limit: 'varnishserver'
+arguments:
+  playbook: 'role'
+command:
+  - name: 'tags'
+    value: 'Config'
+  - name: 'extra-vars'
+    value: 'hosts=%s role=varnish'
+    args:
+      - 'limit'
diff --git a/scripts/varnishconfig.py b/scripts/varnishconfig.py
deleted file mode 100755
index faa58a03d848afac7a7286a4efd4997b0a156d2f..0000000000000000000000000000000000000000
--- a/scripts/varnishconfig.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Quickly configure Varnish"""
-
-def extend(parser):
-    parser.set_defaults(limit='varnishserver')
-
-
-def append(args):
-    args.playbook = 'role'
-
-
-def build(cmd, args):
-    cmd.append('--tags=Config')
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=varnish')
diff --git a/scripts/youtrack.py b/scripts/youtrack.py
deleted file mode 100755
index 4bfce78eb0ac8493461afec7fadf966175c3889f..0000000000000000000000000000000000000000
--- a/scripts/youtrack.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Quickly update YouTrack sites"""
-
-def extend(parser):
-    parser.set_defaults(limit='youtrackserver')
-
-
-def append(args):
-    args.playbook = 'role'
-    args.roles_exclude = 'common,commonauth,commonconnect,commonkeys,apache,php'
-
-
-def build(cmd, args):
-    cmd.append('--extra-vars=hosts=' + args.limit + ' role=youtrack')
diff --git a/scripts/youtrack.yml b/scripts/youtrack.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9d3381193eeecd6b59f384e00cf594d070ad56ae
--- /dev/null
+++ b/scripts/youtrack.yml
@@ -0,0 +1,18 @@
+description: 'Quickly update YouTrack sites'
+cli:
+  defaults:
+    limit: 'youtrackserver'
+arguments:
+  playbook: 'role'
+  roles_exclude:
+    - 'common'
+    - 'commonauth'
+    - 'commonconnect'
+    - 'commonkeys'
+    - 'apache'
+    - 'php'
+command:
+  - name: 'extra-vars'
+    value: 'hosts=%s role=outrack'
+    args:
+      - 'limit'
diff --git a/wiki b/wiki
index 26edcebc00a18d2dafde278ccfdedc20c4ca63a6..0226905216d52ec0c7dac3804a5cbbc50e503f9e 160000
--- a/wiki
+++ b/wiki
@@ -1 +1 @@
-Subproject commit 26edcebc00a18d2dafde278ccfdedc20c4ca63a6
+Subproject commit 0226905216d52ec0c7dac3804a5cbbc50e503f9e