diff --git a/Language/Haskell/Modules.hs b/Language/Haskell/Modules.hs
--- a/Language/Haskell/Modules.hs
+++ b/Language/Haskell/Modules.hs
@@ -79,6 +79,7 @@
       cleanImports
     , splitModule
     , splitModuleDecls
+    , splitModuleBy
     , defaultSymbolToModule
     , mergeModules
     -- * Runtime environment
@@ -115,6 +116,6 @@
 import Language.Haskell.Modules.ModuVerse (findModule, modifyExtensions, putModule)
 import Language.Haskell.Modules.Params (CleanT, extraImport, modifyDryRun, modifyHsFlags, modifyRemoveEmptyImports, modifyTestMode, MonadClean, runCleanT)
 import Language.Haskell.Modules.SourceDirs (modifyDirs, modulePathBase, SourceDirs(putDirs))
-import Language.Haskell.Modules.Split (defaultSymbolToModule, splitModule, splitModuleDecls)
+import Language.Haskell.Modules.Split (defaultSymbolToModule, splitModule, splitModuleDecls, splitModuleBy)
 import Language.Haskell.Modules.Util.QIO (noisily, quietly)
 import Language.Haskell.Modules.Util.Test (findHsFiles, findHsModules) -- (findHsFiles, findHsModules)
diff --git a/Language/Haskell/Modules/Fold.hs b/Language/Haskell/Modules/Fold.hs
--- a/Language/Haskell/Modules/Fold.hs
+++ b/Language/Haskell/Modules/Fold.hs
@@ -1,5 +1,5 @@
 -- | 'foldModule' is a utility function used to implement the clean, split, and merge operations.
