diff --git a/Cargo.lock b/Cargo.lock
index 42128b6f5..5af92f4b3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -303,6 +303,16 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
 
+[[package]]
+name = "clap_mangen"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17415fd4dfbea46e3274fcd8d368284519b358654772afb700dc2e8d2b24eeb"
+dependencies = [
+ "clap",
+ "roff",
+]
+
 [[package]]
 name = "cmdline_words_parser"
 version = "0.2.1"
@@ -1193,6 +1203,12 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "roff"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3"
+
 [[package]]
 name = "rustix"
 version = "0.38.37"
@@ -1610,6 +1626,7 @@ dependencies = [
  "ci_info",
  "clap",
  "clap_complete",
+ "clap_mangen",
  "dirs",
  "envoy",
  "hamcrest2",
diff --git a/Cargo.toml b/Cargo.toml
index 0f54ce3cf..0a12e1153 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,10 @@
 [package]
 name = "volta"
 version = "2.0.1"
-authors = ["David Herman <david.herman@gmail.com>", "Charles Pierce <cpierce.grad@gmail.com>"]
+authors = [
+    "David Herman <david.herman@gmail.com>",
+    "Charles Pierce <cpierce.grad@gmail.com>",
+]
 license = "BSD-2-Clause"
 repository = "https://github.com/volta-cli/volta"
 edition = "2021"
@@ -38,6 +41,7 @@ textwrap = "0.16.1"
 which = "6.0.3"
 dirs = "5.0.1"
 volta-migrate = { path = "crates/volta-migrate" }
+clap_mangen = "0.2.23"
 
 [target.'cfg(windows)'.dependencies]
 winreg = "0.52.0"
diff --git a/crates/volta-core/src/error/kind.rs b/crates/volta-core/src/error/kind.rs
index 6add88efa..b17840634 100644
--- a/crates/volta-core/src/error/kind.rs
+++ b/crates/volta-core/src/error/kind.rs
@@ -530,6 +530,11 @@ pub enum ErrorKind {
     YarnVersionNotFound {
         matching: String,
     },
+
+    /// Thrown when there is an error writing the man pages to a file
+    ManPagesOutFileError {
+        path: PathBuf,
+    },
 }
 
 impl fmt::Display for ErrorKind {
@@ -1452,6 +1457,14 @@ Please verify your internet connection.",
 Please verify that the version is correct."#,
                 matching
             ),
+            ErrorKind::ManPagesOutFileError { path } => write!(
+                f,
+                "Could not write man pages to {}
+
+{}",
+                path.display(),
+                PERMISSIONS_CTA
+            ),
         }
     }
 }
@@ -1577,6 +1590,7 @@ impl ErrorKind {
             ErrorKind::Yarn2NotSupported => ExitCode::NoVersionMatch,
             ErrorKind::YarnLatestFetchError { .. } => ExitCode::NetworkError,
             ErrorKind::YarnVersionNotFound { .. } => ExitCode::NoVersionMatch,
+            ErrorKind::ManPagesOutFileError { .. } => ExitCode::FileSystemError,
         }
     }
 }
diff --git a/crates/volta-core/src/session.rs b/crates/volta-core/src/session.rs
index 001dddfaf..9536b1290 100644
--- a/crates/volta-core/src/session.rs
+++ b/crates/volta-core/src/session.rs
@@ -38,6 +38,7 @@ pub enum ActivityKind {
     Setup,
     Run,
     Args,
+    ManPages,
 }
 
 impl Display for ActivityKind {
@@ -66,6 +67,7 @@ impl Display for ActivityKind {
             ActivityKind::Which => "which",
             ActivityKind::Run => "run",
             ActivityKind::Args => "args",
+            ActivityKind::ManPages => "man-pages",
         };
         f.write_str(s)
     }
diff --git a/dev/unix/volta-install.sh b/dev/unix/volta-install.sh
index fddaaa616..718c266a6 100755
--- a/dev/unix/volta-install.sh
+++ b/dev/unix/volta-install.sh
@@ -191,6 +191,22 @@ create_tree() {
   fi
 }
 
