diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,9 @@
+0.1.0.1: 20140416
+-----------------
+
+* make the Cairo dependency optional
+
+0.1.0.0
+-------
+
+* first release
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+puzzle-draw-cmdline
+===================
+
+Rendering logic puzzles, command-line support.
+
+See [puzzle-draw][puzzle-draw] for the main part of this project.
+
+This repository was split out to move the dependency
+on cairo out of puzzle-draw.
+
+To enable the Cairo backend (required for png/pdf/ps output), use
+    $ cabal install -f cairo
+
+[puzzle-draw]: http://github.com/robx/puzzle-draw
diff --git a/puzzle-draw-cmdline.cabal b/puzzle-draw-cmdline.cabal
--- a/puzzle-draw-cmdline.cabal
+++ b/puzzle-draw-cmdline.cabal
@@ -1,5 +1,5 @@
 name:                puzzle-draw-cmdline
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            Creating graphics for pencil puzzles, command line tools.
 description:         Companion executable to puzzle-draw. Separate to keep
                      the dependency on diagrams-cairo out of the library.
@@ -10,20 +10,28 @@
 category:            Graphics
 build-type:          Simple
 cabal-version:       >=1.8
+Extra-source-files:  README.md, CHANGES.md
 Source-repository head
   type:     git
   location: http://github.com/robx/puzzle-draw-cmdline.git
 
+flag cairo
+  description: Build against Cairo backend
+  default:     False
+
 library
   -- Modules exported by the library.
-  exposed-modules:     Diagrams.Puzzles.CmdLineSized
+  if flag(cairo)
+    exposed-modules:     Diagrams.Puzzles.CmdLineSized
 
   -- Other library packages from which modules are imported.
   build-depends:       base >= 4.2 && < 4.8,
                        diagrams-lib >= 1.0 && <= 1.2,
                        optparse-applicative >= 0.7 && < 0.9,
-                       filepath >= 1.3 && < 1.4,
-                       diagrams-cairo >= 1.0 && < 1.2
+                       filepath >= 1.3 && < 1.4
+  if flag(cairo)
+    build-depends:     diagrams-cairo >= 1.0 && < 1.2
+
   hs-source-dirs:      src
   ghc-options:         -Wall
 
@@ -33,9 +41,14 @@
   build-depends:       base >= 4.2 && < 4.8,
                        puzzle-draw >= 0.1.0 && < 0.1.1,
                        diagrams-lib >= 1.0 && < 1.2,
-                       diagrams-cairo >= 1.0 && < 1.2,
                        yaml >= 0.8 && < 0.9,
                        optparse-applicative >= 0.7 && < 0.9,
                        aeson >= 0.7 && < 0.8,
                        filepath >= 1.3 && < 1.4
+  if flag(cairo)
+    cpp-options: "-DCAIRO"
+    build-depends:     diagrams-cairo >= 1.0 && < 1.2
+  else
+    build-depends:     diagrams-svg >= 1.0 && < 1.2
+
   ghc-options:         -Wall
diff --git a/src/tools/drawpuzzle.hs b/src/tools/drawpuzzle.hs
--- a/src/tools/drawpuzzle.hs
+++ b/src/tools/drawpuzzle.hs
@@ -1,12 +1,20 @@
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleContexts, CPP #-}
 
 module Main where
 
 import Diagrams.Prelude hiding (value, option, (<>), Result)
-import Diagrams.Backend.Cairo.CmdLine
 import Diagrams.BoundingBox
-import Diagrams.Backend.CmdLine
 
+import Diagrams.Backend.CmdLine (DiagramOpts(..))
+
+#ifdef CAIRO
+import Diagrams.Backend.CmdLine (mainRender, DiagramLoopOpts(..))
+import Diagrams.Backend.Cairo (B)
+import Diagrams.Backend.Cairo.CmdLine ()
+#else
+import Diagrams.Backend.SVG (B, renderSVG)
+#endif
+
 import Text.Puzzles.Puzzle
 import Data.Puzzles.Compose
 import Diagrams.Puzzles.Draw
@@ -15,6 +23,7 @@
 import Options.Applicative
 import Control.Monad
 import Data.Maybe
