diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 5939cbd1b46e6d9cdd83226d0b61a6b1de90f823..3834d038d1b1062ff99bbd79f83e78467cf3312c 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -13,13 +13,14 @@
     "settings": {
         "terminal.integrated.shell.linux": "/bin/bash",
         "git.path": "/opt/rh/sclo-git25/root/usr/bin/git",
-        "python.envFile": "/workspaces/build/env.txt",
+        "python.envFile": "${workspaceFolder}/../build/env.txt",
         "python.linting.enabled": true,
         "python.linting.pylintEnabled": false,
         "python.linting.flake8Enabled": true,
         "python.linting.flake8Args": [
-            "--select=ATL,F,E7,E9,W6",
-            "--enable-extension=ATL902"
+            "--select=ATL,F,E101,E7,E9,W6",
+            "--ignore=ATL238,ATL9,E701,E702,E704,E741",
+            "--enable-extensions=ATL902"
         ]
     },
 
diff --git a/.vscode/IDEHelperScripts/Setup.cmake b/.vscode/IDEHelperScripts/Setup.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..6e2c817f7d54694137e0b629701ed88526262bc6
--- /dev/null
+++ b/.vscode/IDEHelperScripts/Setup.cmake
@@ -0,0 +1,45 @@
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+message( STATUS "Preparing IDE helpers" )
+
+# singularity settings
+set( ATLAS_SINGULARITY_IMAGE "" CACHE PATH
+   "Use singularity wrapper" )
+set( ATLAS_SINGULARITY_ARGS "" CACHE STRING
+   "Singularity weapper args" )
+
+# Common prefix
+set( ATLAS_IDE_PREFIX "${CMAKE_BINARY_DIR}/ide_" )
+
+# Dump python environment variables
+set( ATLAS_DUMP_ENV_FILE "${CMAKE_BINARY_DIR}/env.txt" CACHE FILEPATH
+   "File containing dump of environment variables" )
+
+if( ATLAS_DUMP_ENV_FILE )
+   execute_process(
+      COMMAND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/atlas_build_run.sh" printenv
+      COMMAND grep -w ^PYTHONPATH
+      OUTPUT_FILE "${ATLAS_DUMP_ENV_FILE}" )
+endif()
+
+# compiler
+execute_process(
+   COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CXX_COMPILER}" "${ATLAS_IDE_PREFIX}compiler"
+   OUTPUT_FILE "${ATLAS_IDE_PREFIX}compiler" )
+
+# python
+find_package( Python COMPONENTS Interpreter )
+execute_process(
+   COMMAND ${CMAKE_COMMAND} -E create_symlink "${Python_EXECUTABLE}" "${ATLAS_IDE_PREFIX}python"
+   OUTPUT_FILE "${ATLAS_IDE_PREFIX}python" )
+
+# flake8 wrapper
+configure_file( "${CMAKE_CURRENT_LIST_DIR}/flake8_wrapper.sh.in" "${ATLAS_IDE_PREFIX}flake8" @ONLY )
+
+# gdb wrappers
+configure_file( "${CMAKE_CURRENT_LIST_DIR}/gdb_wrapper.sh.in" "${ATLAS_IDE_PREFIX}gdb_wrapper" @ONLY )
+if( ATLAS_SINGULARITY_IMAGE )
+   configure_file( "${CMAKE_CURRENT_LIST_DIR}/gdb_runner_singularity.sh.in" "${ATLAS_IDE_PREFIX}gdb_runner" @ONLY )
+else()
+   configure_file( "${CMAKE_CURRENT_LIST_DIR}/gdb_runner_plain.sh.in" "${ATLAS_IDE_PREFIX}gdb_runner" @ONLY )
+endif()
diff --git a/.vscode/IDEHelperScripts/flake8_wrapper.sh.in b/.vscode/IDEHelperScripts/flake8_wrapper.sh.in
new file mode 100755
index 0000000000000000000000000000000000000000..642fe148f21dd1d1d06794bd7a2dd017b5f99d7c
--- /dev/null
+++ b/.vscode/IDEHelperScripts/flake8_wrapper.sh.in
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+"@CMAKE_BINARY_DIR@@CMAKE_FILES_DIRECTORY@/atlas_build_run.sh" "@Python_EXECUTABLE@" -m flake8 "$@"
diff --git a/.vscode/IDEHelperScripts/gdb_runner_plain.sh.in b/.vscode/IDEHelperScripts/gdb_runner_plain.sh.in
new file mode 100755
index 0000000000000000000000000000000000000000..df3900960593b8813974e316e18a0b8eb87b2606
--- /dev/null
+++ b/.vscode/IDEHelperScripts/gdb_runner_plain.sh.in
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+echo "Running GDB wrapper at '@ATLAS_IDE_PREFIX@gdb_wrapper'"
+echo
+
+"@ATLAS_IDE_PREFIX@gdb_wrapper" "$@"
diff --git a/.vscode/IDEHelperScripts/gdb_runner_singularity.sh.in b/.vscode/IDEHelperScripts/gdb_runner_singularity.sh.in
new file mode 100755
index 0000000000000000000000000000000000000000..235ad9c24f6611cb3188d73533e1b2521e30bc5c
--- /dev/null
+++ b/.vscode/IDEHelperScripts/gdb_runner_singularity.sh.in
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+echo "Using singularity 'singularity exec @ATLAS_SINGULARITY_ARGS@ \"@ATLAS_SINGULARITY_IMAGE@\"'"
+echo "Running GDB wrapper at '@ATLAS_IDE_PREFIX@gdb_wrapper'"
+echo
+
+singularity exec @ATLAS_SINGULARITY_ARGS@ "@ATLAS_SINGULARITY_IMAGE@" "/bin/bash" "@ATLAS_IDE_PREFIX@gdb_wrapper" "$@"
diff --git a/.vscode/IDEHelperScripts/gdb_wrapper.sh.in b/.vscode/IDEHelperScripts/gdb_wrapper.sh.in
new file mode 100755
index 0000000000000000000000000000000000000000..e1f46624eb369651310663cf2213fde4129f386d
--- /dev/null
+++ b/.vscode/IDEHelperScripts/gdb_wrapper.sh.in
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+args=("$@")
+
+set --
+
+export ATLAS_LOCAL_ROOT_BASE="/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase"
+source "${ATLAS_LOCAL_ROOT_BASE}/user/atlasLocalSetup.sh"
+
+echo
+binary_dir="@CMAKE_BINARY_DIR@"
+pushd "${binary_dir}" || exit
+asetup --restore
+source "@ATLAS_PLATFORM@/setup.sh"
+popd || exit
+echo
+
+echo "Running gdb with args '${args[*]}'"
+
+gdb "${args[@]}"
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 44c6152e182f926b878b6d0386b63f787f50ffad..886bba865da22c1a5df6cd9d8cd87fbffaf34ea3 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -6,7 +6,7 @@
                 "${workspaceFolder}/**"
             ],
             "defines": [],
