diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013, Sam T.
+Copyright (c) 2013, Sam Truzjan
 
 All rights reserved.
 
@@ -13,7 +13,7 @@
       disclaimer in the documentation and/or other materials provided
       with the distribution.
 
-    * Neither the name of Sam T. nor the names of other
+    * Neither the name of Sam Truzjan nor the names of other
       contributors may be used to endorse or promote products derived
       from this software without specific prior written permission.
 
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,5 +1,7 @@
 module Main (main) where
 
+import Prelude as P
+
 import Control.Applicative as A
 import Control.Concurrent
 import Control.Concurrent.Async
@@ -8,6 +10,7 @@
 import Data.Default
 import Data.List as L
 import Data.Maybe
+import Data.Monoid
 import Data.Time
 import Data.Time.Clock.POSIX
 import Data.Version (showVersion)
@@ -22,27 +25,21 @@
 
 import UReader.Localization
 import UReader.Options
+import UReader.Outline
 import UReader.Rendering
 import UReader.RSS
 
 
-parseFeedList :: String -> [URI]
-parseFeedList = mapMaybe parseURI . L.lines
-
-getFeedList :: FilePath -> IO [URI]
-getFeedList feedList = parseFeedList <$> Prelude.readFile feedList
-
-
 getLastSeen :: FilePath -> IO UTCTime
 getLastSeen lastPath = do
     exist <- doesFileExist lastPath
     if exist
       then do
-        !mLastSeen <- parsePubDate <$> Prelude.readFile lastPath
-        Prelude.writeFile lastPath . formatPubDate =<< getCurrentTime
+        !mLastSeen <- parsePubDate <$> P.readFile lastPath
+        P.writeFile lastPath . formatPubDate =<< getCurrentTime
         return $ fromMaybe epochStart mLastSeen
       else do
-        Prelude.writeFile lastPath . formatPubDate =<< getCurrentTime
+        P.writeFile lastPath . formatPubDate =<< getCurrentTime
         return epochStart
   where
     epochStart = posixSecondsToUTCTime 0
@@ -69,7 +66,8 @@
   let userFeeds  =  L.map (filterItems isNew) feeds
   unless (L.all emptyFeed userFeeds) $ do
     localTime <- utcToLocalTime <$> getCurrentTimeZone <*> pure lastSeen
-    print $ green $ "Showed from:" <+> text (formatPubDate localTime)
+    print $ green $ linebreak <>
+      "Showed from:" <+> text (formatPubDate localTime)
   return userFeeds
 
 previewFeed :: URI -> IO ()
@@ -79,6 +77,7 @@
 showBatch style @ Style {..} feedList uris = do
   renderRSS style =<< setCurrentZone =<<
     (if newOnly then filterNew feedList else fetch Nothing) uris
+  putStrLn ([] :: String)
 
 streamStyle :: Style
 streamStyle = Style
@@ -105,12 +104,24 @@
 streamFeeds feedList interval uris =
   pollBy interval $ do updateStream feedList uris
 
+addFeed :: FilePath -> URI -> String -> String -> IO ()
+addFeed filePath uri grp topic
+  = modifyOPML filePath (insertURI [grp, topic] uri)
+
+putVersion :: IO ()
+putVersion = P.putStrLn $ "ureader version " ++ showVersion version
+
 run :: Options -> IO ()
-run Add     {..} = appendFile feedList $ show feedURI ++ "\n"
-run Batch   {..} = getFeedList feedList >>= showBatch feedStyle feedList
-run Preview {..} = previewFeed feedURI
-run Stream  {..} = getFeedList feedList >>= streamFeeds feedList feedInterval
-run Version      = putStrLn $ "ureader version " ++ showVersion version
+run Add     {..} = addFeed      feedList   feedURI
+                                feedParent feedTopic
+run Batch   {..} = getFeedList  feedList  feedGroup
+               >>= showBatch    feedStyle feedList
+run Index   {..} = getIndex     feedList  feedGroup
+               >>= renderFeedList
+run Preview {..} = previewFeed  feedURI
+run Stream  {..} = getFeedList  feedList feedGroup
+               >>= streamFeeds  feedList feedInterval
+run Version      = putVersion
 
 main :: IO ()
 main = getOptions >>= run
