diff --git a/anansi.cabal b/anansi.cabal
--- a/anansi.cabal
+++ b/anansi.cabal
@@ -1,5 +1,5 @@
 name: anansi
-version: 0.3
+version: 0.3.1
 synopsis: Simple literate programming preprocessor
 license: GPL-3
 license-file: license.txt
@@ -30,7 +30,8 @@
     , text >= 0.7 && < 0.12
     , monads-tf >= 0.1 && < 0.2
     , containers >= 0.1 && < 0.5
-    , system-filepath >= 0.1.1 && < 0.2
+    , system-filepath >= 0.3 && < 0.4
+    , system-fileio >= 0.1 && < 0.3
 
   exposed-modules:
     Anansi
@@ -58,6 +59,6 @@
     , bytestring >= 0.9 && < 0.10
     , text >= 0.7 && < 0.12
     , monads-tf >= 0.1 && < 0.2
-    , system-filepath >= 0.1.1 && < 0.2
-    , directory >= 1.0 && < 1.2
+    , system-filepath >= 0.3 && < 0.4
+    , system-fileio >= 0.1 && < 0.3
     , anansi
diff --git a/lib/Anansi/Parser.hs b/lib/Anansi/Parser.hs
--- a/lib/Anansi/Parser.hs
+++ b/lib/Anansi/Parser.hs
@@ -27,13 +27,14 @@
 import Data.List (unfoldr)
 import Data.Typeable (Typeable)
 import qualified Text.Parsec as P
-import qualified Data.ByteString as B
+import Data.String (fromString)
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
 import qualified Data.Text.Lazy as TL
 import qualified Data.Map as Map
 import System.FilePath (FilePath)
 import qualified System.FilePath.CurrentOS as FP
+import qualified System.File
 import Anansi.Types
 import Anansi.Util
 
@@ -70,7 +71,7 @@
 getPosition :: Monad m => P.ParsecT s u m Position
 getPosition = do
 	pos <- P.getPosition
-	return $ Position (FP.fromString (P.sourceName pos)) (toInteger (P.sourceLine pos))
+	return $ Position (fromString (P.sourceName pos)) (toInteger (P.sourceLine pos))
 
 parseLines :: P.Parsec String u [Line]
 parseLines = do
@@ -198,7 +199,7 @@
 	genLines' path = lift (getLines path) >>= concatMapM (resolveIncludes path)
 	
 	textToPath :: TL.Text -> FilePath
-	textToPath = FP.fromString . TL.unpack
+	textToPath = fromString . TL.unpack
 	
 	relative :: FilePath -> TL.Text -> FilePath
 	relative x y = FP.append (FP.parent x) (textToPath y)
@@ -219,10 +220,9 @@
 	
 	getLines :: FilePath -> IO [Line]
 	getLines path = do
-		let strPath = FP.toString path
-		bytes <- B.readFile strPath
+		bytes <- System.File.readFile path
 		let contents = T.unpack (TE.decodeUtf8 bytes)
-		case P.parse parseLines strPath contents of
+		case P.parse parseLines (show path) contents of
 			Right x -> return x
 			Left err -> let
 				msg = TL.pack $ "getLines parse failed (internal error): " ++ show err
diff --git a/lib/Anansi/Tangle.hs b/lib/Anansi/Tangle.hs
--- a/lib/Anansi/Tangle.hs
+++ b/lib/Anansi/Tangle.hs
@@ -20,6 +20,7 @@
 import Control.Monad.Trans (lift)
 import qualified Control.Monad.State as S
 import qualified Control.Monad.Writer as W
+import Data.String (fromString)
 import qualified Data.Text.Lazy as TL
 import qualified Data.Map as Map
 import System.FilePath (FilePath)
@@ -70,7 +71,7 @@
 	
 	putFile (path, content) = do
 		text <- W.execWriterT (mapM_ (putContent enableLine) content)
-		lift $ writeFile' (FP.fromString (TL.unpack path)) text
+		lift $ writeFile' (fromString (TL.unpack path)) text
 
 putContent :: Monad m => Bool -> Content -> TangleT m ()
 putContent enableLine (ContentText pos t) = do
