diff --git a/sbp.cabal b/sbp.cabal
--- a/sbp.cabal
+++ b/sbp.cabal
@@ -1,5 +1,5 @@
 name:                  sbp
-version:               2.0.0
+version:               2.1.0
 synopsis:              SwiftNav's SBP Library
 homepage:              https://github.com/swift-nav/libsbp
 license:               LGPL-3
diff --git a/src/SwiftNav/SBP.hs b/src/SwiftNav/SBP.hs
--- a/src/SwiftNav/SBP.hs
+++ b/src/SwiftNav/SBP.hs
@@ -72,6 +72,8 @@
    | SBPMsgBootloaderHandshakeReq MsgBootloaderHandshakeReq Msg
    | SBPMsgBootloaderHandshakeResp MsgBootloaderHandshakeResp Msg
    | SBPMsgBootloaderJumpToApp MsgBootloaderJumpToApp Msg
+   | SBPMsgCommandReq MsgCommandReq Msg
+   | SBPMsgCommandResp MsgCommandResp Msg
    | SBPMsgCwResults MsgCwResults Msg
    | SBPMsgCwStart MsgCwStart Msg
    | SBPMsgDeviceMonitor MsgDeviceMonitor Msg
@@ -182,6 +184,8 @@
           | _msgSBPType == msgBootloaderHandshakeReq = SBPMsgBootloaderHandshakeReq (decode (fromStrict _msgSBPPayload)) m
           | _msgSBPType == msgBootloaderHandshakeResp = SBPMsgBootloaderHandshakeResp (decode (fromStrict _msgSBPPayload)) m
           | _msgSBPType == msgBootloaderJumpToApp = SBPMsgBootloaderJumpToApp (decode (fromStrict _msgSBPPayload)) m
+          | _msgSBPType == msgCommandReq = SBPMsgCommandReq (decode (fromStrict _msgSBPPayload)) m
+          | _msgSBPType == msgCommandResp = SBPMsgCommandResp (decode (fromStrict _msgSBPPayload)) m
           | _msgSBPType == msgCwResults = SBPMsgCwResults (decode (fromStrict _msgSBPPayload)) m
           | _msgSBPType == msgCwStart = SBPMsgCwStart (decode (fromStrict _msgSBPPayload)) m
           | _msgSBPType == msgDeviceMonitor = SBPMsgDeviceMonitor (decode (fromStrict _msgSBPPayload)) m
@@ -284,6 +288,8 @@
       encode' (SBPMsgBootloaderHandshakeReq _ m) = put m
       encode' (SBPMsgBootloaderHandshakeResp _ m) = put m
       encode' (SBPMsgBootloaderJumpToApp _ m) = put m
+      encode' (SBPMsgCommandReq _ m) = put m
+      encode' (SBPMsgCommandResp _ m) = put m
       encode' (SBPMsgCwResults _ m) = put m
       encode' (SBPMsgCwStart _ m) = put m
       encode' (SBPMsgDeviceMonitor _ m) = put m
@@ -389,6 +395,8 @@
         | msgType == msgBootloaderHandshakeReq = SBPMsgBootloaderHandshakeReq <$> parseJSON obj <*> parseJSON obj
         | msgType == msgBootloaderHandshakeResp = SBPMsgBootloaderHandshakeResp <$> parseJSON obj <*> parseJSON obj
         | msgType == msgBootloaderJumpToApp = SBPMsgBootloaderJumpToApp <$> parseJSON obj <*> parseJSON obj
+        | msgType == msgCommandReq = SBPMsgCommandReq <$> parseJSON obj <*> parseJSON obj
+        | msgType == msgCommandResp = SBPMsgCommandResp <$> parseJSON obj <*> parseJSON obj
         | msgType == msgCwResults = SBPMsgCwResults <$> parseJSON obj <*> parseJSON obj
         | msgType == msgCwStart = SBPMsgCwStart <$> parseJSON obj <*> parseJSON obj
         | msgType == msgDeviceMonitor = SBPMsgDeviceMonitor <$> parseJSON obj <*> parseJSON obj
@@ -496,6 +504,8 @@
   toJSON (SBPMsgBootloaderHandshakeReq n m) = toJSON n `mergeValues` toJSON m
   toJSON (SBPMsgBootloaderHandshakeResp n m) = toJSON n `mergeValues` toJSON m
   toJSON (SBPMsgBootloaderJumpToApp n m) = toJSON n `mergeValues` toJSON m
