diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+debug-me (1.20181208) unstable; urgency=medium
+
+  * Update to lts-12.10, support ghc 8.4, and aeson 1.3.
+
+ -- Joey Hess <id@joeyh.name>  Sat, 08 Dec 2018 13:29:33 -0400
+
 debug-me (1.20170810) unstable; urgency=medium
 
   * Fix build with websockets-0.10.0.0 which did not support compression.
diff --git a/CmdLine.hs b/CmdLine.hs
--- a/CmdLine.hs
+++ b/CmdLine.hs
@@ -8,7 +8,6 @@
 import Types
 import ServerList
 
-import Data.Monoid
 import Options.Applicative
 import Network.URI
 import Network.Wai.Handler.Warp (Port)
diff --git a/Crypto.hs b/Crypto.hs
--- a/Crypto.hs
+++ b/Crypto.hs
@@ -16,6 +16,7 @@
 import Crypto.Random.Entropy
 import Data.ByteArray (convert)
 import qualified Data.ByteString as B
+import qualified Data.Semigroup as Sem
 
 dummySignature :: Signature
 dummySignature = OtherSignature (Val mempty)
@@ -78,10 +79,13 @@
 		CryptoPassed pk' -> SigVerifier 1 (Ed25519.verify pk')
 		CryptoFailed _ -> mempty
 
+instance Sem.Semigroup SigVerifier where
+	SigVerifier na a <> SigVerifier nb b =
+		SigVerifier (na+nb) $ \d s -> b d s || a d s
+
 instance Monoid SigVerifier where
 	mempty = SigVerifier 0 $ \_b _s -> False
-	mappend (SigVerifier na a) (SigVerifier nb b) =
-		SigVerifier (na+nb) $ \d s -> b d s || a d s
+	mappend = (Sem.<>)
 
 data MySessionKey = MySessionKey Ed25519.SecretKey Ed25519.PublicKey
 
diff --git a/Graphviz.hs b/Graphviz.hs
--- a/Graphviz.hs
+++ b/Graphviz.hs
@@ -12,7 +12,6 @@
 import Log
 
 import Data.Char hiding (Control)
-import Data.Monoid
 import Data.GraphViz
 import Data.GraphViz.Attributes.Complete
 import Data.GraphViz.Types.Generalised as G
@@ -23,6 +22,8 @@
 import qualified Data.Text.Lazy as T
 import qualified Data.Text.Lazy.Encoding as T
 import Data.Text.Encoding.Error
+import Data.Monoid
+import Prelude
 
 graphviz :: GraphvizOpts -> IO ()
 graphviz opts = do
