diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,19 +2,20 @@
 
 [![Build Status](https://travis-ci.com/leshow/i3ipc.svg?branch=master)](https://travis-ci.com/leshow/i3ipc)
 
-Haskell type-safe bindings for working with i3 using it's unix socket IPC
+Haskell type-safe bindings for working with i3 using it's unix socket IPC. Sway is supposed to be protocl compatible with i3, I've included a function to bind to sway's socket also.
 
 ## Subscribing
 
 Subscribe to events:
 
 ```haskell
-import qualified I3IPC.Subscribe   as Sub
-import           I3IPC              ( subscribe )
+import qualified I3IPC.Subscribe         as Sub
+import           I3IPC                   ( subscribe )
+import           Control.Monad.IO.Class
 
 -- will print all events
 main :: IO ()
-main = subscribe print [Sub.Workspace, Sub.Window]
+main = liftIO $ subscribe print [Sub.Workspace, Sub.Window]
 ```
 
 An example of explicitly matching on some events and printing their fields:
@@ -22,12 +23,13 @@
 ```haskell
 import qualified I3IPC.Subscribe               as Sub
 import           I3IPC.Event
-import           I3IPC                          ( subscribe )
+import           I3IPC                         ( subscribe )
+import           Control.Monad.IO.Class
 
 main :: IO ()
-main = subscribe handle [Sub.Workspace, Sub.Window]
+main = liftIO $ subscribe handle [Sub.Workspace, Sub.Window]
  where
-  handle :: Either String Event -> IO ()
+  handle :: MonadIO m => Either String Event -> m ()
   handle (Right evt) = case evt of
     Workspace WorkspaceEvent { wrk_current } -> print wrk_current
     Window WindowEvent { win_container } -> print win_container
@@ -43,10 +45,11 @@
 import           I3IPC              ( connecti3
                                     , getWorkspaces
                                     )
+import           Control.Monad.IO.Class                                    
 
 main :: IO ()
 main = do
-    soc <- connecti3
+    soc <- liftIO $ connecti3
     print $ getWorkspaces soc
 ```
 
@@ -57,10 +60,11 @@
 import           I3IPC              ( connecti3
                                     , receiveMsg
                                     )
+import           Control.Monad.IO.Class                                    
 
 main :: IO ()
 main = do
-    soc <- connecti3
+    soc <- liftIO $ connecti3
     print $ Msg.sendMsg soc Msg.Workspaces >> receiveMsg soc
 ```
 
diff --git a/i3ipc.cabal b/i3ipc.cabal
--- a/i3ipc.cabal
+++ b/i3ipc.cabal
@@ -1,5 +1,5 @@
 name:                i3ipc
-version:             0.1.0.1
+version:             0.2.0.0
 description:         Library for controlling i3 through it's IPC. i3 communicates using a JSON interface over a unix socket.
                      For JSON parsing I'm using Aeson. I've written out all the records and types to allow anyone to 
                      easily interact with i3 from a Haskell application.
@@ -12,7 +12,7 @@
 copyright:           2019 Evan Cameron
 category:            Lib
 build-type:          Simple
-extra-source-files:  README.md
+extra-source-files:  README.md test/event/*.json test/reply/*.json
 cabal-version:       >=1.10
 
 library
@@ -29,8 +29,9 @@
                      , binary               >= 0.8.6 && < 0.10
                      , text                 >= 1.2.1.0 && < 1.3
                      , vector               >= 0.11.0 && < 0.13
-                     , network              >= 2.6.3.5 && < 3.1
+                     , network              >= 2.6.3.5 && < 3.2
                      , typed-process        >= 0.2.4 && < 0.3
+                     , exceptions           >= 0.8.1 && < 0.10.5
                      
   default-language:    Haskell2010
   ghc-options:         -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints 
diff --git a/src/I3IPC.hs b/src/I3IPC.hs
--- a/src/I3IPC.hs
+++ b/src/I3IPC.hs
@@ -19,6 +19,7 @@
     -- ** Convenience functions
     -- $func    
       getSocketPath
+    , getSwaySocketPath
     , Response(..)
     , subscribe
     , subscribeM
@@ -28,6 +29,7 @@
     , receiveMsg'
     , getReply
     , connecti3
+    , connectsway
     , receiveEvent
     , receiveEvent'
     , runCommand
@@ -62,15 +64,17 @@
 import           I3IPC.Reply
 
 import           Control.Monad.IO.Class
+import           Control.Exception                   ( Exception )
+import           Control.Monad.Catch                 ( MonadThrow
+                                                     , throwM
+                                                     )
 import           System.Environment                  ( lookupEnv )
 import           Data.Maybe                          ( isJust )
 import           Data.Semigroup                      ( (<>) )
 import           System.Process.Typed                ( proc
                                                      , readProcess
                                                      )
-import           System.Exit                         ( ExitCode(..)
-                                                     , exitFailure
-                                                     )
+import           System.Exit                         ( ExitCode(..) )
 
 import           Network.Socket               hiding ( send
                                                      , sendTo
@@ -82,14 +86,22 @@
 import           Data.Binary.Get
 import           Data.Bifunctor                      ( second )
 import qualified Data.ByteString.Lazy.Char8         as BL
+import           Data.Typeable                       ( Typeable )
+import qualified Data.Text                          as T
 import           Data.Bits                           ( testBit
                                                      , clearBit
                                                      )
 
+-- | Exception type
+data I3Exception = ConnectException T.Text | ProcessException
+    deriving stock (Show, Eq, Typeable)
+
+instance Exception I3Exception
+
 -- | Get a new unix socket path from i3
-getSocketPath :: IO (Maybe BL.ByteString)
+getSocketPath :: MonadIO m => m (Maybe BL.ByteString)
 getSocketPath = do
-    res <- lookupEnv "I3SOCK"
+    res <- liftIO $ lookupEnv "I3SOCK"
     if isJust res
         then pure $ fmap BL.pack res
         else do
@@ -98,61 +110,81 @@
                 then pure Nothing
                 else pure $ Just (BL.filter (/= '\n') out)
 
+-- | Get a new unix socket path from sway
+getSwaySocketPath :: MonadIO m => m (Maybe BL.ByteString)
+getSwaySocketPath = fmap BL.pack <$> liftIO (lookupEnv "SWAYSOCK")
 
 -- | Subscribe with a list of 'I3IPC.Subscribe.Subscribe' types, and subscribe will to respond with specific 'I3IPC.Event.Event'
-subscribe :: (Either String Evt.Event -> IO ()) -> [Sub.Subscribe] -> IO ()
+subscribe
+    :: (MonadThrow m, MonadIO m)
+    => (Either String Evt.Event -> m ())
+    -> [Sub.Subscribe]
+    -> m ()
 subscribe handle subtypes = do
     soc <- connecti3
     Msg.sendMsgPayload soc Msg.Subscribe (encode subtypes)
         >> receiveMsg soc
         >> handleSoc soc
-        >> close soc
+        >> liftIO (close soc)
   where
     handleSoc soc = do
         r <- receiveEvent soc
         handle r
         handleSoc soc
 
--- | A version of 'subscribe' that allows the use of any monad transformer on top of MonadIO
+-- | A version of 'subscribe' that allows the use of any monad transformer on top of MonadIO (kept around for backwards compatibility)
 subscribeM
-    :: MonadIO m => (Either String Evt.Event -> m ()) -> [Sub.Subscribe] -> m ()
+    :: (MonadThrow m, MonadIO m)
+    => (Either String Evt.Event -> m ())
+    -> [Sub.Subscribe]
+    -> m ()
 subscribeM handle subtypes = do
-    soc <- liftIO connecti3
-    liftIO
-        $  Msg.sendMsgPayload soc Msg.Subscribe (encode subtypes)
+    soc <- connecti3
+    Msg.sendMsgPayload soc Msg.Subscribe (encode subtypes)
         >> receiveMsg soc
         >> pure ()
     handleSoc soc >> liftIO (close soc)
   where
     handleSoc soc = do
-        r <- liftIO $ receiveEvent soc
+        r <- receiveEvent soc
         handle r
         handleSoc soc
 
 -- | Connect to an i3 socket and return it
-connecti3 :: IO Socket
+connecti3 :: (MonadThrow m, MonadIO m) => m Socket
 connecti3 = do
-    soc <- socket AF_UNIX Stream 0
+    soc <- liftIO $ socket AF_UNIX Stream 0
     getSocketPath >>= \case
-        Nothing    -> putStrLn "Failed to get i3 socket path" >> exitFailure
+        Nothing    -> throwM $ ConnectException "Failed to get i3 socket path"
         Just addr' -> do
-            connect soc (SockAddrUnix $ BL.unpack addr')
+            liftIO $ connect soc (SockAddrUnix $ BL.unpack addr')
             pure soc
 
+-- | Connect to SWAY socket and return it
+connectsway :: (MonadThrow m, MonadIO m) => m Socket
+connectsway = do
+    soc <- liftIO $ socket AF_UNIX Stream 0
+    getSwaySocketPath >>= \case
+        Nothing    -> throwM $ ConnectException "Failed to get i3 socket path"
+        Just addr' -> do
+            liftIO $ connect soc (SockAddrUnix $ BL.unpack addr')
+            pure soc
+
 -- | Useful for when you are receiving Events or Messages.
 data Response = Message MsgReply | Event Evt.Event deriving (Show, Eq)
 
 -- | Get and parse the response using i3's IPC
-getReply :: Socket -> IO (Either String (Int, BL.ByteString))
+getReply :: MonadIO m => Socket -> m (Either String (Int, BL.ByteString))
 getReply soc = do
-    magic <- recv soc 6
+    magic <- liftIO $ recv soc 6
     if magic == "i3-ipc"
         then do
-            len  <- fromIntegral . runGet getWord32le <$> recv soc 4
-            ty   <- fromIntegral . runGet getWord32le <$> recv soc 4
-            body <- recv soc len
-            pure $ Right (ty, body)
+            len  <- getInt <$> liftIO (recv soc 4)
+            ty   <- getInt <$> liftIO (recv soc 4)
+            body <- liftIO $ recv soc len
+            pure $ Right (fromIntegral ty, body)
         else pure $ Left "Failed to get reply"
+    where getInt = fromIntegral . runGet getWord32le
 
 test :: Int -> BL.ByteString -> IO Int
 test ty body = do
@@ -162,7 +194,7 @@
     pure ty
 
 -- | Parse response from socket, returning either an error or a 'I3IPC.Response', representing a sum type of a 'I3IPC.Reply.MsgReply' or 'I3IPC.Event.Event'
-receive :: Socket -> IO (Either String Response)
+receive :: MonadIO m => Socket -> m (Either String Response)
 receive soc = do
     reply <- getReply soc
     case reply of
@@ -172,7 +204,7 @@
         _ -> pure $ Left "Get Reply failed"
 
 -- | Like receive but strict-- will use eitherDecode' under the hood to parse
-receive' :: Socket -> IO (Either String Response)
+receive' :: MonadIO m => Socket -> m (Either String Response)
 receive' soc = do
     reply <- getReply soc
     case reply of
@@ -182,7 +214,7 @@
         _ -> pure $ Left "Get Reply failed"
 
 -- | Receive but specifically for msgs, for when you know the response won't include any Events
-receiveMsg :: Socket -> IO (Either String MsgReply)
+receiveMsg :: MonadIO m => Socket -> m (Either String MsgReply)
 receiveMsg soc = do
     r <- getReply soc
     pure $ do
@@ -190,7 +222,7 @@
         toMsgReply ty body
 
 -- | Like 'I3IPC.receiveMsg' but strict-- uses eitherDecode'
-receiveMsg' :: Socket -> IO (Either String MsgReply)
+receiveMsg' :: MonadIO m => Socket -> m (Either String MsgReply)
 receiveMsg' soc = do
     r <- getReply soc
     pure $ do
@@ -198,7 +230,7 @@
         toMsgReply' ty body
 
 -- | 'I3IPC.receive' specifically for Event
-receiveEvent :: Socket -> IO (Either String Evt.Event)
+receiveEvent :: MonadIO m => Socket -> m (Either String Evt.Event)
 receiveEvent soc = do
     r <- getReply soc
     pure $ do
@@ -206,7 +238,7 @@
         Evt.toEvent (ty `clearBit` 31) body
 
 -- | like 'receiveEvent' but strict-- uses eitherDecode'
-receiveEvent' :: Socket -> IO (Either String Evt.Event)
+receiveEvent' :: MonadIO m => Socket -> m (Either String Evt.Event)
 receiveEvent' soc = do
     r <- getReply soc
     pure $ do
@@ -220,37 +252,38 @@
 -- Or, if there is no message body:
 --
 -- > Msg.sendMsg soc Msg.X >> receiveMsg soc
-runCommand :: Socket -> BL.ByteString -> IO (Either String MsgReply)
+runCommand :: MonadIO m => Socket -> BL.ByteString -> m (Either String MsgReply)
 runCommand soc b = Msg.sendMsgPayload soc Msg.RunCommand b >> receiveMsg soc
 
-runCommand' :: Socket -> BL.ByteString -> IO (Either String MsgReply)
+runCommand'
+    :: MonadIO m => Socket -> BL.ByteString -> m (Either String MsgReply)
 runCommand' soc b = Msg.sendMsgPayload soc Msg.RunCommand b >> receiveMsg' soc
 
-getWorkspaces :: Socket -> IO (Either String MsgReply)
+getWorkspaces :: MonadIO m => Socket -> m (Either String MsgReply)
 getWorkspaces soc = Msg.sendMsg soc Msg.Workspaces >> receiveMsg soc
 
-getWorkspaces' :: Socket -> IO (Either String MsgReply)
+getWorkspaces' :: MonadIO m => Socket -> m (Either String MsgReply)
 getWorkspaces' soc = Msg.sendMsg soc Msg.Workspaces >> receiveMsg' soc
 
-getOutputs :: Socket -> IO (Either String MsgReply)
+getOutputs :: MonadIO m => Socket -> m (Either String MsgReply)
 getOutputs soc = Msg.sendMsg soc Msg.Outputs >> receiveMsg soc
 
-getOutputs' :: Socket -> IO (Either String MsgReply)
+getOutputs' :: MonadIO m => Socket -> m (Either String MsgReply)
 getOutputs' soc = Msg.sendMsg soc Msg.Outputs >> receiveMsg' soc
 
-getTree :: Socket -> IO (Either String MsgReply)
+getTree :: MonadIO m => Socket -> m (Either String MsgReply)
 getTree soc = Msg.sendMsg soc Msg.Tree >> receiveMsg soc
 
-getTree' :: Socket -> IO (Either String MsgReply)
+getTree' :: MonadIO m => Socket -> m (Either String MsgReply)
 getTree' soc = Msg.sendMsg soc Msg.Tree >> receiveMsg' soc
 
-getMarks :: Socket -> IO (Either String MsgReply)
+getMarks :: MonadIO m => Socket -> m (Either String MsgReply)
 getMarks soc = Msg.sendMsg soc Msg.Marks >> receiveMsg soc
 
-getMarks' :: Socket -> IO (Either String MsgReply)
+getMarks' :: MonadIO m => Socket -> m (Either String MsgReply)
 getMarks' soc = Msg.sendMsg soc Msg.Marks >> receiveMsg' soc
 
-getBarIds :: Socket -> IO (Either String BarIds)
+getBarIds :: MonadIO m => Socket -> m (Either String BarIds)
 getBarIds soc = do
     _ <- Msg.sendMsg soc Msg.BarConfig
     r <- getReply soc
@@ -259,41 +292,43 @@
         decodeBarIds (snd body)
 
 -- | Get a bar's config based on it's id
-getBarConfig :: Socket -> BL.ByteString -> IO (Either String MsgReply)
+getBarConfig
+    :: MonadIO m => Socket -> BL.ByteString -> m (Either String MsgReply)
 getBarConfig soc b = Msg.sendMsgPayload soc Msg.BarConfig b >> receiveMsg' soc
 
 -- | Like 'I3IPC.getBarConfig' but strict
-getBarConfig' :: Socket -> BL.ByteString -> IO (Either String MsgReply)
+getBarConfig'
+    :: MonadIO m => Socket -> BL.ByteString -> m (Either String MsgReply)
 getBarConfig' soc b = Msg.sendMsgPayload soc Msg.BarConfig b >> receiveMsg' soc
 
-getVersion :: Socket -> IO (Either String MsgReply)
+getVersion :: MonadIO m => Socket -> m (Either String MsgReply)
 getVersion soc = Msg.sendMsg soc Msg.Version >> receiveMsg soc
 
-getVersion' :: Socket -> IO (Either String MsgReply)
+getVersion' :: MonadIO m => Socket -> m (Either String MsgReply)
 getVersion' soc = Msg.sendMsg soc Msg.Version >> receiveMsg' soc
 
-getBindingModes :: Socket -> IO (Either String MsgReply)
+getBindingModes :: MonadIO m => Socket -> m (Either String MsgReply)
 getBindingModes soc = Msg.sendMsg soc Msg.BindingModes >> receiveMsg soc
 
-getBindingModes' :: Socket -> IO (Either String MsgReply)
+getBindingModes' :: MonadIO m => Socket -> m (Either String MsgReply)
 getBindingModes' soc = Msg.sendMsg soc Msg.BindingModes >> receiveMsg' soc
 
-getConfig :: Socket -> IO (Either String MsgReply)
+getConfig :: MonadIO m => Socket -> m (Either String MsgReply)
 getConfig soc = Msg.sendMsg soc Msg.Config >> receiveMsg soc
 
-getConfig' :: Socket -> IO (Either String MsgReply)
+getConfig' :: MonadIO m => Socket -> m (Either String MsgReply)
 getConfig' soc = Msg.sendMsg soc Msg.Config >> receiveMsg' soc
 
-getTick :: Socket -> IO (Either String MsgReply)
+getTick :: MonadIO m => Socket -> m (Either String MsgReply)
 getTick soc = Msg.sendMsg soc Msg.Tick >> receiveMsg soc
 
-getTick' :: Socket -> IO (Either String MsgReply)
+getTick' :: MonadIO m => Socket -> m (Either String MsgReply)
 getTick' soc = Msg.sendMsg soc Msg.Tick >> receiveMsg' soc
 
-getSync :: Socket -> IO (Either String MsgReply)
+getSync :: MonadIO m => Socket -> m (Either String MsgReply)
 getSync soc = Msg.sendMsg soc Msg.Sync >> receiveMsg soc
 
-getSync' :: Socket -> IO (Either String MsgReply)
+getSync' :: MonadIO m => Socket -> m (Either String MsgReply)
 getSync' soc = Msg.sendMsg soc Msg.Sync >> receiveMsg' soc
 
 
@@ -305,9 +340,10 @@
 -- > import qualified I3IPC.Subscribe               as Sub
 -- > import           I3IPC.Event
 -- > import           I3IPC                          ( subscribe )
+-- > import           Control.Monad.IO.Class 
 -- > 
 -- > main :: IO ()
--- > main = subscribe handle [Sub.Workspace, Sub.Window]
+-- > main = liftIO $ subscribe handle [Sub.Workspace, Sub.Window]
 -- >  where
 -- >   handle :: Either String Event -> IO ()
 -- >   handle (Right evt) = case evt of
@@ -324,10 +360,11 @@
 -- > import           I3IPC              ( connecti3
 -- >                                     , getWorkspaces
 -- >                                     )
+-- > import           Control.Monad.IO.Class 
 -- > 
 -- > main :: IO ()
 -- > main = do
--- >     soc <- connecti3
+-- >     soc <- liftIO $ connecti3
 -- >     print getWorkspaces
 -- 
 -- $func
@@ -340,8 +377,9 @@
 -- > import           I3IPC              ( connecti3
 -- >                                     , receiveMsg
 -- >                                     )
+-- > import           Control.Monad.IO.Class 
 -- > 
 -- > main :: IO ()
 -- > main = do
--- >     soc <- connecti3
+-- >     soc <- liftIO $ connecti3
 -- >     print $ Msg.sendMsg soc Msg.Workspaces >> receiveMsg soc
diff --git a/src/I3IPC/Event.hs b/src/I3IPC/Event.hs
--- a/src/I3IPC/Event.hs
+++ b/src/I3IPC/Event.hs
@@ -40,7 +40,7 @@
 toEvent' :: Int -> BL.ByteString -> Either String Event
 toEvent' 0 = (Workspace <$>) . eitherDecode'
 toEvent' 1 = (Output <$>) . eitherDecode'
-toEvent' 2 = (Mode <$>) . eitherDecode' 
+toEvent' 2 = (Mode <$>) . eitherDecode'
 toEvent' 3 = (Window <$>) . eitherDecode'
 toEvent' 4 = (BarConfigUpdate <$>) . eitherDecode'
 toEvent' 5 = (Binding <$>) . eitherDecode'
@@ -68,18 +68,20 @@
     | Reload
     | Restored
     | Move
+    | UnknownChange
     deriving (Eq, Generic, Show)
 
 instance ToJSON WorkspaceChange where
     toEncoding = \case
-        Focus    -> text "focus"
-        Init     -> text "init"
-        Empty    -> text "empty"
-        Urgent   -> text "urgent"
-        Rename   -> text "rename"
-        Reload   -> text "reload"
-        Restored -> text "restored"
-        Move     -> text "move"
+        Focus         -> text "focus"
+        Init          -> text "init"
+        Empty         -> text "empty"
+        Urgent        -> text "urgent"
+        Rename        -> text "rename"
+        Reload        -> text "reload"
+        Restored      -> text "restored"
+        Move          -> text "move"
+        UnknownChange -> text "unknown"
 
 instance FromJSON WorkspaceChange where
     parseJSON (String s) = pure $! case s of
@@ -91,7 +93,7 @@
         "reload"   -> Reload
         "restored" -> Restored
         "move"     -> Move
-        _          -> error "Received unrecognized WorkspaceChange"
+        _          -> UnknownChange
     parseJSON _ = mzero
 
 -- | Workspace Event
@@ -168,6 +170,7 @@
     | WinFloating -- ^ the window has transitioned to or from floating 
     | WinUrgent -- ^ the window has become urgent or lost its urgent status 
     | WinMark -- ^ a mark has been added to or removed from the window 
+    | WinUnknown -- ^ an unknown change, submit a PR to add a new WindowChange if you get this
     deriving (Eq, Show, Generic)
 
 instance ToJSON WindowChange where
@@ -181,6 +184,7 @@
         WinUrgent         -> text "urgent"
         WinMark           -> text "mark"
         WinClose          -> text "close"
+        WinUnknown        -> text "unknown"
 
 instance FromJSON WindowChange where
     parseJSON (String s) = pure $! case s of
@@ -193,7 +197,7 @@
         "urgent"          -> WinUrgent
         "mark"            -> WinMark
         "close"           -> WinClose
-        _                 -> error "Received unrecognized WorkspaceChange"
+        _                 -> WinUnknown
     parseJSON _ = mzero
 
 
diff --git a/src/I3IPC/Message.hs b/src/I3IPC/Message.hs
--- a/src/I3IPC/Message.hs
+++ b/src/I3IPC/Message.hs
@@ -7,6 +7,7 @@
     )
 where
 
+import           Control.Monad.IO.Class
 import           Network.Socket.ByteString.Lazy
 import           Network.Socket                      ( Socket )
 import qualified Data.ByteString.Lazy               as BSL
@@ -60,9 +61,11 @@
     putWord32host $ fromIntegral (fromEnum msgtype)
 
 -- | Send a message over the socket of 'MessageType' and some content
-sendMsgPayload :: Socket -> MessageType -> BSL.ByteString -> IO Int64
-sendMsgPayload soc msgtype msg = createMsgPayload msgtype msg & send soc
+sendMsgPayload
+    :: MonadIO m => Socket -> MessageType -> BSL.ByteString -> m Int64
+sendMsgPayload soc msgtype msg =
+    liftIO $ createMsgPayload msgtype msg & send soc
 
 -- | Similar to 'sendMsg' but with no message body
-sendMsg :: Socket -> MessageType -> IO Int64
-sendMsg soc msgtype = createMsg msgtype & send soc
+sendMsg :: MonadIO m => Socket -> MessageType -> m Int64
+sendMsg soc msgtype = liftIO $ createMsg msgtype & send soc
diff --git a/src/I3IPC/Reply.hs b/src/I3IPC/Reply.hs
--- a/src/I3IPC/Reply.hs
+++ b/src/I3IPC/Reply.hs
@@ -161,6 +161,7 @@
     Horizontal
     | Vertical
     | OrientNone
+    | UnknownOrient
     deriving (Eq, Generic, Show)
 
 instance FromJSON NodeOrientation where
@@ -168,14 +169,15 @@
         "none"       -> OrientNone
         "horizontal" -> Horizontal
         "vertical"   -> Vertical
-        _            -> error "Unrecognized NodeOrientation"
+        _            -> UnknownOrient
     parseJSON _ = mzero
 
 instance ToJSON NodeOrientation where
     toEncoding = \case
-        OrientNone -> text "none"
-        Vertical   -> text "vertical"
-        Horizontal -> text "horizontal"
+        OrientNone    -> text "none"
+        Vertical      -> text "vertical"
+        Horizontal    -> text "horizontal"
+        UnknownOrient -> text "unknown"
 
 instance ToJSON Node where
     toEncoding =
@@ -190,6 +192,7 @@
     | Class
     | WindowRole
     | TransientFor
+    | UnknownProperty
     deriving (Eq, Enum, Ord, Generic, Show)
 
 instance FromJSONKey WindowProperty where
@@ -201,23 +204,25 @@
             "class"         -> Class
             "window_role"   -> WindowRole
             "transient_for" -> TransientFor
-            _               -> error "Unrecognized window property"
+            _               -> UnknownProperty
 
 instance ToJSONKey WindowProperty where
     toJSONKey = ToJSONKeyText f g
       where
         f x = case x of
-            Title        -> "title"
-            Instance     -> "instance"
-            Class        -> "class"
-            WindowRole   -> "window_role"
-            TransientFor -> "transient_for"
+            Title           -> "title"
+            Instance        -> "instance"
+            Class           -> "class"
+            WindowRole      -> "window_role"
+            TransientFor    -> "transient_for"
+            UnknownProperty -> "unknown"
         g x = case x of
-            Title        -> text "title"
-            Instance     -> text "instance"
-            Class        -> text "class"
-            WindowRole   -> text "window_role"
-            TransientFor -> text "transient_for"
+            Title           -> text "title"
+            Instance        -> text "instance"
+            Class           -> text "class"
+            WindowRole      -> text "window_role"
+            TransientFor    -> text "transient_for"
+            UnknownProperty -> text "unknown"
 
 instance FromJSON WindowProperty where
     parseJSON (String s) = pure $! case s of
@@ -226,17 +231,18 @@
         "class"         -> Class
         "window_role"   -> WindowRole
         "transient_for" -> TransientFor
-        _               -> error "Unrecognized WindowProperty variant found"
+        _               -> UnknownProperty
     parseJSON _ = mzero
 
 
 instance ToJSON WindowProperty where
     toEncoding = \case
-        Title        -> text "title"
-        Instance     -> text "instance"
-        Class        -> text "class"
-        WindowRole   -> text "window_role"
-        TransientFor -> text "transient_for"
+        Title           -> text "title"
+        Instance        -> text "instance"
+        Class           -> text "class"
+        WindowRole      -> text "window_role"
+        TransientFor    -> text "transient_for"
+        UnknownProperty -> text "unknown"
 
 -- | Marks Reply
 -- The reply consists of a single array of strings for each container that has a mark. A mark can only be set on one container, so the array is unique. The order of that array is undefined.
@@ -250,20 +256,22 @@
     Normal
     | None
     | Pixel
+    | UnknownBorder
     deriving (Eq, Generic, Show)
 
 instance ToJSON NodeBorder where
     toEncoding = \case
-        Normal -> text "normal"
-        None   -> text "none"
-        Pixel  -> text "pixel"
+        Normal        -> text "normal"
+        None          -> text "none"
+        Pixel         -> text "pixel"
+        UnknownBorder -> text "unknown"
 
 instance FromJSON NodeBorder where
     parseJSON (String s) = pure $! case s of
         "normal" -> Normal
         "none"   -> None
         "pixel"  -> Pixel
-        _        -> error "Unrecognized NodeBorder found"
+        _        -> UnknownBorder
     parseJSON _ = mzero
 
 data Rect = Rect {
@@ -283,6 +291,7 @@
     | FloatingConType
     | WorkspaceType
     | DockAreaType
+    | UnknownType
     deriving (Eq, Generic, Show)
 
 instance ToJSON NodeType where
@@ -293,6 +302,7 @@
         FloatingConType -> text "floating_con"
         WorkspaceType   -> text "workspace"
         DockAreaType    -> text "dockarea"
+        UnknownType     -> text "unknown"
 
 instance FromJSON NodeType where
     parseJSON (String s) = pure $! case s of
@@ -302,7 +312,7 @@
         "floating_con" -> FloatingConType
         "workspace"    -> WorkspaceType
         "dockarea"     -> DockAreaType
-        _              -> error "Received unrecognized NodeType"
+        _              -> UnknownType
     parseJSON _ = mzero
 
 data NodeLayout =
@@ -312,6 +322,7 @@
     | TabbedLayout
     | DockAreaLayout
     | OutputLayout
+    | UnknownLayout
     deriving (Eq, Generic, Show)
 
 instance ToJSON NodeLayout where
@@ -322,6 +333,7 @@
         TabbedLayout          -> text "tabbed"
         DockAreaLayout        -> text "dockarea"
         OutputLayout          -> text "output"
+        UnknownLayout         -> text "unknown"
 
 instance FromJSON NodeLayout where
     parseJSON (String s) = pure $! case s of
@@ -331,7 +343,7 @@
         "tabbed"   -> TabbedLayout
         "dockarea" -> DockAreaLayout
         "output"   -> OutputLayout
-        _          -> error "Received unrecognized NodeLayout"
+        _          -> UnknownLayout
     parseJSON _ = mzero
 
 -- | BarConfig Reply
@@ -385,6 +397,7 @@
     | BindingModeText
     | BindingModeBg
     | BindingModeBorder
+    | UnknownBarPart
     deriving (Eq, Enum, Ord, Generic, Show, FromJSONKey)
 
 instance ToJSONKey BarPart where
@@ -412,6 +425,7 @@
             BindingModeText         -> "binding_mode_text"
             BindingModeBg           -> "binding_mode_bg"
             BindingModeBorder       -> "binding_mode_border"
+            UnknownBarPart          -> "unknown"
         g x = case x of
             Background              -> text "background"
             Statusline              -> text "statusline"
@@ -434,6 +448,7 @@
             BindingModeText         -> text "binding_mode_text"
             BindingModeBg           -> text "binding_mode_bg"
             BindingModeBorder       -> text "binding_mode_border"
+            UnknownBarPart          -> text "unknown"
 
 instance FromJSON BarPart where
     parseJSON (String s) = pure $! case s of
@@ -458,7 +473,7 @@
         "binding_mode_text"         -> BindingModeText
         "binding_mode_bg"           -> BindingModeBg
         "binding_mode_border"       -> BindingModeBorder
-        _ -> error "Unrecognized BarPart variant found"
+        _                           -> UnknownBarPart
     parseJSON _ = mzero
 
 instance ToJSON BarPart where
@@ -484,6 +499,7 @@
         BindingModeText         -> text "binding_mode_text"
         BindingModeBg           -> text "binding_mode_bg"
         BindingModeBorder       -> text "binding_mode_border"
+        UnknownBarPart          -> text "unknown"
 
 -- | Version Reply
 data VersionReply = VersionReply {
diff --git a/test/event/winevent.json b/test/event/winevent.json
new file mode 100644
--- /dev/null
+++ b/test/event/winevent.json
@@ -0,0 +1,57 @@
+{
+  "change": "focus",
+  "container": {
+    "id": 94131357905936,
+    "type": "con",
+    "orientation": "none",
+    "scratchpad_state": "none",
+    "percent": 0.5,
+    "urgent": false,
+    "focused": true,
+    "output": "DP-4.8",
+    "layout": "splith",
+    "workspace_layout": "default",
+    "last_split_layout": "splith",
+    "border": "pixel",
+    "current_border_width": 3,
+    "rect": {
+      "x": 3207,
+      "y": 54,
+      "width": 1249,
+      "height": 1362
+    },
+    "deco_rect": {
+      "x": 0,
+      "y": 0,
+      "width": 0,
+      "height": 0
+    },
+    "window_rect": {
+      "x": 3,
+      "y": 3,
+      "width": 1243,
+      "height": 1356
+    },
+    "geometry": {
+      "x": 0,
+      "y": 0,
+      "width": 980,
+      "height": 435
+    },
+    "name": "i3ipc: stack ghci",
+    "window": 33554442,
+    "window_properties": {
+      "class": "URxvt",
+      "instance": "urxvt",
+      "title": "i3ipc: stack ghci",
+      "transient_for": null
+    },
+    "nodes": [],
+    "floating_nodes": [],
+    "focus": [],
+    "fullscreen_mode": 0,
+    "sticky": false,
+    "floating": "auto_off",
+    "swallows": []
+  }
+}
diff --git a/test/event/workspace.json b/test/event/workspace.json
new file mode 100644
--- /dev/null
+++ b/test/event/workspace.json
@@ -0,0 +1,204 @@
+{
+  "change": "focus",
+  "current": {
+    "id": 106996225489920,
+    "type": "workspace",
+    "orientation": "horizontal",
+    "scratchpad_state": "none",
+    "percent": null,
+    "urgent": false,
+    "focused": false,
+    "output": "DVI-I-3",
+    "layout": "splith",
+    "workspace_layout": "default",
+    "last_split_layout": "splith",
+    "border": "pixel",
+    "current_border_width": -1,
+    "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+    "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+    "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+    "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+    "name": "9",
+    "num": 9,
+    "gaps": { "inner": 0, "outer": 0 },
+    "window": null,
+    "nodes": [
+      {
+        "id": 106996225488640,
+        "type": "con",
+        "orientation": "none",
+        "scratchpad_state": "none",
+        "percent": 0.5,
+        "urgent": false,
+        "focused": true,
+        "output": "DVI-I-3",
+        "layout": "splith",
+        "workspace_layout": "default",
+        "last_split_layout": "splith",
+        "border": "pixel",
+        "current_border_width": 1,
+        "rect": { "x": 2572, "y": 41, "width": 1261, "height": 1547 },
+        "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+        "window_rect": { "x": 1, "y": 1, "width": 1259, "height": 1545 },
+        "geometry": { "x": 3328, "y": 416, "width": 1024, "height": 768 },
+        "name": "I3IPC.hs - i3ipc - Visual Studio Code",
+        "window": 62915005,
+        "window_properties": {
+          "class": "Code",
+          "instance": "code",
+          "window_role": "browser-window",
+          "title": "I3IPC.hs - i3ipc - Visual Studio Code",
+          "transient_for": null
+        },
+        "nodes": [],
+        "floating_nodes": [],
+        "focus": [],
+        "fullscreen_mode": 0,
+        "sticky": false,
+        "floating": "auto_off",
+        "swallows": []
+      },
+      {
+        "id": 106996225489280,
+        "type": "con",
+        "orientation": "none",
+        "scratchpad_state": "none",
+        "percent": 0.5,
+        "urgent": false,
+        "focused": false,
+        "output": "DVI-I-3",
+        "layout": "splith",
+        "workspace_layout": "default",
+        "last_split_layout": "splith",
+        "border": "pixel",
+        "current_border_width": 1,
+        "rect": { "x": 3847, "y": 41, "width": 1261, "height": 1547 },
+        "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+        "window_rect": { "x": 1, "y": 1, "width": 1259, "height": 1545 },
+        "geometry": { "x": 0, "y": 0, "width": 860, "height": 460 },
+        "name": "i3ipc: stack ghci",
+        "window": 58720329,
+        "window_properties": {
+          "class": "URxvt",
+          "instance": "urxvt",
+          "title": "i3ipc: stack ghci",
+          "transient_for": null
+        },
+        "nodes": [],
+        "floating_nodes": [],
+        "focus": [],
+        "fullscreen_mode": 0,
+        "sticky": false,
+        "floating": "auto_off",
+        "swallows": []
+      }
+    ],
+    "floating_nodes": [],
+    "focus": [106996225488640, 106996225489280],
+    "fullscreen_mode": 1,
+    "sticky": false,
+    "floating": "auto_off",
+    "swallows": []
+  },
+  "old": {
+    "id": 106996225529600,
+    "type": "workspace",
+    "orientation": "horizontal",
+    "scratchpad_state": "none",
+    "percent": 0.5,
+    "urgent": false,
+    "focused": false,
+    "output": "DVI-I-2",
+    "layout": "splith",
+    "workspace_layout": "default",
+    "last_split_layout": "splith",
+    "border": "pixel",
+    "current_border_width": -1,
+    "rect": { "x": 0, "y": 30, "width": 2560, "height": 1570 },
+    "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+    "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+    "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+    "name": "4",
+    "num": 4,
+    "gaps": { "inner": 0, "outer": 0 },
+    "window": null,
+    "nodes": [
+      {
+        "id": 106996225528960,
+        "type": "con",
+        "orientation": "none",
+        "scratchpad_state": "none",
+        "percent": 0.30000000000000004441,
+        "urgent": false,
+        "focused": false,
+        "output": "DVI-I-2",
+        "layout": "splith",
+        "workspace_layout": "default",
+        "last_split_layout": "splith",
+        "border": "pixel",
+        "current_border_width": 1,
+        "rect": { "x": 12, "y": 42, "width": 749, "height": 1546 },
+        "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+        "window_rect": { "x": 1, "y": 1, "width": 747, "height": 1544 },
+        "geometry": { "x": 0, "y": 0, "width": 747, "height": 1544 },
+        "name": "Inbox - evan@vectorface.com - Mozilla Thunderbird",
+        "window": 73400336,
+        "window_properties": {
+          "class": "Thunderbird",
+          "instance": "Mail",
+          "window_role": "3pane",
+          "title": "Inbox - evan@vectorface.com - Mozilla Thunderbird",
+          "transient_for": null
+        },
+        "nodes": [],
+        "floating_nodes": [],
+        "focus": [],
+        "fullscreen_mode": 0,
+        "sticky": false,
+        "floating": "auto_off",
+        "swallows": []
+      },
+      {
+        "id": 106996225528320,
+        "type": "con",
+        "orientation": "none",
+        "scratchpad_state": "none",
+        "percent": 0.69999999999999995559,
+        "urgent": false,
+        "focused": false,
+        "output": "DVI-I-2",
+        "layout": "splith",
+        "workspace_layout": "default",
+        "last_split_layout": "splith",
+        "border": "pixel",
+        "current_border_width": 1,
+        "rect": { "x": 775, "y": 42, "width": 1773, "height": 1546 },
+        "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+        "window_rect": { "x": 1, "y": 1, "width": 1771, "height": 1544 },
+        "geometry": { "x": 0, "y": 0, "width": 1771, "height": 1544 },
+        "name": "haskell - No output will be generated because there is no Main module - Stack Overflow - Mozilla Firefox",
+        "window": 31457296,
+        "window_properties": {
+          "class": "Firefox",
+          "instance": "Navigator",
+          "window_role": "browser",
+          "title": "haskell - No output will be generated because there is no Main module - Stack Overflow - Mozilla Firefox",
+          "transient_for": null
+        },
+        "nodes": [],
+        "floating_nodes": [],
+        "focus": [],
+        "fullscreen_mode": 0,
+        "sticky": false,
+        "floating": "auto_off",
+        "swallows": []
+      }
+    ],
+    "floating_nodes": [],
+    "focus": [106996225528320, 106996225528960],
+    "fullscreen_mode": 1,
+    "sticky": false,
+    "floating": "auto_off",
+    "swallows": []
+  }
+}
diff --git a/test/reply/output.json b/test/reply/output.json
new file mode 100644
--- /dev/null
+++ b/test/reply/output.json
@@ -0,0 +1,23 @@
+[
+  {
+    "name": "xroot-0",
+    "active": false,
+    "primary": false,
+    "rect": { "x": 0, "y": 0, "width": 5120, "height": 1600 },
+    "current_workspace": null
+  },
+  {
+    "name": "DVI-I-2",
+    "active": true,
+    "primary": false,
+    "rect": { "x": 0, "y": 0, "width": 2560, "height": 1600 },
+    "current_workspace": "1"
+  },
+  {
+    "name": "DVI-I-3",
+    "active": true,
+    "primary": false,
+    "rect": { "x": 2560, "y": 0, "width": 2560, "height": 1600 },
+    "current_workspace": "7"
+  }
+]
diff --git a/test/reply/tree.json b/test/reply/tree.json
new file mode 100644
--- /dev/null
+++ b/test/reply/tree.json
@@ -0,0 +1,1249 @@
+{
+  "id": 106996225351040,
+  "type": "root",
+  "orientation": "horizontal",
+  "scratchpad_state": "none",
+  "percent": null,
+  "urgent": false,
+  "focused": false,
+  "layout": "splith",
+  "workspace_layout": "default",
+  "last_split_layout": "splith",
+  "border": "pixel",
+  "current_border_width": -1,
+  "rect": { "x": 0, "y": 0, "width": 5120, "height": 1600 },
+  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+  "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+  "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+  "name": "root",
+  "window": null,
+  "nodes": [
+    {
+      "id": 106996225350400,
+      "type": "output",
+      "orientation": "none",
+      "scratchpad_state": "none",
+      "percent": 0.33333333333333331483,
+      "urgent": false,
+      "focused": false,
+      "layout": "output",
+      "workspace_layout": "default",
+      "last_split_layout": "splith",
+      "border": "pixel",
+      "current_border_width": -1,
+      "rect": { "x": 0, "y": 0, "width": 2560, "height": 1600 },
+      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "name": "__i3",
+      "window": null,
+      "nodes": [
+        {
+          "id": 106996225349760,
+          "type": "con",
+          "orientation": "horizontal",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "__i3",
+          "layout": "splith",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "content",
+          "window": null,
+          "nodes": [
+            {
+              "id": 106996225349120,
+              "type": "workspace",
+              "orientation": "none",
+              "scratchpad_state": "none",
+              "percent": null,
+              "urgent": false,
+              "focused": false,
+              "output": "__i3",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": -1,
+              "rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "name": "__i3_scratch",
+              "num": -1,
+              "gaps": { "inner": 0, "outer": 0 },
+              "window": null,
+              "nodes": [],
+              "floating_nodes": [],
+              "focus": [],
+              "fullscreen_mode": 1,
+              "sticky": false,
+              "floating": "auto_off",
+              "swallows": []
+            }
+          ],
+          "floating_nodes": [],
+          "focus": [106996225349120],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": []
+        }
+      ],
+      "floating_nodes": [],
+      "focus": [106996225349760],
+      "fullscreen_mode": 0,
+      "sticky": false,
+      "floating": "auto_off",
+      "swallows": []
+    },
+    {
+      "id": 106996225345920,
+      "type": "output",
+      "orientation": "none",
+      "scratchpad_state": "none",
+      "percent": 0.33333333333333331483,
+      "urgent": false,
+      "focused": false,
+      "layout": "output",
+      "workspace_layout": "default",
+      "last_split_layout": "splith",
+      "border": "pixel",
+      "current_border_width": -1,
+      "rect": { "x": 2560, "y": 0, "width": 2560, "height": 1600 },
+      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "name": "DVI-I-3",
+      "window": null,
+      "nodes": [
+        {
+          "id": 106996225345280,
+          "type": "dockarea",
+          "orientation": "none",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "DVI-I-3",
+          "layout": "dockarea",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 2560, "y": 0, "width": 2560, "height": 29 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "topdock",
+          "window": null,
+          "nodes": [
+            {
+              "id": 106996225536000,
+              "type": "con",
+              "orientation": "none",
+              "scratchpad_state": "none",
+              "percent": 1.0,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-3",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": 3,
+              "rect": { "x": 2560, "y": 0, "width": 2560, "height": 29 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 2560, "height": 29 },
+              "geometry": { "x": 2560, "y": 0, "width": 2560, "height": 29 },
+              "name": "polybar-dvi3_DVI-I-3",
+              "window": 23068674,
+              "window_properties": {
+                "class": "Polybar",
+                "instance": "polybar",
+                "title": "polybar-dvi3_DVI-I-3",
+                "transient_for": null
+              },
+              "nodes": [],
+              "floating_nodes": [],
+              "focus": [],
+              "fullscreen_mode": 0,
+              "sticky": true,
+              "floating": "auto_off",
+              "swallows": []
+            }
+          ],
+          "floating_nodes": [],
+          "focus": [106996225536000],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": [{ "dock": 2, "insert_where": 2 }]
+        },
+        {
+          "id": 106996225344640,
+          "type": "con",
+          "orientation": "horizontal",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "DVI-I-3",
+          "layout": "splith",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "content",
+          "window": null,
+          "nodes": [
+            {
+              "id": 106996225538560,
+              "type": "workspace",
+              "orientation": "vertical",
+              "scratchpad_state": "none",
+              "percent": 0.5,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-3",
+              "layout": "splitv",
+              "workspace_layout": "default",
+              "last_split_layout": "splitv",
+              "border": "pixel",
+              "current_border_width": -1,
+              "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "name": "2",
+              "num": 2,
+              "gaps": { "inner": 0, "outer": 0 },
+              "window": null,
+              "nodes": [
+                {
+                  "id": 106996225532160,
+                  "type": "con",
+                  "orientation": "none",
+                  "scratchpad_state": "none",
+                  "percent": 1.0,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-3",
+                  "layout": "splith",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splith",
+                  "border": "pixel",
+                  "current_border_width": 1,
+                  "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": {
+                    "x": 0,
+                    "y": 0,
+                    "width": 2560,
+                    "height": 1571
+                  },
+                  "geometry": {
+                    "x": 3847,
+                    "y": 41,
+                    "width": 1259,
+                    "height": 1545
+                  },
+                  "name": "Rust Track | Exercism - Mozilla Firefox",
+                  "window": 31457330,
+                  "window_properties": {
+                    "class": "Firefox",
+                    "instance": "Navigator",
+                    "window_role": "browser",
+                    "title": "Rust Track | Exercism - Mozilla Firefox",
+                    "transient_for": null
+                  },
+                  "nodes": [],
+                  "floating_nodes": [],
+                  "focus": [],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                }
+              ],
+              "floating_nodes": [],
+              "focus": [106996225532160],
+              "fullscreen_mode": 0,
+              "sticky": false,
+              "floating": "auto_off",
+              "swallows": []
+            },
+            {
+              "id": 106996225511680,
+              "type": "workspace",
+              "orientation": "horizontal",
+              "scratchpad_state": "none",
+              "percent": null,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-3",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": -1,
+              "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "name": "7",
+              "num": 7,
+              "gaps": { "inner": 0, "outer": 0 },
+              "window": null,
+              "nodes": [
+                {
+                  "id": 106996225509760,
+                  "type": "con",
+                  "orientation": "none",
+                  "scratchpad_state": "none",
+                  "percent": 0.5,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-3",
+                  "layout": "splith",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splith",
+                  "border": "pixel",
+                  "current_border_width": 1,
+                  "rect": { "x": 2572, "y": 41, "width": 1261, "height": 1547 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": {
+                    "x": 1,
+                    "y": 1,
+                    "width": 1259,
+                    "height": 1545
+                  },
+                  "geometry": {
+                    "x": 3328,
+                    "y": 416,
+                    "width": 1024,
+                    "height": 768
+                  },
+                  "name": "Reply.hs - i3ipc - Visual Studio Code",
+                  "window": 62914600,
+                  "window_properties": {
+                    "class": "Code",
+                    "instance": "code",
+                    "window_role": "browser-window",
+                    "title": "Reply.hs - i3ipc - Visual Studio Code",
+                    "transient_for": null
+                  },
+                  "nodes": [],
+                  "floating_nodes": [],
+                  "focus": [],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                },
+                {
+                  "id": 106996225509120,
+                  "type": "con",
+                  "orientation": "vertical",
+                  "scratchpad_state": "none",
+                  "percent": 0.5,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-3",
+                  "layout": "splitv",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splitv",
+                  "border": "pixel",
+                  "current_border_width": -1,
+                  "rect": { "x": 3840, "y": 29, "width": 1280, "height": 1571 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "name": null,
+                  "window": null,
+                  "nodes": [
+                    {
+                      "id": 106996225511040,
+                      "type": "con",
+                      "orientation": "none",
+                      "scratchpad_state": "none",
+                      "percent": 0.5,
+                      "urgent": false,
+                      "focused": true,
+                      "output": "DVI-I-3",
+                      "layout": "splith",
+                      "workspace_layout": "default",
+                      "last_split_layout": "splith",
+                      "border": "pixel",
+                      "current_border_width": 1,
+                      "rect": {
+                        "x": 3847,
+                        "y": 41,
+                        "width": 1261,
+                        "height": 766
+                      },
+                      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                      "window_rect": {
+                        "x": 1,
+                        "y": 1,
+                        "width": 1259,
+                        "height": 764
+                      },
+                      "geometry": {
+                        "x": 0,
+                        "y": 0,
+                        "width": 860,
+                        "height": 460
+                      },
+                      "name": "i3ipc: stack ghci",
+                      "window": 58720285,
+                      "window_properties": {
+                        "class": "URxvt",
+                        "instance": "urxvt",
+                        "title": "i3ipc: stack ghci",
+                        "transient_for": null
+                      },
+                      "nodes": [],
+                      "floating_nodes": [],
+                      "focus": [],
+                      "fullscreen_mode": 0,
+                      "sticky": false,
+                      "floating": "auto_off",
+                      "swallows": []
+                    },
+                    {
+                      "id": 106996225510400,
+                      "type": "con",
+                      "orientation": "none",
+                      "scratchpad_state": "none",
+                      "percent": 0.5,
+                      "urgent": false,
+                      "focused": false,
+                      "output": "DVI-I-3",
+                      "layout": "splith",
+                      "workspace_layout": "default",
+                      "last_split_layout": "splith",
+                      "border": "pixel",
+                      "current_border_width": 1,
+                      "rect": {
+                        "x": 3847,
+                        "y": 821,
+                        "width": 1261,
+                        "height": 767
+                      },
+                      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                      "window_rect": {
+                        "x": 1,
+                        "y": 1,
+                        "width": 1259,
+                        "height": 765
+                      },
+                      "geometry": {
+                        "x": 0,
+                        "y": 0,
+                        "width": 860,
+                        "height": 460
+                      },
+                      "name": "~/personal/haskell/i3ipc",
+                      "window": 58720305,
+                      "window_properties": {
+                        "class": "URxvt",
+                        "instance": "urxvt",
+                        "title": "~/personal/haskell/i3ipc",
+                        "transient_for": null
+                      },
+                      "nodes": [],
+                      "floating_nodes": [],
+                      "focus": [],
+                      "fullscreen_mode": 0,
+                      "sticky": false,
+                      "floating": "auto_off",
+                      "swallows": []
+                    }
+                  ],
+                  "floating_nodes": [],
+                  "focus": [106996225511040, 106996225510400],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                }
+              ],
+              "floating_nodes": [],
+              "focus": [106996225509120, 106996225509760],
+              "fullscreen_mode": 1,
+              "sticky": false,
+              "floating": "auto_off",
+              "swallows": []
+            },
+            {
+              "id": 106996225516160,
+              "type": "workspace",
+              "orientation": "horizontal",
+              "scratchpad_state": "none",
+              "percent": 0.5,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-3",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": -1,
+              "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "name": "8",
+              "num": 8,
+              "gaps": { "inner": 0, "outer": 0 },
+              "window": null,
+              "nodes": [
+                {
+                  "id": 106996225514880,
+                  "type": "con",
+                  "orientation": "none",
+                  "scratchpad_state": "none",
+                  "percent": 0.5999999999999999778,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-3",
+                  "layout": "splith",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splith",
+                  "border": "pixel",
+                  "current_border_width": 1,
+                  "rect": { "x": 2572, "y": 41, "width": 1517, "height": 1547 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": {
+                    "x": 1,
+                    "y": 1,
+                    "width": 1515,
+                    "height": 1545
+                  },
+                  "geometry": {
+                    "x": 2573,
+                    "y": 42,
+                    "width": 1515,
+                    "height": 1545
+                  },
+                  "name": "Game.js - unified-components - Visual Studio Code",
+                  "window": 62914561,
+                  "window_properties": {
+                    "class": "Code",
+                    "instance": "code",
+                    "window_role": "browser-window",
+                    "title": "Game.js - unified-components - Visual Studio Code",
+                    "transient_for": null
+                  },
+                  "nodes": [],
+                  "floating_nodes": [],
+                  "focus": [],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                },
+                {
+                  "id": 106996225515520,
+                  "type": "con",
+                  "orientation": "none",
+                  "scratchpad_state": "none",
+                  "percent": 0.4000000000000000222,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-3",
+                  "layout": "splith",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splith",
+                  "border": "pixel",
+                  "current_border_width": 1,
+                  "rect": { "x": 4103, "y": 41, "width": 1005, "height": 1547 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": {
+                    "x": 1,
+                    "y": 1,
+                    "width": 1003,
+                    "height": 1545
+                  },
+                  "geometry": { "x": 0, "y": 0, "width": 860, "height": 460 },
+                  "name": "~/dev/unified-components",
+                  "window": 58720266,
+                  "window_properties": {
+                    "class": "URxvt",
+                    "instance": "urxvt",
+                    "title": "~/dev/unified-components",
+                    "transient_for": null
+                  },
+                  "nodes": [],
+                  "floating_nodes": [],
+                  "focus": [],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                }
+              ],
+              "floating_nodes": [],
+              "focus": [106996225514880, 106996225515520],
+              "fullscreen_mode": 0,
+              "sticky": false,
+              "floating": "auto_off",
+              "swallows": []
+            }
+          ],
+          "floating_nodes": [],
+          "focus": [106996225511680, 106996225516160, 106996225538560],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": []
+        },
+        {
+          "id": 106996225344000,
+          "type": "dockarea",
+          "orientation": "none",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "DVI-I-3",
+          "layout": "dockarea",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 2560, "y": 1600, "width": 2560, "height": 0 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "bottomdock",
+          "window": null,
+          "nodes": [],
+          "floating_nodes": [],
+          "focus": [],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": [{ "dock": 3, "insert_where": 2 }]
+        }
+      ],
+      "floating_nodes": [],
+      "focus": [106996225344640, 106996225345280, 106996225344000],
+      "fullscreen_mode": 0,
+      "sticky": false,
+      "floating": "auto_off",
+      "swallows": []
+    },
+    {
+      "id": 106996225348480,
+      "type": "output",
+      "orientation": "none",
+      "scratchpad_state": "none",
+      "percent": 0.33333333333333331483,
+      "urgent": false,
+      "focused": false,
+      "layout": "output",
+      "workspace_layout": "default",
+      "last_split_layout": "splith",
+      "border": "pixel",
+      "current_border_width": -1,
+      "rect": { "x": 0, "y": 0, "width": 2560, "height": 1600 },
+      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+      "name": "DVI-I-2",
+      "window": null,
+      "nodes": [
+        {
+          "id": 106996225347840,
+          "type": "dockarea",
+          "orientation": "none",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "DVI-I-2",
+          "layout": "dockarea",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 0, "y": 0, "width": 2560, "height": 30 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "topdock",
+          "window": null,
+          "nodes": [
+            {
+              "id": 106996225535360,
+              "type": "con",
+              "orientation": "none",
+              "scratchpad_state": "none",
+              "percent": 1.0,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-2",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": 3,
+              "rect": { "x": 0, "y": 0, "width": 2560, "height": 30 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 2560, "height": 30 },
+              "geometry": { "x": 0, "y": 0, "width": 2560, "height": 30 },
+              "name": "polybar-dvi2_DVI-I-2",
+              "window": 10485762,
+              "window_properties": {
+                "class": "Polybar",
+                "instance": "polybar",
+                "title": "polybar-dvi2_DVI-I-2",
+                "transient_for": null
+              },
+              "nodes": [],
+              "floating_nodes": [],
+              "focus": [],
+              "fullscreen_mode": 0,
+              "sticky": true,
+              "floating": "auto_off",
+              "swallows": []
+            }
+          ],
+          "floating_nodes": [],
+          "focus": [106996225535360],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": [{ "dock": 2, "insert_where": 2 }]
+        },
+        {
+          "id": 106996225347200,
+          "type": "con",
+          "orientation": "horizontal",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "DVI-I-2",
+          "layout": "splith",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 0, "y": 30, "width": 2560, "height": 1570 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "content",
+          "window": null,
+          "nodes": [
+            {
+              "id": 106996225343360,
+              "type": "workspace",
+              "orientation": "horizontal",
+              "scratchpad_state": "none",
+              "percent": null,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-2",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": -1,
+              "rect": { "x": 0, "y": 30, "width": 2560, "height": 1570 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "name": "1",
+              "num": 1,
+              "gaps": { "inner": 0, "outer": 0 },
+              "window": null,
+              "nodes": [
+                {
+                  "id": 106996225525760,
+                  "type": "con",
+                  "orientation": "vertical",
+                  "scratchpad_state": "none",
+                  "percent": 0.25999999999999989786,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-2",
+                  "layout": "splitv",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splitv",
+                  "border": "pixel",
+                  "current_border_width": -1,
+                  "rect": { "x": 0, "y": 30, "width": 666, "height": 1570 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "name": null,
+                  "window": null,
+                  "nodes": [
+                    {
+                      "id": 106996225518080,
+                      "type": "con",
+                      "orientation": "vertical",
+                      "scratchpad_state": "none",
+                      "percent": 0.5,
+                      "urgent": false,
+                      "focused": false,
+                      "output": "DVI-I-2",
+                      "layout": "stacked",
+                      "workspace_layout": "default",
+                      "last_split_layout": "splith",
+                      "border": "pixel",
+                      "current_border_width": -1,
+                      "rect": { "x": 12, "y": 42, "width": 647, "height": 766 },
+                      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                      "window_rect": {
+                        "x": 0,
+                        "y": 0,
+                        "width": 0,
+                        "height": 0
+                      },
+                      "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                      "name": null,
+                      "window": null,
+                      "nodes": [
+                        {
+                          "id": 106996225537920,
+                          "type": "con",
+                          "orientation": "none",
+                          "scratchpad_state": "none",
+                          "percent": 0.5,
+                          "urgent": false,
+                          "focused": false,
+                          "output": "DVI-I-2",
+                          "layout": "splith",
+                          "workspace_layout": "default",
+                          "last_split_layout": "splith",
+                          "border": "pixel",
+                          "current_border_width": 1,
+                          "rect": {
+                            "x": 12,
+                            "y": 78,
+                            "width": 647,
+                            "height": 730
+                          },
+                          "deco_rect": {
+                            "x": 0,
+                            "y": 0,
+                            "width": 647,
+                            "height": 18
+                          },
+                          "window_rect": {
+                            "x": 1,
+                            "y": 0,
+                            "width": 645,
+                            "height": 729
+                          },
+                          "geometry": {
+                            "x": 12,
+                            "y": 42,
+                            "width": 747,
+                            "height": 1544
+                          },
+                          "name": "Buddy List",
+                          "window": 20971615,
+                          "window_properties": {
+                            "class": "Pidgin",
+                            "instance": "Pidgin",
+                            "window_role": "buddy_list",
+                            "title": "Buddy List",
+                            "transient_for": null
+                          },
+                          "nodes": [],
+                          "floating_nodes": [],
+                          "focus": [],
+                          "fullscreen_mode": 0,
+                          "sticky": false,
+                          "floating": "auto_off",
+                          "swallows": []
+                        },
+                        {
+                          "id": 106996225517440,
+                          "type": "con",
+                          "orientation": "none",
+                          "scratchpad_state": "none",
+                          "percent": 0.5,
+                          "urgent": false,
+                          "focused": false,
+                          "output": "DVI-I-2",
+                          "layout": "splith",
+                          "workspace_layout": "default",
+                          "last_split_layout": "splith",
+                          "border": "pixel",
+                          "current_border_width": 1,
+                          "rect": {
+                            "x": 12,
+                            "y": 78,
+                            "width": 647,
+                            "height": 730
+                          },
+                          "deco_rect": {
+                            "x": 0,
+                            "y": 18,
+                            "width": 647,
+                            "height": 18
+                          },
+                          "window_rect": {
+                            "x": 1,
+                            "y": 0,
+                            "width": 645,
+                            "height": 729
+                          },
+                          "geometry": {
+                            "x": 13,
+                            "y": 78,
+                            "width": 800,
+                            "height": 1509
+                          },
+                          "name": "Signal",
+                          "window": 48234497,
+                          "window_properties": {
+                            "class": "Signal",
+                            "instance": "signal",
+                            "window_role": "browser-window",
+                            "title": "Signal",
+                            "transient_for": null
+                          },
+                          "nodes": [],
+                          "floating_nodes": [],
+                          "focus": [],
+                          "fullscreen_mode": 0,
+                          "sticky": false,
+                          "floating": "auto_off",
+                          "swallows": []
+                        }
+                      ],
+                      "floating_nodes": [],
+                      "focus": [106996225537920, 106996225517440],
+                      "fullscreen_mode": 0,
+                      "sticky": false,
+                      "floating": "auto_off",
+                      "swallows": []
+                    },
+                    {
+                      "id": 106996225526400,
+                      "type": "con",
+                      "orientation": "none",
+                      "scratchpad_state": "none",
+                      "percent": 0.5,
+                      "urgent": false,
+                      "focused": false,
+                      "output": "DVI-I-2",
+                      "layout": "splith",
+                      "workspace_layout": "default",
+                      "last_split_layout": "splith",
+                      "border": "pixel",
+                      "current_border_width": 1,
+                      "rect": {
+                        "x": 12,
+                        "y": 822,
+                        "width": 647,
+                        "height": 766
+                      },
+                      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                      "window_rect": {
+                        "x": 1,
+                        "y": 1,
+                        "width": 645,
+                        "height": 764
+                      },
+                      "geometry": {
+                        "x": 0,
+                        "y": 0,
+                        "width": 491,
+                        "height": 753
+                      },
+                      "name": "Francis",
+                      "window": 20974804,
+                      "window_properties": {
+                        "class": "Pidgin",
+                        "instance": "Pidgin",
+                        "window_role": "conversation",
+                        "title": "Francis",
+                        "transient_for": null
+                      },
+                      "nodes": [],
+                      "floating_nodes": [],
+                      "focus": [],
+                      "fullscreen_mode": 0,
+                      "sticky": false,
+                      "floating": "auto_off",
+                      "swallows": []
+                    }
+                  ],
+                  "floating_nodes": [],
+                  "focus": [106996225526400, 106996225518080],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                },
+                {
+                  "id": 106996225512960,
+                  "type": "con",
+                  "orientation": "vertical",
+                  "scratchpad_state": "none",
+                  "percent": 0.73999999999999999112,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-2",
+                  "layout": "splitv",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splitv",
+                  "border": "pixel",
+                  "current_border_width": -1,
+                  "rect": { "x": 666, "y": 30, "width": 1894, "height": 1570 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "name": null,
+                  "window": null,
+                  "nodes": [
+                    {
+                      "id": 106996225532800,
+                      "type": "con",
+                      "orientation": "none",
+                      "scratchpad_state": "none",
+                      "percent": 1.0,
+                      "urgent": false,
+                      "focused": false,
+                      "output": "DVI-I-2",
+                      "layout": "splith",
+                      "workspace_layout": "default",
+                      "last_split_layout": "splith",
+                      "border": "pixel",
+                      "current_border_width": 1,
+                      "rect": {
+                        "x": 673,
+                        "y": 42,
+                        "width": 1875,
+                        "height": 1546
+                      },
+                      "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                      "window_rect": {
+                        "x": 1,
+                        "y": 1,
+                        "width": 1873,
+                        "height": 1544
+                      },
+                      "geometry": {
+                        "x": 775,
+                        "y": 42,
+                        "width": 1771,
+                        "height": 1544
+                      },
+                      "name": "i3: IPC interface (interprocess communication) - Mozilla Firefox",
+                      "window": 31457319,
+                      "window_properties": {
+                        "class": "Firefox",
+                        "instance": "Navigator",
+                        "window_role": "browser",
+                        "title": "i3: IPC interface (interprocess communication) - Mozilla Firefox",
+                        "transient_for": null
+                      },
+                      "nodes": [],
+                      "floating_nodes": [],
+                      "focus": [],
+                      "fullscreen_mode": 0,
+                      "sticky": false,
+                      "floating": "auto_off",
+                      "swallows": []
+                    }
+                  ],
+                  "floating_nodes": [],
+                  "focus": [106996225532800],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                }
+              ],
+              "floating_nodes": [],
+              "focus": [106996225512960, 106996225525760],
+              "fullscreen_mode": 1,
+              "sticky": false,
+              "floating": "auto_off",
+              "swallows": []
+            },
+            {
+              "id": 106996225531520,
+              "type": "workspace",
+              "orientation": "horizontal",
+              "scratchpad_state": "none",
+              "percent": null,
+              "urgent": false,
+              "focused": false,
+              "output": "DVI-I-2",
+              "layout": "splith",
+              "workspace_layout": "default",
+              "last_split_layout": "splith",
+              "border": "pixel",
+              "current_border_width": -1,
+              "rect": { "x": 0, "y": 30, "width": 2560, "height": 1570 },
+              "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+              "name": "4",
+              "num": 4,
+              "gaps": { "inner": 0, "outer": 0 },
+              "window": null,
+              "nodes": [
+                {
+                  "id": 106996225513600,
+                  "type": "con",
+                  "orientation": "none",
+                  "scratchpad_state": "none",
+                  "percent": 0.30000000000000004441,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-2",
+                  "layout": "splith",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splith",
+                  "border": "pixel",
+                  "current_border_width": 1,
+                  "rect": { "x": 12, "y": 42, "width": 749, "height": 1546 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": {
+                    "x": 1,
+                    "y": 1,
+                    "width": 747,
+                    "height": 1544
+                  },
+                  "geometry": { "x": 0, "y": 0, "width": 747, "height": 1544 },
+                  "name": "Inbox - evan@vectorface.com - Mozilla Thunderbird",
+                  "window": 73400336,
+                  "window_properties": {
+                    "class": "Thunderbird",
+                    "instance": "Mail",
+                    "window_role": "3pane",
+                    "title": "Inbox - evan@vectorface.com - Mozilla Thunderbird",
+                    "transient_for": null
+                  },
+                  "nodes": [],
+                  "floating_nodes": [],
+                  "focus": [],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                },
+                {
+                  "id": 106996225533440,
+                  "type": "con",
+                  "orientation": "none",
+                  "scratchpad_state": "none",
+                  "percent": 0.69999999999999995559,
+                  "urgent": false,
+                  "focused": false,
+                  "output": "DVI-I-2",
+                  "layout": "splith",
+                  "workspace_layout": "default",
+                  "last_split_layout": "splith",
+                  "border": "pixel",
+                  "current_border_width": 1,
+                  "rect": { "x": 775, "y": 42, "width": 1773, "height": 1546 },
+                  "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+                  "window_rect": {
+                    "x": 1,
+                    "y": 1,
+                    "width": 1771,
+                    "height": 1544
+                  },
+                  "geometry": { "x": 0, "y": 0, "width": 1771, "height": 1544 },
+                  "name": "Phil lobby gamelist p2 (!96) · Merge Requests · Client / unified-components · GitLab - Mozilla Firefox",
+                  "window": 31457296,
+                  "window_properties": {
+                    "class": "Firefox",
+                    "instance": "Navigator",
+                    "window_role": "browser",
+                    "title": "Phil lobby gamelist p2 (!96) · Merge Requests · Client / unified-components · GitLab - Mozilla Firefox",
+                    "transient_for": null
+                  },
+                  "nodes": [],
+                  "floating_nodes": [],
+                  "focus": [],
+                  "fullscreen_mode": 0,
+                  "sticky": false,
+                  "floating": "auto_off",
+                  "swallows": []
+                }
+              ],
+              "floating_nodes": [],
+              "focus": [106996225513600, 106996225533440],
+              "fullscreen_mode": 0,
+              "sticky": false,
+              "floating": "auto_off",
+              "swallows": []
+            }
+          ],
+          "floating_nodes": [],
+          "focus": [106996225343360, 106996225531520],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": []
+        },
+        {
+          "id": 106996225346560,
+          "type": "dockarea",
+          "orientation": "none",
+          "scratchpad_state": "none",
+          "percent": null,
+          "urgent": false,
+          "focused": false,
+          "output": "DVI-I-2",
+          "layout": "dockarea",
+          "workspace_layout": "default",
+          "last_split_layout": "splith",
+          "border": "pixel",
+          "current_border_width": -1,
+          "rect": { "x": 0, "y": 1600, "width": 2560, "height": 0 },
+          "deco_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "window_rect": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "geometry": { "x": 0, "y": 0, "width": 0, "height": 0 },
+          "name": "bottomdock",
+          "window": null,
+          "nodes": [],
+          "floating_nodes": [],
+          "focus": [],
+          "fullscreen_mode": 0,
+          "sticky": false,
+          "floating": "auto_off",
+          "swallows": [{ "dock": 3, "insert_where": 2 }]
+        }
+      ],
+      "floating_nodes": [],
+      "focus": [106996225347200, 106996225347840, 106996225346560],
+      "fullscreen_mode": 0,
+      "sticky": false,
+      "floating": "auto_off",
+      "swallows": []
+    }
+  ],
+  "floating_nodes": [],
+  "focus": [106996225345920, 106996225348480, 106996225350400],
+  "fullscreen_mode": 0,
+  "sticky": false,
+  "floating": "auto_off",
+  "swallows": []
+}
diff --git a/test/reply/version.json b/test/reply/version.json
new file mode 100644
--- /dev/null
+++ b/test/reply/version.json
@@ -0,0 +1,7 @@
+{
+  "major": 4,
+  "minor": 16,
+  "patch": 0,
+  "human_readable": "4.16-3-gecbfb2b4 (2018-11-04, branch \"gaps\")",
+  "loaded_config_file_name": "/home/evan/.config/i3/config"
+}
diff --git a/test/reply/workspace.json b/test/reply/workspace.json
new file mode 100644
--- /dev/null
+++ b/test/reply/workspace.json
@@ -0,0 +1,47 @@
+[
+  {
+    "num": 2,
+    "name": "2",
+    "visible": false,
+    "focused": false,
+    "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+    "output": "DVI-I-3",
+    "urgent": false
+  },
+  {
+    "num": 7,
+    "name": "7",
+    "visible": true,
+    "focused": true,
+    "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+    "output": "DVI-I-3",
+    "urgent": false
+  },
+  {
+    "num": 8,
+    "name": "8",
+    "visible": false,
+    "focused": false,
+    "rect": { "x": 2560, "y": 29, "width": 2560, "height": 1571 },
+    "output": "DVI-I-3",
+    "urgent": false
+  },
+  {
+    "num": 1,
+    "name": "1",
+    "visible": true,
+    "focused": false,
+    "rect": { "x": 0, "y": 30, "width": 2560, "height": 1570 },
+    "output": "DVI-I-2",
+    "urgent": false
+  },
+  {
+    "num": 4,
+    "name": "4",
+    "visible": false,
+    "focused": false,
+    "rect": { "x": 0, "y": 30, "width": 2560, "height": 1570 },
+    "output": "DVI-I-2",
+    "urgent": false
+  }
+]