diff --git a/src/UReader/Localization.hs b/src/UReader/Localization.hs
--- a/src/UReader/Localization.hs
+++ b/src/UReader/Localization.hs
@@ -1,3 +1,16 @@
+-- |
+--   Copyright   :  (c) Sam Truzjan 2013
+--   License     :  BSD3
+--   Maintainer  :  pxqr.sta@gmail.com
+--   Stability   :  experimental
+--   Portability :  portable
+--
+--   This module provides simple localization for feed items.
+--   Currently an UTC time (pubdate) translated to the LocalTime which
+--   user expect to see.
+--
+--   +0000(UTC) -> +0004(MSK)
+--
 {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE OverlappingInstances #-}
 module UReader.Localization
diff --git a/src/UReader/Options.hs b/src/UReader/Options.hs
--- a/src/UReader/Options.hs
+++ b/src/UReader/Options.hs
@@ -1,7 +1,16 @@
+-- |
+--   Copyright   :  (c) Sam Truzjan 2013
+--   License     :  BSD3
+--   Maintainer  :  pxqr.sta@gmail.com
+--   Stability   :  experimental
+--   Portability :  portable
+--
+--   All stuff relate to command line options should be in this
+--   module: parsers, help, reasonable defaults.
+--
 module UReader.Options
        ( Order (..)
        , Style (..)
-
        , Options (..)
        , getOptions
        ) where
@@ -15,6 +24,7 @@
 import System.FilePath
 
 import UReader.Rendering
+import UReader.Outline
 
 
 styleParser :: Parser Style
@@ -43,7 +53,7 @@
       )
 
 feedListParser :: Implicit_ FilePath => Parser FilePath
-feedListParser = option
+feedListParser = strOption
    ( long    "feeds"
   <> metavar "PATH"
   <> value   param_ <> showDefault
@@ -65,22 +75,49 @@
   <> help    "Minimal interval between feed updates"
    )
 
+feedGroupParser :: Parser Selector
+feedGroupParser = optional $ argument Just
+   ( metavar "GROUP"
+  <> help    "Feed group used to specify some subset of feeds"
+   )
+
+feedParentParser :: Parser String
+feedParentParser = argument Just
+  ( metavar  "GROUP"
+ <> help     "The group feed belongs to"
+  )
+
+feedTopicParser :: Parser String
+feedTopicParser = argument Just
+   ( metavar "TOPIC"
+ <>  help    "The main feed topic used as feed name"
+   )
+
 data Options
    = Add     { feedList   :: FilePath
+             , feedParent :: String
+             , feedTopic  :: String
              , feedURI    :: URI
              }
    | Batch   { feedList   :: FilePath
              , feedStyle  :: Style
+             , feedGroup  :: Selector
              }
    | Preview { feedURI    :: URI  }
    | Stream  { feedList   :: FilePath
              , feedInterval :: Int
+             , feedGroup  :: Selector
              }
+   | Index   { feedList   :: FilePath
+             , feedGroup  :: Selector
+             }
    | Version
      deriving (Show, Eq)
 
 addParser :: Implicit_ String => Parser Options
-addParser = Add <$> feedListParser <*> feedLinkParser
+addParser = Add <$> feedListParser
+                <*> feedParentParser <*> feedTopicParser
+                <*> feedLinkParser
 
 addInfo :: Implicit_ String => ParserInfo Options
 addInfo = info (helper <*> addParser) modifier
@@ -88,7 +125,7 @@
     modifier = progDesc "Add a feed to the feed list"
 
 streamParser :: Implicit_ String => Parser Options
-streamParser = Stream <$> feedListParser <*> intervalTime
+streamParser = Stream <$> feedListParser <*> intervalTime <*> feedGroupParser
 
 streamInfo :: Implicit_ String => ParserInfo Options
 streamInfo = info (helper <*> streamParser) modifier
@@ -96,7 +133,7 @@
     modifier = progDesc "Show feed as never ending stream"
 
 feedParser :: Implicit_ String => Parser Options
-feedParser = Batch <$> feedListParser <*> styleParser
+feedParser = Batch <$> feedListParser <*> styleParser <*> feedGroupParser
 
 feedInfo :: Implicit_ String => ParserInfo Options
 feedInfo = info (helper <*> feedParser) modifier
@@ -111,6 +148,14 @@
   where
     modifier = progDesc "Show feed specified by URI or file path"
 
