diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04aafd397701544c5ed132dca958123e3a0d2f94..c5f134900048553d6767f04fabb207a9fb787681 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * Improved output during IOC startup
 * e3-sequencer tests added, as well as removing pre-processing of .stt files.
 * Remove Win32 and CYGWIN32 support
+* Remove `/tools` directory, including `test_installed_modules.sh` utility
+* Remove `runScript`
+* Drop file extension from `build_number.sh`
 
 ## [4.0.0]
 
diff --git a/configure/module/RULES_REQUIRE b/configure/module/RULES_REQUIRE
index f8579c9d538db3bbe208de4c1efaaeb8d795a3ca..f5c33b927fc1aabf3abda9b30a5092d8f86f2456 100644
--- a/configure/module/RULES_REQUIRE
+++ b/configure/module/RULES_REQUIRE
@@ -24,7 +24,7 @@ install: requireconf
 requireconf: e3-site-path e3-require-path
 	$(QUIET) install    -m 755 $(wildcard $(E3_MODULE_SRC_PATH)/tools/*.tcl)  $(E3_REQUIRE_TOOLS)/
 	$(QUIET) install    -m 644 $(E3_MODULE_SRC_PATH)/tools/driver.makefile    $(E3_REQUIRE_TOOLS)/
-	$(QUIET) install    -m 755 $(E3_MODULE_SRC_PATH)/tools/*.sh    $(E3_REQUIRE_TOOLS)/
+	$(QUIET) install    -m 755 $(E3_MODULE_SRC_PATH)/tools/build_number       $(E3_REQUIRE_TOOLS)/
 	$(QUIET) install    -m 755 $(E3_SHELL_FILES)             $(E3_REQUIRE_BIN)/
 	$(QUIET) install    -m 644 $(E3_IOC_CFG_FILES)           $(E3_REQUIRE_BIN)/
 	$(QUIET) install    -m 644 $(E3_REQUIRE_CONF_FILES)      $(E3_REQUIRE_CONFIG)/
diff --git a/require-ess/src/expr.c b/require-ess/src/expr.c
deleted file mode 100644
index 150548b7b5c0a8cb743a836d8ca5b0f0a7f7bd08..0000000000000000000000000000000000000000
--- a/require-ess/src/expr.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/* Copyright (C) 2020 Dirk Zimoch */
-/* Copyright (C) 2020-2022 European Spallation Source, ERIC */
-
-#include "expr.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int exprDebug;
-
-static int parseSubExpr(const char **pp, long *v, int pr, int op);
-static long parseString(const char **pp, const char **pstart);
-#define parseExpr(pp, v) parseSubExpr(pp, v, 0, 0)
-#define skipSpace(p) \
-  while (isspace((unsigned char)*p)) p++
-
-static int parseValue(const char **pp, long *v) {
-  long val;
-  const char *p = *pp;
-  char o;
-
-  /* A value is optionally prefixed with an unary operator + - ! ~.
-   * It is either a number (decimal, octal or hex)
-   * or an expression in ().
-   * Allowed chars after a number: operators, closing parenthesis, whitespace,
-   * quotes, end of string
-   */
-
-  /* first look for value */
-  skipSpace(p);
-  o = *p;
-  if (memchr("+-~!", o, 4)) {
-    /* unary operators */
-    p++;
-    if (!parseValue(&p, &val)) return 0; /* no valid value */
-    if (exprDebug) printf("parseValue: %c %ld\n", o, val);
-    if (o == '-')
-      val = -val;
-    else if (o == '~')
-      val = ~val;
-    else if (o == '!')
-      val = !val;
-  } else if (o == '(') {
-    /* sub-expression */
-    p++;
-    if (parseExpr(&p, &val) < 0) return 0; /* no valid expression */
-    skipSpace(p);
-    if (*p++ != ')') return 0; /* missing ) */
-  } else if (o == '#') {
-    /* string length operator */
-    p++;
-    if (exprDebug) printf("parseValue: string length of %s\n", p);
-    if (*p == '"' || *p == '\'')
-      val = parseString(&p, NULL);
-    else
-      return 0;
-  } else {
-    /* number */
-    char *e;
-    val = strtol(p, &e, 0);
-    if (e == p) return 0; /* no number */
-
-    if (isalpha((unsigned char)*e) || *e == '.') {
-      /* part of plain word or floating point number */
-      return 0;
-    }
-    p = e;
-  }
-  *pp = p;
-  *v = val;
-  return 1;
-}
-
-static long ipow(long base, long exp) {
-  long val;
-  if (exp == 2) return base * base;
-  if (exp == 3) return base * base * base;
-  if (exp == 1) return base;
-  if (exp == 0) return 1;
-  if (exp < 0) return 0;
-  val = ipow(base, exp >> 1);
-  val *= val;
-  if (exp & 1) val *= base;
-  return val;
-}
-
-static char parseSep(const char **pp, const char *seps) {
-  const char *p = *pp;
-
-  skipSpace(p);
-  if (!*p || !strchr(seps, *p)) return 0;
-  *pp = p + 1;
-  return *p;
-}
-
-struct {
-  char str[4];
-  int pr;
-} ops[] = {{":=", 0},  {"**", 14}, {"*", 13},  {"/", 13},   {"%", 13},
-           {"+", 12},  {"-", 12},  {"<<", 11}, {">>>", 11}, {">>", 11},
-           {"<?", 10}, {">?", 10}, {"<=>", 9}, {"<=", 8},   {">=", 8},
-           {"<", 8},   {">", 8},   {"==", 7},  {"!=", 7},   {"&&", 3},
-           {"||", 2},  {"&", 6},   {"^", 5},   {"|", 4},    {"?:", 1},
-           {"?", 1}};
-
-enum op {
-  op_none,
-  op_pow,
-  op_mul,
-  op_div,
-  op_mod,
-  op_plus,
-  op_minus,
-  op_lshift,
-  op_urshift,
-  op_rshift,
-  op_min,
-  op_max,
-  op_cmp,
-  op_lteq,
-  op_gteq,
-  op_lt,
-  op_gt,
-  op_eq,
-  op_neq,
-  op_logicand,
-  op_logicor,
-  op_bitand,
-  op_bitxor,
-  op_bitor,
-  op_alt,
-  op_if
-};
-
-static int startsWith(const char *p, const char *s) {
-  int i = 0;
-  while (*s) {
-    i++;
-    if (*p++ != *s++) return 0;
-  }
-  return i;
-}
-
-static int parseOp(const char **pp) {
-  const char *p = *pp;
-
-  skipSpace(p);
-  if (ispunct((unsigned char)*p)) {
-    for (int o = 1; o < (int)(sizeof(ops) / sizeof(ops[0])); o++) {
-      int l;
-      if ((l = startsWith(p, ops[o].str))) {
-        /* operator found */
-        *pp = p + l;
-        return o;
-      }
-    }
-  }
-  return 0;
-}
-
-static int parseSubExpr(const char **pp, long *v, int pr, int o) {
-  const char *p = *pp;
-  long val = o ? *v : 0;
-  long val2;
-  int o2;
-
-  if (exprDebug)
-    printf("parseExpr(%d): start %ld %s \"%s\"\n", pr, val, ops[o].str, p);
-  do {
-    if (!parseValue(&p, &val2)) {
-      if (exprDebug)
-        printf("parseExpr(%d): no value after %ld %s\n", pr, val, ops[o].str);
-      return -1;
-    }
-  nextop:
-    if ((o2 = parseOp(&p))) {
-      if (exprDebug)
-        printf("parseExpr(%d): %ld %s %ld %s \"%s\"\n", pr, val, ops[o].str,
-               val2, ops[o2].str, p);
-      if (o && ops[o2].pr > ops[o].pr) {
-        if ((o2 = parseSubExpr(&p, &val2, ops[o].pr, o2)) < 0) {
-          if (exprDebug)
-            printf("parseExpr(%d): parse failed after %ld %s %ld\n", pr, val,
-                   ops[o].str, val2);
-          return -1;
-        }
-      }
-    }
-    if (exprDebug)
-      printf("parseExpr(%d): calc %ld %s %ld\n", pr, val, ops[o].str, val2);
-    switch (o) {
-      case op_none:
-        val = val2;
-        break;
-      case op_pow:
-        val = ipow(val, val2);
-        break;
-      case op_mul:
-        val *= val2;
-        break;
-      case op_div:
-        val /= val2;
-        break;
-      case op_mod:
-        val %= val2;
-        break;
-      case op_plus:
-        val += val2;
-        break;
-      case op_minus:
-        val -= val2;
-        break;
-      case op_lshift:
-        val <<= val2;
-        break;
-      case op_urshift:
-        val = (unsigned long)val >> val2;
-        break;
-      case op_rshift:
-        val >>= val2;
-        break;
-      case op_min:
-        if (val2 < val) val = val2;
-        break;
-      case op_max:
-        if (val2 > val) val = val2;
-        break;
-      case op_cmp:
-        val = val < val2 ? -1 : val == val2 ? 0 : 1;
-        break;
-      case op_lteq:
-        val = val <= val2;
-        break;
-      case op_gteq:
-        val = val >= val2;
-        break;
-      case op_lt:
-        val = val < val2;
-        break;
-      case op_gt:
-        val = val > val2;
-        break;
-      case op_eq:
-        val = val == val2;
-        break;
-      case op_neq:
-        val = val != val2;
-        break;
-      case op_logicand:
-        val = val && val2;
-        break;
-      case op_logicor:
-        val = val || val2;
-        break;
-      case op_bitand:
-        val &= val2;
-        break;
-      case op_bitxor:
-        val ^= val2;
-        break;
-      case op_bitor:
-        val |= val2;
-        break;
-      case op_alt:
-        if (!val) val = val2;
-        break;
-    }
-    if (exprDebug) printf("parseExpr(%d): result %ld\n", pr, val);
-    if (o2 == op_if) {
-      long val3 = 0;
-      val2 = 1;
-      if (exprDebug) printf("parseExpr(%d) if %ld\n", pr, val);
-      if ((o2 = parseExpr(&p, &val2)) >= 0) {
-        if (exprDebug) printf("parseExpr(%d) then %ld\n", pr, val2);
-        if (parseSep(&p, ":")) {
-          parseExpr(&p, &val3);
-          if (exprDebug) printf("parseExpr(%d) else %ld\n", pr, val3);
-        }
-      }
-      if (exprDebug)
-        printf("parseExpr(%d) if %ld then %ld else %ld\n", pr, val, val2, val3);
-      val = val ? val2 : val3;
-      if (exprDebug)
-        printf("parseExpr(%d): result %ld, o2=%d, rest \"%s\" \n", pr, val, o2,
-               p);
-      if (o2 == -1) goto nextop;
-    }
-    o = o2;
-  } while (ops[o].pr && pr <= ops[o].pr);
-  if (exprDebug)
-    printf("parseExpr(%d): value = %ld return %d %s\n", pr, val, o, ops[o].str);
-  *pp = p;
-  *v = val;
-  return o;
-}
-
-static const char *getFormat(const char **pp) {
-  static char format[20];
-  const char *p = *pp;
-  if (exprDebug) printf("getFormat %s\n", p);
-  if ((format[0] = *p++) == '%') {
-    unsigned int i = 1;
-    while (i < sizeof(format) && memchr(" #-+0", *p, 5)) format[i++] = *p++;
-    while (i < sizeof(format) && *p >= '0' && *p <= '9') format[i++] = *p++;
-    if (i < sizeof(format)) format[i++] = 'l';
-    if (i < sizeof(format) && memchr("diouxXc", *p, 7)) {
-      format[i++] = *p++;
-      format[i] = 0;  // FIXME (alo): not our memory!
-      *pp = p;
-      if (exprDebug) printf("format = '%s'\n", format);
-      return format;
-    }
-  }
-  if (exprDebug) printf("no format\n");
-  return NULL;
-}
-
-static int parseSlice(const char **pp, long *pstart, long *plength) {
-  const char *p = *pp;
-  long slice_start = 0;
-  long slice_length = 0;
-  long string_length = *plength;
-  char o;
-
-  if (*p++ != '[') return 0;
-  parseExpr(&p, &slice_start);
-  if (slice_start < 0) slice_start += string_length;
-  if ((o = parseSep(&p, ":,"))) /* [start,length] or [start:end] */ {
-    parseExpr(&p, &slice_length);
-    if (o == ':') {
-      if (slice_length < 0) slice_length += string_length;
-      slice_length -= slice_start;
-    }
-  } else {
-    slice_length = 1;
-  }
-  if (slice_start < 0) {
-    slice_length += slice_start;
-    slice_start = 0;
-  }
-  if (slice_start > string_length) slice_length = 0;
-  if (slice_length > string_length - slice_start)
-    slice_length = string_length - slice_start;
-  if (slice_length < 0) slice_length = 0;
-  skipSpace(p);
-  if (*p++ != ']') return 0;
-  *pstart += slice_start;
-  *plength = slice_length;
-  *pp = p;
-  return 1;
-}
-
-static long parseString(const char **pp, const char **pstart) {
-  const char *p = *pp;
-  const char *string_start = p;
-  long slice_start = 0;
-  long length = 0;
-  char q;
-
-  q = *p++;
-  while (*p) /* string length with escapes */ {
-    if (*p == '\\')
-      if (*++p == 0) break;
-    if (*p++ == q) break;
-    length++;
-  }
-  while (parseSlice(&p, &slice_start, &length)) {
-  }
-  if (exprDebug)
-    printf("parseString %.*s[%ld,%ld]\n", (int)(p - string_start), string_start,
-           slice_start, length);
-  if (length && pstart) {
-    while (slice_start-- > 0) {
-      if (*string_start++ == '\\') string_start++;
-    }
-    *pstart = ++string_start;
-  }
-  *pp = p;
-  return length;
-}
-
-static void writeString(char **pw, const char *r, long length, char q) {
-  char *w = *pw;
-  *w++ = q;
-  while (length-- > 0) {
-    if (*r == '\\') *w++ = *r++;
-    *w++ = *r++;
-  }
-  *w++ = q;
-  *w++ = 0;
-  *pw = w;
-}
-
-size_t replaceExpressions(const char *r, char *buffer, size_t buffersize) {
-  long val, string_length;
-  char *w = buffer;
-  char *s;
-  const char *string_start = r;
-  char q;
-
-  *w = 0;
-  while (*r) {
-    s = w;
-    if (*r == '"' || *r == '\'') {
-      /* quoted strings */
-      q = *r;
-      string_length = parseString(&r, &string_start);
-      writeString(&w, string_start, string_length, q);
-      if (exprDebug) printf("quoted string %s\n", s);
-    } else if (*r == '%') {
-      /* formatted expression */
-      const char *r2 = r;
-      const char *f;
-      if (exprDebug) printf("formatted expression after '%s'\n", s);
-      if ((f = getFormat(&r2)) && parseExpr(&r2, &val) >= 0) {
-        r = r2;
-        if (w > buffer && w[-1] == '(' && *r2++ == ')') {
-          w--;
-          r = r2;
-        }
-        w += sprintf(w, f, val);
-        if (exprDebug) printf("formatted expression %s\n", s);
-      }
-    } else if (parseExpr(&r, &val) >= 0) {
-      /* unformatted expression */
-      if (r[-1] == '?' && (q = parseSep(&r, "\"'"))) {
-        /* handle expression ? "string1" : "string2" */
-        w = s;
-        r--;
-        string_length = parseString(&r, &string_start);
-        if (val) writeString(&w, string_start, string_length, q);
-        if (parseSep(&r, ":")) {
-          string_length = parseString(&r, &string_start);
-          if (!val) writeString(&w, string_start, string_length, q);
-        }
-      } else {
-        w += sprintf(w, "%ld", val);
-      }
-      if (exprDebug) printf("expression %s\n", s);
-    } else {
-      /* unquoted string (i.e plain word) */
-      do {
-        if ((*w++ = *r++) == '\\')
-          if (*r) *w++ = *r++;
-      } while (*r && !strchr("%(\"', \t\n", *r));
-      *w = 0;
-      if (exprDebug) printf("plain word '%s'\n", s);
-    }
-    /* copy space */
-    while (isspace((unsigned char)*r) || *r == ',') *w++ = *r++;
-    /* terminate */
-    *w = 0;
-  }
-  return w - buffer;
-}
diff --git a/require-ess/src/expr.h b/require-ess/src/expr.h
deleted file mode 100644
index ecea81172d767cc25397e687b0baf93fb958738c..0000000000000000000000000000000000000000
--- a/require-ess/src/expr.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2020 Dirk Zimoch */
-/* Copyright (C) 2020-2022 European Spallation Source, ERIC */
-
-#pragma once
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern {
-#endif  // __cplusplus
-
-  extern int exprDebug;
-
-  size_t replaceExpressions(const char *source, char *buffer,
-                            size_t buffersize);
-  /* Resolve integer expressions that are either free standing
-   * or in parentheses () embedded in an unquoted word.
-   * Do not resolve expressions in single or double quoted strings.
-   * An expression optionally starts with a integer format such as %x.
-   * It consists of integer numbers, operators and parentheses ().
-   */
-
-#ifdef __cplusplus
-}
-#endif  // __cplusplus
diff --git a/require-ess/src/require.h b/require-ess/src/require.h
index e961d02df192e06d1e2e5297506570c40844f0a5..f9ba5060f7852d74077d162d0c6c034b67ccd5c6 100644
--- a/require-ess/src/require.h
+++ b/require-ess/src/require.h
@@ -20,7 +20,6 @@ size_t foreachLoadedLib(size_t (*func)(const char *name, const char *version,
 const char *getLibVersion(const char *libname);
 const char *getLibLocation(const char *libname);
 int libversionShow(const char *outfile);
-int runScript(const char *filename, const char *args);
 int putenvprintf(const char *format, ...)
     __attribute__((__format__(__printf__, 1, 2)));
 void pathAdd(const char *varname, const char *dirname);
diff --git a/require-ess/src/runScript.dbd b/require-ess/src/runScript.dbd
deleted file mode 100644
index ab7b21dc3715dc551931416a2a39d9e7719e02a3..0000000000000000000000000000000000000000
--- a/require-ess/src/runScript.dbd
+++ /dev/null
@@ -1,3 +0,0 @@
-registrar(runScriptRegister)
-variable(runScriptDebug,int)
-variable(exprDebug,int)
diff --git a/require-ess/test/testscript b/require-ess/test/testscript
deleted file mode 100644
index b4b2d4caa8108e590618348cac8224f36e5d8adb..0000000000000000000000000000000000000000
--- a/require-ess/test/testscript
+++ /dev/null
@@ -1,95 +0,0 @@
-#var exprDebug 1
-
-x=3, !3, !!3, -3, --3, ~3, ~~3, 3?, 3??
-# $(x) should be: 3, 0, 1, -3, 3, -4, 3, 1, 1
-
-x=x, !x, !!x, -x, --x, ~x, ~~x, x?, x??
-# $(x) should be: x, !x, !!x, -x, --x, ~x, ~~x, x?, x??
-
-x=10+3, 10-3, 10*3, 10/3, 10%3, 10**3
-# $(x) should be: 13, 7, 30, 3, 1, 1000
-
-x=7**-2 7**-1 7**0 7**1 7**2 7**3 7**4 7**5 7**6
-# $(x) should be: 0 0 1 7 49 343 2401 16807 117649
-
-x=%x -10<<2, %x -10>>2, %x -10>>>2
-# $(x) should be: ffffffffffffffd8, fffffffffffffffd, 3ffffffffffffffd
-
-x=%x 0xaa & 0x0f, %x 0xaa | 0x0f, %x 0xaa ^ 0x0f
-# $(x) should be: a, af, a5
-
-x=10<20 10<=20 10==20 10>=20 10>20 10<=>20 10<?20 10>?20 10?<20 10?>20
-# $(x) should be: 1 1 0 0 0 -1 10 20 1 0
-
-x=20<20 20<=20 20==20 20>=20 20>20 20<=>20 20<?20 20>?20 20?<20 20?>20
-# $(x) should be: 0 1 1 1 0 0 20 20 1 0
-
-x=20<10 20<=10 20==10 20>=10 20>10 20<=>10 20<?10 20>?10 20?<10 20?>10
-# $(x) should be: 0 0 0 1 1 1 10 20 1 0
-
-x= (0|0)(0|1)(1|0)(1|1) (0&0)(0&1)(1&0)(1&1) (0^0)(0^1)(1^0)(1^1)
-# $(x) should be: 0111 0001 0110
-
-x=1*2*3+4*5*6-7-8
-# $(x) should be: 111
-
-x=1*2*3+4*5*6-7*8
-# $(x) should be: 70
-
-x=-3**2+1, -(3**2)+1, (-3)**2+1, -3**-2+1, (1+2), (1+2, 1+2)
-# $(x) should be: 10, -8, 10, 1, 3, (1+2, 3)
-
-x=%#X 0x5555&0xfff0|0xaf<<8^0xa00a0>>4
-# $(x) should be: 0X5F5A
-
-x=7+4*2|32
-# $(x) should be: 47
-
-x=3<5 ? 7+4*2|32 : 9 & 10
-# $(x) should be: 47
-
-x=3>5 ? 7+4*2|32 : 9 & 10
-# $(x) should be: 8
-
-x=7 ?: -1
-# $(x) should be: 7
-
-x=0 ?: -1
-# $(x) should be: -1
-
-x=7 ? -1
-# $(x) should be: -1
-
-x=0 ? -1
-# $(x) should be: 0
-
-x=1+0?7?1:2:3?4:5
-# $(x) should be: 1
-
-x=1+0?0?1:2:3?4:5
-# $(x) should be: 2
-
-x=1-1?0?1:2:3?4:5
-# $(x) should be: 4
-
-x=1-1?0?1:2:3-3?4:5
-# $(x) should be: 5
-
-x=0?; 1?; 2?; -4?; 3?+1
-# $(x) should be: 0; 1; 1; 1; 4
-
-x=a030b a(030)b a( 030 )b "a"030"b" a(%x 030)b
-# $(x) should be: a030b a24b a24b a24b a18b
-
-x=030b (030)b ( 030 )b 030"b" %x 030'b'
-# $(x) should be: 030b 24b 24b 24b 18b
-
-x=-0bla -0.1
-# $(x) should be: -0bla -0.1
-
-x=-2**2 0-2**2 0+-2**2 0--2**2
-# $(x) should be: 4 -4 4 -4
-
-x=
-y=$(x)
-# <$(x)><$(y)> should be: <><>
diff --git a/require-ess/test/teststrings b/require-ess/test/teststrings
deleted file mode 100644
index 5c2990abfb6c4a57e58825dbab54afde7afbc31f..0000000000000000000000000000000000000000
--- a/require-ess/test/teststrings
+++ /dev/null
@@ -1,92 +0,0 @@
-x=string0
-y=$(x)
-# $(x) $(y)
-
-x="string1"
-y=$(x)
-# $(x) $(y)
-
-x="'string2'"
-y=$(x)
-# $(x) $(y)
-
-x='"string3"'
-y=$(x)
-# $(x) $(y)
-
-x=\"string4\"
-y=$(x)
-# $(x) $(y)
-
-x=\'string5\'
-y=$(x)
-# $(x) $(y)
-
-x="Hello World"[2:8]
-# $(x) should be: llo Wo
-
-x=Hello World[2:8]
-# "$(x)" should be: "Hello World[2:8]"
-
-x="Hello World"[2,3]
-# $(x) should be: llo
-
-x="Hello World"[1]
-# $(x) should be: e
-
-x="Hello World"[-1]
-# $(x) should be: d
-
-x="Hello World"[-2:]
-# $(x) should be: ld
-
-x="Hello World"[-2,6]
-# $(x) should be: ld
-
-x="Hello World"[1:1000]
-# $(x) should be: ello World
-
-x="Hello World"[1:-1000]
-# "$(x)" should be: ""
-
-x="Hello World"[:]
-# "$(x)" should be: "Hello World"
-
-x="Hello World"[1?6:0:]
-# "$(x)" should be: "World"
-
-x="Hello World"[1000]
-# "$(x)" should be: ""
-
-x="Hello World"[-1000]
-# "$(x)" should be: ""
-
-x="Hello World"[-1000,1005]
-# "$(x)" should be: "World"
-
-x="Hello World"[-1000:5]
-# "$(x)" should be: "World"
-
-x="Hello World"[7:4]
-# "$(x)" should be: ""
-
-x="Hello World"[1?3+4:0:7-8]
-# "$(x)" should be: "orl"
-
-x="Hello World"[7,-1]
-# "$(x)" should be: ""
-
-x='\"\\x'[2]
-# $(x) should be: x
-
-x=#"Hello World"
-# $(x) should be: 11
-
-x=#"Hello World"[2:8]
-# $(x) should be: 6
-
-x=#Hello World
-# $(x) should be: #Hello World
-
-x=1 ? "true" : "false"
-# $(x) should be: true
diff --git a/require-ess/tools/README.md b/require-ess/tools/README.md
deleted file mode 100644
index 39bf3fafbc314a862b7995e02aa322a60a90b096..0000000000000000000000000000000000000000
--- a/require-ess/tools/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-iocsh
-====
-
-## E3 Unique Variables
-
-```
-E3_CMD_TOP   : the absolute path where a startup script (cmd file) is
-E3_IOCSH_TOP : the absolute path where the iocsh is executed
-```
-
-For example, one executes the iocsh ```${HOME}``` to call ```e3_local/cmds``` via
-
-```sh
-$ iocsh e3_local/cmds/iocStats.cmd
-```
-In this case,
-```E3_CMD_TOP``` is defined as ```"${HOME}/e3_local/cmds"```
-```E3_IOCSH_TOP``` is defined as ```"${HOME}"```
diff --git a/require-ess/tools/build_number.sh b/require-ess/tools/build_number
old mode 100755
new mode 100644
similarity index 100%
rename from require-ess/tools/build_number.sh
rename to require-ess/tools/build_number
diff --git a/require-ess/tools/driver.makefile b/require-ess/tools/driver.makefile
index c4ddc74ccbeb78e1d49ffb4358a3da3a0d5d2e84..e77379a9de459580f5ef126338ab1739f7826067 100644
--- a/require-ess/tools/driver.makefile
+++ b/require-ess/tools/driver.makefile
@@ -141,7 +141,7 @@ endef
 #   $(call FETCH_BUILD_NUMBER,$(E3_SITEMODS_PATH),module)
 #
 define FETCH_BUILD_NUMBER
-$(shell $(MAKEHOME)/build_number.sh $(1) $(2) $($(2)_VERSION))
+$(shell $(MAKEHOME)/build_number $(1) $(2) $($(2)_VERSION))
 endef
 
 # Functions used for recursive dependency fetching. These are modified from https://github.com/markpiffer/gmtt.git
@@ -446,7 +446,7 @@ INSTALL_INCLUDES =
 #
 # The default behaviour is to start with <module>_VERSION and to select the highest
 # available build number, unless a build no. is specified. This is determined with the
-# shell script build_number.sh included with require.
+# shell script `build_number` included with require.
 
 define ADD_INCLUDES_TEMPLATE
 INSTALL_INCLUDES += $$(patsubst %,-I${2}/${1}/%/include,$${${1}_VERSION})
diff --git a/require.Makefile b/require.Makefile
index f1fe3ec0b77386c857f18868e837976185d90db0..e9b528f1926721681a585c6d491fefeb44849aa6 100644
--- a/require.Makefile
+++ b/require.Makefile
@@ -38,9 +38,6 @@ APPDB := $(APP)/Db
 SOURCES += $(APPSRC)/require.c
 SOURCES += $(APPSRC)/version.c
 DBDS    += $(APPSRC)/require.dbd
-SOURCES += $(APPSRC)/runScript.c
-DBDS    += $(APPSRC)/runScript.dbd
-SOURCES += $(APPSRC)/expr.c
 
 SOURCES += $(APPSRC)/dbLoadTemplate.y
 DBDS    += $(APPSRC)/dbLoadTemplate.dbd
diff --git a/tools/README.md b/tools/README.md
deleted file mode 100644
index 39bf3fafbc314a862b7995e02aa322a60a90b096..0000000000000000000000000000000000000000
--- a/tools/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-iocsh
-====
-
-## E3 Unique Variables
-
-```
-E3_CMD_TOP   : the absolute path where a startup script (cmd file) is
-E3_IOCSH_TOP : the absolute path where the iocsh is executed
-```
-
-For example, one executes the iocsh ```${HOME}``` to call ```e3_local/cmds``` via
-
-```sh
-$ iocsh e3_local/cmds/iocStats.cmd
-```
-In this case,
-```E3_CMD_TOP``` is defined as ```"${HOME}/e3_local/cmds"```
-```E3_IOCSH_TOP``` is defined as ```"${HOME}"```
diff --git a/tools/test_installed_modules.sh b/tools/test_installed_modules.sh
deleted file mode 100644
index c251075c7c34fc38ecdfd818179c34f103fc77d3..0000000000000000000000000000000000000000
--- a/tools/test_installed_modules.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2020-Present European Spallation Source ERIC
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-REQUIRE_DIR=$(
-  cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/.. || exit
-  pwd
-)
-REQUIRE_VERSION=${REQUIRE_DIR##*/}
-BASE_LOCATION=$(
-  cd "${REQUIRE_DIR}"/../.. || exit
-  pwd
-)
-
-if ! command -v run-iocsh >/dev/null 2>&1; then
-  echo "You need to install run-iocsh to use this script" >&2 && exit 1
-fi
-
-for d in "$REQUIRE_DIR"/siteMods/*/*; do
-  mod=$(dirname "$d" | xargs basename)
-  ver=$(basename "$d")
-  echo "Running test: $mod,$ver"
-  echo "======================================================="
-
-  if run-iocsh --base_location "${BASE_LOCATION}" --require_version "${REQUIRE_VERSION}" --delay 2 --timeout 5 "$mod,$ver"; then
-    echo -e "Module $mod, version $ver: \e[32mTEST PASSED\e[0m"
-  else
-    echo -e "Module $mod, version $ver: \e[31mFAILED\e[0m" >&2
-  fi
-  echo "======================================================="
-  echo ""
-done