diff --git a/algebra-sql.cabal b/algebra-sql.cabal
--- a/algebra-sql.cabal
+++ b/algebra-sql.cabal
@@ -2,7 +2,7 @@
 Name:           algebra-sql
 synopsis:       Relational Algebra and SQL Code Generation
 Category:       Database
-Version:        0.1.0.0
+Version:        0.1.0.1
 Description:    This library contains data types for relational table algebra operators. DAG plans
                 (<http://hackage.haskell.org/package/algebra-dag algebra-dag>) over these operators
                 can be compiled into compact SQL:2003 queries.
@@ -29,6 +29,8 @@
                       ansi-wl-pprint     >= 0.6,
                       multiset           >= 0.2,
                       aeson              >= 0.8,
+                      filepath           >= 1.3,
+                      process            >= 1.2,
                       algebra-dag        >= 0.1
 
     exposed-modules:  Database.Algebra.Table.Render.Dot
@@ -49,6 +51,7 @@
                       Database.Algebra.SQL.Query.Util
                       Database.Algebra.SQL.Termination
                       Database.Algebra.SQL.Tile
+                      Database.Algebra.SQL.File
                       Database.Algebra.SQL.Tile.Flatten
                       Database.Algebra.SQL.Render
                       Database.Algebra.SQL.Render.Tile
diff --git a/src/Database/Algebra/SQL/File.hs b/src/Database/Algebra/SQL/File.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Algebra/SQL/File.hs
@@ -0,0 +1,38 @@
+-- | Provides file tools used for outputting and converting JSON plan
+-- files.
+module Database.Algebra.SQL.File where
+
+import           Control.Monad.Error.Class
+import qualified Data.IntMap                        as IntMap
+import           System.FilePath
+import           System.Process
+
+import qualified Database.Algebra.Dag               as D
+import           Database.Algebra.Table.Render.Dot
+import qualified Database.Algebra.Table.Render.JSON as JSON
+
+import qualified Database.Algebra.SQL.Tile          as T
+
+readDagFromFile :: FilePath -> IO (Either String T.TADag)
+readDagFromFile filename = case takeExtension filename of
+    ".plan" -> do
+        -- FIXME This function is a mess, does an unchecked fromJust, which
+        -- easily fails.
+        (_, rootNodes, nodeMap) <- JSON.planFromFile filename
+
+        return $ return $ D.mkDag nodeMap rootNodes
+
+    format ->
+        return $ throwError $ "unkown file format '" ++ format ++ "'"
+
+outputDot :: FilePath -> T.TADag -> IO ()
+outputDot filename dag = do
+    writeFile filename result
+    putStrLn $ "Writing dot file to '" ++ filename ++ "'"
+  where result = renderTADot IntMap.empty (D.rootNodes dag) (D.nodeMap dag)
+
+renderDot :: FilePath -> FilePath -> IO ()
+renderDot dotPath pdfPath = do
+    putStrLn $ "Rendering dot file to '" ++ pdfPath ++ "'"
+    _ <- rawSystem "dot" ["-Tpdf", "-o", pdfPath, dotPath]
+    return ()
