diff --git a/lib/app.ex b/lib/app.ex
index a02b70a..489008a 100644
--- a/lib/app.ex
+++ b/lib/app.ex
@@ -1,10 +1,10 @@
 defmodule ExIrc.App do
   @moduledoc """
   Entry point for the ExIrc application.
   """
-  use Application.Behaviour
+  use Application
 
   def start(_type, _args) do
     ExIrc.start!
   end
-end
\ No newline at end of file
+end
diff --git a/lib/exirc/channels.ex b/lib/exirc/channels.ex
index 17f5d24..a96cb2e 100644
--- a/lib/exirc/channels.ex
+++ b/lib/exirc/channels.ex
@@ -1,230 +1,230 @@
 defmodule ExIrc.Channels do
   @moduledoc """
   Responsible for managing channel state
   """
   use Irc.Commands
 
   import String, only: [downcase: 1]
 
   defmodule Channel do
     defstruct name:  '',
               topic: '',
               users: [],
               modes: '',
               type:  ''
   end
 
   @doc """
   Initialize a new Channels data store
   """
   def init() do
     :gb_trees.empty()
   end
 
   ##################
   # Self JOIN/PART
   ##################
 
   @doc """
   Add a channel to the data store when joining a channel
   """
   def join(channel_tree, channel_name) do
     name = downcase(channel_name)
     case :gb_trees.lookup(name, channel_tree) do
       {:value, _} ->
         channel_tree
       :none ->
         :gb_trees.insert(name, %Channel{name: name}, channel_tree)
     end
   end
 
   @doc """
   Remove a channel from the data store when leaving a channel
   """
   def part(channel_tree, channel_name) do
     name = downcase(channel_name)
     case :gb_trees.lookup(name, channel_tree) do
       {:value, _} ->
         :gb_trees.delete(name, channel_tree)
       :none ->
         channel_tree
     end
   end
 
   ###########################
   # Channel Modes/Attributes
   ###########################
 
   @doc """
   Update the topic for a tracked channel when it changes
   """
   def set_topic(channel_tree, channel_name, topic) do
     name = downcase(channel_name)
     case :gb_trees.lookup(name, channel_tree) do
       {:value, channel} ->
         :gb_trees.enter(name, %{channel | :topic => topic}, channel_tree)
       :none ->
         channel_tree
     end
   end
 
   @doc """
   Update the type of a tracked channel when it changes
   """
   def set_type(channel_tree, channel_name, channel_type) when is_binary(channel_type) do
