diff --git a/pyimgui-wheels/imgui-2.0.0-cp310-cp310-linux_x86_64.whl b/pyimgui-wheels/imgui-2.0.0-cp310-cp310-linux_x86_64.whl
deleted file mode 100644
index f147c1ff402c539dbdb313ea0faae7e3d00cc761..0000000000000000000000000000000000000000
Binary files a/pyimgui-wheels/imgui-2.0.0-cp310-cp310-linux_x86_64.whl and /dev/null differ
diff --git a/pyimgui-wheels/imgui-2.0.0-cp310-cp310-win_amd64.whl b/pyimgui-wheels/imgui-2.0.0-cp310-cp310-win_amd64.whl
deleted file mode 100644
index c621fc787d27c336c48296c4fa6f4ac4e083912d..0000000000000000000000000000000000000000
Binary files a/pyimgui-wheels/imgui-2.0.0-cp310-cp310-win_amd64.whl and /dev/null differ
diff --git a/pyimgui-wheels/imgui-2.0.0-cp39-cp39-linux_x86_64.whl b/pyimgui-wheels/imgui-2.0.0-cp39-cp39-linux_x86_64.whl
deleted file mode 100644
index 818b4eba2f70fd1eb1395d0e5f6bd2344346d9ee..0000000000000000000000000000000000000000
Binary files a/pyimgui-wheels/imgui-2.0.0-cp39-cp39-linux_x86_64.whl and /dev/null differ
diff --git a/requirements.txt b/requirements.txt
index 646989e0b4317f47e1ecee4e90c1fdef33da491c..cabcdb71c457e01f5e5473d26676efada62d7152 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,15 +1,16 @@
 PySDL2
 PyOpenGL
-signalslot
+# >= 0.2.0 required for python 3.11 (not yet on pypi): see https://github.com/Numergy/signalslot/issues/19
+git+https://github.com/Numergy/signalslot#egg=signalslot
 ifaddr
 appdirs
 bcrypt
 cffi
 cryptography
-cx-Freeze == 6.13; sys_platform == 'win32'
+cx-Freeze; sys_platform == 'win32'
 pywin32; sys_platform == 'win32'
 shiv; sys_platform == 'linux'
-# used by the packaging script on linux
+# packaging script on linux expects pipenv
 pipenv; sys_platform == 'linux'
 idna
 netifaces
@@ -17,4 +18,4 @@ paramiko
 pycparser
 PyNaCl
 six
-# imgui: not listed here, install the matching version from pyimgui-wheels/
+imgui[sdl2]
diff --git a/setup/cxfreeze-windows.py b/setup/cxfreeze-windows.py
index 258bfccec75cf3d8dbb01827a524748d7e9d7441..b6126ac1ec02982613ba5e028ca6817c57cbcbb9 100644
--- a/setup/cxfreeze-windows.py
+++ b/setup/cxfreeze-windows.py
@@ -36,6 +36,8 @@ module_map = {
     'PySDL2': 'sdl2',
     'PyOpenGL': 'OpenGL',
     'PyNaCl': 'nacl',
+    'imgui[sdl2]': 'imgui',
+    'git+https://github.com/Numergy/signalslot#egg=signalslot': 'signalslot',
 }
 
 # explicitly include all top level modules, extracted from requirements.txt
@@ -53,7 +55,6 @@ for req in open('requirements.txt').readlines():
         modules.append(module_map[req])
     else:
         modules.append(req)
-modules.append('imgui')
 
 print(f'modules: {modules!r}')
 
diff --git a/setup/gitlab-linux.py b/setup/gitlab-linux.py
index 1f58922c029cd0f0e872e2011821c53e72287bdb..633b497c857eb019a6be8c52646f4c42ed159b5b 100755
--- a/setup/gitlab-linux.py
+++ b/setup/gitlab-linux.py
@@ -14,15 +14,34 @@ ARTIFACTS_DIR = os.path.join(ROOT_DIR, 'artifacts')
 assert sys.platform == 'linux'
 assert sys.prefix == sys.base_prefix    # executed at build VM OS level
 
+
+# don't let python buffering get in the way or readable output
+# https://stackoverflow.com/questions/107705/disable-output-buffering
+class Unbuffered(object):
+   def __init__(self, stream):
+       self.stream = stream
+   def write(self, data):
+       self.stream.write(data)
+       self.stream.flush()
+   def writelines(self, datas):
+       self.stream.writelines(datas)
+       self.stream.flush()
+   def __getattr__(self, attr):
+       return getattr(self.stream, attr)
+
+
 def call(cmd, cwd):
     print(f'BEGIN CMD: {cmd}')
-    output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True)
-    sys.stdout.write(output)
+    subprocess.check_call(cmd, cwd=cwd, shell=True, stderr=subprocess.STDOUT)
     print(f'END CMD: {cmd}')
 
+
 if __name__ == '__main__':
+    sys.stdout = Unbuffered(sys.stdout)
+    sys.stderr = Unbuffered(sys.stderr)
+
     os.makedirs(ARTIFACTS_DIR, exist_ok=True)
-    for python_minor in (9, 10):
+    for python_minor in (9, 10, 11):
         build_dir = os.path.abspath(os.path.join(ROOT_DIR, f'../steamos-devkit-py3{python_minor}'))
         interpreter = f'python3.{python_minor}'
         # using pipenv wasn't the best idea for CI, it leaves it's files in ~/.local/share/virtualenvs/,