@@ -95,7 +96,7 @@
 putPosition enableLine pos = do
 	TangleState lastPos indent macros <- S.get
 	let expectedPos = Position (positionFile lastPos) (positionLine lastPos + 1)
-	let filename = FP.toString (positionFile pos)
+	let filename = FP.toText (positionFile pos)
 	let line = if enableLine
 		then "\n#line " ++ show (positionLine pos) ++ " " ++ show filename ++ "\n"
 		else "\n"
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -20,6 +20,8 @@
 
 import Prelude hiding (FilePath)
 import Control.Monad.Writer
+import Data.String (fromString)
+import qualified Data.Text as T
 import qualified Data.Text.Lazy as TL
 import qualified Data.Text.Lazy.IO as TLIO
 import Data.Text.Lazy.Encoding (encodeUtf8)
@@ -33,6 +35,7 @@
 import System.FilePath (FilePath)
 import qualified System.FilePath.CurrentOS as FP
 import System.IO hiding (withFile, FilePath)
+import qualified System.File
 
 data Output = Tangle | Weave
 	deriving (Eq)
@@ -51,7 +54,7 @@
 	  "Generate tangled source code (default)"
 	, Option ['w'] ["weave"] (NoArg (OptionOutput Weave))
 	  "Generate woven markup"
-	, Option ['o'] ["out", "output"] (ReqArg (OptionOutputPath . FP.fromString) "PATH")
+	, Option ['o'] ["out", "output"] (ReqArg (OptionOutputPath . fromString) "PATH")
 	  "Output path (directory for tangle, file for weave)"
 	, Option ['l'] ["loom"] (ReqArg (OptionLoom . TL.pack) "NAME")
 	  "Which loom should be used to weave output"
@@ -78,7 +81,7 @@
 withFile :: FilePath -> (Handle -> IO a) -> IO a
 withFile path io = if FP.null path
 	then io stdout
-	else withBinaryFile (FP.toString path) WriteMode io
+	else System.File.withFile path WriteMode io
 
 loomMap :: [(TL.Text, Loom)]
 loomMap = [(loomName l, l) | l <- looms]
@@ -130,7 +133,7 @@
 
 debugTangle :: FilePath -> TL.Text -> IO ()
 debugTangle path text = do
-	let strPath = FP.toString path
+	let strPath = either T.unpack T.unpack (FP.toText path)
 	putStr "\n"
 	putStrLn strPath
 	putStrLn $ replicate (fromIntegral (length strPath)) '='
@@ -139,9 +142,9 @@
 realTangle :: FilePath -> FilePath -> TL.Text -> IO ()
 realTangle root path text = do
 	let fullpath = FP.append root path
-	createDirectoryIfMissing True (FP.toString (FP.parent fullpath))
+	createTree (FP.parent fullpath)
 	let bytes = encodeUtf8 text
-	withBinaryFile (FP.toString fullpath) ReadWriteMode $ \h -> do
+	System.File.withFile fullpath ReadWriteMode $ \h -> do
 		equal <- fileContentsEqual h bytes
 		unless equal $ do
 			hSetFileSize h 0
@@ -163,7 +166,7 @@
 
 parseInputs :: [String] -> IO (Either ParseError [Block])
 parseInputs inputs = do
-	eithers <- mapM (parseFile . FP.fromString) inputs
+	eithers <- mapM (parseFile . fromString) inputs
 	return $ case catEithers eithers of
 		Left err -> Left err
 		Right bs -> Right $ concat bs
@@ -171,7 +174,7 @@
 formatError :: ParseError -> String
 formatError err = concat [filename, ":", line, ": error: ", message] where
 	pos = parseErrorPosition err
-	filename = FP.toString (positionFile pos)
+	filename = either T.unpack T.unpack (FP.toText (positionFile pos))
 	line = show $ positionLine pos
 	message = TL.unpack $ parseErrorMessage err
 