+  toJSON (SBPMsgCommandReq n m) = toJSON n `mergeValues` toJSON m
+  toJSON (SBPMsgCommandResp n m) = toJSON n `mergeValues` toJSON m
   toJSON (SBPMsgCwResults n m) = toJSON n `mergeValues` toJSON m
   toJSON (SBPMsgCwStart n m) = toJSON n `mergeValues` toJSON m
   toJSON (SBPMsgDeviceMonitor n m) = toJSON n `mergeValues` toJSON m
@@ -597,6 +607,8 @@
   msg f (SBPMsgBootloaderHandshakeReq n m) = SBPMsgBootloaderHandshakeReq n <$> f m
   msg f (SBPMsgBootloaderHandshakeResp n m) = SBPMsgBootloaderHandshakeResp n <$> f m
   msg f (SBPMsgBootloaderJumpToApp n m) = SBPMsgBootloaderJumpToApp n <$> f m
+  msg f (SBPMsgCommandReq n m) = SBPMsgCommandReq n <$> f m
+  msg f (SBPMsgCommandResp n m) = SBPMsgCommandResp n <$> f m
   msg f (SBPMsgCwResults n m) = SBPMsgCwResults n <$> f m
   msg f (SBPMsgCwStart n m) = SBPMsgCwStart n <$> f m
   msg f (SBPMsgDeviceMonitor n m) = SBPMsgDeviceMonitor n <$> f m
diff --git a/src/SwiftNav/SBP/Piksi.hs b/src/SwiftNav/SBP/Piksi.hs
--- a/src/SwiftNav/SBP/Piksi.hs
+++ b/src/SwiftNav/SBP/Piksi.hs
@@ -526,3 +526,63 @@
 $(deriveJSON defaultOptions {fieldLabelModifier = fromMaybe "_msgDeviceMonitor_" . stripPrefix "_msgDeviceMonitor_"}
              ''MsgDeviceMonitor)
 $(makeLenses ''MsgDeviceMonitor)
+
+msgCommandReq :: Word16
+msgCommandReq = 0x00B8
+
+-- | SBP class for message MSG_COMMAND_REQ (0x00B8).
+--
+-- Request the recipient to execute an command. Output will be sent in MSG_LOG
+-- messages, and the exit code will be returned with MSG_COMMAND_RESP.
+data MsgCommandReq = MsgCommandReq
+  { _msgCommandReq_sequence :: Word32
+    -- ^ Sequence number
+  , _msgCommandReq_command :: Text
+    -- ^ Command line to execute
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgCommandReq where
+  get = do
+    _msgCommandReq_sequence <- getWord32le
+    _msgCommandReq_command <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    return MsgCommandReq {..}
+
+  put MsgCommandReq {..} = do
+    putWord32le _msgCommandReq_sequence
+    putByteString $ encodeUtf8 _msgCommandReq_command
+
+$(deriveSBP 'msgCommandReq ''MsgCommandReq)
+
+$(deriveJSON defaultOptions {fieldLabelModifier = fromMaybe "_msgCommandReq_" . stripPrefix "_msgCommandReq_"}
+             ''MsgCommandReq)
+$(makeLenses ''MsgCommandReq)
+
+msgCommandResp :: Word16
+msgCommandResp = 0x00B9
+
+-- | SBP class for message MSG_COMMAND_RESP (0x00B9).
+--
+-- The response to MSG_COMMAND_REQ with the return code of the command.  A
+-- return code of zero indicates success.
+data MsgCommandResp = MsgCommandResp
+  { _msgCommandResp_sequence :: Word32
+    -- ^ Sequence number
+  , _msgCommandResp_code   :: Int32
+    -- ^ Exit code
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgCommandResp where
+  get = do
+    _msgCommandResp_sequence <- getWord32le
+    _msgCommandResp_code <- fromIntegral <$> getWord32le
+    return MsgCommandResp {..}
+
+  put MsgCommandResp {..} = do
+    putWord32le _msgCommandResp_sequence
+    putWord32le $ fromIntegral _msgCommandResp_code
+
+$(deriveSBP 'msgCommandResp ''MsgCommandResp)
+
+$(deriveJSON defaultOptions {fieldLabelModifier = fromMaybe "_msgCommandResp_" . stripPrefix "_msgCommandResp_"}
+             ''MsgCommandResp)
+$(makeLenses ''MsgCommandResp)