-            "compilerPath": "${env:CXX}",
+            "compilerPath": "${workspaceFolder}/../build/ide_compiler",
             "cStandard": "c11",
             "cppStandard": "c++17",
             "intelliSenseMode": "gcc-x64",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 260ecde21786e2178331aeee8fd808f77ca969ef..27b9095cf60a8c9959fbbee5814cc8395b7100d3 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,8 +1,20 @@
 {
     "remote.SSH.defaultExtensions": [
         "ms-vscode.cpptools",
+        "ms-python.python",
         "twxs.cmake"
     ],
     "remote.SSH.lockfilesInTmp": true,
-    "gitlab.instanceUrl": "https://gitlab.cern.ch"
+    "gitlab.instanceUrl": "https://gitlab.cern.ch",
+    "python.pythonPath": "${workspaceFolder}/../build/ide_python",
+    "python.envFile": "${workspaceFolder}/../build/env.txt",
+    "python.linting.enabled": true,
+    "python.linting.pylintEnabled": false,
+    "python.linting.flake8Enabled": true,
+    "python.linting.flake8Path": "${workspaceFolder}/../build/ide_flake8",
+    "python.linting.flake8Args": [
+        "--select=ATL,F,E101,E7,E9,W6",
+        "--ignore=ATL238,ATL9,E701,E702,E704,E741",
+        "--enable-extensions=ATL902"
+    ]
 }
diff --git a/Projects/WorkDir/CMakeLists.txt b/Projects/WorkDir/CMakeLists.txt
index 0e97de9b6e029f13061d19ad97a3cd9accd87729..5fe5dbf05ae6b01e882cd7464b28d1b5fe7d89d5 100644
--- a/Projects/WorkDir/CMakeLists.txt
+++ b/Projects/WorkDir/CMakeLists.txt
@@ -110,16 +110,11 @@ lcg_generate_env( SH_FILE ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}/env_setup.sh )
 install( FILES ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}/env_setup.sh
    DESTINATION . )
 
-# Dump some environment variables for IDE use:
-set( CMAKE_DUMP_ENV_FILE ${CMAKE_BINARY_DIR}/env.txt CACHE FILEPATH
-   "File containing dump of environment variables" )
-
-if( CMAKE_DUMP_ENV_FILE )
-   execute_process(
-      COMMAND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/atlas_build_run.sh printenv
-      COMMAND grep -w ^PYTHONPATH
-      OUTPUT_FILE "${CMAKE_DUMP_ENV_FILE}" )
-endif()
+# Setup IDE integration:
+set( ATLAS_IDEHELPERSCRIPTS_SETUP
+   "${CMAKE_SOURCE_DIR}/../../.vscode/IDEHelperScripts/Setup.cmake"
+   CACHE FILEPATH "Setup file for the IDE / VS Code helpers" )
+include( "${ATLAS_IDEHELPERSCRIPTS_SETUP}" OPTIONAL )
 
 # Set up CPack:
 atlas_cpack_setup()