diff --git a/ProtocolBuffers.hs b/ProtocolBuffers.hs
--- a/ProtocolBuffers.hs
+++ b/ProtocolBuffers.hs
@@ -5,7 +5,7 @@
 
 {-# LANGUAGE DeriveGeneric, DataKinds, MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleContexts, UndecidableInstances #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, MonoLocalBinds #-}
 
 {- | Protocol buffers serialization for the debug-me wire protocol.
  - 
@@ -319,6 +319,7 @@
 -- This is why UndecidableInstances is needed. The need
 -- for a Monoid instance is an implementation detail of
 -- Data.ProtocolBuffers.
+-- MonoLocalBinds is also used to avoid a ghc warning.
 instance (Monoid (Message a), Generic a, Decode a) => Decode (MessageP a)
 instance Encode a => Encode (ActivityP a)
 instance (Monoid (Message a), Generic a, Decode a) => Decode (ActivityP a)
diff --git a/Role/Developer.hs b/Role/Developer.hs
--- a/Role/Developer.hs
+++ b/Role/Developer.hs
@@ -38,9 +38,10 @@
 import Data.List
 import Data.Maybe
 import Control.Monad
-import Data.Monoid
 import Data.Time.Clock.POSIX
 import Network.URI
+import Data.Monoid
+import Prelude
 
 run :: DeveloperOpts -> IO ()
 run = run' developer . debugUrl
diff --git a/Role/User.hs b/Role/User.hs
--- a/Role/User.hs
+++ b/Role/User.hs
@@ -30,11 +30,12 @@
 import qualified Data.Text.IO as T
 import qualified Data.ByteString as B
 import Data.List.NonEmpty (NonEmpty(..), toList)
-import Data.Monoid
 import Data.Maybe
 import Data.Time.Clock.POSIX
 import System.IO
 import System.Environment
+import Data.Monoid
+import Prelude
 
 run :: UserOpts -> IO ExitCode
 run os = fromMaybe (ExitFailure 101) <$> connect
diff --git a/Session.hs b/Session.hs
--- a/Session.hs
+++ b/Session.hs
@@ -11,6 +11,7 @@
 import qualified Data.ByteString.Char8 as B8
 import System.Exit
 import Data.Monoid
+import Prelude
 
 startSession :: B.ByteString
 startSession = "** debug-me session started"
diff --git a/Types.hs b/Types.hs
--- a/Types.hs
+++ b/Types.hs
@@ -22,6 +22,7 @@
 
 import qualified Data.Text as T
 import Data.Time.Clock.POSIX
+import qualified Data.Semigroup as Sem
 
 -- | Things that the developer sees.
 data Seen = Seen
@@ -194,9 +195,12 @@
 mkElapsedTime :: POSIXTime -> POSIXTime -> ElapsedTime
 mkElapsedTime start end = ElapsedTime $ fromRational $ toRational (end - start)
 
+instance Sem.Semigroup ElapsedTime where
+	ElapsedTime a <> ElapsedTime b = ElapsedTime (a+b)
+
 instance Monoid ElapsedTime where
 	mempty = ElapsedTime 0
-	mappend (ElapsedTime a) (ElapsedTime b) = ElapsedTime (a+b)
+	mappend = (Sem.<>)
 
 instance DataSize ElapsedTime where
 	dataSize _ = 16 -- 128 bit Double
diff --git a/Val.hs b/Val.hs
--- a/Val.hs
+++ b/Val.hs
@@ -16,10 +16,11 @@
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
 import qualified Data.ByteString as B
+import qualified Data.Semigroup as Sem
 
 -- | Newtype of ByteString so we can have JSON instances without orphans.
 newtype Val = Val { val :: B.ByteString }
-	deriving (Show, Generic, Eq, Monoid)
+	deriving (Show, Generic, Eq, Sem.Semigroup, Monoid)
 
 instance DataSize Val where
 	dataSize (Val b) = fromIntegral (B.length b)
diff --git a/WebSockets.hs b/WebSockets.hs
--- a/WebSockets.hs
+++ b/WebSockets.hs
@@ -40,12 +40,13 @@
 import qualified Data.Text as T
 import qualified Data.ByteString.Lazy as L
 import Data.List
-import Data.Monoid
 import Data.Maybe
 import Text.Read
 import Control.Monad
 import Network.URI
 import System.IO
+import Data.Monoid
+import Prelude
 
 -- | Framing protocol used over a websocket connection.
 --
diff --git a/debug-me.cabal b/debug-me.cabal
--- a/debug-me.cabal
+++ b/debug-me.cabal
@@ -1,5 +1,5 @@
 Name: debug-me
-Version: 1.20170810
+Version: 1.20181208
 Cabal-Version: >= 1.8
 Maintainer: Joey Hess <joey@kitenet.net>
 Author: Joey Hess
@@ -45,6 +45,9 @@
   debug-me.default
   developer-keyring.gpg
 
+custom-setup
+  Setup-Depends: base (>= 4.9 && < 5.0), Cabal, filepath
+
 Executable debug-me
   Main-Is: debug-me.hs
   GHC-Options: -threaded -Wall -fno-warn-tabs -O2
@@ -60,11 +63,11 @@
     , stm-chans (>= 3.0)
     , posix-pty (>= 0.2.1)
     , terminal-size (>= 0.3)
-    , aeson (>= 0.11 && < 1.3)
+    , aeson (>= 0.11 && < 1.4)
     , sandi (>= 0.4)
     , text (>= 1.2.2)
     , optparse-applicative (>= 0.12)
-    , graphviz (== 2999.18.*)
+    , graphviz (>= 2999.18.0 && < 2999.21)
     , time (>= 1.6)
     , filepath (>= 1.4)
     , directory (>= 1.2)
