diff --git a/src/cli/add.rs b/src/cli/add.rs
index afcca3c53..1fde21b17 100644
--- a/src/cli/add.rs
+++ b/src/cli/add.rs
@@ -1,9 +1,12 @@
+use crate::environment::update_prefix;
+use crate::prefix::Prefix;
 use crate::{
     environment::{load_lock_file, update_lock_file},
     project::Project,
     virtual_packages::get_minimal_virtual_packages,
 };
 use clap::Parser;
+use console::style;
 use indexmap::IndexMap;
 use itertools::Itertools;
 use miette::{IntoDiagnostic, WrapErr};
@@ -48,6 +51,10 @@ pub struct Args {
     /// This is a build dependency
     #[arg(long, conflicts_with = "host")]
     pub build: bool,
+
+    /// Don't install the package to the environment, only add the package to the lock-file.
+    #[arg(long)]
+    pub no_install: bool,
 }
 
 #[derive(Debug, Copy, Clone)]
@@ -72,13 +79,14 @@ impl SpecType {
 pub async fn execute(args: Args) -> miette::Result<()> {
     let mut project = Project::load_or_else_discover(args.manifest_path.as_deref())?;
     let spec_type = SpecType::from_args(&args);
-    add_specs_to_project(&mut project, args.specs, spec_type).await
+    add_specs_to_project(&mut project, args.specs, spec_type, args.no_install).await
 }
 
 pub async fn add_specs_to_project(
     project: &mut Project,
     specs: Vec<MatchSpec>,
     spec_type: SpecType,
+    no_install: bool,
 ) -> miette::Result<()> {
     // Split the specs into package name and version specifier
     let new_specs = specs
@@ -160,7 +168,7 @@ pub async fn add_specs_to_project(
     }
 
     // Update the lock file and write to disk
-    update_lock_file(
+    let lock_file = update_lock_file(
         project,
         load_lock_file(project).await?,
         Some(sparse_repo_data),
@@ -168,6 +176,20 @@ pub async fn add_specs_to_project(
     .await?;
     project.save()?;
 
+    if !no_install {
+        let platform = Platform::current();
+        if project.platforms().contains(&platform) {
+            // Get the currently installed packages
+            let prefix = Prefix::new(project.root().join(".pixi/env"))?;
+            let installed_packages = prefix.find_installed_packages(None).await?;
+
+            // Update the prefix
+            update_prefix(&prefix, installed_packages, &lock_file, platform).await?;
+        } else {
+            eprintln!("{} skipping installation of environment because your platform ({platform}) is not supported by this project.", style("!").yellow().bold())
+        }
+    }
+
     for spec in added_specs {
         eprintln!(
             "{}Added {}",
diff --git a/src/environment.rs b/src/environment.rs
index 80f101669..43f70cba3 100644
--- a/src/environment.rs
+++ b/src/environment.rs
@@ -68,10 +68,29 @@ pub async fn get_up_to_date_prefix(project: &Project) -> miette::Result<Prefix>
         lock_file
     };
 
+    // Update the environment
+    update_prefix(
+        &prefix,
+        installed_packages_future.await.into_diagnostic()??,
+        &lock_file,
+        platform,
+    )
+    .await?;
+
+    Ok(prefix)
+}
+
+/// Updates the environment to contain the packages from the specified lock-file
+pub async fn update_prefix(
+    prefix: &Prefix,
+    installed_packages: Vec<PrefixRecord>,
+    lock_file: &CondaLock,
+    platform: Platform,
+) -> miette::Result<()> {
     // Construct a transaction to bring the environment up to date with the lock-file content
     let transaction = Transaction::from_current_and_desired(
-        installed_packages_future.await.into_diagnostic()??,
-        get_required_packages(&lock_file, platform)?,
+        installed_packages,
+        get_required_packages(lock_file, platform)?,
         platform,
     )
     .into_diagnostic()?;
@@ -91,8 +110,7 @@ pub async fn get_up_to_date_prefix(project: &Project) -> miette::Result<Prefix>
         )
         .await?;
     }
-
-    Ok(prefix)
+    Ok(())
 }
 
 /// Loads the lockfile for the specified project or returns a dummy one if none could be found.
diff --git a/tests/common/builders.rs b/tests/common/builders.rs
index 8ee47f003..bcdeddc5e 100644
--- a/tests/common/builders.rs
+++ b/tests/common/builders.rs
@@ -92,6 +92,13 @@ impl AddBuilder {
         }
         self
     }
+
+    /// Set whether or not to also install the environment. By default the environment is NOT
+    /// installed to reduce test times.
+    pub fn with_install(mut self, install: bool) -> Self {
+        self.args.no_install = !install;
+        self
+    }
 }
 
 impl IntoFuture for AddBuilder {
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 597181ca4..88bbe747c 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -119,6 +119,7 @@ impl PixiControl {
                 host: false,
                 specs: vec![spec.into()],
                 build: false,
+                no_install: true,
             },
         }
     }
diff --git a/tests/install_tests.rs b/tests/install_tests.rs
index 46ced883d..31af5d27b 100644
--- a/tests/install_tests.rs
+++ b/tests/install_tests.rs
@@ -13,7 +13,7 @@ use tempfile::TempDir;
 async fn install_run_python() {
     let pixi = PixiControl::new().unwrap();
     pixi.init().await.unwrap();
-    pixi.add("python==3.11.0").await.unwrap();
+    pixi.add("python==3.11.0").with_install(true).await.unwrap();
 
     // Check if lock has python version
     let lock = pixi.lock_file().await.unwrap();