diff --git a/game/engines/default/engine/Module.lua b/game/engines/default/engine/Module.lua
index e7508670e54bceb97bb55573b5fb5b3f1e120ae0..3a023cb76bcf0df2b94a9c52202a862181b0005f 100644
--- a/game/engines/default/engine/Module.lua
+++ b/game/engines/default/engine/Module.lua
@@ -268,6 +268,9 @@ function _M:instanciate(mod, name, new_game, no_reboot)
 	-- And now run it!
 	_G.game:run()
 
+	-- Add user chat if needed
+	if mod.allow_userchat and _G.game.key then profile.chat:setupOnGame() end
+
 	-- Disable the profile if ungood
 	if mod.short_name ~= "boot" then
 		if not hash_valid then
diff --git a/game/engines/default/engine/PlayerProfile.lua b/game/engines/default/engine/PlayerProfile.lua
index c2a10fe46df121c63f577eb92b80c2bfd276ef9c..1a03128b3097a10bd00e22d718e48c6a0f1c4cdb 100644
--- a/game/engines/default/engine/PlayerProfile.lua
+++ b/game/engines/default/engine/PlayerProfile.lua
@@ -23,6 +23,7 @@ local url = require "socket.url"
 local ltn12 = require "ltn12"
 local lanes = require "lanes"
 local Dialog = require "engine.ui.Dialog"
+local UserChat = require "engine.UserChat"
 require "Json2"
 
 ------------------------------------------------------------
@@ -72,6 +73,7 @@ end
 module(..., package.seeall, class.make)
 
 function _M:init()
+	self.chat = UserChat.new()
 	self.generic = {}
 	self.modules = {}
 	self.evt_cbs = {}
@@ -376,11 +378,6 @@ function _M:eventGetNews(e)
 	end
 end
 
-function _M:eventPushCode(e)
-	local f = loadstring(e.code)
-	if f then pcall(f) end
-end
-
 function _M:eventGetConfigs(e)
 	local data = e.data:unserialize()
 	local module = e.module
@@ -408,6 +405,15 @@ function _M:eventGetConfigs(e)
 	if self.evt_cbs.GetConfigs then self.evt_cbs.GetConfigs(e) self.evt_cbs.GetConfigs = nil end
 end
 
+function _M:eventPushCode(e)
+	local f = loadstring(e.code)
+	if f then pcall(f) end
+end
+
+function _M:eventChat(e)
+	self.chat:event(e)
+end
+
 --- Got an event from the profile thread
 function _M:handleEvent(e)
 	e = e:unserialize()
diff --git a/game/modules/tome/init.lua b/game/modules/tome/init.lua
index 0bdc7586e7e276fd8138eb64695aaf736ffbcf08..589c53fec2783ab1efeab08ef225de086b7e23b3 100644
--- a/game/modules/tome/init.lua
+++ b/game/modules/tome/init.lua
@@ -46,3 +46,4 @@ You are an adventurer, set out to discover wonders, explore old places, and vent
 ]]
 starter = "mod.load"
 profile_stats_fields = {"artifacts", "characters", "deaths", "uniques"}
+allow_userchat = true
diff --git a/game/profile-thread/Client.lua b/game/profile-thread/Client.lua
index f691bb63263b6cf1da4533779717399adc69bcd6..f223a766ace12e5545e9dc23c61cd8bb9aa28f44 100644
--- a/game/profile-thread/Client.lua
+++ b/game/profile-thread/Client.lua
@@ -19,10 +19,12 @@
 
 require "engine.class"
 local socket = require "socket"
+local UserChat = require "profile-thread.UserChat"
 
 module(..., package.seeall, class.make)
 
 function _M:init()
+	self.chat = UserChat.new(self)
 end
 
 function _M:connected()
@@ -125,7 +127,9 @@ function _M:step()
 				local data = l:sub(5)
 				if code == "101" then
 					local e = data:unserialize()
-					if e and e.e and self["push"..e.e] then self["push"..e.e](self, e) end
+					if e and e.e:find("^Chat") then self.chat:event(e)
+					elseif e and e.e and self["push"..e.e] then self["push"..e.e](self, e)
+					end
 				end
 			end
 		end
@@ -148,6 +152,12 @@ function _M:run()
 	end
 end
 
+function _M:handleOrder(o)
+	o = o:unserialize()
+	if not self.sock and o.o ~= "Login" then return end -- Dont do stuff without a connection, unless we try to auth
+	if self["order"..o.o] then self["order"..o.o](self, o) end
+end
+
 --------------------------------------------------------------------
 -- Orders comming from the main thread
 --------------------------------------------------------------------
@@ -251,30 +261,20 @@ function _M:orderSaveChardump(o)
 	cprofile.pushEvent("e='SaveChardump' ok=true")
 end
 
-function _M:handleOrder(o)
-	o = o:unserialize()
-	if not self.sock and o.o ~= "Login" then return end -- Dont do stuff without a connection, unless we try to auth
-	if self["order"..o.o] then self["order"..o.o](self, o) end
+function _M:orderChatTalk(o)
+	self:command("BRDC", o.channel, o.msg)
+	self:read("200")
 end
 
 --------------------------------------------------------------------
 -- Pushes comming from the push socket
 --------------------------------------------------------------------
 
-function _M:pushCode(o)
-	if o.profile then
-		local f = loadstring(o.code)
-		if f then pcall(f) end
-	else
-		cprofile.pushEvent(string.format("e='PushCode' code=%q", o.code))
-	end
-end
-
-function _M:pushChatTalk(o)
-	if o.profile then
-		local f = loadstring(o.code)
+function _M:pushCode(e)
+	if e.profile then
+		local f = loadstring(e.code)
 		if f then pcall(f) end
 	else
-		cprofile.pushEvent(string.format("e='PushCode' code=%q", o.code))
+		cprofile.pushEvent(string.format("e='PushCode' code=%q", e.code))
 	end
 end