diff --git a/System/Process.hs b/System/Process.hs
--- a/System/Process.hs
+++ b/System/Process.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE CPP, ForeignFunctionInterface #-}
+{-# LANGUAGE LambdaCase #-}
 #if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
 #else
@@ -31,23 +32,57 @@
 
 module System.Process (
     -- * Running sub-processes
+
+    -- ** General interface to process creation
+
+    -- | @createProcess@ and @createProcess_@ are general interfaces
+    -- to process creation. To start with might instead want to use
+    -- one of the [simpler process creation functions](#g:simpler)
+    -- below.
+
     createProcess,
     createProcess_,
+
+    -- ** Creating a @CreateProcess@
+
+    -- | Once you have a @CreateProcess@ you can launch it with
+    -- 'createProcess' or one of the [simpler process creation
+    -- functions](#g:simpler).
+
     shell, proc,
+
+    -- ** @CreateProcess@ and associated types
+
     CreateProcess(..),
     CmdSpec(..),
     StdStream(..),
     ProcessHandle,
 
-    -- ** Simpler functions for common tasks
+    -- * Simpler functions for common tasks #simpler#
+
+    -- ** Call, the simplest way of launching a process
+
+    callCreateProcess,
     callProcess,
     callCommand,
+
+    -- ** Spawn, obtaining a @ProcessHandle@
+
     spawnProcess,
     spawnCommand,
+
+    -- ** Read, passing @stdin@ and obtaining @stdout@
+
     readCreateProcess,
     readProcess,
+
+    -- ** Read with exit code, passing @stdin@, obtaining exit code, @stdout@ and @stderr@
+
     readCreateProcessWithExitCode,
     readProcessWithExitCode,
+
+    -- ** Other
+
     withCreateProcess,
     cleanupProcess,
 
@@ -337,43 +372,47 @@
 -- ----------------------------------------------------------------------------
 -- callProcess/callCommand
 
--- | Creates a new process to run the specified command with the given
--- arguments, and wait for it to finish.  If the command returns a non-zero
--- exit code, an exception is raised.
+-- | Creates a new process from the provided `CreateProcess`, and wait for it
+-- to finish.  If the process returns a non-zero exit code, an exception is
+-- raised.
 --
 -- If an asynchronous exception is thrown to the thread executing
--- @callProcess@, the forked process will be terminated and
--- @callProcess@ will wait (block) until the process has been
+-- @callCreateProcess@, the forked process will be terminated and
+-- @callCreateProcess@ will wait (block) until the process has been
 -- terminated.
 --
+-- @since TODO
+callCreateProcess :: CreateProcess -> IO ()
+callCreateProcess = callCreateProcess_ "callCreateProcess"
+
+-- | \"@callProcess cmd args@\" is a shorthand for
+-- \"@'callCreateProcess' ('proc' cmd args)@\".
+--
 -- @since 1.2.0.0
 callProcess :: FilePath -> [String] -> IO ()
-callProcess cmd args = do
-    exit_code <- withCreateProcess_ "callProcess"
-                   (proc cmd args) { delegate_ctlc = True } $ \_ _ _ p ->
-                   waitForProcess p
-    case exit_code of
-      ExitSuccess   -> return ()
-      ExitFailure r -> processFailedException "callProcess" cmd args r
+callProcess cmd = callCreateProcess_ "callProcess" . proc cmd
 
--- | Creates a new process to run the specified shell command.  If the
--- command returns a non-zero exit code, an exception is raised.
---
--- If an asynchronous exception is thrown to the thread executing
--- @callCommand@, the forked process will be terminated and
--- @callCommand@ will wait (block) until the process has been
--- terminated.
+-- | \"@callCommand cmd@\" is a shorthand for \"@'callCreateProcess'
+-- ('shell' cmd)@\".
 --
 -- @since 1.2.0.0
 callCommand :: String -> IO ()
-callCommand cmd = do
-    exit_code <- withCreateProcess_ "callCommand"
-                   (shell cmd) { delegate_ctlc = True } $ \_ _ _ p ->
+callCommand = callCreateProcess_ "callCommand" . shell
+
+callCreateProcess_ :: String -> CreateProcess -> IO ()
+callCreateProcess_ fun command = do
+    exit_code <- withCreateProcess_ fun
+                   command { delegate_ctlc = True } $ \_ _ _ p ->
                    waitForProcess p
     case exit_code of
       ExitSuccess   -> return ()
-      ExitFailure r -> processFailedException "callCommand" cmd [] r
+      ExitFailure r -> processFailed fun (cmdspec command) r
 
+processFailed :: String -> CmdSpec -> Int -> IO a
+processFailed fun = \ case
+    ShellCommand cmd -> processFailedException fun cmd []
+    RawCommand cmd args -> processFailedException fun cmd args
+
 processFailedException :: String -> String -> [String] -> Int -> IO a
 processFailedException fun cmd args exit_code =
       ioError (mkIOError OtherError (fun ++ ": " ++ cmd ++
@@ -574,14 +613,7 @@
 
     case ex of
      ExitSuccess   -> return output
-     ExitFailure r -> processFailedException "readCreateProcess" cmd args r
-  where
-    cmd = case cp of
-            CreateProcess { cmdspec = ShellCommand sc } -> sc
-            CreateProcess { cmdspec = RawCommand fp _ } -> fp
-    args = case cp of
-             CreateProcess { cmdspec = ShellCommand _ } -> []
-             CreateProcess { cmdspec = RawCommand _ args' } -> args'
+     ExitFailure r -> processFailed "readCreateProcess" (cmdspec cp) r
 
 
 -- | @readProcessWithExitCode@ is like 'readProcess' but with two differences:
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
 # Changelog for [`process` package](http://hackage.haskell.org/package/process)
 
+## 1.6.28.0 *April 2026*
+
+* Add `callCreateProcess`
+* Improve Haddock
+
 ## 1.6.27.0 *March 2026*
 
 * Support being configured without fork
diff --git a/process.cabal b/process.cabal
--- a/process.cabal
+++ b/process.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.4
 name:          process
-version:       1.6.27.0
+version:       1.6.28.0
 -- NOTE: Don't forget to update ./changelog.md
 license:       BSD-3-Clause
 license-file:  LICENSE