-{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, ScopedTypeVariables #-}
+{-# LANGUAGE BangPatterns, CPP, FlexibleContexts, FlexibleInstances, ScopedTypeVariables #-}
 {-# OPTIONS_GHC -Wall #-}
 module Language.Haskell.Modules.Fold
     ( foldModule
diff --git a/Language/Haskell/Modules/ModuVerse.hs b/Language/Haskell/Modules/ModuVerse.hs
--- a/Language/Haskell/Modules/ModuVerse.hs
+++ b/Language/Haskell/Modules/ModuVerse.hs
@@ -45,6 +45,7 @@
 import System.IO.Error (isDoesNotExistError, isUserError)
 
 #if MIN_VERSION_haskell_src_exts(1,14,0)
+nameToExtension :: KnownExtension -> Extension
 nameToExtension x = EnableExtension x
 #else
 deriving instance Ord Extension
diff --git a/Language/Haskell/Modules/SourceDirs.hs b/Language/Haskell/Modules/SourceDirs.hs
--- a/Language/Haskell/Modules/SourceDirs.hs
+++ b/Language/Haskell/Modules/SourceDirs.hs
@@ -104,7 +104,7 @@
            return $ if exists then Just (APath x) else Nothing
     pathKeyMaybe x =
         do mpath <- findFileMaybe x
-           maybe (return Nothing) (\ (APath x) -> liftIO (canonicalizePath x) >>= return . Just . PathKey) mpath
+           maybe (return Nothing) (\ (APath y) -> liftIO (canonicalizePath y) >>= return . Just . PathKey) mpath
 
 findFile :: (SourceDirs m, Path p, Show p) => p -> m APath
 findFile path =
diff --git a/Language/Haskell/Modules/Split.hs b/Language/Haskell/Modules/Split.hs
--- a/Language/Haskell/Modules/Split.hs
+++ b/Language/Haskell/Modules/Split.hs
@@ -3,6 +3,7 @@
 module Language.Haskell.Modules.Split
     ( splitModule
     , splitModuleDecls
+    , splitModuleBy
     , defaultSymbolToModule
     ) where
 
diff --git a/Language/Haskell/Modules/Util/SrcLoc.hs b/Language/Haskell/Modules/Util/SrcLoc.hs
--- a/Language/Haskell/Modules/Util/SrcLoc.hs
+++ b/Language/Haskell/Modules/Util/SrcLoc.hs
@@ -141,6 +141,10 @@
     spanInfo (A.InstSig l _ _) = l
 #endif
     spanInfo (A.AnnPragma l _) = l
+#if MIN_VERSION_haskell_src_exts(1,16,0)
+    spanInfo (A.ClosedTypeFamDecl l _ _ _) = l
+    spanInfo (A.MinimalPragma l _) = l
+#endif
 
 instance HasSpanInfo SrcSpanInfo where
     spanInfo = id
diff --git a/Language/Haskell/Modules/Util/Symbols.hs b/Language/Haskell/Modules/Util/Symbols.hs
--- a/Language/Haskell/Modules/Util/Symbols.hs
+++ b/Language/Haskell/Modules/Util/Symbols.hs
@@ -22,7 +22,9 @@
 
 -- | Do a fold over the names that are declared in a declaration (not
 -- every name that appears, just the ones that the declaration is
--- causing to exist - what's the word for that?  Reify!)
+-- causing to exist - what's the word for that?  Reify!)  The function
+-- argument takes a Maybe because some declarations don't cause a
+-- symbol to become bound - instances, for example.
 class FoldDeclared a where
     foldDeclared :: forall r. (Maybe S.Name -> r -> r) -> r -> a -> r
 
@@ -83,9 +85,9 @@
 #endif
     foldDeclared f r (A.DHParen _ x) = foldDeclared f r x
 instance FoldDeclared (A.ClassDecl a) where
-    foldDeclared f r (A.ClsDecl _ x) = foldDeclared f r x	-- ordinary declaration
-    foldDeclared f r (A.ClsDataFam _ _ x _) = foldDeclared f r x	-- declaration of an associated data type
-    foldDeclared f r (A.ClsTyFam _ x _) = foldDeclared f r x	-- declaration of an associated type synonym
+    foldDeclared f r (A.ClsDecl _ x) = foldDeclared f r x       -- ordinary declaration
+    foldDeclared f r (A.ClsDataFam _ _ x _) = foldDeclared f r x        -- declaration of an associated data type
+    foldDeclared f r (A.ClsTyFam _ x _) = foldDeclared f r x    -- declaration of an associated type synonym
     foldDeclared _ r (A.ClsTyDef _ _ _) = r -- default choice for an associated type synonym
 #if MIN_VERSION_haskell_src_exts(1,16,0)
     foldDeclared f r (A.ClsDefSig _ x _) = foldDeclared f r x -- default signature
@@ -115,53 +117,53 @@
     foldDeclared f r (A.UnQual _ x) = foldDeclared f r x
     foldDeclared _ r (A.Special _ _) = r
 instance FoldDeclared (A.Pat a) where
-    foldDeclared f r (A.PVar _ x) = foldDeclared f r x	-- variable
+    foldDeclared f r (A.PVar _ x) = foldDeclared f r x  -- variable
 #if MIN_VERSION_haskell_src_exts(1,16,0)
-    foldDeclared _ r (A.PLit _ _ _) = r	-- literal constant
+    foldDeclared _ r (A.PLit _ _ _) = r -- literal constant
 #else
-    foldDeclared _ r (A.PLit _ _) = r	-- literal constant
-    foldDeclared f r (A.PNeg _ x) = foldDeclared f r x	-- negated pattern
+    foldDeclared _ r (A.PLit _ _) = r   -- literal constant
+    foldDeclared f r (A.PNeg _ x) = foldDeclared f r x  -- negated pattern
 #endif
-    foldDeclared f r (A.PNPlusK _ x _) = foldDeclared f r x	-- n+k pattern
-    foldDeclared f r (A.PInfixApp _ p1 _qn p2) = let r' = foldDeclared f r p1 in foldDeclared f r' p2	-- pattern with an infix data constructor
-    foldDeclared f r (A.PApp _ _ ps) = foldl (foldDeclared f) r ps	-- data constructor and argument patterns
+    foldDeclared f r (A.PNPlusK _ x _) = foldDeclared f r x     -- n+k pattern
+    foldDeclared f r (A.PInfixApp _ p1 _qn p2) = let r' = foldDeclared f r p1 in foldDeclared f r' p2   -- pattern with an infix data constructor
+    foldDeclared f r (A.PApp _ _ ps) = foldl (foldDeclared f) r ps      -- data constructor and argument patterns
 #if MIN_VERSION_haskell_src_exts(1,14,0)
-    foldDeclared f r (A.PTuple _ _ ps) = foldl (foldDeclared f) r ps	-- tuple pattern
+    foldDeclared f r (A.PTuple _ _ ps) = foldl (foldDeclared f) r ps    -- tuple pattern
 #else
-    foldDeclared f r (A.PTuple _ ps) = foldl (foldDeclared f) r ps	-- tuple pattern
+    foldDeclared f r (A.PTuple _ ps) = foldl (foldDeclared f) r ps      -- tuple pattern
 #endif
-    foldDeclared f r (A.PList _ ps) = foldl (foldDeclared f) r ps	-- list pattern
-    foldDeclared f r (A.PParen _ x) = foldDeclared f r x	-- parenthesized pattern
-    foldDeclared f r (A.PRec _ _qn fs) = foldl (foldDeclared f) r fs	-- labelled pattern, record style
-    foldDeclared f r (A.PAsPat _ x y) = let r' = foldDeclared f r x in foldDeclared f r' y	-- @-pattern
-    foldDeclared _ r (A.PWildCard _) = r	-- wildcard pattern: _
-    foldDeclared f r (A.PIrrPat _ x) = foldDeclared f r x	-- irrefutable pattern: ~pat
-    foldDeclared f r (A.PatTypeSig _ x _) = foldDeclared f r x	-- pattern with type signature
-    foldDeclared f r (A.PViewPat _ _ x) = foldDeclared f r x	-- view patterns of the form (exp -> pat)
-    foldDeclared f r (A.PRPat _ rps) = foldl (foldDeclared f) r rps	-- regular list pattern
-    foldDeclared _f _r (A.PXTag _ _xn _pxs _mp _ps) = error "Unimplemented FoldDeclared instance: PXTag"	-- XML element pattern
-    foldDeclared _f _r (A.PXETag _ _xn _pxs _mp) = error "Unimplemented FoldDeclared instance: PXETag"	-- XML singleton element pattern
-    foldDeclared _f _r (A.PXPcdata _ _s) = error "Unimplemented FoldDeclared instance: XPcdata"	-- XML PCDATA pattern
-    foldDeclared _f _r (A.PXPatTag _ _p) = error "Unimplemented FoldDeclared instance: PXPatTag"	-- XML embedded pattern
-    foldDeclared _f _r (A.PXRPats _ _rps) = error "Unimplemented FoldDeclared instance: PXRPats"	-- XML regular list pattern
+    foldDeclared f r (A.PList _ ps) = foldl (foldDeclared f) r ps       -- list pattern
+    foldDeclared f r (A.PParen _ x) = foldDeclared f r x        -- parenthesized pattern
+    foldDeclared f r (A.PRec _ _qn fs) = foldl (foldDeclared f) r fs    -- labelled pattern, record style
+    foldDeclared f r (A.PAsPat _ x y) = let r' = foldDeclared f r x in foldDeclared f r' y      -- @-pattern
+    foldDeclared _ r (A.PWildCard _) = r        -- wildcard pattern: _
+    foldDeclared f r (A.PIrrPat _ x) = foldDeclared f r x       -- irrefutable pattern: ~pat
+    foldDeclared f r (A.PatTypeSig _ x _) = foldDeclared f r x  -- pattern with type signature
+    foldDeclared f r (A.PViewPat _ _ x) = foldDeclared f r x    -- view patterns of the form (exp -> pat)
+    foldDeclared f r (A.PRPat _ rps) = foldl (foldDeclared f) r rps     -- regular list pattern
+    foldDeclared _f _r (A.PXTag _ _xn _pxs _mp _ps) = error "Unimplemented FoldDeclared instance: PXTag"        -- XML element pattern
+    foldDeclared _f _r (A.PXETag _ _xn _pxs _mp) = error "Unimplemented FoldDeclared instance: PXETag"  -- XML singleton element pattern
+    foldDeclared _f _r (A.PXPcdata _ _s) = error "Unimplemented FoldDeclared instance: XPcdata" -- XML PCDATA pattern
+    foldDeclared _f _r (A.PXPatTag _ _p) = error "Unimplemented FoldDeclared instance: PXPatTag"        -- XML embedded pattern
+    foldDeclared _f _r (A.PXRPats _ _rps) = error "Unimplemented FoldDeclared instance: PXRPats"        -- XML regular list pattern
 #if !MIN_VERSION_haskell_src_exts(1,15,0)
-    foldDeclared _f _r (A.PExplTypeArg _ _n _t) = error "Unimplemented FoldDeclared instance: PExplTypeArg"	-- Explicit generics style type argument e.g. f {| Int |} x = ...
+    foldDeclared _f _r (A.PExplTypeArg _ _n _t) = error "Unimplemented FoldDeclared instance: PExplTypeArg"     -- Explicit generics style type argument e.g. f {| Int |} x = ...
 #endif
-    foldDeclared _ r (A.PQuasiQuote _ _ _) = r	-- quasi quote pattern: [$name| string |]
-    foldDeclared f r (A.PBangPat _ x) = foldDeclared f r x	-- strict (bang) pattern: f !x = ...
+    foldDeclared _ r (A.PQuasiQuote _ _ _) = r  -- quasi quote pattern: [$name| string |]
+    foldDeclared f r (A.PBangPat _ x) = foldDeclared f r x      -- strict (bang) pattern: f !x = ...
 instance FoldDeclared (A.PatField a) where
-    foldDeclared f r (A.PFieldPat _ _n x) = foldDeclared f r x 	-- ordinary label-pattern pair
-    foldDeclared f r (A.PFieldPun _ x) = foldDeclared f r x 	-- record field pun
+    foldDeclared f r (A.PFieldPat _ _n x) = foldDeclared f r x  -- ordinary label-pattern pair
+    foldDeclared f r (A.PFieldPun _ x) = foldDeclared f r x     -- record field pun
     foldDeclared _ r (A.PFieldWildcard _) = r
 instance FoldDeclared (A.RPat a) where
-    foldDeclared f r (A.RPOp _ x _) = foldDeclared f r x	-- operator pattern, e.g. pat*
-    foldDeclared f r (A.RPEither _ x y) = let r' = foldDeclared f r x in foldDeclared f r' y 	-- choice pattern, e.g. (1 | 2)
-    foldDeclared f r (A.RPSeq _ xs) = foldl (foldDeclared f) r xs	-- sequence pattern, e.g. (| 1, 2, 3 |)
-    foldDeclared f r (A.RPGuard _ x _) = foldDeclared f r x	-- guarded pattern, e.g. (| p | p < 3 |)
-    foldDeclared f r (A.RPCAs _ n x) = let r' = foldDeclared f r n in foldDeclared f r' x 	-- non-linear variable binding, e.g. (foo@:(1 | 2))*
-    foldDeclared f r (A.RPAs _ n x) = let r' = foldDeclared f r n in foldDeclared f r' x  	-- linear variable binding, e.g. foo@(1 | 2)
-    foldDeclared f r (A.RPParen _ x) = foldDeclared f r x	-- parenthesised pattern, e.g. (2*)
-    foldDeclared f r (A.RPPat _ x) = foldDeclared f r x	-- an ordinary pattern
+    foldDeclared f r (A.RPOp _ x _) = foldDeclared f r x        -- operator pattern, e.g. pat*
+    foldDeclared f r (A.RPEither _ x y) = let r' = foldDeclared f r x in foldDeclared f r' y    -- choice pattern, e.g. (1 | 2)
+    foldDeclared f r (A.RPSeq _ xs) = foldl (foldDeclared f) r xs       -- sequence pattern, e.g. (| 1, 2, 3 |)
+    foldDeclared f r (A.RPGuard _ x _) = foldDeclared f r x     -- guarded pattern, e.g. (| p | p < 3 |)
+    foldDeclared f r (A.RPCAs _ n x) = let r' = foldDeclared f r n in foldDeclared f r' x       -- non-linear variable binding, e.g. (foo@:(1 | 2))*
+    foldDeclared f r (A.RPAs _ n x) = let r' = foldDeclared f r n in foldDeclared f r' x        -- linear variable binding, e.g. foo@(1 | 2)
+    foldDeclared f r (A.RPParen _ x) = foldDeclared f r x       -- parenthesised pattern, e.g. (2*)
+    foldDeclared f r (A.RPPat _ x) = foldDeclared f r x -- an ordinary pattern
 
 instance FoldDeclared (A.Name l) where
     foldDeclared f r x = f (Just (sName x)) r
@@ -251,9 +253,9 @@
 
 -- Constructors and field names
 instance FoldDeclared (A.ConDecl l) where
-    foldDeclared f r (A.ConDecl _ x _ts) = foldDeclared f r x	-- ordinary data constructor
-    foldDeclared f r (A.InfixConDecl _ _t1 x _t2) = foldDeclared f r x	-- infix data constructor
-    foldDeclared f r (A.RecDecl _ x fs) = let r' = foldDeclared f r x in foldl (foldDeclared f) r' fs 	-- record constructor
+    foldDeclared f r (A.ConDecl _ x _ts) = foldDeclared f r x   -- ordinary data constructor
+    foldDeclared f r (A.InfixConDecl _ _t1 x _t2) = foldDeclared f r x  -- infix data constructor
+    foldDeclared f r (A.RecDecl _ x fs) = let r' = foldDeclared f r x in foldl (foldDeclared f) r' fs   -- record constructor
 
 instance FoldDeclared (A.FieldDecl l) where
     foldDeclared f r (A.FieldDecl _ xs _) = foldl (foldDeclared f) r xs
diff --git a/module-management.cabal b/module-management.cabal
--- a/module-management.cabal
+++ b/module-management.cabal
@@ -1,5 +1,5 @@
 Name:               module-management
-Version:            0.20.3
+Version:            0.20.4
 Synopsis:           Clean up module imports, split and merge modules
 Description:        Clean up module imports, split and merge modules.
 Homepage:           https://github.com/seereason/module-management
@@ -544,11 +544,14 @@
     cmdargs,
     directory,
     haskeline,
+    haskell-src-exts,
     lens,
     module-management,
     monad-control,
     mtl,
+    regex-compat,
     set-extra,
+    template-haskell,
     transformers-base
 
   -- In ghc-7.6.3, -O0 prevents one of two failures: either a GHC out
diff --git a/scripts/CLI.hs b/scripts/CLI.hs
--- a/scripts/CLI.hs
+++ b/scripts/CLI.hs
@@ -15,17 +15,17 @@
 import Data.Char (toLower)
 import qualified Data.Set as S (member, toList, map)
 import Data.Set.Extra as Set (Set, toList)
-#if MIN_VERSION_Cabal(1,21,0)
-import Distribution.InstalledPackageInfo (ModuleReexport(..))
-#endif
 import Distribution.Package (InstalledPackageId(..))
 import GHC.Generics (Generic)
-import Language.Haskell.Modules (cleanImports, CleanT, findHsModules, mergeModules, modifyDirs, ModuleName(..), MonadClean, noisily, putDirs, putModule, runCleanT, splitModuleDecls)
-import Language.Haskell.Modules.ModuVerse (getNames)
+import Language.Haskell.Exts.Syntax (Name(Ident, Symbol))
+import Language.Haskell.Modules (cleanImports, CleanT, findHsModules, mergeModules, modifyDirs, ModuleName(..), MonadClean, noisily, putDirs, putModule, runCleanT, splitModuleDecls, splitModuleBy)
+import Language.Haskell.Modules.ModuVerse (getNames, getInfo, moduleName)
 import Language.Haskell.Modules.SourceDirs (getDirs)
 import Language.Haskell.Modules.Util.QIO (modifyVerbosity)
+import Language.Haskell.TH.Syntax as TH (nameBase)
 import System.Console.Haskeline (completeFilename, CompletionFunc, defaultSettings, getInputLine, InputT, noCompletion, runInputT, setComplete, simpleCompletion)
 import System.IO (hPutStrLn, stderr)
+import Text.Regex (mkRegex, matchRegex)
 
 import System.Console.CmdArgs
 import Control.Lens
@@ -207,15 +207,15 @@
 cmd :: [String] -> CmdM ()
 cmd [] = cli
 cmd (s : args) =
-      case filter (any (== s) . fst) cmds of
-        [(_, f)] -> f
+      case filter (any (== s) . names) cmds of
+        [x] -> action x
         -- No exact matches - look for prefix matches
-        [] -> case filter (any (isPrefixOf s) . fst) cmds of
-                [(_, f)] -> f
+        [] -> case filter (any (isPrefixOf s) . names) cmds of
+                [x] -> action x
                 [] -> liftIO (hPutStrLn stderr $
-                                show s ++ " invalid - expected " ++ intercalate ", " (concatMap fst cmds)) >> cli
+                                show s ++ " invalid - expected " ++ intercalate ", " (concatMap names cmds)) >> cli
                 xs -> liftIO (hPutStrLn stderr $
-                                show s ++ " ambiguous - expected " ++ intercalate ", " (concatMap fst xs)) >> cli
+                                show s ++ " ambiguous - expected " ++ intercalate ", " (concatMap names xs) ++ "\n\n" ) >> cli
         _ -> error $ "Internal error - multiple definitions for " ++ show s
         where
         cmds = cmds_ args
@@ -226,31 +226,79 @@
     show (Callback x _) = x
 instance Exception Callback
 
+data Command
+    = Command
+       { names :: [String]
+       , action :: CmdM ()
+       , usage :: String }
+
 commandNames :: [String]
-commandNames = concatMap fst (cmds_ undefined)
+commandNames = concatMap names (cmds_ undefined)
 
-cmds_ :: [String] -> [([String], CmdM ())]
+cmds_ :: [String] -> [Command]
 cmds_ args =
-          [(["quit", "exit", "bye", ".", "\EOT"], do
-                liftIO (hPutStrLn stderr "Exiting")
-                throwIO ExitSuccess),
-           (["v"], throwIO . Callback "louder" $ \next -> do
-                    liftIO (hPutStrLn stderr "Increasing Verbosity")
-                    noisily' next),
-           (["q"], throwIO . Callback "quieter" $ \next -> do
-                    liftIO (hPutStrLn stderr "Decreasing Verbosity")
-                    quietly' next),
+          [Command { names = ["quit", "exit", "bye", ".", "\EOT"],
+                     action = do liftIO (hPutStrLn stderr "Exiting")
+                                 throwIO ExitSuccess,
+                     usage = "quit\n" ++ "Exit the interpreter." },
+           Command { names = ["v"],
+                     action = throwIO . Callback "louder" $ \next -> do
+                                liftIO (hPutStrLn stderr "Increasing Verbosity")
+                                noisily' next,
+                     usage = "v\n" ++ "Increase the verbosity of the interpreter messages" },
+           Command { names = ["q"],
+                     action = throwIO . Callback "quieter" $ \next -> do
+                                liftIO (hPutStrLn stderr "Decreasing Verbosity")
+                                quietly' next,
+                     usage = "q\n" ++ "Decrease the verbosity of the interpreter messages" },
            -- The error message is more helpful
-           -- (["help"],  liftIO (hPutStrLn stderr "help text")),
-           (["verse"], liftCT (verse args)),
-           (["clean"], liftCT (clean args)),
-           (["dir"],   liftCT (dir args)),
-           (["split"], split args),
-           (["merge"], merge args),
-           (["cabalPrint"], cabalPrint),
-           (["cabalRead"], cabalRead args),
-           (["cabalWrite"], cabalWrite args)]
+           Command { names = ["help"],
+                     action = liftIO (hPutStrLn stderr helpMessage),
+                     usage = "help\n" ++ "Print usage information.  Remember that this script doesn't understand shell escaping and quoting." },
+           Command { names = ["verse"],
+                     action = liftCT (verse args),
+                     usage = "verse <pathormodule1> <pathormodule2> ...\n" ++
+                             "Add the module or all the modules below a directory to the module universe.  " ++
+                             "This is the set of modules whose references will be updated when a symbol " ++
+                             "is moved from one module to another." },
+           Command { names = ["clean"],
+                     action =  liftCT (clean args),
+                     usage = "clean <modulepath1> <modulepath2> ...\n" ++
+                             "Clean up the import lists of the named modules" },
+           Command { names = ["dir"],
+                     action =    liftCT (dir args),
+                     usage = "dir <directory> <directory> ...\n" ++
+                             "Add paths to the list of search directories - similar to the ghc -i option." },
+           Command { names = ["split"],
+                     action =  split args,
+                     usage = "split <modulepath>\n" ++
+                             "Split each of the symbols in a module into individual sub-modules.  Updates all\n" ++
+                             "references to these symbols throughout the moduverse." },
+           Command { names = ["splitBy"],
+                     action =  splitBy args,
+                     usage = "splitBy <regex> <newmodule> <oldmodule>\n" ++
+                             "Partition the symbols of a module into new modules based on the function\n" ++
+                             "mapping the symbol name to the new module name.  For example,\n" ++
+                             "split '(\\ s -> case s of \"foo\" -> \"Module.One\"; _ -> \"Module.Two\")' Module.Orig\n" ++
+                             "Updates all references to these symbols throughout the moduverse." },
+           Command { names = ["merge"],
+                     action =  merge args,
+                     usage = "merge <inputmodulepath1> <inputmodulepath2> ... <outputmodulepath>\n" ++
+                             "Merge the given input modules into a single output module.  Updates all\n" ++
+                             "references to these symbols throughout the moduverse." },
+           Command { names = ["cabalPrint"],
+                     action =  cabalPrint,
+                     usage = "" },
+           Command {names = ["cabalRead"],
+                     action =  cabalRead args,
+                     usage = "" },
+           Command {names = ["cabalWrite"],
+                     action =  cabalWrite args,
+                     usage = "" }]
 
+helpMessage :: String
+helpMessage = intercalate "\n\n" (map usage (cmds_ undefined))
+
 cabalPrint :: CmdM ()
 cabalPrint = do
     pkgDesc <- liftS get
@@ -318,15 +366,34 @@
        liftIO (putStrLn $ "sourceDirs updated:\n  [ " ++ intercalate "\n  , " xs' ++ " ]")
 
 clean :: MonadClean m => [FilePath] -> m ()
-clean [] = liftIO $ putStrLn "Usage: clean <modulepath1> <modulepath2> ..."
+clean [] = liftIO $ putStrLn $ "Usage: clean <modulepath1> <modulepath2> ...\n" ++
+                                    "Clean up the import lists of the named modules\n"
 clean args = cleanImports args >> return ()
 
-split :: [FilePath] -> CmdM ()
+split :: [String] -> CmdM ()
 split [arg] = do
     r <- liftCT (splitModuleDecls arg)
     lift (modify (Cabal.update r))
     return ()
 split _ = liftIO $ putStrLn "Usage: split <modulepath>"
+
+splitBy :: [String] -> CmdM ()
+splitBy [regex, newModule, oldModule] = do
+  r <- liftCT (getInfo (ModuleName oldModule) >>= maybe (error $ "Module not found: " ++ show oldModule) (\ oldModuleInfo -> splitModuleBy pred oldModuleInfo))
+  lift (modify (Cabal.update r))
+  return ()
+    where
+      pred :: Maybe Name -> ModuleName
+      pred name =
+          -- declarations not associated with symbols stay in
+          -- oldModules (e.g. instances.)  Decarations of matching
+          -- symbols go to newModule
+          let match = name >>= (\ x -> Just $ case x of Ident s -> s; Symbol s -> s) >>= matchRegex (mkRegex regex)
+              modname = ModuleName (maybe oldModule (const newModule) match) in
+          {- trace ("Symbol " ++ show name ++ " -> " ++ show modname ++ ", matchRegex (mkRegex " ++ show regex ++ ") -> " ++ show match)-}
+                modname
+
+splitBy _ = liftIO $ putStrLn "Usage: splitBy <regexp> <newmodule> <oldmodule>"
 
 merge :: [String] -> CmdM ()
 merge args =
diff --git a/scripts/CLI/Cabal.hs b/scripts/CLI/Cabal.hs
--- a/scripts/CLI/Cabal.hs
+++ b/scripts/CLI/Cabal.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE FlexibleContexts, ViewPatterns #-}
 -- | Adjust contents of a cabal file to follow
 -- rearrangements of the underlying modules
 module CLI.Cabal (
