diff --git a/morpheus-graphql-code-gen-utils.cabal b/morpheus-graphql-code-gen-utils.cabal
--- a/morpheus-graphql-code-gen-utils.cabal
+++ b/morpheus-graphql-code-gen-utils.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           morpheus-graphql-code-gen-utils
-version:        0.26.0
+version:        0.27.0
 synopsis:       Morpheus GraphQL CLI
 description:    code generator for Morpheus GraphQL
 category:       web, graphql, cli
@@ -32,6 +32,7 @@
       Data.Morpheus.CodeGen.TH
       Data.Morpheus.CodeGen.Utils
   other-modules:
+      Data.Morpheus.CodeGen.Internal.Flags
       Data.Morpheus.CodeGen.Internal.Name
       Paths_morpheus_graphql_code_gen_utils
   hs-source-dirs:
@@ -41,7 +42,8 @@
       base >=4.7.0 && <5.0.0
     , bytestring >=0.10.4 && <0.12.0
     , containers >=0.4.2.1 && <0.7.0
-    , morpheus-graphql-core >=0.26.0 && <0.27.0
+    , morpheus-graphql-core >=0.27.0 && <0.28.0
+    , mtl >=2.0.0 && <3.0.0
     , prettyprinter >=1.7.0 && <2.0.0
     , relude >=0.3.0 && <2.0.0
     , template-haskell >=2.0.0 && <3.0.0
diff --git a/src/Data/Morpheus/CodeGen/Internal/AST.hs b/src/Data/Morpheus/CodeGen/Internal/AST.hs
--- a/src/Data/Morpheus/CodeGen/Internal/AST.hs
+++ b/src/Data/Morpheus/CodeGen/Internal/AST.hs
@@ -23,6 +23,7 @@
   )
 where
 
+import qualified Data.HashMap.Lazy as HM
 import Data.Morpheus.CodeGen.Internal.Name (camelCaseTypeName)
 import Data.Morpheus.CodeGen.Printer
 import Data.Morpheus.Types.Internal.AST
@@ -33,6 +34,7 @@
     TypeWrapper,
     unpackName,
   )
+import qualified Data.Set as S
 import qualified Data.Text as T
 import Language.Haskell.TH.Syntax (Lift)
 import qualified Language.Haskell.TH.Syntax as TH
@@ -200,7 +202,7 @@
 instance Pretty dec => Pretty (ModuleDefinition dec) where
   pretty ModuleDefinition {..} =
     vsep
-      (map renderExtension extensions)
+      (map renderExtension (sort extensions))
       <> line
       <> line
       <> "module"
@@ -208,7 +210,7 @@
       <+> "where"
         <> line
         <> line
-        <> vsep (map renderImport $ sortWith fst imports)
+        <> vsep (map renderImport $ organizeImports imports)
         <> line
         <> line
         <> vsep (filter notEmpty $ map pretty types)
@@ -220,6 +222,17 @@
 renderExtension txt
   | T.isPrefixOf "{-#" txt = pretty txt
   | otherwise = "{-#" <+> "LANGUAGE" <+> pretty txt <+> "#-}"
+
+organizeImports :: [(Text, [Text])] -> [(Text, [Text])]
+organizeImports xs = sortWith fst $ HM.toList $ fmap (sort . toList) (groupImports xs)
+
+groupImports :: [(Text, [Text])] -> HashMap Text (Set Text)
+groupImports = foldr insertImport mempty
+
+insertImport :: (Text, [Text]) -> HashMap Text (Set Text) -> HashMap Text (Set Text)
+insertImport (moduleName, names) = HM.alter f moduleName
+  where
+    f x = Just (S.fromList names <> fromMaybe mempty x)
 
 renderImport :: (Text, [Text]) -> Doc ann
 renderImport (src, ls) = "import" <+> pretty src <> renderImportList ls
diff --git a/src/Data/Morpheus/CodeGen/Internal/Flags.hs b/src/Data/Morpheus/CodeGen/Internal/Flags.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/CodeGen/Internal/Flags.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module Data.Morpheus.CodeGen.Internal.Flags
+  ( Flags,
+    Flag (..),
+    runCodeGenT,
+    CodeGenT,
+    langExtension,
+    requireExternal,
+  )
+where
+
+import Control.Monad.Except
+import Data.Morpheus.Types.Internal.AST (GQLError)
+import Data.Text
+import Relude hiding (ByteString, get)
+
+type Flags = [Flag]
+
+data Flag
+  = FlagLanguageExtension Text
+  | FlagExternal Text
+  deriving (Ord, Eq, Show)
+
+newtype CodeGenT ctx (m :: Type -> Type) a = CodeGenT
+  { _runCodeGenT :: ReaderT ctx (StateT Flags m) a
+  }
+  deriving newtype
+    ( Functor,
+      Applicative,
+      Monad,
+      MonadFail,
+      MonadReader ctx,
+      MonadState
+        Flags
+    )
+
+deriving instance MonadError GQLError m => MonadError GQLError (CodeGenT ctx m)
+
+instance MonadTrans (CodeGenT ctx) where
+  lift = CodeGenT . lift . lift
+
+runCodeGenT :: Monad m => CodeGenT ctx m a -> ctx -> m (a, Flags)
+runCodeGenT (CodeGenT m) ctx = runStateT (runReaderT m ctx) mempty
+
+langExtension :: MonadState Flags m => Text -> m ()
+langExtension ext = modify (FlagLanguageExtension ext :)
+
+requireExternal :: MonadState Flags m => Text -> m ()
+requireExternal ext = modify (FlagExternal ext :)
diff --git a/src/Data/Morpheus/CodeGen/TH.hs b/src/Data/Morpheus/CodeGen/TH.hs
--- a/src/Data/Morpheus/CodeGen/TH.hs
+++ b/src/Data/Morpheus/CodeGen/TH.hs
@@ -49,13 +49,13 @@
     toHaskellTypeName,
   )
 import Data.Morpheus.Types.Internal.AST