-    set_type(channel_tree, channel_name, List.from_char_data!(channel_type))
+    set_type(channel_tree, channel_name, String.to_char_list(channel_type))
   end
   def set_type(channel_tree, channel_name, channel_type) do
     name = downcase(channel_name)
     case :gb_trees.lookup(name, channel_tree) do
       {:value, channel} ->
         type = case channel_type do
              '@' -> :secret
              '*' -> :private
              '=' -> :public
         end
         :gb_trees.enter(name, %{channel | :type => type}, channel_tree)
       :none ->
         channel_tree
     end
   end
 
   ####################################
   # Users JOIN/PART/AKAs(namechange)
   ####################################
 
   @doc """
   Add a user to a tracked channel when they join
   """
   def user_join(channel_tree, channel_name, nick) when not is_list(nick) do
     users_join(channel_tree, channel_name, [nick])
   end
 
   @doc """
   Add multiple users to a tracked channel (used primarily in conjunction with the NAMES command)
   """
   def users_join(channel_tree, channel_name, nicks) do
     pnicks = strip_rank(nicks)
     manipfn = fn(channel_nicks) -> :lists.usort(channel_nicks ++ pnicks) end
     users_manip(channel_tree, channel_name, manipfn)
   end
 
   @doc """
   Remove a user from a tracked channel when they leave
   """
   def user_part(channel_tree, channel_name, nick) do
     pnick = strip_rank([nick])
     manipfn = fn(channel_nicks) -> :lists.usort(channel_nicks -- pnick) end
     users_manip(channel_tree, channel_name, manipfn)
   end
 
   @doc """
   Update the nick of a user in a tracked channel when they change their nick
   """
   def user_rename(channel_tree, nick, new_nick) do
     manipfn = fn(channel_nicks) ->
       case Enum.member?(channel_nicks, nick) do
         true  -> [new_nick | channel_nicks -- [nick]] |> Enum.uniq |> Enum.sort
         false -> channel_nicks
        end
     end
     foldl = fn(channel_name, new_channel_tree) ->
       name = downcase(channel_name)
       users_manip(new_channel_tree, name, manipfn)
     end
     :lists.foldl(foldl, channel_tree, channels(channel_tree))
   end
 
   ################
   # Introspection
   ################
 
   @doc """
   Get a list of all currently tracked channels
   """
   def channels(channel_tree) do
     (for {channel_name, _chan} <- :gb_trees.to_list(channel_tree), do: channel_name) |> Enum.reverse
   end
 
   @doc """
   Get a list of all users in a tracked channel
   """
   def channel_users(channel_tree, channel_name) do
     get_attr(channel_tree, channel_name, fn(%Channel{:users => users}) -> users end) |> Enum.reverse
   end
 
   @doc """
   Get the current topic for a tracked channel
   """
   def channel_topic(channel_tree, channel_name) do
     case get_attr(channel_tree, channel_name, fn(%Channel{:topic => topic}) -> topic end) do
       []    -> "No topic"
       topic -> topic
     end
   end
 
   @doc """
   Get the type of a tracked channel
   """
   def channel_type(channel_tree, channel_name) do
     case get_attr(channel_tree, channel_name, fn(%Channel{:type => type}) -> type end) do
       []   -> :unknown
       type -> type
     end
   end
 
   @doc """
   Determine if a user is present in a tracked channel
   """
   def channel_has_user?(channel_tree, channel_name, nick) do
     get_attr(channel_tree, channel_name, fn(%Channel{:users => users}) -> :lists.member(nick, users) end)
   end
 
   @doc """
   Get all channel data as a tuple of the channel name and a proplist of metadata.
 
   Example Result:
 
       [{"#testchannel", [users: ["userA", "userB"], topic: "Just a test channel.", type: :public] }]
   """
   def to_proplist(channel_tree) do
     for {channel_name, chan} <- :gb_trees.to_list(channel_tree) do
       {channel_name, [users: chan.users, topic: chan.topic, type: chan.type]}
     end |> Enum.reverse
   end
 
   ####################
   # Internal API
   ####################
   defp users_manip(channel_tree, channel_name, manipfn) do
     name = downcase(channel_name)
     case :gb_trees.lookup(name, channel_tree) do
       {:value, channel} ->
         channel_list = manipfn.(channel.users)
         :gb_trees.enter(channel_name, %{channel | :users => channel_list}, channel_tree)
       :none ->
         channel_tree
     end
   end
 
   defp strip_rank(nicks) do
     nicks |> Enum.map(fn(n) -> case n do
         << "@", nick :: binary >> -> nick
         << "+", nick :: binary >> -> nick
         << "%", nick :: binary >> -> nick
         << "&", nick :: binary >> -> nick
         << "~", nick :: binary >> -> nick
         nick -> nick
       end
     end)
   end
 
   defp get_attr(channel_tree, channel_name, getfn) do
     name = downcase(channel_name)
     case :gb_trees.lookup(name, channel_tree) do
       {:value, channel} -> getfn.(channel)
       :none -> {:error, :no_such_channel}
     end
   end
 
 end
diff --git a/lib/exirc/exirc.ex b/lib/exirc/exirc.ex
index 0f818c1..7f1ff63 100644
--- a/lib/exirc/exirc.ex
+++ b/lib/exirc/exirc.ex
@@ -1,64 +1,64 @@
 defmodule ExIrc do
   @moduledoc """
   Supervises IRC client processes
 
   Usage:
 
       # Start the supervisor (started automatically when ExIrc is run as an application)
       ExIrc.start_link
 
       # Start a new IRC client
       {:ok, client} = ExIrc.start_client!
 
       # Connect to an IRC server
       ExIrc.Client.connect! client, "localhost", 6667
 
       # Logon
       ExIrc.Client.logon client, "password", "nick", "user", "name"
 
       # Join a channel (password is optional)
       ExIrc.Client.join client, "#channel", "password"
 
       # Send a message
       ExIrc.Client.msg client, :privmsg, "#channel", "Hello world!"
 
       # Quit (message is optional)
       ExIrc.Client.quit client, "message"
-      
+
       # Stop and close the client connection
       ExIrc.Client.stop! client
 
   """
