diff --git a/lib/exirc/client.ex b/lib/exirc/client.ex
index 95d1829..6e6e71a 100644
--- a/lib/exirc/client.ex
+++ b/lib/exirc/client.ex
@@ -1,381 +1,381 @@
 defmodule ExIrc.Client do
   @moduledoc """
   Maintains the state and behaviour for individual IRC client connections
   """
-  import  Irc.Commands
-  import  ExIrc.Logger
+  use    Irc.Commands
+  import ExIrc.Logger
 
   alias ExIrc.Channels, as: Channels
   alias ExIrc.Utils,    as: Utils
 
   # Records
   defrecord ClientState,
     event_handlers:   [],
     server:           'localhost',
     port:             6667,
     socket:           nil,
     nick:             '',
     pass:             '',
     user:             '',
     name:             '',
     logged_on?:       false,
     autoping:         true,
     channel_prefixes: '',
     network:          '',
     user_prefixes:    '',
     login_time:       '',
     channels:         [],
     debug:            false
 
   defrecord IrcMessage,
     server:  '',
     nick:    '',
     user:    '',
     host:    '',
     ctcp:    nil,
     cmd:     '',
     args:    []
 
   #################
   # Module API
   #################
   def start!(options // []) do
     start_link(options)
   end
 
   def start_link(options // []) do
     :gen_server.start_link(__MODULE__, options, [])
   end
 
   def stop!(client) do
     :gen_server.call(client, :stop)
   end
 
   def connect!(client, server, port) do
     :gen_server.call(client, {:connect, server, port}, :infinity)
   end
 
   def logon(client, pass, nick, user, name) do
     :gen_server.call(client, {:logon, pass, nick, user, name}, :infinity)
   end
 
   def msg(client, type, nick, msg) do
     :gen_server.call(client, {:msg, type, nick, msg}, :infinity)
   end
 
   def nick(client, new_nick) do
     :gen_server.call(client, {:nick, new_nick}, :infinity)
   end
 
   def cmd(client, raw_cmd) do
     :gen_server.call(client, {:cmd, raw_cmd})
   end
 
   def join(client, channel, key) do
     :gen_server.call(client, {:join, channel, key}, :infinity)
   end
 
   def part(client, channel) do
     :gen_server.call(client, {:part, channel}, :infinity)
   end
 
   def quit(client, msg // 'Leaving..') do
     :gen_server.call(client, {:quit, msg}, :infinity)
   end
 
   def is_logged_on?(client) do
     :gen_server.call(client, :is_logged_on?)
   end
 
   def channels(client) do
     :gen_server.call(client, :channels)
   end
 
   def channel_users(client, channel) do
     :gen_server.call(client, {:channel_users, channel})
   end
 
   def channel_topic(client, channel) do
     :gen_server.call(client, {:channel_topic, channel})
   end
 
   def channel_type(client, channel) do
     :gen_server.call(client, {:channel_type, channel})
   end
 
   def channel_has_user?(client, channel, nick) do
     :gen_server.call(client, {:channel_has_user?, channel, nick})
   end
 
   def add_handler(client, pid) do
     :gen_server.call(client, {:add_handler, pid})
   end
 
   def remove_handler(client, pid) do
     :gen_server.call(client, {:remove_handler, pid})
   end
 
   def add_handler_async(client, pid) do
     :gen_server.cast(client, {:add_handler, pid})
   end
 
   def remove_handler_async(client, pid) do
     :gen_server.cast(client, {:remove_handler, pid})
   end
 
   def state(client) do
     :gen_server.call(client, :state)
   end
 
   ###############
   # GenServer API
   ###############
   def init(options // []) do
     autoping = Keyword.get(options, :autoping, true)
     debug    = Keyword.get(options, :debug, false)
     # Add event handlers
     handlers = 
       Keyword.get(options, :event_handlers, []) 
       |> Enum.foldl(&do_add_handler/2)
     # Return initial state
     {:ok, ClientState.new(
       event_handlers: handlers,
       autoping:       autoping,
       logged_on?:     false,
       debug:          debug,
       channels:       ExIrc.Channels.init())}
   end
 
 
   def handle_call({:add_handler, pid}, _from, state) do
     handlers = do_add_handler(pid, state.event_handlers)
     {:reply, :ok, state.event_handlers(handlers)}
   end
 
   def handle_call({:remove_handler, pid}, _from, state) do
     handlers = do_remove_handler(pid, state.event_handlers)
     {:reply, :ok, state.event_handlers(handlers)}
   end
 
   def handle_call(:state, _from, state), do: {:reply, state, state}
   def handle_call(:stop, _from, state),  do: {:stop, :normal, :ok, state}
 
   def handle_call({:connect, server, port}, _from, state) do
     case :gen_tcp.connect(server, port, [:list, {:packet, :line}]) do
       {:ok, socket} ->
         send_event {:connect, server, port}, state
         {:reply, :ok, state.server(server).port(port).socket(socket)}
       error ->
         {:reply, error, state}
     end
   end
 
   def handle_call({:logon, pass, nick, user, name}, _from, ClientState[logged_on?: false] = state) do
     send! state.socket, pass!(pass)
     send! state.socket, nick!(nick)
     send! state.socket, user!(user, name)
     send_event({:login, pass, nick, user, name}, state)
     {:reply, :ok, state.pass(pass).nick(nick).user(user).name(name)}
   end
 
   def handle_call(:is_logged_on?, _from, state),                     do: {:reply, state.is_logged_on?, state}
   def handle_call(_, _from, ClientState[logged_on?: false] = state), do: {:reply, {:error, :not_connected}, state}
 
   def handle_call({:msg, type, nick, msg}, _from, state) do
     data = case type do
       :privmsg -> privmsg!(nick, msg)
       :notice  -> notice!(nick, msg)
       :ctcp    -> notice!(nick, ctcp!(msg))
     end
     send! state.stocket, data
     {:reply, :ok, state}
   end
 
   def handle_call({:quit, msg}, _from, state),           do: send!(state.socket, quit!(msg)) and {:reply, :ok, state}
   def handle_call({:join, channel, key}, _from, state),  do: send!(state.socket, join!(channel, key)) and {:reply, :ok, state}
   def handle_call({:part, channel}, _from, state),       do: send!(state.socket, part!(channel)) and {:reply, :ok, state}
   def handle_call({:nick, new_nick}, _from, state),      do: send!(state.socket, nick!(new_nick)) and {:reply, :ok, state}
   def handle_call({:cmd, raw_cmd}, _from, state),        do: send!(state.socket, command!(raw_cmd)) and {:reply, :ok, state}
 
   def handle_call(:channels, _from, state),                 do: {:reply, Channels.channels(state.channels), state}
   def handle_call({:channel_users, channel}, _from, state), do: {:reply, Channels.channel_users(state.channels, channel), state}
   def handle_call({:channel_topic, channel}, _from, state), do: {:reply, Channels.channel_topic(state.channels, channel), state}
   def handle_call({:channel_type, channel}, _from, state),  do: {:reply, Channels.channel_type(state.channels, channel), state}
   def handle_call({:channel_has_user?, channel, nick}, _from, state) do
     {:reply, Channels.channel_has_user?(state.channels, channel, nick), state}
   end
 
   def handle_cast({:add_handler, pid}, state) do
     handlers = do_add_handler(pid, state.event_handlers)
     {:noreply, state.event_handlers(handlers)}
   end
 
   def handle_cast({:remove_handler, pid}, state) do
     handlers = do_remove_handler(pid, state.event_handlers)
     {:noreply, state.event_handlers(handlers)}
   end
 
   def handle_info({:tcp_closed, _socket}, ClientState[server: server, port: port] = state) do
     info "Connection to #{server}:#{port} closed!"
     {:noreply, state.channels(Channels.init())}
   end
 
   def handle_info({:tcp_error, socket}, state) do
     {:stop, {:tcp_error, socket}, state}
   end
 
   def handle_info({:tcp, _, data}, state) do
     debug? = state.debug
     case Utils.parse(data) do
       IrcMessage[ctcp: true] = msg ->
         send_event(msg, state)
         {:noreply, state}
       IrcMessage[ctcp: false] = msg ->
         send_event(msg, state)
         handle_data(msg, state)
       IrcMessage[ctcp: :invalid] = msg when debug? ->
         send_event(msg, state)
         {:noreply, state}
       _ ->
         {:noreply, state}
     end
   end
 
   def handle_info({'DOWN', _, _, pid, _}, state) do
     handlers = do_remove_handler(pid, state.event_handlers)
     {:noreply, state.event_handlers(handlers)}
   end
   def handle_info(_, state) do
     {:noreply, state}
   end
 
   # Handle termination
   def terminate(_reason, _state), do: :ok
   # Handle code changes
   def code_change(_old, state, _extra), do: {:ok, state}
 
   ###############
   # Data handling
   ###############
 
   # Sucessfully logged in
-  def handle_data(IrcMessage[cmd: @rpl_WELCOME] = _msg, ClientState[logged_on?: false] = state) do
+  def handle_data(IrcMessage[cmd: @rpl_welcome] = _msg, ClientState[logged_on?: false] = state) do
     {:noreply, state.logged_on?(true).login_time(:erlang.now())}
   end
 
   # Server capabilities
-  def handle_data(IrcMessage[cmd: @rpl_ISUPPORT] = msg, state) do
+  def handle_data(IrcMessage[cmd: @rpl_isupport] = msg, state) do
     {:noreply, Utils.isup(msg.args, state)}
   end
 
   # Client entered a channel
   def handle_data(IrcMessage[nick: nick, cmd: 'JOIN'] = msg, ClientState[nick: nick] = state) do
     channels = Channels.join(state.channels, Enum.first(msg.args))
     {:noreply, state.channels(channels)}
   end
 
   # Someone joined the client's channel
   def handle_data(IrcMessage[nick: user_nick, cmd: 'JOIN'] = msg, state) do
     channels = Channels.user_join(state.channels, Enum.first(msg.args), user_nick)
     {:noreply, state.channels(channels)}
   end
 
   # Topic message on join
   # 3 arguments is not RFC compliant but _very_ common
   # 2 arguments is RFC compliant
-  def handle_data(IrcMessage[cmd: @rpl_TOPIC] = msg, state) do
+  def handle_data(IrcMessage[cmd: @rpl_topic] = msg, state) do
     {channel, topic} = case msg.args do
       [_nick, channel, topic] -> {channel, topic}
       [channel, topic]        -> {channel, topic}
     end
     channels = Channels.set_topic(state.channels, channel, topic)
     {:noreply, state.channels(channels)}
   end
 
   # Topic message while in channel
   def handle_data(IrcMessage[cmd: 'TOPIC', args: [channel, topic]], state) do
     channels = Channels.set_topic(state.channels, channel, topic)
     {:noreply, state.channels(channels)}
   end
 
   # NAMES reply
-  def handle_data(IrcMessage[cmd: @rpl_NAMEREPLY] = msg, state) do
+  def handle_data(IrcMessage[cmd: @rpl_namereply] = msg, state) do
     {channel_type, channel, names} = case msg.args do
       [_nick, channel_type, channel, names] -> {channel_type, channel, names}
       [channel_type, channel, names]        -> {channel_type, channel, names}
     end
     channels = Channels.set_type(
       Channels.users_join(state.channels, channel, String.split(names, ' '),
       channel,
       channel_type))
     {:noreply, state.channels(channels)}
   end
 
   # We successfully changed name 
   def handle_data(IrcMessage[cmd: 'NICK', nick: nick, args: [new_nick]], ClientState[nick: nick] = state) do
     {:noreply, state.nick(new_nick)}
   end
 
   # Someone we know (or can see) changed name
   def handle_data(IrcMessage[cmd: 'NICK', nick: nick, args: [new_nick]], state) do
     channels = Channels.user_rename(state.channels, nick, new_nick)
     {:noreply, state.channels(channels)}
   end
 
   # We left a channel
   def handle_data(IrcMessage[cmd: 'PART', nick: nick] = msg, ClientState[nick: nick] = state) do
     channels = Channels.part(state.channels, Enum.first(msg.args))
     {:noreply, state.channels(channels)}
   end
 
   # Someone left a channel we are in
   def handle_data(IrcMessage[cmd: 'PART', nick: user_nick] = msg, state) do
     channels = Channels.user_part(state.channels, Enum.first(msg.args), user_nick)
     {:noreply, state.channels(channels)}
   end
       
   # We got a ping, reply if autoping is on.
   def handle_data(IrcMessage[cmd: 'PING'] = msg, ClientState[autoping: true] = state) do
     case msg do
       IrcMessage[args: [from]] -> send!(state.socket, pong2!(state.nick, from))
                              _ -> send!(state.socket, pong1!(state.nick))
     end
     {:noreply, state};
   end
 
   # "catch-all" (probably should remove this)
   def handle_data(_msg, state) do
     {:noreply, state}
   end
 
   ###############
   # Internal API
   ###############
   def send_event(msg, ClientState[event_handlers: handlers]) when is_list(handlers) do
     Enum.each(handlers, fn({pid, _}) -> pid <- msg end)
   end
 
   def gv(key, options),          do: :proplists.get_value(key, options)
   def gv(key, options, default), do: :proplists.get_value(key, options, default)
 
   def do_add_handler(pid, handlers) do
     case Process.alive?(pid) and not Enum.member(handlers, pid) do
       true ->
         ref = Process.monitor(pid)
         [{pid, ref} | handlers]
       false ->
         handlers
     end
   end
 
   def do_remove_handler(pid, handlers) do
     case List.keyfind(handlers, pid, 1) do
       {pid, ref} ->
         Process.demonitor(ref)
         List.keydelete(handlers, pid, 1)
       false ->
           handlers
     end
   end
 
 end
\ No newline at end of file
diff --git a/lib/exirc/commands.ex b/lib/exirc/commands.ex
index ded3704..dcd7a5f 100644
--- a/lib/exirc/commands.ex
+++ b/lib/exirc/commands.ex
@@ -1,87 +1,206 @@
 defmodule Irc.Commands do
 
+  defmacro __using__(_) do
+
+    quote do
+      import Irc.Commands
+
+      ####################
+      # IRC Numeric Codes
+      ####################
+
+      @rpl_welcome '001'
+      @rpl_yourhost '002'
+      @rpl_created '003'
+      @rpl_myinfo '004'
+      @rpl_isupport '005' # Defacto standard for server support
+      @rpl_bounce '010'   # Defacto replacement of '005' in RFC2812
+      @rpl_statsdline '250'
+      #@doc """
+      #":There are <integer> users and <integer> invisible on <integer> servers"
+      #"""
+      @rpl_luserclient '251'
+      #@doc """
+      # "<integer> :operator(s) online"
+      #"""
+      @rpl_luserop '252'
+      #@doc """
+      #"<integer> :unknown connection(s)"
+      #"""
+      @rpl_luserunknown '253'
+      #@doc """
+      #"<integer> :channels formed"
+      #"""
+      @rpl_luserchannels '254'
+      #@doc """
+      #":I have <integer> clients and <integer> servers"
+      #"""
+      @rpl_luserme '255'
+      #@doc """
+      #Local/Global user stats
+      #"""
+      @rpl_localusers '265'
+      @rpl_globalusers '266'
+      #@doc """
+      #When sending a TOPIC message to determine the channel topic, 
+      #one of two replies is sent. If the topic is set, RPL_TOPIC is sent back else
+      #RPL_NOTOPIC.
+      #"""
+      @rpl_notopic '331'
+      @rpl_topic '332'
+      #@doc """
+      #To reply to a NAMES message, a reply pair consisting
+      #of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+      #server back to the client. If there is no channel
+      #found as in the query, then only RPL_ENDOFNAMES is
+      #returned. The exception to this is when a NAMES
+      #message is sent with no parameters and all visible
+      #channels and contents are sent back in a series of
+      #RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+      #the end.
+
+      #Format: "<channel> :[[@|+]<nick> [[@|+]<nick> [...]]]"
+      #"""
+      @rpl_namereply '353'
+      @rpl_endofnames '366'
+      #@doc """
+      #When responding to the MOTD message and the MOTD file
+      #is found, the file is displayed line by line, with
+      #each line no longer than 80 characters, using
+      #RPL_MOTD format replies. These should be surrounded
+      #by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+      #RPL_ENDOFMOTD (after).
+      #"""
+      @rpl_motd '372'
+      @rpl_motdstart '375'
+      @rpl_endofmotd '376'
+
+      ################
+      # Error Codes
+      ################
+
+      #@doc """
+      #Used to indicate the nickname parameter supplied to a command is currently unused.
+      #"""
+      @err_no_such_nick '401'
+      #@doc """
+      #Used to indicate the server name given currently doesn't exist.
+      #"""
+      @err_no_such_server '402'
+      #@doc """
+      #Used to indicate the given channel name is invalid.
+      #"""
+      @err_no_such_channel '403'
+      #@doc """
+      #Sent to a user who is either (a) not on a channel which is mode +n or (b),
+      #not a chanop (or mode +v) on a channel which has mode +m set, and is trying 
+      #to send a PRIVMSG message to that channel.
+      #"""
+      @err_cannot_send_to_chan '404'
+      #@doc """
+      #Sent to a user when they have joined the maximum number of allowed channels 
+      #and they try to join another channel.
+      #"""
+      @err_too_many_channels '405'
+      #@doc """
+      #Returned to a registered client to indicate that the command sent is unknown by the server.
+      #"""
+      @err_unknown_command '421'
+      #@doc """
+      #Returned when a nickname parameter expected for a command and isn't found.
+      #"""
+      @err_no_nickname_given '431'
+      #@doc """
+      #Returned after receiving a NICK message which contains characters which do not fall in the defined set.
+      #"""
+      @err_erroneus_nickname '432'
+      #@doc """
+      #Returned when a NICK message is processed that results in an attempt to 
+      #change to a currently existing nickname.
+      #"""
+      @err_nickname_in_use '433'
+      #@doc """
+      #Returned by a server to a client when it detects a nickname collision
+      #(registered of a NICK that already exists by another server).
+      #"""
+      @err_nick_collision '436'
+      #@doc """
+      #"""
+      @err_unavail_resource '437'
+      #@doc """
+      #Returned by the server to indicate that the client must be registered before 
+      #the server will allow it to be parsed in detail.
+      #"""
+      @err_not_registered '451'
+      #"""
+      # Returned by the server by numerous commands to indicate to the client that 
+      # it didn't supply enough parameters.
+      #"""
+      @err_need_more_params '461'
+      #@doc """
+      #Returned by the server to any link which tries to change part of the registered 
+      #details (such as password or user details from second USER message).
+      #"""
+      @err_already_registered '462'
+      #@doc """
+      #Returned by the server to the client when the issued command is restricted
+      #"""
+      @err_restricted '484'
+
+      ###############
+      # Code groups
+      ###############
+
+      @logon_errors [ unquote(@err_no_nickname_given),   unquote(@err_erroneus_nickname),
+                      unquote(@err_nickname_in_use),     unquote(@err_nick_collision),
+                      unquote(@err_unavail_resource),    unquote(@err_need_more_params),
+                      unquote(@err_already_registered),  unquote(@err_restricted) ]
+    end
+
+  end
+
   # Helpers
   @crlf '\r\n'
   defmacro command!(cmd) do
     quote do: [unquote(cmd), @crlf]
   end
   defmacro ctcp!(cmd) do
     quote do: [1, unquote(cmd), 1]
   end
   defmacro send!(socket, data) do
     quote do: :gen_tcp.send(unquote(socket), unquote(data))
   end
 
   # IRC Commands
   defmacro pass!(pwd) do
     quote do: command! ['PASS ', unquote(pwd)]
   end
   defmacro nick!(nick) do
     quote do: command! ['NICK ', unquote(nick)]
   end
   defmacro user!(user, name) do
     quote do: command! ['USER ', unquote(user), ' 0 * :', unquote(name)]
   end
   defmacro pong1!(nick) do
     quote do: command! ['PONG ', unquote(nick)]
   end
   defmacro pong2!(nick, to) do
     quote do: command! ['PONG ', unquote(nick), ' ', unquote(to)]
   end
   defmacro privmsg!(nick, msg) do
     quote do: command! ['PRIVMSG ', unquote(nick), ' :', unquote(msg)]
   end
   defmacro notice!(nick, msg) do
     quote do: command! ['NOTICE ', unquote(nick), ' :', unquote(msg)]
   end
   defmacro join!(channel, key) do
     quote do: command! ['JOIN ', unquote(channel), ' ', unquote(key)]
   end
   defmacro part!(channel) do
     quote do: command! ['PART ', unquote(channel)]
   end
   defmacro quit!(msg // 'Leaving') do
-    quote do: command! ['QUITE :', unquote(msg)]
+    quote do: command! ['QUIT :', unquote(msg)]
   end
 
-  ####################
-  # IRC Numeric Codes
-  ####################
-  @rpl_WELCOME          '001'
-  @rpl_YOURHOST         '002'
-  @rpl_CREATED          '003'
-  @rpl_MYINFO           '004'
-  # @rpl_BOUNCE         '005' # RFC2812
-  @rpl_ISUPPORT         '005' # Defacto standard for server support
-  @rpl_BOUNCE           '010' # Defacto replacement of '005' in RFC2812
-  @rpl_STATSDLINE       '250'
-  @rpl_LUSERCLIENT      '251'
-  @rpl_LUSEROP          '252'
-  @rpl_LUSERUNKNOWN     '253'
-  @rpl_LUSERCHANNELS    '254'
-  @rpl_LUSERME          '255'
-  @rpl_LOCALUSERS       '265'
-  @rpl_GLOBALUSERS      '266'
-  @rpl_TOPIC            '332'
-  @rpl_NAMEREPLY         '353'
-  @rpl_ENDOFNAMES       '366'
-  @rpl_MOTD             '372'
-  @rpl_MOTDSTART        '375'
-  @rpl_ENDOFMOTD        '376'
-  # Error Codes
-  @err_NONICKNAMEGIVEN  '431'
-  @err_ERRONEUSNICKNAME '432'
-  @err_NICKNAMEINUSE    '433'
-  @err_NICKCOLLISION    '436'
-  @err_UNAVAILRESOURCE  '437'
-  @err_NEEDMOREPARAMS   '461'
-  @err_ALREADYREGISTRED '462'
-  @err_RESTRICTED       '484'
-
-  # Code groups
-  @logon_errors [@err_NONICKNAMEGIVEN,  @err_ERRONEUSNICKNAME,
-                 @err_NICKNAMEINUSE,    @err_NICKCOLLISION,
-                 @err_UNAVAILRESOURCE,  @err_NEEDMOREPARAMS,
-                 @err_ALREADYREGISTRED, @err_RESTRICTED]
-
 end
\ No newline at end of file