+generate_man_page() {
+  local install_dir="$1"
+  local man_dir="$install_dir/share/man/man1"
+  
+  info 'Generating' "man page"
+  
+  mkdir -p "$man_dir"
+  
+  if ! "$install_dir/bin/volta" man > "$man_dir/volta.1" 2>/dev/null; then
+    warning "Failed to generate man page. Man pages may not be available."
+    return 1
+  fi
+  
+  info 'Generated' "man page at $man_dir/volta.1"
+}
+
 install_version() {
   local version_to_install="$1"
   local install_dir="$2"
@@ -223,6 +239,7 @@ install_version() {
 
   if [ "$?" == 0 ]
   then
+      generate_man_page "$install_dir"
       if [ "$should_run_setup" == "true" ]; then
         info 'Finished' "installation. Updating user profile settings."
         "$install_dir"/bin/volta setup
diff --git a/src/cli.rs b/src/cli.rs
index 56453cde2..b844f19ad 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -101,6 +101,9 @@ pub(crate) enum Subcommand {
 
     /// Run a command with custom Node, npm, pnpm, and/or Yarn versions
     Run(command::Run),
+
+    /// Man pages
+    Man(command::ManPages),
 }
 
 impl Subcommand {
@@ -116,6 +119,7 @@ impl Subcommand {
             Subcommand::Use(r#use) => r#use.run(session),
             Subcommand::Setup(setup) => setup.run(session),
             Subcommand::Run(run) => run.run(session),
+            Subcommand::Man(man) => man.run(session),
         }
     }
 }
diff --git a/src/command/man_pages.rs b/src/command/man_pages.rs
new file mode 100644
index 000000000..8cae157fb
--- /dev/null
+++ b/src/command/man_pages.rs
@@ -0,0 +1,84 @@
+use std::path::PathBuf;
+
+use clap::CommandFactory;
+use clap_mangen::Man;
+use log::info;
+
+use volta_core::{
+    error::{Context, ErrorKind, ExitCode, Fallible},
+    session::{ActivityKind, Session},
+    style::{note_prefix, success_prefix},
+};
+
+use crate::command::Command;
+
+#[derive(Debug, clap::Args)]
+pub(crate) struct ManPages {
+    /// File to write generated man pages to
+    #[arg(short, long = "output")]
+    out_file: Option<PathBuf>,
+
+    /// Write over an existing file, if any.
+    #[arg(short, long)]
+    force: bool,
+}
+
+impl Command for ManPages {
+    fn run(self, session: &mut Session) -> Fallible<ExitCode> {
+        session.add_event_start(ActivityKind::ManPages);
+
+        let app = crate::cli::Volta::command();
+        let man = Man::new(app);
+
+        match self.out_file {
+            Some(path) => {
+                if path.is_file() && !self.force {
+                    return Err(ErrorKind::ManPagesOutFileError { path }.into());
+                }
+
+                // Create parent directory if it doesn't exist
+                if let Some(parent) = path.parent() {
+                    if !parent.is_dir() {
+                        info!(
+                            "{} {} does not exist, creating it",
+                            note_prefix(),
+                            parent.display()
+                        );
+                        std::fs::create_dir_all(parent).with_context(|| {
+                            ErrorKind::CreateDirError {
+                                dir: parent.to_path_buf(),
+                            }
+                        })?;
+                    }
+                }
+
+                let mut file = std::fs::File::create(&path).with_context(|| {
+                    ErrorKind::ManPagesOutFileError {
+                        path: path.to_path_buf(),
+                    }
+                })?;
+
+                man.render(&mut file)
+                    .map_err(|_e| ErrorKind::ManPagesOutFileError {
+                        path: path.to_path_buf(),
+                    })?;
+
+                info!(
+                    "{} generated man pages to {}",
+                    success_prefix(),
+                    path.display()
+                );
+            }
+            None => {
+                man.render(&mut std::io::stdout()).map_err(|_e| {
+                    ErrorKind::ManPagesOutFileError {
+                        path: PathBuf::from("stdout"),
+                    }
+                })?;
+            }
+        };
+
+        session.add_event_end(ActivityKind::ManPages, ExitCode::Success);
+        Ok(ExitCode::Success)
+    }
+}
diff --git a/src/command/mod.rs b/src/command/mod.rs
index f219fb307..9ff7c1912 100644
--- a/src/command/mod.rs
+++ b/src/command/mod.rs
@@ -2,6 +2,7 @@ pub(crate) mod completions;
 pub(crate) mod fetch;
 pub(crate) mod install;
 pub(crate) mod list;
+pub(crate) mod man_pages;
 pub(crate) mod pin;
 pub(crate) mod run;
 pub(crate) mod setup;
@@ -14,6 +15,7 @@ pub(crate) use completions::Completions;
 pub(crate) use fetch::Fetch;
 pub(crate) use install::Install;
 pub(crate) use list::List;
+pub(crate) use man_pages::ManPages;
 pub(crate) use pin::Pin;
 pub(crate) use r#use::Use;
 pub(crate) use run::Run;