-  use Supervisor.Behaviour
+  use Supervisor
 
   ##############
   # Public API
   ##############
 
   @doc """
   Start the ExIrc supervisor.
   """
   @spec start! :: {:ok, pid} | {:error, term}
   def start! do
     :supervisor.start_link({:local, :exirc}, __MODULE__, [])
   end
 
   @doc """
   Start a new ExIrc client
   """
   @spec start_client! :: {:ok, pid} | {:error, term}
   def start_client! do
     # Start the client worker
     :supervisor.start_child(:exirc, worker(ExIrc.Client, []))
   end
 
   ##############
   # Supervisor API
   ##############
 
   @spec init(any) :: {:ok, pid} | {:error, term}
   def init(_) do
     supervise [], strategy: :one_for_one
   end
 
 end
diff --git a/lib/exirc/utils.ex b/lib/exirc/utils.ex
index 45e6c76..3da2832 100644
--- a/lib/exirc/utils.ex
+++ b/lib/exirc/utils.ex
@@ -1,171 +1,169 @@
 defmodule ExIrc.Utils do
 
-  import String, only: [from_char_data!: 1]
-
   ######################
   # IRC Message Parsing
   ######################
 
   @doc """
   Parse an IRC message
 
   Example:
 
       data    = ':irc.example.org 005 nick NETWORK=Freenode PREFIX=(ov)@+ CHANTYPES=#&'
       message = ExIrc.Utils.parse data
       assert "irc.example.org" = message.server
   """
   @spec parse(raw_data :: char_list) :: IrcMessage.t
   def parse(raw_data) do
     data = :string.substr(raw_data, 1, length(raw_data))
     case data do
       [?:|_] ->
           [[?:|from]|rest] = :string.tokens(data, ' ')
           get_cmd(rest, parse_from(from, %IrcMessage{ctcp: false}))
       data ->
           get_cmd(:string.tokens(data, ' '), %IrcMessage{ctcp: false})
     end
   end
 
   defp parse_from(from, msg) do
-    case Regex.split(~r/(!|@|\.)/, iodata_to_binary(from)) do
+    case Regex.split(~r/(!|@|\.)/, IO.iodata_to_binary(from)) do
       [nick, "!", user, "@", host | host_rest] ->
         %{msg | :nick => nick, :user => user, :host => host <> host_rest}
       [nick, "@", host | host_rest] ->
         %{msg | :nick => nick, :host => host <> host_rest}
       [_, "." | _] ->
         # from is probably a server name
-        %{msg | :server => from_char_data!(from)}
+        %{msg | :server => to_string(from)}
       [nick] ->
         %{msg | :nick => nick}
     end
   end
 
   # Parse command from message
   defp get_cmd([cmd, arg1, [?:, 1 | ctcp_trail] | restargs], msg) when cmd == 'PRIVMSG' or cmd == 'NOTICE' do
     get_cmd([cmd, arg1, [1 | ctcp_trail] | restargs], msg)
   end
 
   defp get_cmd([cmd, _arg1, [1 | ctcp_trail] | restargs], msg) when cmd == 'PRIVMSG' or cmd == 'NOTICE' do
     args = ctcp_trail ++ for arg <- restargs, do: ' ' ++ arg
       |> Enum.flatten
       |> Enum.reverse
     case args do
       [1 | ctcp_rev] ->
         [ctcp_cmd | args] = ctcp_rev |> Enum.reverse |> :string.tokens(' ')
-        %{msg | :cmd => from_char_data!(ctcp_cmd), :args => args, :ctcp => true}
+        %{msg | :cmd => to_string(ctcp_cmd), :args => args, :ctcp => true}
       _ ->
-        %{msg | :cmd => from_char_data!(cmd), :ctcp => :invalid}
+        %{msg | :cmd => to_string(cmd), :ctcp => :invalid}
     end
   end
 
   defp get_cmd([cmd | rest], msg) do
-    get_args(rest, %{msg | :cmd => from_char_data!(cmd)})
+    get_args(rest, %{msg | :cmd => to_string(cmd)})
   end
 
 
   # Parse command args from message
   defp get_args([], msg) do
     args = msg.args
-      |> Enum.reverse 
+      |> Enum.reverse
       |> Enum.filter(fn(arg) -> arg != [] end)
