diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,15 @@
 
 #### Upcoming
 
-#### v0.2.0.1
+#### v0.2.1.0
 
+*Minor*
+
+* Added Bash completion for `--mode` and arguments. ([#13](https://github.com/hjwylde/omnifmt/issues/13))
+
 *Revisions*
 
-* Fixed a bug causing prettifying to fail across filesystem boundaries. ([#14](https://github.com/hjwylde/omnifmt/issues/14))
+* Fixed a bug that disallowed global info options in a non-omnifmt directory. ([#13](https://github.com/hjwylde/omnifmt/issues/13))
 
 #### v0.2.0.0
 
@@ -17,12 +21,6 @@
 *Revisions*
 
 * Changed path outputs to be relative to the root directory. ([#12](https://github.com/hjwylde/omnifmt/issues/12))
-
-#### v0.1.0.1
-
-*Revisions*
-
-* Fixed a bug causing prettifying to fail across filesystem boundaries. ([#14](https://github.com/hjwylde/omnifmt/issues/14))
 
 #### v0.1.0.0
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -105,3 +105,20 @@
 
 **NB:** I haven't tested them fully, be careful in case one is buggy.
 
+### Auto-completion
+
+Add the following (depending on your shell) to include support for auto-completion.
+
+**Bash:**
+
+```bash
+source <(omnifmt --bash-completion-script `which omnifmt`)
+```
+
+**zsh:**
+
+```zsh
+autoload -Uz bashcompinit && bashcompinit
+source <(omnifmt --bash-completion-script `which omnifmt`)
+```
+
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -10,6 +10,7 @@
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 {-# OPTIONS_HADDOCK hide, prune #-}
 
+{-# LANGUAGE BangPatterns          #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
@@ -61,7 +62,7 @@
 
 main :: IO ()
 main = do
-    options     <- customExecParser omnifmtPrefs omnifmtInfo
+    !options    <- customExecParser omnifmtPrefs omnifmtInfo
     let chatty  = if optMode options == Diff then Quiet else optChatty options
 
     flip runLoggingT (log $ optChatty options) . filter chatty $ do
diff --git a/app/Omnifmt/Options.hs b/app/Omnifmt/Options.hs
--- a/app/Omnifmt/Options.hs
+++ b/app/Omnifmt/Options.hs
@@ -21,6 +21,7 @@
 import Data.Char    (isDigit)
 import Data.Version (showVersion)
 
+import Omnifmt.Config  as Config
 import Omnifmt.Version as This
 
 import Options.Applicative
@@ -52,18 +53,20 @@
 
 -- | An optparse parser of a omnifmt command.
 omnifmtInfo :: ParserInfo Options
-omnifmtInfo = info (infoOptions <*> omnifmt) fullDesc
+omnifmtInfo = info (infoOptions <*> omnifmt) (fullDesc <> progDesc')
     where
-        infoOptions = helper <*> version <*> numericVersion
-        version = infoOption ("Version " ++ showVersion This.version) $ mconcat [
+        infoOptions     = helper <*> version <*> numericVersion
+        version         = infoOption ("Version " ++ showVersion This.version) $ mconcat [
             long "version", short 'V', hidden,
             help "Show this binary's version"
             ]
-        numericVersion = infoOption (showVersion This.version) $ mconcat [
+        numericVersion  = infoOption (showVersion This.version) $ mconcat [
             long "numeric-version", hidden,
             help "Show this binary's version (without the prefix)"
             ]
 
+        progDesc' = progDesc $ "Formats the paths given by applying the rules found in the root `" ++ Config.defaultFileName ++ "'"
+
 -- | An options parser.
 omnifmt :: Parser Options
 omnifmt = Options
@@ -84,6 +87,7 @@
     <*> modeOption (mconcat [
         long "mode", short 'm', metavar "MODE",
         value Normal, showDefaultWith $ const "normal",
+        completeWith ["normal", "dry-run", "diff"],
         help "Specify the mode as either `normal', `dry-run' or `diff'"
         ])
     <*> natOption (mconcat [
@@ -92,7 +96,8 @@
         help "Specify the number of threads to use"
         ])
     <*> many (strArgument $ mconcat [
-        metavar "-- PATHS..."
+        metavar "-- PATHS...",
+        action "file"
         ])
     where
         natOption   = option $ readerAsk >>= \opt -> if all isDigit opt
diff --git a/omnifmt.cabal b/omnifmt.cabal
--- a/omnifmt.cabal
+++ b/omnifmt.cabal
@@ -1,5 +1,5 @@
 name:           omnifmt
-version:        0.2.0.1
+version:        0.2.1.0
 
 author:         Henry J. Wylde
 maintainer:     public@hjwylde.com
@@ -33,6 +33,7 @@
 
     default-language: Haskell2010
     other-extensions:
+        BangPatterns
         FlexibleContexts
         MultiParamTypeClasses
         OverloadedStrings
diff --git a/src/Omnifmt/Pipes.hs b/src/Omnifmt/Pipes.hs
--- a/src/Omnifmt/Pipes.hs
+++ b/src/Omnifmt/Pipes.hs
@@ -36,8 +36,6 @@
 import qualified Data.Text        as T
 import           Data.Tuple.Extra (fst3)
 
-import GHC.IO.Exception (IOErrorType (..))
-
 import Omnifmt.Config
 import Omnifmt.Process
 
@@ -47,7 +45,6 @@
 import System.Directory.Extra
 import System.Exit
 import System.FilePath
-import System.IO.Error
 
 -- | A status for a file going through the omnifmt pipeline.
 data Status = Unknown       -- ^ The file has not been processed.
@@ -128,11 +125,7 @@
 --   This function updates the status to 'Prettified'.
 commit :: MonadIO m => Pipe (Status, FilePath, FilePath) (Status, FilePath, FilePath) m ()
 commit = select [Ugly] $ \(_, uglyFilePath, prettyFilePath) -> do
-    -- Try move the file, but if it's across a filesystem boundary then we may need to copy instead
-    liftIO $ renameFile prettyFilePath uglyFilePath `catchIOError` \e ->
-        if ioeGetErrorType e == UnsupportedOperation
-            then copyFile prettyFilePath uglyFilePath >> removeFile prettyFilePath
-            else ioError e
+    liftIO $ renameFile prettyFilePath uglyFilePath
 
     return (Prettified, uglyFilePath, prettyFilePath)
 