-  ( FieldName,
+  ( DirectiveLocation (..),
+    FieldName,
     TypeName,
     TypeRef (..),
     TypeWrapper (..),
     unpackName,
   )
-import qualified Data.Morpheus.Types.Internal.AST as AST
 import qualified Data.Text as T
 import Language.Haskell.TH
 import Relude hiding
@@ -295,25 +295,25 @@
 instance PrintType CodeGenTypeName where
   printType name = applyVars (toName name) (map toName $ typeParameters name)
 
-instance ToName AST.DirectiveLocation where
-  toName AST.QUERY = 'AST.QUERY
-  toName AST.MUTATION = 'AST.MUTATION
-  toName AST.SUBSCRIPTION = 'AST.SUBSCRIPTION
-  toName AST.FIELD = 'AST.FIELD
-  toName AST.FRAGMENT_DEFINITION = 'AST.FRAGMENT_DEFINITION
-  toName AST.FRAGMENT_SPREAD = 'AST.FRAGMENT_SPREAD
-  toName AST.INLINE_FRAGMENT = 'AST.INLINE_FRAGMENT
-  toName AST.SCHEMA = 'AST.SCHEMA
-  toName AST.SCALAR = 'AST.SCALAR
-  toName AST.OBJECT = 'AST.OBJECT
-  toName AST.FIELD_DEFINITION = 'AST.FIELD_DEFINITION
-  toName AST.ARGUMENT_DEFINITION = 'AST.ARGUMENT_DEFINITION
-  toName AST.INTERFACE = 'AST.INTERFACE
-  toName AST.UNION = 'AST.UNION
-  toName AST.ENUM = 'AST.ENUM
-  toName AST.ENUM_VALUE = 'AST.ENUM_VALUE
-  toName AST.INPUT_OBJECT = 'AST.INPUT_OBJECT
-  toName AST.INPUT_FIELD_DEFINITION = 'AST.INPUT_FIELD_DEFINITION
+instance ToName DirectiveLocation where
+  toName LOCATION_QUERY = 'LOCATION_QUERY
+  toName LOCATION_MUTATION = 'LOCATION_MUTATION
+  toName LOCATION_SUBSCRIPTION = 'LOCATION_SUBSCRIPTION
+  toName LOCATION_FIELD = 'LOCATION_FIELD
+  toName LOCATION_FRAGMENT_DEFINITION = 'LOCATION_FRAGMENT_DEFINITION
+  toName LOCATION_FRAGMENT_SPREAD = 'LOCATION_FRAGMENT_SPREAD
+  toName LOCATION_INLINE_FRAGMENT = 'LOCATION_INLINE_FRAGMENT
+  toName LOCATION_SCHEMA = 'LOCATION_SCHEMA
+  toName LOCATION_SCALAR = 'LOCATION_SCALAR
+  toName LOCATION_OBJECT = 'LOCATION_OBJECT
+  toName LOCATION_FIELD_DEFINITION = 'LOCATION_FIELD_DEFINITION
+  toName LOCATION_ARGUMENT_DEFINITION = 'LOCATION_ARGUMENT_DEFINITION
+  toName LOCATION_INTERFACE = 'LOCATION_INTERFACE
+  toName LOCATION_UNION = 'LOCATION_UNION
+  toName LOCATION_ENUM = 'LOCATION_ENUM
+  toName LOCATION_ENUM_VALUE = 'LOCATION_ENUM_VALUE
+  toName LOCATION_INPUT_OBJECT = 'LOCATION_INPUT_OBJECT
+  toName LOCATION_INPUT_FIELD_DEFINITION = 'LOCATION_INPUT_FIELD_DEFINITION
 
 instance PrintType AssociatedType where
   printType (AssociatedLocations xs) = pure $ foldr (AppT . AppT PromotedConsT . PromotedT . toName) PromotedNilT xs
diff --git a/src/Data/Morpheus/CodeGen/Utils.hs b/src/Data/Morpheus/CodeGen/Utils.hs
--- a/src/Data/Morpheus/CodeGen/Utils.hs
+++ b/src/Data/Morpheus/CodeGen/Utils.hs
@@ -3,9 +3,23 @@
     camelCaseTypeName,
     toHaskellName,
     camelCaseFieldName,
+    Flags,
+    Flag (..),
+    runCodeGenT,
+    CodeGenT,
+    langExtension,
+    requireExternal,
   )
 where
 
+import Data.Morpheus.CodeGen.Internal.Flags
+  ( CodeGenT,
+    Flag (..),
+    Flags,
+    langExtension,
+    requireExternal,
+    runCodeGenT,
+  )
 import Data.Morpheus.CodeGen.Internal.Name
   ( camelCaseFieldName,
     camelCaseTypeName,