@@ -45,7 +64,6 @@ if __name__ == '__main__':
         pipenv_cmd = f'{interpreter} -m pipenv --python 3.{python_minor} run'
         call(f'{pipenv_cmd} pip install -r requirements.txt', build_dir)
         pipenv_cmd = f'{interpreter} -m pipenv run'
-        call(f'{pipenv_cmd} pip install pyimgui-wheels/imgui-2.0.0-cp3{python_minor}-cp3{python_minor}-linux_x86_64.whl', build_dir)
         call(f'{pipenv_cmd} {interpreter} ./setup/package-linux.py', build_dir)
         g = glob.glob(f'{build_dir}/devkit-gui*.pyz')
         if len(g) != 1:
diff --git a/setup/gitlab-windows.py b/setup/gitlab-windows.py
index 29f4f80c839413dcd918aacaea8b2844a71d8c4c..ef9bb75417f4f4d40fa101790b870648eaf9f63a 100644
--- a/setup/gitlab-windows.py
+++ b/setup/gitlab-windows.py
@@ -12,19 +12,38 @@ PACKAGE_FILE = 'devkit-gui-win64.zip'
 assert sys.platform == 'win32'
 assert sys.prefix == sys.base_prefix    # executed at build VM OS level
 
+
+# don't let python buffering get in the way or readable output
+# https://stackoverflow.com/questions/107705/disable-output-buffering
+class Unbuffered(object):
+   def __init__(self, stream):
+       self.stream = stream
+   def write(self, data):
+       self.stream.write(data)
+       self.stream.flush()
+   def writelines(self, datas):
+       self.stream.writelines(datas)
+       self.stream.flush()
+   def __getattr__(self, attr):
+       return getattr(self.stream, attr)
+
+
 def call(cmd):
     print(f'BEGIN CMD: {cmd}')
     subprocess.check_call(cmd, cwd=ROOT_DIR, shell=True)
     print(f'END CMD: {cmd}')
 
+
 if __name__ == '__main__':
+    sys.stdout = Unbuffered(sys.stdout)
+    sys.stderr = Unbuffered(sys.stderr)
+
     call(f'python -m venv .')
     interpreter = os.path.join(ROOT_DIR, r'Scripts\python.exe')
     call(f'{interpreter} -m pip install --upgrade pip')
     pip = os.path.join(ROOT_DIR, r'Scripts\pip.exe')
     call(f'{pip} install --upgrade setuptools')
     call(f'{pip} install -r requirements.txt')
-    call(rf'{pip} install .\pyimgui-wheels\imgui-2.0.0-cp310-cp310-win_amd64.whl')
     call(rf'{interpreter} .\setup\package-windows.py')
     if not os.path.exists(PACKAGE_FILE):
         raise Exception(f'{PACKAGE_FILE} not found')
diff --git a/setup/package-linux.py b/setup/package-linux.py
index c25fc3148bf589d1996f0e6579bcff403d63fc57..76db817992df8c2f6b7dc1004c0dc5de253d60c2 100755
--- a/setup/package-linux.py
+++ b/setup/package-linux.py
@@ -17,7 +17,26 @@ SETUP_DIR = os.path.abspath(os.path.dirname(__file__))
 ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
 CLIENT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '../client'))
 
+
+# don't let python buffering get in the way or readable output
+# https://stackoverflow.com/questions/107705/disable-output-buffering
+class Unbuffered(object):
+   def __init__(self, stream):
+       self.stream = stream
+   def write(self, data):
+       self.stream.write(data)
+       self.stream.flush()
+   def writelines(self, datas):
+       self.stream.writelines(datas)
+       self.stream.flush()
+   def __getattr__(self, attr):
+       return getattr(self.stream, attr)
+
+
 if __name__ == '__main__':
+    sys.stdout = Unbuffered(sys.stdout)
+    sys.stderr = Unbuffered(sys.stderr)
+
     parser = argparse.ArgumentParser(description='Prepare a shiv package of the devkit client for Linux')
     parser.add_argument('--output-directory', required=False, action='store', default='.', help='Output directory')
     conf = parser.parse_args()
diff --git a/setup/package-windows.py b/setup/package-windows.py
index fcb6fe43339d5ccb4c386455578738e3af146926..443da492e8bbcdd1a0540832b99d9df918cf8d53 100644
--- a/setup/package-windows.py
+++ b/setup/package-windows.py
@@ -16,7 +16,26 @@ CLIENT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), r'..\client
 BUILD_DIR = os.path.join(ROOT_DIR, 'build')
 DIST_DIR = os.path.join(ROOT_DIR, 'dist')
 
+
+# don't let python buffering get in the way or readable output
+# https://stackoverflow.com/questions/107705/disable-output-buffering
+class Unbuffered(object):
+   def __init__(self, stream):
+       self.stream = stream
+   def write(self, data):
+       self.stream.write(data)
+       self.stream.flush()
+   def writelines(self, datas):
+       self.stream.writelines(datas)
+       self.stream.flush()
+   def __getattr__(self, attr):
+       return getattr(self.stream, attr)
+
+
 if __name__ == '__main__':
+    sys.stdout = Unbuffered(sys.stdout)
+    sys.stderr = Unbuffered(sys.stderr)
+
     parser = argparse.ArgumentParser(description='Prepare a package of the devkit client for Windows')
     parser.add_argument('--refresh', required=False, action='store_true', default='.', help='Refresh only')
     conf = parser.parse_args()