diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+
+# Version [0.1.2.0](https://github.com/sorki/haskell-zre/compare/0.1.1.0...0.1.2.0) (2020-07-10)
+
+* Added
+  * `zreChanWith` - principled variant of `zreChan` accepting runner function
+  * `runZreEnvConfig` - runner utilizing config files only
+
 # Version [0.1.1.0](https://github.com/sorki/haskell-zre/compare/0.1.0.2...0.1.1.0) (2020-06-17)
 
 * Changelog started. Previous release was `0.1.0.2`.
diff --git a/README.rst b/README.rst
--- a/README.rst
+++ b/README.rst
@@ -71,7 +71,7 @@
 
 Implementation of gossip protocol is included in form of key value TTL server.
 This allows connecting peers from different networks (or subnets) not reachable via multicast
-beacon. This service requires TCP port 31337 and can be started with `zgossip_server` binary.
+beacon. This service requires TCP port 31337 and can be started with `zgossip-server` binary.
 
 Run server::
 
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -31,9 +31,6 @@
 
   return $ filter (isPrefixOf n) (map ('/':) names)
 
-ini :: Repl ()
-ini = liftIO $ putStrLn "Welcome!"
-
 main :: IO ()
 main = runZre replApp
 
@@ -62,8 +59,11 @@
 
     repl = do
       q <- getApiQueue
-      liftIO $ evalRepl (pure ">>> ") (cmd q) [] Nothing (Word completer) ini
+      liftIO $ evalRepl (const $ pure ">>> ") (cmd q) [] Nothing Nothing (Word completer) ini end
       liftIO $ atomically $ writeTBQueue q DoQuit
+
+    ini = liftIO $ putStrLn "Welcome!"
+    end = liftIO $ putStrLn "Exiting" >> return Exit
 
     cmd :: APIQueue -> String -> Repl ()
     cmd q x = do
diff --git a/src/Network/ZRE.hs b/src/Network/ZRE.hs
--- a/src/Network/ZRE.hs
+++ b/src/Network/ZRE.hs
@@ -3,6 +3,7 @@
 module Network.ZRE (
     runZre
   , runZreCfg
+  , runZreEnvConfig
   , runZreParse
   , readZ
   , writeZ
@@ -86,8 +87,13 @@
      x { zreIfaces = M.insert iface [r] (zreIfaces x) }
 
 runZre :: ZRE a -> IO ()
-runZre app = runZreParse (pure ()) (\() -> app)
+runZre app = runZreParse (pure ()) (const app)
 
+-- | Run with config file loaded from the enviornment variable ENVCFG
+-- (@/etc/zre.conf@ or @~/.zre.conf@), possibly overriden by command-line options.
+--
+-- Accepts another `optparse-applicative` `Parser` for extending
+-- built-in one.
 runZreParse :: Parser extra -> (extra -> ZRE a) -> IO ()
 runZreParse parseExtra app = do
   -- try to get config from the enviornment variable ENVCFG, /etc/zre.conf
@@ -100,6 +106,13 @@
       ( fullDesc
      <> progDesc "ZRE"
      <> header "zre tools" )
+
+-- | Run with config file loaded from the enviornment variable ENVCFG
+-- (@/etc/zre.conf@ or @~/.zre.conf@)
+runZreEnvConfig :: ZRE a -> IO ()
+runZreEnvConfig app = do
+  cfgIni <- envZRECfg "zre"
+  runZreCfg cfgIni app
 
 runZreCfg :: ZRECfg -> ZRE a -> IO ()
 runZreCfg cfg@ZRECfg{..} app = do
diff --git a/src/Network/ZRE/Chan.hs b/src/Network/ZRE/Chan.hs
--- a/src/Network/ZRE/Chan.hs
+++ b/src/Network/ZRE/Chan.hs
@@ -5,6 +5,7 @@
 module Network.ZRE.Chan (
     zreChan
   , zreChan'
+  , zreChanWith
   , mapToGroup
   , mapToGroup'
   ) where
@@ -83,11 +84,20 @@
          -> Group
          -> IO ( TChan input
                , TChan output)
-zreChan' outputGroup inputGroup = do
+zreChan' = zreChanWith Network.ZRE.runZre
+
+-- | Principled version accepting runner function
+zreChanWith :: (Serialize input, Serialize output)
+            => (ZRE () -> IO ())
+            -> Group
+            -> Group
+            -> IO ( TChan input
+                  , TChan output)
+zreChanWith runner outputGroup inputGroup = do
   chanInput  <- Control.Concurrent.STM.newTChanIO
   chanOutput <- Control.Concurrent.STM.newTChanIO
 
-  _ <- Control.Concurrent.Async.Lifted.async $ Network.ZRE.runZre $ do
+  _ <- Control.Concurrent.Async.Lifted.async $ runner $ do
 
     -- joining the outputGroup is not strictly needed for
     -- shouts to pass thru, for indication only
diff --git a/zre.cabal b/zre.cabal
--- a/zre.cabal
+++ b/zre.cabal
@@ -1,5 +1,5 @@
 name:                zre
-version:             0.1.1.0
+version:             0.1.2.0
 synopsis:            ZRE protocol implementation
 description:         Peer-to-peer local area networking with reliable group messaging
                      and automatic peer discovery.
@@ -14,7 +14,7 @@
 copyright:           2020 Richard Marko
 category:            Networking
 build-type:          Simple
-cabal-version:       >=1.10
+cabal-version:       2.0
 extra-source-files:
   CHANGELOG.md
   README.rst
@@ -46,17 +46,17 @@
                        , Data.ZMQParse
                        , Data.ZGossip
                        , System.ZMQ4.Endpoint
-  build-depends:       base >= 4.7 && < 5
+  build-depends:       base ^>= 4.14
                      , async
                      , lifted-async
-                     , attoparsec
+                     , attoparsec ^>= 0.13
                      , cereal
                      , data-default
-                     , network
-                     , network-bsd
-                     , network-info
-                     , network-multicast
-                     , binary
+                     , network ^>= 3.1
+                     , network-bsd ^>= 2.8
+                     , network-info ^>= 0.2
+                     , network-multicast ^>= 0.3
+                     , binary ^>= 0.8
                      , bytestring
                      , containers
                      , directory
@@ -72,7 +72,7 @@
                      , stm
                      , time
                      , uuid
-                     , zeromq4-haskell
+                     , zeromq4-haskell ^>= 0.8
   default-language:    Haskell2010
   ghc-options:         -Wall
 
@@ -84,7 +84,7 @@
                      , bytestring
                      , async
                      , lifted-async
-                     , repline
+                     , repline ^>= 0.4
                      , stm
                      , zre
   default-language:    Haskell2010
