) -> None:
         pass
 
-    def send(self, verb: str, *args) -> None:
+    def send(self, verb: str, *args) -> IrcMessage:
         'Send msg over socket, on success log .raw.'
         if not self.conn:
             raise SendFail('cannot send, connection seems closed')
         msg = IrcMessage(verb, args)
         self.conn.send(msg)
-        self._log(msg.raw, scope=LogScope.RAW, out=True)
+        return msg
 
     def handle_msg(self, msg: IrcMessage) -> None:
         'Log msg.raw, then process incoming msg into appropriate client steps.'
-        self._log(msg.raw, scope=LogScope.RAW, out=False)
         ret = {}
         for ex in [ex for ex in MSG_EXPECTATIONS if ex.verb == msg.verb]:
             result = ex.parse_msg(
 
         AutoAttrMixin, Channel, Client, ClientQueueMixin, Dict, DictItem,
         IrcConnSetup, LogScope, NewClientEvent, NickUserHost, SendFail,
         ServerCapability, SharedClientDbFields, User)
+from ircplom.irc_conn import IrcMessage
 
 CMD_SHORTCUTS['disconnect'] = 'window.disconnect'
 CMD_SHORTCUTS['join'] = 'window.join'
             return
         self.connect()
 
+    def send(self, verb: str, *args) -> IrcMessage:
+        msg = super().send(verb, *args)
+        self._log(msg.raw, scope=LogScope.RAW, out=True)
+        return msg
+
+    def handle_msg(self, msg: IrcMessage) -> None:
+        self._log(msg.raw, scope=LogScope.RAW, out=False)
+        super().handle_msg(msg)
+
     def _log(self, msg: str, scope: Optional[LogScope] = None, **kwargs
              ) -> None:
         to_log = []