+import Data.List (intercalate)
 
 import System.FilePath
 import System.Environment (getProgName)
@@ -35,9 +44,9 @@
 puzzleOpts = PuzzleOpts
     <$> strOption
             (long "format" <> short 'f'
-             <> value "png"
+             <> value (head formats)
              <> metavar "FMT"
-             <> help "Desired output format by file extension")
+             <> help ("Desired output format by file extension " ++ fmts))
     <*> (optional . strOption $
             (long "type" <> short 't'
              <> metavar "TYPE"
@@ -54,9 +63,8 @@
     <*> argument str
             (metavar "INPUT"
              <> help "Puzzle file in .pzl format")
-
-instance Parseable PuzzleOpts where
-    parser = puzzleOpts
+  where
+    fmts = "(" ++ intercalate ", " formats ++ ")"
 
 cmtopoint :: Double -> Double
 cmtopoint = (* 28.3464567)
@@ -66,16 +74,32 @@
 outputSuffix DrawSolution = "-sol"
 outputSuffix DrawExample = ""
 
-toDiagramOpts :: OutputChoice -> Double -> PuzzleOpts -> DiagramOpts
-toDiagramOpts oc w opts =
-    DiagramOpts (Just w') Nothing out
+data RenderOpts = RenderOpts { _file :: FilePath, _w :: Double }
+
+toRenderOpts :: OutputChoice -> Double -> PuzzleOpts -> RenderOpts
+toRenderOpts oc w opts = RenderOpts out w'
   where
     f = _format opts
-    w' = case f of "png" -> round (40 * w)
-                   _     -> round . cmtopoint $ (0.8 * w)
+    w' = case f of "png" -> round' (40 * w)
+                   _     -> cmtopoint (0.8 * w)
     base = takeBaseName (_input opts)
     out = addExtension (base ++ outputSuffix oc) f
+    round' = (fromIntegral :: Int -> Double) . round
 
+toDiagramOpts :: RenderOpts -> DiagramOpts
+toDiagramOpts ropts = DiagramOpts (Just . round $ _w ropts)
+                                  Nothing
+                                  (_file ropts)
+
+renderToFile :: RenderOpts -> Diagram B R2 -> IO ()
+#ifdef CAIRO
+renderToFile ropts = mainRender (toDiagramOpts ropts, lopts)
+  where
+    lopts = DiagramLoopOpts False Nothing 0
+#else
+renderToFile ropts = renderSVG (_file ropts) (Width $ _w ropts)
+#endif
+
 renderPuzzle :: PuzzleOpts -> (OutputChoice -> Maybe (Diagram B R2)) ->
                 (OutputChoice, Bool) -> IO ()
 renderPuzzle opts r (oc, req) = do
@@ -86,9 +110,8 @@
     when (isJust x) $ do
         let Just x' = x
             w = fst . unr2 . boxExtents . boundingBox $ x'
-            dopts = toDiagramOpts oc w opts
-            lopts = DiagramLoopOpts False Nothing 0
-        mainRender (dopts, lopts) x'
+            ropts = toRenderOpts oc w opts
+        renderToFile ropts x'
 
 defaultOpts :: Parser a -> IO a
 defaultOpts optsParser = do
@@ -114,6 +137,20 @@
     req x = (x, True)
     opt x = (x, False)
 
+formats :: [String]
+#ifdef CAIRO
+formats = ["png", "svg", "ps", "pdf"]
+#else
+formats = ["svg"]
+#endif
+
+checkFormat :: PuzzleOpts -> IO ()
+checkFormat opts = if f `elem` formats
+                     then return ()
+                     else exitErr $ "unknown format: " ++ f
+  where
+    f = _format opts
+
 checkType :: Maybe String -> IO PuzzleType
 checkType mt = do
     t <- maybe errno return mt
@@ -132,6 +169,7 @@
 main = do
     opts <- defaultOpts puzzleOpts
     ocs <- checkOutput opts
+    checkFormat opts
     mp <- readPuzzle (_input opts)
     TP mt pv msv <- case mp of Left  e -> exitErr $
                                           "parse failure: " ++ show e
