diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,30 @@
+# Changelog
+
+## Unreleased
+
+## 0.1.5
+
+* feat: Add sort order toggle.
+* fix: Search now does not contain false-positives.
+
+## 0.1.4 - 2021-02-23
+
+* feat: Make search case insensitive.
+* fix: Can close the help modal now.
+
+## 0.1.3.1 - 2021-01-07
+
+* fix: Correctly pass --derivation flag to Nix >= 2.4
+
+## 0.1.3.0 - 2020-12-22
+
+* feat: Ability to work on .drv files.
+
+## 0.1.2.0 - 2020-09-15
+
+* feat: Add --version flag
+* fix: Can search the letter 'q' without closing the search modal.
+
+## 0.1.1.0 - 2020-08-23
+
+* feat: Seach functionality.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 
 Interactively browse the dependency graph of your Nix derivations.
 
-[![asciicast](https://asciinema.org/a/ahDveBL1gs5t36z1myePtrKpR.svg)](https://asciinema.org/a/ahDveBL1gs5t36z1myePtrKpR)
+[![asciicast](https://asciinema.org/a/cnilbmPXW51g97hdNJZcM5F6h.svg)](https://asciinema.org/a/cnilbmPXW51g97hdNJZcM5F6h)
 
 ## Installation
 
@@ -33,11 +33,19 @@
   q/Esc:          : Quit / close modal
   w               : Open why-depends mode
   /               : Open search mode
-  i               : Toggle modeline
+  s               : Change sort order
   ?               : Show help
 ```
 
-[home-manager]: https://github.com/rycee/home-manager
+### Glossary
+
+* **NAR Size**: Size of the store path itself.
+* **Closure size**: Total size of the store path and all its transitive dependencies.
+* **Added size**:  Size of the store path, and all its _unique_ transitive
+  dependencies. In other words, the cost of having that store path on top
+  of all other paths. See [issue #14] for a better explanation.
+
+[issue #14]: https://github.com/utdemir/nix-tree/issues/14
 
 ### Tips
 
diff --git a/nix-tree.cabal b/nix-tree.cabal
--- a/nix-tree.cabal
+++ b/nix-tree.cabal
@@ -3,7 +3,7 @@
 name:                nix-tree
 synopsis:            Interactively browse a Nix store paths dependencies
 description:         A terminal curses application to browse a Nix store paths dependencies
-version:             0.1.4
+version:             0.1.5
 homepage:            https://github.com/utdemir/nix-tree
 license:             BSD-3-Clause
 license-file:        LICENSE
@@ -12,7 +12,7 @@
 copyright:           Utku Demir
 category:            Language.Nix
 build-type:          Simple
-extra-source-files:  README.md
+extra-source-files:  README.md, CHANGELOG.md
 
 common common-options
   ghc-options:        -threaded
@@ -36,6 +36,7 @@
                       NamedFieldPuns
                       RankNTypes
                       ScopedTypeVariables
+                      NumericUnderscores
   other-modules:      PathStats
                       StorePath
                       App
@@ -50,6 +51,7 @@
                     , brick
                     , bytestring
                     , containers
+                    , clock
                     , deepseq
                     , directory
                     , filepath
diff --git a/src/App.hs b/src/App.hs
--- a/src/App.hs
+++ b/src/App.hs
@@ -1,6 +1,7 @@
 module App (run, helpText) where
 
 import qualified Brick as B
+import qualified Brick.BChan as B
 import qualified Brick.Widgets.Border as B
 import qualified Brick.Widgets.Center as B
 import qualified Brick.Widgets.List as B
@@ -11,8 +12,12 @@
 import qualified Graphics.Vty as V
 import InvertedIndex
 import PathStats
+import qualified System.Clock as Clock
 import qualified System.HrfSize as HRF
 
+data Event
+  = EventTick Clock.TimeSpec
+
 data Widgets
   = WidgetPrevPane
   | WidgetCurrPane
@@ -26,6 +31,11 @@
   | ModalWhyDepends (B.GenericList Widgets Seq (NonEmpty (Path s)))
   | ModalSearch Text Text (B.GenericList Widgets Seq (Path s))
 
+succCycle :: forall a. (Bounded a, Enum a) => a -> a
+succCycle a
+  | fromEnum a == fromEnum (maxBound @a) = minBound
+  | otherwise = succ a
+
 data AppEnv s = AppEnv
   { aeActualStoreEnv :: StoreEnv s (PathStats s),
     aeInvertedIndex :: InvertedIndex,
@@ -34,23 +44,42 @@
     aeNextPane :: List s,
     aeParents :: [List s],
     aeOpenModal :: Maybe (Modal s),
-    aeShowInfoPane :: Bool
+    aeSortOrder :: SortOrder,
+    aeSortOrderLastChanged :: Clock.TimeSpec,
+    aeCurrTime :: Clock.TimeSpec
   }
 
 type Path s = StorePath s (StoreName s) (PathStats s)
 
 type List s = B.GenericList Widgets Seq (Path s)
 
-attrTerminal :: B.AttrName
+data SortOrder
+  = SortOrderAlphabetical
+  | SortOrderClosureSize
+  | SortOrderAddedSize
+  deriving (Show, Eq, Enum, Bounded)
+
+compareBySortOrder :: SortOrder -> Path s -> Path s -> Ordering
+compareBySortOrder SortOrderAlphabetical = compare `on` T.toLower . storeNameToShortText . spName
+compareBySortOrder SortOrderClosureSize = compare `on` Down . psTotalSize . spPayload
+compareBySortOrder SortOrderAddedSize = compare `on` Down . psAddedSize . spPayload
+
+attrTerminal, attrUnderlined :: B.AttrName
 attrTerminal = "terminal"
+attrUnderlined = "underlined"
 
 run :: StoreEnv s (PathStats s) -> IO ()
-run env = void . B.defaultMain app =<< appEnv
-  where
-    appEnv = do
-      let ii = iiFromList . toList . map (storeNameToText . spName) $ seAll env
-      _ <- forkIO $ evaluate (rnf ii)
-      return $
+run env = do
+  -- Create the inverted index, and start evaluating it in the background
+  let ii = iiFromList . toList . map (storeNameToText . spName) $ seAll env
+  _ <- forkIO $ evaluate (rnf ii)
+
+  -- Initial state
+  let getTime = Clock.getTime Clock.Monotonic
+  currTime <- getTime
+  let defaultSortOrder = SortOrderClosureSize
+
+  let appEnv =
         AppEnv
           { aeActualStoreEnv =
               env,
@@ -59,23 +88,47 @@
             aePrevPane =
               B.list WidgetPrevPane S.empty 0,
             aeCurrPane =
-              B.list WidgetCurrPane (S.fromList . NE.toList $ seGetRoots env) 0,
+              B.list
+                WidgetCurrPane
+                (S.fromList . sortBy (compareBySortOrder defaultSortOrder) . NE.toList $ seGetRoots env)
+                0,
             aeNextPane =
               B.list WidgetNextPane S.empty 0,
             aeParents =
               [],
             aeOpenModal =
               Nothing,
-            aeShowInfoPane =
-              True
+            aeSortOrder =
+              defaultSortOrder,
+            aeSortOrderLastChanged =
+              Clock.TimeSpec 0 0,
+            aeCurrTime =
+              currTime
           }
           & repopulateNextPane
 
+  -- Create a channel that's fed by current time
+  chan <- B.newBChan 10
+  void . forkIO $
+    forever $ do
+      threadDelay (100 * 100)
+      t <- getTime
+      _ <- B.writeBChanNonBlocking chan (EventTick t)
+      return ()
+
+  -- And run the application
+  let mkVty = V.mkVty V.defaultConfig
+  initialVty <- mkVty
+  _ <- B.customMain initialVty mkVty (Just chan) app appEnv
+
+  return ()
+
 renderList ::
+  Maybe SortOrder ->
   Bool ->
   List s ->
   B.Widget Widgets
-renderList isFocused =
+renderList highlightSort isFocused =
   B.renderList
     ( \_
        StorePath
@@ -88,22 +141,35 @@
                   then B.withAttr attrTerminal
                   else identity
            in color $
-                B.padRight B.Max (B.txt $ storeNameToShortText spName)
-                  B.<+> B.padLeft
-                    B.Max
-                    ( B.txt $
-                        prettySize psTotalSize
-                          <> if not (null spRefs)
-                            then
-                              " ("
-                                <> prettySize psAddedSize
-                                <> ")"
-                            else mempty
-                    )
+                B.hBox
+                  [ B.txt (storeNameToShortText spName)
+                      & underlineWhen SortOrderAlphabetical
+                      & B.padRight (B.Pad 1)
+                      & B.padRight B.Max,
+                    if null spRefs
+                      then
+                        B.txt (prettySize psTotalSize)
+                          & underlineWhen SortOrderClosureSize
+                          & underlineWhen SortOrderAddedSize
+                      else
+                        B.hBox
+                          [ B.txt (prettySize psTotalSize)
+                              & underlineWhen SortOrderClosureSize,
+                            B.txt " (",
+                            B.txt (prettySize psAddedSize)
+                              & underlineWhen SortOrderAddedSize,
+                            B.txt ")"
+                          ]
+                  ]
     )
     isFocused
+  where
+    underlineWhen so =
+      if Just so == highlightSort
+        then B.withDefAttr attrUnderlined
+        else identity
 
-app :: B.App (AppEnv s) () Widgets
+app :: B.App (AppEnv s) Event Widgets
 app =
   B.App
     { B.appDraw = \env@AppEnv {aeOpenModal} ->
@@ -127,8 +193,13 @@
             B.continue $ showWhyDepends s
           (B.VtyEvent (V.EvKey (V.KChar '/') []), Nothing) ->
             B.continue $ showAndUpdateSearch "" "" s
-          (B.VtyEvent (V.EvKey (V.KChar 'i') []), Nothing) ->
-            B.continue $ s {aeShowInfoPane = not (aeShowInfoPane s)}
+          (B.VtyEvent (V.EvKey (V.KChar 's') []), Nothing) ->
+            B.continue $
+              s
+                { aeSortOrder = succCycle (aeSortOrder s),
+                  aeSortOrderLastChanged = aeCurrTime s
+                }
+                & sortPanes
           (B.VtyEvent (V.EvKey k []), Nothing)
             | k `elem` [V.KChar 'h', V.KLeft] ->
               B.continue $ moveLeft s
@@ -205,6 +276,9 @@
           (B.VtyEvent (V.EvKey k []), Just ModalHelp)
             | k `elem` [V.KChar 'q', V.KEsc] ->
               B.continue s {aeOpenModal = Nothing}
+          -- handle our events
+          (B.AppEvent (EventTick t), Nothing) ->
+            B.continue $ s {aeCurrTime = t}
           -- ignore otherwise
           _ ->
             B.continue s,
@@ -213,7 +287,8 @@
         B.attrMap
           (V.white `B.on` V.black)
           [ (B.listSelectedFocusedAttr, V.black `B.on` V.white),
-            (attrTerminal, B.fg V.blue)
+            (attrTerminal, B.fg V.blue),
+            (attrUnderlined, V.currentAttr `V.withStyle` V.underline)
           ]
     }
   where
@@ -229,45 +304,50 @@
         )
 
 renderMainScreen :: AppEnv s -> B.Widget Widgets
-renderMainScreen env@AppEnv {aePrevPane, aeCurrPane, aeNextPane, aeShowInfoPane} =
+renderMainScreen env@AppEnv {aePrevPane, aeCurrPane, aeNextPane} =
   (B.joinBorders . B.border)
     ( B.hBox
-        [ renderList True aePrevPane,
+        [ renderList Nothing True aePrevPane,
           B.vBorder,
-          renderList True aeCurrPane,
+          renderList shouldHighlightSortOrder True aeCurrPane,
           B.vBorder,
-          renderList False aeNextPane
+          renderList Nothing False aeNextPane
         ]
     )
-    B.<=> if aeShowInfoPane then renderInfoPane env else renderModeline env
-
-renderModeline :: AppEnv s -> B.Widget Widgets
-renderModeline env =
-  let selected = selectedPath env
-   in B.txt $
-        T.intercalate
-          " - "
-          [ T.pack $ storeNameToPath (spName selected),
-            "NAR Size: " <> prettySize (spSize selected),
-            "Closure Size: " <> prettySize (psTotalSize $ spPayload selected)
-          ]
+    B.<=> renderInfoPane env
+  where
+    shouldHighlightSortOrder =
+      let timePassed = Clock.diffTimeSpec (aeCurrTime env) (aeSortOrderLastChanged env)
+       in if timePassed < Clock.TimeSpec 0 (500 * 1_000_000)
+            then Just (aeSortOrder env)
+            else Nothing
 
 renderInfoPane :: AppEnv s -> B.Widget Widgets
 renderInfoPane env =
   let selected = selectedPath env
       immediateParents = psImmediateParents $ spPayload selected
-   in B.txt $
-        T.intercalate
-          "\n"
-          [ T.pack $ storeNameToPath (spName selected),
-            "NAR Size: " <> prettySize (spSize selected),
-            "Closure Size: " <> prettySize (psTotalSize $ spPayload selected),
+   in B.vBox
+        [ ( let (f, s) = storeNameToSplitShortText (spName selected)
+             in B.txt f B.<+> underlineWhen SortOrderAlphabetical (B.txt s)
+          ),
+          [ B.txt $ "NAR Size: " <> prettySize (spSize selected),
+            underlineWhen SortOrderClosureSize . B.txt $ "Closure Size: " <> prettySize (psTotalSize $ spPayload selected),
+            underlineWhen SortOrderAddedSize . B.txt $ "Added Size: " <> prettySize (psAddedSize $ spPayload selected)
+          ]
+            & intersperse (B.txt " | ")
+            & B.hBox,
+          B.txt $
             if null immediateParents
               then "Immediate Parents: -"
               else
                 "Immediate Parents (" <> T.pack (show $ length immediateParents) <> "): "
                   <> T.intercalate ", " (map storeNameToShortText immediateParents)
-          ]
+        ]
+  where
+    underlineWhen so =
+      if so == aeSortOrder env
+        then B.withAttr attrUnderlined
+        else identity
 
 renderModal :: Text -> B.Widget a -> B.Widget a
 renderModal title widget =
@@ -285,7 +365,7 @@
       "q/Esc:          : Quit / close modal",
       "w               : Open why-depends mode",
       "/               : Open search mode",
-      "i               : Toggle modeline",
+      "s               : Change sort order",
       "?               : Show help"
     ]
 
@@ -326,7 +406,7 @@
     window =
       B.txt left B.<+> B.txt "|" B.<+> B.txt right
         B.<=> B.hBorder
-        B.<=> renderList True l
+        B.<=> renderList Nothing True l
 
 showAndUpdateSearch :: Text -> Text -> AppEnv s -> AppEnv s
 showAndUpdateSearch left right env@AppEnv {aeActualStoreEnv, aeInvertedIndex} =
@@ -368,12 +448,12 @@
       & repopulateNextPane
 
 repopulateNextPane :: AppEnv s -> AppEnv s
-repopulateNextPane env@AppEnv {aeActualStoreEnv, aeNextPane} =
+repopulateNextPane env@AppEnv {aeActualStoreEnv, aeNextPane, aeSortOrder} =
   let ref = selectedPath env
    in env
         { aeNextPane =
             B.listReplace
-              ( S.sortOn (Down . psTotalSize . spPayload)
+              ( S.sortBy (compareBySortOrder aeSortOrder)
                   . S.fromList
                   . map (seLookup aeActualStoreEnv)
                   $ spRefs ref
@@ -382,6 +462,24 @@
               aeNextPane
         }
 
+sortPane :: SortOrder -> List s -> List s
+sortPane so l =
+  let selected = B.listSelectedElement l
+      elems =
+        B.listElements l
+          & S.sortBy (compareBySortOrder so)
+      name = B.getName l
+   in mkList so name elems (snd <$> selected)
+
+sortPanes :: AppEnv s -> AppEnv s
+sortPanes env@AppEnv {aeParents, aePrevPane, aeCurrPane, aeNextPane, aeSortOrder} =
+  env
+    { aeCurrPane = sortPane aeSortOrder aeCurrPane,
+      aeNextPane = sortPane aeSortOrder aeNextPane,
+      aeParents = sortPane aeSortOrder <$> aeParents,
+      aePrevPane = sortPane aeSortOrder aePrevPane
+    }
+
 selectedPath :: AppEnv s -> Path s
 selectedPath = NE.head . selectedPaths
 
@@ -412,8 +510,7 @@
           (NE.toList (seGetRoots aeActualStoreEnv), root)
           children
           & NE.reverse
-          & fmap
-            (\(possible, selected) -> mkList WidgetPrevPane possible selected)
+          & fmap (\(possible, selected) -> mkList (aeSortOrder env) WidgetPrevPane (S.fromList possible) (Just selected))
           & (<> (emptyPane :| []))
    in case lists of
         (curr :| prevs) ->
@@ -427,13 +524,20 @@
                 }
                 & repopulateNextPane
   where
-    mkList name possible selected =
-      let contents = S.sortOn (Down . psTotalSize . spPayload) (S.fromList possible)
-       in B.list name contents 1
-            & B.listMoveTo
-              (fromMaybe (0) $ (((==) `on` spName) selected) `S.findIndexL` contents)
     emptyPane =
       B.list WidgetPrevPane S.empty 0
+
+mkList ::
+  SortOrder ->
+  n ->
+  Seq (Path s) ->
+  Maybe (Path s) ->
+  B.GenericList n Seq (Path s)
+mkList sortOrder name possible selected =
+  let contents = S.sortBy (compareBySortOrder sortOrder) possible
+   in B.list name contents 1
+        & B.listMoveTo
+          (fromMaybe 0 $ selected >>= \s -> (((==) `on` spName) s) `S.findIndexL` contents)
 
 -- Utils
 
diff --git a/src/StorePath.hs b/src/StorePath.hs
--- a/src/StorePath.hs
+++ b/src/StorePath.hs
@@ -3,6 +3,7 @@
     storeNameToPath,
     storeNameToText,
     storeNameToShortText,
+    storeNameToSplitShortText,
     StorePath (..),
     StoreEnv (..),
     withStoreEnv,
@@ -44,7 +45,13 @@
 storeNameToPath (StoreName sn) = "/nix/store/" <> toS sn
 
 storeNameToShortText :: StoreName a -> Text
-storeNameToShortText = T.drop 1 . T.dropWhile (/= '-') . storeNameToText
+storeNameToShortText = snd . storeNameToSplitShortText
+
+storeNameToSplitShortText :: StoreName a -> (Text, Text)
+storeNameToSplitShortText txt =
+  case T.span (/= '-') . T.pack $ storeNameToPath txt of
+    (f, s) | Just (c, s'') <- T.uncons s -> (T.snoc f c, s'')
+    e -> e
 
 --------------------------------------------------------------------------------
 