+indexParser :: Implicit_ FilePath => Parser Options
+indexParser = Index <$> feedListParser <*> feedGroupParser
+
+indexInfo :: Implicit_ FilePath => ParserInfo Options
+indexInfo = info (helper <*> indexParser) modifier
+  where
+    modifier = progDesc "Show your feed list"
+
 versionParser :: Parser Options
 versionParser = flag' Version
     ( long  "version"
@@ -123,6 +168,7 @@
 optionsParser = subparser $ mconcat
   [ command "add"    addInfo
   , command "feed"   feedInfo
+  , command "index"  indexInfo
   , command "stream" streamInfo
   , command "view"   previewInfo
   ]
diff --git a/src/UReader/RSS.hs b/src/UReader/RSS.hs
--- a/src/UReader/RSS.hs
+++ b/src/UReader/RSS.hs
@@ -1,3 +1,12 @@
+-- |
+--   Copyright   :  (c) Sam Truzjan 2013
+--   License     :  BSD3
+--   Maintainer  :  pxqr.sta@gmail.com
+--   Stability   :  experimental
+--   Portability :  portable
+--
+--   This module provides network related stuff.
+--
 module UReader.RSS
        ( filterItems
        , reverseItems
diff --git a/src/UReader/Rendering.hs b/src/UReader/Rendering.hs
--- a/src/UReader/Rendering.hs
+++ b/src/UReader/Rendering.hs
@@ -1,8 +1,19 @@
+-- |
+--   Copyright   :  (c) Sam Truzjan 2013
+--   License     :  BSD3
+--   Maintainer  :  pxqr.sta@gmail.com
+--   Stability   :  experimental
+--   Portability :  portable
+--
+--   This module provides colored (ansi-terminal compatible) rendering
+--   for OPML, RSS, (Atom not yet) and HTML.
+--
 {-# OPTIONS -fno-warn-orphans #-}
 module UReader.Rendering
        ( Order (..)
        , Style (..)
        , renderRSS
+       , renderFeedList
        ) where
 
 import Control.Applicative
@@ -16,16 +27,59 @@
 import Data.List.Split as L
 import Data.Set as S
 import Text.HTML.TagSoup
+import Text.OPML.Syntax
 import Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>), width)
 import Text.RSS.Syntax
 import Text.XML.Light.Types
+import Network.URI
 import System.IO
 import System.Console.Terminal.Size as Terminal
 
 import UReader.RSS
 import UReader.Localization
+import UReader.Outline
 
+{-----------------------------------------------------------------------
+  Feed list
+-----------------------------------------------------------------------}
 
+renderFeedList :: OPML -> IO ()
+renderFeedList = print . pretty
+
+instance Pretty Outline where
+  pretty Outline  {..} =
+    fill 28 (topicTy (pretty opmlText))
+                      <+> ppURI opmlOutlineAttrs <>
+      if L.null opmlOutlineChildren then mempty else linebreak <>
+        indent 4 (vsep $ L.map pretty opmlOutlineChildren)
+--    , "type" <+> pretty opmlType
+--    , "categories" <+> pretty opmlCategories
+--    , "comment"    <+> pretty opmlIsComment
+--    , "breakpoint" <+> pretty opmlIsBreakpoint
+--    , "other"      <+> pretty (show opmlOutlineOther)
+    where
+      topicTy
+        | L.null opmlOutlineChildren = blue    . underline
+        |         otherwise          = magenta . bold
+
+      ppURI (lookupAttr uriQName -> Just uriStr)
+        | Just uri <- parseURI uriStr = "<" <> text (show uri) <> ">"
+        |         otherwise           = red "invalid URL"
+      ppURI _ = mempty
+
+instance Pretty OPMLHead where
+  pretty OPMLHead {..} = pretty opmlTitle
+
+instance Pretty OPML where
+  pretty OPML {..}
+    = --"version" <+> text opmlVersion </>
+      --"head   " <+> pretty opmlHead  </>
+      vsep (L.map pretty opmlBody)
+
+{-----------------------------------------------------------------------
+  Feed
+-----------------------------------------------------------------------}
+
 data Order = NewFirst
            | OldFirst
              deriving (Show, Read, Eq, Ord, Bounded, Enum)
@@ -138,8 +192,8 @@
 
 instance Pretty RSSCategory where
   pretty RSSCategory {..} =
-    dullyellow (maybe mempty text rssCategoryDomain) <>
-    dullred    (hsep $ L.map pretty rssCategoryAttrs)  <>
+    dullyellow (maybe mempty text rssCategoryDomain)  <>
+    dullred    (hsep $ L.map pretty rssCategoryAttrs) <>
     dullblue   (text rssCategoryValue)
 
 instance Pretty Attr where
diff --git a/ureader.cabal b/ureader.cabal
--- a/ureader.cabal
+++ b/ureader.cabal
@@ -1,10 +1,10 @@
 name:                ureader
-version:             0.1.0.0
+version:             0.2.0.0
 license:             BSD3
 license-file:        LICENSE
-author:              Sam T.
-maintainer:          Sam T. <pxqr.sta@gmail.com>
-copyright:           (c) 2013, Sam T.
+author:              Sam Truzjan
+maintainer:          Sam Truzjan <pxqr.sta@gmail.com>
+copyright:           (c) 2013, Sam Truzjan
 category:            RSS
 build-type:          Simple
 cabal-version:       >= 1.10
@@ -18,11 +18,13 @@
         and color support. Everything it does is fetch RSS documents,
         merge them according to specified options, format and flush
         resulting feed to stdout. So `ureader` could be used with
-        pagers like `more(1)` or in linux terminal.
+        pagers like more(1) or in linux terminal.
         .
         [/Release Notes/]
         .
           * /0.1.0.0:/ Initial version.
+        .
+          * /0.2.0.0:/ Use OPML for subscription list.
 
 
 source-repository head
@@ -49,6 +51,7 @@
   build-depends:       base       == 4.*
                      , implicit-params == 0.2.*
                      , data-default
+                     , deepseq
 
                      , async
                      , parallel-io == 0.3.*
@@ -71,6 +74,7 @@
                      , optparse-applicative == 0.5.*
                      , terminal-size        == 0.2.*
 
+                     , opml    == 0.4.*
                      , xml     == 1.3.*
                      , feed    == 0.3.*
                      , tagsoup == 0.12.*