-      |> Enum.map(&String.from_char_data!/1)
+      |> Enum.map(&List.to_string/1)
     %{msg | :args => args}
   end
 
   defp get_args([[?: | first_arg] | rest], msg) do
     args = (for arg <- [first_arg | rest], do: ' ' ++ trim_crlf(arg)) |> List.flatten
     case args do
       [_ | []] ->
           get_args [], %{msg | :args => [msg.args]}
       [_ | full_trail] ->
           get_args [], %{msg | :args => [full_trail | msg.args]}
     end
   end
 
   defp get_args([arg | []], msg) do
     get_args [], %{msg | :args => [arg | msg.args]}
   end
 
   defp get_args([arg | rest], msg) do
     get_args rest, %{msg | :args => [arg | msg.args]}
   end
 
   ############################
   # Parse RPL_ISUPPORT (005)
   ############################
 
   @doc """
   Parse RPL_ISUPPORT message.
 
   If an empty list is provided, do nothing, otherwise parse CHANTYPES,
   NETWORK, and PREFIX parameters for relevant data.
   """
   @spec isup(parameters :: list(binary), state :: ExIrc.Client.ClientState.t) :: ExIrc.Client.ClientState.t
   def isup([], state), do: state
   def isup([param | rest], state) do
     try do
       isup(rest, isup_param(param, state))
     rescue
       _ -> isup(rest, state)
     end
   end
 
   defp isup_param("CHANTYPES=" <> channel_prefixes, state) do
     prefixes = channel_prefixes |> String.split("", trim: true)
     %{state | :channel_prefixes => prefixes}
   end
   defp isup_param("NETWORK=" <> network, state) do
     %{state | :network => network}
   end
   defp isup_param("PREFIX=" <> user_prefixes, state) do
     prefixes = Regex.run(~r/\((.*)\)(.*)/, user_prefixes, capture: :all_but_first)
-               |> Enum.map(&List.from_char_data!/1)
+               |> Enum.map(&String.to_char_list/1)
                |> List.zip
     %{state | :user_prefixes => prefixes}
   end
   defp isup_param(_, state) do
     state
   end
 
   ###################
   # Helper Functions
   ###################
 
   @days_of_week   ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
   @months_of_year ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
   @doc """
   Get CTCP formatted time from a tuple representing the current calendar time:
 
   Example:
 
       iex> local_time = {{2013,12,6},{14,5,00}}
       {{2013,12,6},{14,5,00}}
       iex> ExIrc.Utils.ctcp_time local_time
       "Fri Dec 06 14:05:00 2013"
   """
   @spec ctcp_time(datetime :: {{integer, integer, integer}, {integer, integer, integer}}) :: binary
   def ctcp_time({{y, m, d}, {h, n, s}} = _datetime) do
     [:lists.nth(:calendar.day_of_the_week(y,m,d), @days_of_week),
      ' ',
      :lists.nth(m, @months_of_year),
      ' ',
-     :io_lib.format("~2..0s", [integer_to_list(d)]),
+     :io_lib.format("~2..0s", [Integer.to_char_list(d)]),
      ' ',
-     :io_lib.format("~2..0s", [integer_to_list(h)]),
+     :io_lib.format("~2..0s", [Integer.to_char_list(h)]),
      ':',
-     :io_lib.format("~2..0s", [integer_to_list(n)]),
+     :io_lib.format("~2..0s", [Integer.to_char_list(n)]),
      ':',
-     :io_lib.format("~2..0s", [integer_to_list(s)]),
+     :io_lib.format("~2..0s", [Integer.to_char_list(s)]),
      ' ',
-     integer_to_list(y)] |> List.flatten |> String.from_char_data!
+     Integer.to_char_list(y)] |> List.flatten |> List.to_string
   end
 
   defp trim_crlf(charlist) do
     case Enum.reverse(charlist) do
       [?\n, ?\r | text] -> Enum.reverse(text)
       _ -> charlist
     end
   end
 
-end
\ No newline at end of file
+end
diff --git a/mix.exs b/mix.exs
index 813d12d..535b7e1 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,26 +1,26 @@
 defmodule ExIrc.Mixfile do
   use Mix.Project
 
   def project do
     [ app: :exirc,
       version: "0.5.0",
-      elixir: "~> 0.13.3",
+      elixir: "~> 0.14.1",
       description: "An IRC client library for Elixir.",
       package: package,
       deps: [] ]
   end
 
   # Configuration for the OTP application
   def application do
     [mod: {ExIrc.App, []}]
   end
 
   defp package do
     [ files: ["lib", "mix.exs", "README.md", "LICENSE"],
       contributors: ["Paul Schoenfelder"],
       licenses: ["MIT"],
       links: [ { "GitHub", "https://github.com/bitwalker/exirc" },
                { "Home Page", "http://bitwalker.org/exirc"} ] ]
   end
 
 end