diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt
index ddc55ba..f607ea1 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/domain/DesktopService.kt
@@ -157,6 +157,7 @@ fun Prov.provisionIdeDesktop() {
     installDocker()
     aptInstall(JAVA)
     aptInstall(CLOJURE_TOOLS)
+    installNpmByNvm()
     installShadowCljs()
     installDevOps()
     provisionPython()
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScript.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScript.kt
index a3526c0..c6d9d79 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScript.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScript.kt
@@ -6,28 +6,10 @@ import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackag
 
 fun Prov.installShadowCljs(): ProvResult = task {
 
-    if (!isPackageInstalled("npm")) {
-        // installation of npm is too chatty even with quite install and will hang when using Java ProcessBuilder => install with output must be ignored
-        optional {
-            // may fail for some packages, but this should in general not be an issue
-            cmd("sudo apt-get update")
-        }
-        cmd("sudo apt-get install -qy apt-utils")
-        cmd("sudo DEBIAN_FRONTEND=noninteractive apt-get install -qy npm > /dev/null")
-        cmd("sudo npm install -g npx")
-        cmd("sudo npm install -g shadow-cljs")
+    if (!isPackageInstalled("shadow-cljs")) {
+        cmd(". .nvm/nvm.sh && npm install -g shadow-cljs")
+        cmd(". .nvm/nvm.sh && shadow-cljs --help")
     } else {
-        val npmVersion = cmd("npm --version")
-        addResultToEval(ProvResult(true, out = "Package npm v$npmVersion already installed. Checking shadow-cljs now."))
-        if (chk("npm list -g shadow-cljs | grep empty")) {
-            cmd("sudo npm install -g shadow-cljs")
-        } else {
-            addResultToEval(ProvResult(true, out = "Package shadow-cljs already installed."))
-        }
-        if (chk("npm list -g npx|grep empty")) {
-            cmd("sudo npm install -g npx")
-        } else {
-            addResultToEval(ProvResult(true, out = "Package npx already installed."))
-        }
+        ProvResult(true, out = "shadow-cljs already installed")
     }
 }
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/NVMnpm.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/NVMnpm.kt
new file mode 100644
index 0000000..7d63655
--- /dev/null
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/NVMnpm.kt
@@ -0,0 +1,40 @@
+package org.domaindrivenarchitecture.provs.desktop.infrastructure
+
+import org.domaindrivenarchitecture.provs.framework.core.Prov
+import org.domaindrivenarchitecture.provs.framework.core.ProvResult
+import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.addTextToFile
+import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalledCheckCommand
+import java.io.File
+
+fun Prov.installNpmByNvm(): ProvResult = task {
+
+    if (!isPackageInstalledCheckCommand("npm")) {
+        //Node-Version-Manager from https://github.com/nvm-sh/nvm
+        val versNvm = "0.40.1"
+        cmd("sudo curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v$versNvm/install.sh | bash")
+
+        cmd("chmod 755 .nvm/nvm.sh")
+
+        addTextToFile("\n##### NVM #####\n", File("~/.bashrc"))
+        addTextToFile("""export NVM_DIR="${"\$HOME/.nvm"}" """ + "\n", File("~/.bashrc"))
+        addTextToFile("""[ -s "${"\$NVM_DIR/nvm.sh"}" ] && \. "${"\$NVM_DIR/nvm.sh"}" """ + "\n", File("~/.bashrc"))
+        addTextToFile("""[ -s "${"\$NVM_DIR/bash_completion"}" ] && \. "${"\$NVM_DIR/bash_completion"}" """ + "\n", File("~/.bashrc"))
+
+        cmd(". .nvm/nvm.sh && nvm install --lts")
+        //to be discussed, sourcing in docker test container, separtely?
+        val nvmRes = cmd(". .nvm/nvm.sh && nvm --version").toString()
+        if (versNvm == nvmRes) {
+            println("NVM version $versNvm")
+            addResultToEval(ProvResult(true, out = "SUCCESS: NVM version $versNvm installed !!"))
+        } else {
+            println("FAIL: NVM version $versNvm is not installed !!")
+            addResultToEval(ProvResult(true, out = "FAIL: NVM version $versNvm is not installed !!"))
+        }
+        cmd(". .nvm/nvm.sh && node -v")
+        cmd(". .nvm/nvm.sh && npm --version")
+     } else {
+        ProvResult(true, out = "npm already installed")
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt
index 84f41e0..10db980 100644
--- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt
+++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/install/base/Install.kt
@@ -22,16 +22,17 @@ fun Prov.aptInstall(packages: String, ignoreAlreadyInstalled: Boolean = true): P
             if (!aptInit) {
                 optional {
                     // may fail for some packages, but this should in general not be an issue
-                    cmd("sudo apt-get update")
+                    cmd("sudo apt-get update -q=2 && sudo apt-get upgrade -q=2")
                 }
-                cmd("sudo apt-get install -qy apt-utils")
+                cmd("sudo apt-get install -q=2 apt-utils")
                 aptInit = true
             }
         }
 
         for (packg in packageList) {
             // see https://superuser.com/questions/164553/automatically-answer-yes-when-using-apt-get-install
-            cmd("sudo DEBIAN_FRONTEND=noninteractive apt-get install -qy $packg")
+            cmd("sudo apt-get install -q=2 $packg")
+            //DEBIAN_FRONTEND=noninteractive
         }
         ProvResult(true) // dummy
     } else {
@@ -82,6 +83,9 @@ fun Prov.checkPackageInstalled(packageName: String): ProvResult = taskWithResult
     cmd("dpkg -s $packageName")
 }
 
+fun Prov.isPackageInstalledCheckCommand(packageName: String): Boolean {
+    return chk("command -v $packageName")
+}
 
 /**
  * Removes a package including its configuration and data file
diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScriptKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScriptKtTest.kt
index c97b063..1eb057c 100644
--- a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScriptKtTest.kt
+++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/ClojureScriptKtTest.kt
@@ -1,5 +1,6 @@
 package org.domaindrivenarchitecture.provs.desktop.infrastructure
 
+import org.domaindrivenarchitecture.provs.framework.core.processors.ContainerStartMode
 import org.domaindrivenarchitecture.provs.test.defaultTestContainer
 import org.domaindrivenarchitecture.provs.test.tags.ContainerTest
 import org.junit.jupiter.api.Assertions.assertTrue
@@ -11,6 +12,8 @@ internal class ClojureScriptKtTest {
         // given
         val prov = defaultTestContainer()
 
+        prov.installNpmByNvm()
+
         // when
         val res = prov.installShadowCljs()
         val res2 = prov.installShadowCljs()  // check if it can be run twice successfully
diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/NVMnpmKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/NVMnpmKtTest.kt
new file mode 100644
index 0000000..49ababd
--- /dev/null
+++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure/NVMnpmKtTest.kt
@@ -0,0 +1,25 @@
+package org.domaindrivenarchitecture.provs.desktop.infrastructure
+
+import org.domaindrivenarchitecture.provs.framework.core.processors.ContainerStartMode
+import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall
+import org.domaindrivenarchitecture.provs.test.defaultTestContainer
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+
+
+internal class NVMnpmKtTest {
+
+ @Test
+  fun installNVMnpm() {
+     // given
+     val container = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING)
+     container.aptInstall("curl")
+     // when
+     val res01 = container.installNpmByNvm()
+     //test repeatability
+     val res02 = container.installNpmByNvm()
+     // then
+     assertTrue(res01.success)
+     assertTrue(res02.success)
+  }
+}
\ No newline at end of file
diff --git a/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt b/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt
index 08417d0..f66df13 100644
--- a/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt
+++ b/src/testFixtures/kotlin/org/domaindrivenarchitecture/provs/test/TestSetup.kt
@@ -41,7 +41,7 @@ private fun initDefaultTestContainer(startMode: ContainerStartMode): Prov {
 
     containerProv.sh("""
             sudo apt-get update
-            sudo apt-get upgrade -qq
+            sudo apt-get upgrade -q=2
         """.trimIndent())
 
     return containerProv