diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 06f21f7a4c196ede8ebb74385ef4d1fe01afdb2f..af91fa7d11c489ed3e42ba0f8c73fdd411e3f284 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -15,7 +15,7 @@ stages:
   - ls -l
   - pip install -U pip
   - pip --version
-  - pip install pytest black ruff
+  - pip install pytest black ruff pydocstyle
   - pytest --version
   - cat /etc/issue
 
@@ -79,6 +79,9 @@ style:
     - ruff --version
     - ruff .
     - black --check --diff .
+    - pydocstyle mpsd-software-environment.py
+    - pydocstyle tests.py
+    # we could also use `ruff --select D` for pycodestyle. But the behaviour is not exactly the same.
 
 
 test-bullseye:
diff --git a/mpsd-software-environment.py b/mpsd-software-environment.py
index 7e2688348056dfb7dc27c0901dc5355cf2784a7e..02982e8c63392a351e0f6fef809bb7c3ba248a53 100755
--- a/mpsd-software-environment.py
+++ b/mpsd-software-environment.py
@@ -1,4 +1,7 @@
 #!/usr/bin/env python3
+
+"""mpsd-software-environment: tool for installation of toolchains."""
+
 import argparse
 import datetime
 import os
@@ -29,21 +32,23 @@ config_vars = {
 
 # Helper class to change directory via context manager
 class os_chdir:
-    """
-    The os_chdir class is a context manager.
+    """The os_chdir class is a context manager.
 
     It changes the current directory to a specified directory
     and returns to the original directory after execution.
     """
 
     def __init__(self, new_dir):
+        """Initialize, save original directory."""
         self.new_dir = new_dir
         self.saved_dir = os.getcwd()
 
     def __enter__(self):
+        """Go to target directory (main action for context)."""
         os.chdir(self.new_dir)
 
     def __exit__(self, exc_type, exc_val, exc_tb):
+        """On exist we return to original directory."""
         os.chdir(self.saved_dir)
 
 
@@ -132,7 +137,7 @@ def run(*args, counter=[0], **kwargs):
 
 
 def setup_log_cmd(
-    mpsd_release: str, script_dir: str, msg: str = None, *args, **kwargs
+    mpsd_release: str, script_dir: str, msg: str = None, **kwargs
 ) -> None:
     """
     Log the command used to build the toolchains.
@@ -150,6 +155,12 @@ def setup_log_cmd(
         The path to the directory where the scripts are located.
     - msg : str, optional
         An optional message to log in the command log file.
+    - **kwargs : dict
+        A dictionary with values for
+        - spe_branch : str
+            The name of the Spack environments branch.
+        - spe_commit_hash : str
+            The commit hash of the Spack environments branch.
 
     Returns
     -------
@@ -453,18 +464,21 @@ def install_environment(
 
 
 def remove_environment(release, toolchains, target_dir):
+    """Remove release from installation."""
     msg = f"Removing release {release} with toolchains {toolchains} from {target_dir}"
     print(msg)
     raise NotImplementedError(msg)
 
 
 def start_new_environment(release, from_release, target_dir):
+    """Start new MPSD software environment version."""
     msg = f"Starting new release {release} from {from_release} to {target_dir}"
     print(msg)
     raise NotImplementedError(msg)
 
 
 def main():
+    """Execute main entry point."""
     parser = argparse.ArgumentParser(description=about_tool)
     subparsers = parser.add_subparsers(
         dest="action", title="actions", description="valid actions", required=True
diff --git a/tests.py b/tests.py
index b3e7cefb0ee486560ff468ec4497b52d93685c02..04e1e4e099405555cb5837cf6ea7e89f816273f0 100644
--- a/tests.py
+++ b/tests.py
@@ -1,3 +1,5 @@
+"""Tests for mpsd-software-environment.py."""
+
 import importlib
 import os
 import shutil
@@ -10,6 +12,7 @@ mod = importlib.import_module("mpsd-software-environment")
 
 
 def test_os_chdir(tmp_path):
+    """Test the os_chdir context manager."""
     # create a temporary directory for testing
     temp_dir = tmp_path / "test_os_chdir"
     temp_dir.mkdir()
@@ -26,11 +29,13 @@ def test_os_chdir(tmp_path):
 
 
 def test_prepare_environment(tmp_path):
-    # simulate running ./install-software-environment.py --release dev-23a \
-    #   --target-directory /tmp/test_prepare_env
-    # prepare_env is run when cmd is not specified, we can test cmd='prepare'
-    # and cmd=None to check both cases
+    """Simulate running preparation of environment.
 
+    Simulate running ./install-software-environment.py --release dev-23a \
+      --target-directory /tmp/test_prepare_env
+    prepare_env is run when cmd is not specified, we can test cmd='prepare'
+    and cmd=None to check both cases
+    """
     script_dir = tmp_path / "test_prepare_env"
     spack_environments = "spack-environments"
     mpsd_release_to_test = "dev-23a"
@@ -71,7 +76,10 @@ def test_prepare_environment(tmp_path):
 
 
 def test_setup_log_cmd(tmp_path):
-    # check that logs/install-software-environment.log is updated when the module is run
+    """Check that log is updated.
+
+    Check that logs/install-software-environment.log is updated when the module is run
+    """
     log_file = "install.log"
 
     script_dir = tmp_path / "test_prepare_env"
@@ -96,11 +104,13 @@ def test_setup_log_cmd(tmp_path):
 
 
 def test_install_environment(tmp_path):
-    # Test the installation part
-    # This is a long test, its handy to test this with print statements printed to
-    # stdout, use:
-    #   pytest -s
-    # Expect an Exception when wrong toolchains are provided
+    """Test the installation of a toolchain.
+
+    This is a long test, its handy to test this with print statements printed to
+    stdout, use:
+      pytest -s
+    Expect an Exception when wrong toolchains are provided
+    """
     with pytest.raises(Exception):
         mod.install_environment(
             mpsd_release="dev-23a",
@@ -215,6 +225,7 @@ def test_install_environment(tmp_path):
 
 
 def test_interface(tmp_path):
+    """Test other things (not implemented yet)."""
     pass
     # ensure that installing without toolchains only passes the available toolchains
     # check that the script branch and hash are correct when running the script