diff --git a/GrowlNotify.cabal b/GrowlNotify.cabal
--- a/GrowlNotify.cabal
+++ b/GrowlNotify.cabal
@@ -1,5 +1,5 @@
 Name:           GrowlNotify
-Version:        0.2
+Version:        0.3
 Author:         Nick Burlett
 Maintainer:     nickburlett@mac.com
 Description:    Notification utility for Growl.
diff --git a/Network/GrowlNotify.hs b/Network/GrowlNotify.hs
--- a/Network/GrowlNotify.hs
+++ b/Network/GrowlNotify.hs
@@ -1,3 +1,8 @@
+-- | A network notification utility to work with Growl <http://growl.info/>. 
+-- 
+--   An application must register itself by sending a registrationPacket. Then, to send
+--   a notification, send a notificationPacket. Any packet must have an md5sum tacked on
+--   to the end before being sent. 
 module Network.GrowlNotify 
     ( registrationPacket
     , notificationPacket
@@ -12,6 +17,7 @@
 import qualified Char
 import Data.Digest.MD5
 import Network.Socket
+import Network.BSD
 
 
 growl_udp_port=9887
@@ -24,9 +30,11 @@
 putString :: String -> Put
 putString = do putLazyByteString . makeBS
 
--- register this application and its notification with growl
--- any notifications will be on by default
-registrationPacket :: String -> [String]  -> B.ByteString
+-- | register this application and its notification with growl
+-- |  any notifications will be on by default
+registrationPacket :: String        -- ^ The name of this application
+                   -> [String]      -- ^ A list of notifications
+                   -> B.ByteString  -- ^ The packet
 registrationPacket appName notiNames = runPut $ do
     putWord8 growl_protocol_version
     putWord8 growl_type_registration
@@ -43,12 +51,17 @@
             putLazyByteString $ makeBS s
         lengthnames = length notiNames
 
--- make a notification
-notificationPacket :: String -> String -> String -> String -> B.ByteString
-notificationPacket appName notification title description = runPut $ do
+-- | Create a notification packet
+notificationPacket :: Bool          -- ^ True iff the notification should be sticky
+                   -> String        -- ^ The name of this application
+                   -> String        -- ^ The notification name
+                   -> String        -- ^ The title of this notification
+                   -> String        -- ^ The notification text
+                   -> B.ByteString  -- ^ The packet
+notificationPacket sticky appName notification title description = runPut $ do
     putWord8 growl_protocol_version
     putWord8 growl_type_notification
-    putWord16be 0
+    putWord16be $ if sticky then 1 else 0
     putLength notification
     putLength title
     putLength description
@@ -60,21 +73,27 @@
     where
         putLength = putWord16be . fromIntegral . length
 
-addMD5Sum :: String -> B.ByteString -> B.ByteString
+-- | Tack on the md5sum to the end of the message, with a (possibly empty) password
+addMD5Sum :: String         -- ^ The password
+          -> B.ByteString   -- ^ The packet (from notificationPacket or registrationPacket)
+          -> B.ByteString   -- ^ The message with appended md5sum, ready for sendMessage
 addMD5Sum password message = B.append message s
     where
         s = B.pack $ hash $ map fromIntegral $ B.unpack $ B.append message bspassword
         bspassword = makeBS password
 
-sendMessage :: String -> B.ByteString -> IO ()
+-- | Send the packet 
+sendMessage :: String       -- ^ The server (an IP address or hostname)
+            -> B.ByteString -- ^ The message (with md5sum) to send
+            -> IO ()
 sendMessage server m = do
+    server' <- getHostByName server
     let d = map (Char.chr . fromIntegral) $ B.unpack m
     s <- socket AF_INET Datagram  0
-    write server s d
+    write (hostAddress server') s d
     sClose s
     
-write :: String -> Socket -> String -> IO ()
-write server sock s = do
-    addr <- inet_addr server
+write :: HostAddress -> Socket -> String -> IO ()
+write addr sock s = do
     sendTo sock s (SockAddrInet (fromIntegral growl_udp_port) addr) 
     return ()
diff --git a/growlnotify.hs b/growlnotify.hs
--- a/growlnotify.hs
+++ b/growlnotify.hs
@@ -1,14 +1,60 @@
 import Network.GrowlNotify
 import System (getArgs)
+import System.Console.GetOpt
+import Data.Maybe ( fromMaybe )
 
 main = do
     args <- getArgs
-    (server, password, title, message) <- case args of
-        server:password:title:message -> return $ (server, password, title, message)
-        _ -> error "Usage: server password title message"
-    let b =  registrationPacket "growlnotify" ["Command-Line Growl Notification"]
+    (opts, message) <- growlOpts args
+    let Options { optSticky = sticky
+                , optName = name
+                , optNotification = notification
+                , optTitle = title 
+                , optServer = server
+                , optPassword = password } = opts
+    let b =  registrationPacket name [notification]
     let m = addMD5Sum password b
-    let b2 = notificationPacket "growlnotify" "Command-Line Growl Notification" title (unwords message)
+    let b2 = notificationPacket sticky name notification title (unwords message)
     let m2 = addMD5Sum password b2
     sendMessage server m 
     sendMessage server m2
+
+
+data Options = Options  { optSticky   :: Bool
+                        , optNotification :: String
+                        , optName      :: String
+                        , optTitle     :: String
+                        , optServer    :: String
+                        , optPassword  :: String
+                        }
+                        
+startOptions :: Options
+startOptions = Options { optSticky   = False
+                       , optNotification = "Cmdline Growl Notification"
+                       , optName     = "growlnotify"
+                       , optTitle    = "Network Notification"
+                       , optServer   = "127.0.0.1"
+                       , optPassword = ""
+                       }
+                        
+options :: [OptDescr (Options -> IO Options)]
+options =
+ [ Option ['k']  ["sticky"]       (NoArg (\opt -> return opt {optSticky=True}) ) "sticky message"
+ , Option ['n']  ["programname"]  (ReqArg (\arg opt -> return opt {optName=arg}) "NAME")   "program registration NAME"
+ , Option ['s']  ["server"]       (ReqArg (\arg opt -> return opt {optServer=arg}) "SERVER") "growl SERVER"
+ , Option ['p']  ["password"]     (ReqArg (\arg opt -> return opt {optPassword=arg}) "PASSWORD")   "growl PASSWORD"
+ , Option ['N']  ["notification"] (ReqArg (\arg opt -> return opt {optNotification=arg}) "NOTIFICATION") "NOTIFICATION"
+ , Option ['t']  ["title"]        (ReqArg (\arg opt -> return opt {optTitle=arg}) "TITLE") "message TITLE"
+ ]
+
+
+
+growlOpts :: [String] -> IO (Options, [String])
+growlOpts argv = do
+    -- Parse options, getting a list of option actions
+    let (actions, nonOptions, errors) = getOpt RequireOrder options argv
+
+    -- Here we thread startOptions through all supplied option actions
+    opts <- foldl (>>=) (return startOptions) actions
+    
+    return (opts, nonOptions)
