diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for corecursive-main
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2018
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+# corecursive-main
+
+Functional programmers are used to program with (co-)recursive functions.  What
+if the main program was itself recursive? One could benefit the underlying
+operating system scheduler to orchestrate resources. For instance, limiting
+memory, file-descriptor on a per-recursive-call basis. Another instance is
+supporting distributed computations across multiple machines.
+
+## This package
+
+This package demonstrates the idea of replacing the main entry-point of the
+program (i.e., `main :: IO ()`) with a recursion-aware main. The program first
+pattern matches on an "argument". This argument defines which action to take
+for the rest of the program. The rest of the program runs with a
+"Self-reference", which allows the program to call itself back. Explicitly
+passing a Self-reference is very similar to how the `fix` function allows to
+factor recursion out of the body of a self-referential function.
+
+Unlike `fix`, which executes recursive-call in the same memory-space as the
+call-site, developper using this package need to teach the program to transfer
+arguments and return values back-and-forth the call-site and the execution
+site. This package minimizes the developper effort to perform this translation.
+
+Currently, one mode is supported: spawning a child process on the same OS while
+serializing arguments over the command-line parameters.
+
+Future versions of this package or sibling packages will likely provide:
+- support for 'JSON' or 'Dhall' serialization format
+- support for 'stdin' or networked serialization mechanisms
+- remote calls using `ssh`
+
+## Envisionned usages
+
+Distributed computating:
+- run a same copy of the program on many places, each on a subset of the data (much like Map/Reduce)
+
+Dev/Ops:
+- use a single binary to reconfigure the whole datacenter and services after a cataclysmic outage (see #History) as well
+
+- orchestrate processes locally
+
+## History
+
+This package is factored out of code and findings made while writing
+[DepTrack](https://github.com/lucasdicioccio/deptrack-project). If you like
+this package you may find other interesting ideas in DepTrack.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,28 @@
+module Main where
+
+import System.Process.Corecursive
+import System.Posix.Process
+
+newtype Arg = Arg { getListOfThings :: [String] }
+
+numberOfThings :: Arg -> Int
+numberOfThings = length . getListOfThings
+
+append :: Show a => a -> Arg -> Arg
+append x (Arg xs) = Arg (show x:xs)
+
+main :: IO ()
+main = runCorecursiveApp (app parse unparse go)
+  where
+    parse :: [String] -> IO Arg
+    parse = pure . Arg
+
+    unparse :: Arg -> IO [String]
+    unparse = pure  . getListOfThings
+
+    go self arg
+      | numberOfThings arg > 10 = print "done"
+      | otherwise               = do
+          pid <- getProcessID
+          dat <- readCallback self (append pid arg)
+          putStr $ show pid ++ show (getListOfThings arg) ++ " " ++ dat
diff --git a/corecursive-main.cabal b/corecursive-main.cabal
new file mode 100644
--- /dev/null
+++ b/corecursive-main.cabal
@@ -0,0 +1,68 @@
+-- This file has been generated from package.yaml by hpack version 0.28.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 24db3f929122337c798281c9a462b828f1136db68cc113c224e0ae537470b42c
+
+name:           corecursive-main
+version:        0.1.0.0
+synopsis:       Write your main like it can call itself back.
+description:    Please see the README on GitHub at <https://github.com/githubuser/corecursive-main#readme>
+category:       Control
+homepage:       https://github.com/githubuser/corecursive-main#readme
+bug-reports:    https://github.com/githubuser/corecursive-main/issues
+author:         Author name here
+maintainer:     example@example.com
+copyright:      2018 Author name here
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+extra-source-files:
+    ChangeLog.md
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/githubuser/corecursive-main
+
+library
+  exposed-modules:
+      System.Process.Corecursive
+      System.Process.Corecursive.Base
+  other-modules:
+      Paths_corecursive_main
+  hs-source-dirs:
+      src
+  build-depends:
+      base >=4.7 && <5
+    , process
+  default-language: Haskell2010
+
+executable corecursive-main-exe
+  main-is: Main.hs
+  other-modules:
+      Paths_corecursive_main
+  hs-source-dirs:
+      app
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , corecursive-main
+    , process
+    , unix
+  default-language: Haskell2010
+
+test-suite corecursive-main-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_corecursive_main
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , corecursive-main
+    , process
+  default-language: Haskell2010
diff --git a/src/System/Process/Corecursive.hs b/src/System/Process/Corecursive.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Process/Corecursive.hs
@@ -0,0 +1,41 @@
+-- | A module to facilitate and demonstrate a programming pattern where
+-- application instances for a system is (co-)recursive.
+module System.Process.Corecursive
+    ( runCorecursiveApp
+    , callback
+    , readCallback
+    -- * re-exported for convenience
+    , App
+    , Self
+    , app
+    ) where
+
+import Control.Monad (void)
+import Control.Monad.IO.Class (liftIO, MonadIO)
+import System.Environment (getArgs, getExecutablePath)
+import System.Process (callProcess, readProcess)
+
+import System.Process.Corecursive.Base (runApp, app, App, Self(..))
+
+-- | Run function for an App which arguments are read from the command line
+-- using 'getArgs' and for which the binary is discovered from
+-- 'getExecutablePath'.
+runCorecursiveApp :: MonadIO m => App m [String] arg FilePath () -> m ()
+runCorecursiveApp =
+    runApp (liftIO getExecutablePath) (liftIO getArgs)
+
+-- | Callback running the Self executable locally and waiting until completion
+-- using 'callProcess'.
+callback :: MonadIO m => Self m [String] arg FilePath -> arg -> m ()
+callback self a = do
+    exe <- executable self
+    args <- unparse self $ a
+    liftIO $ callProcess exe args
+
+-- | Callback running the Self executable locally and waiting until completion
+-- using 'readProcess'.
+readCallback :: MonadIO m => Self m [String] arg FilePath -> arg -> m String
+readCallback self a = do
+    exe <- executable self
+    args <- unparse self $ a
+    liftIO $ readProcess exe args ""
diff --git a/src/System/Process/Corecursive/Base.hs b/src/System/Process/Corecursive/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Process/Corecursive/Base.hs
@@ -0,0 +1,86 @@
+
+-- | Types for building (co-)recursive system programs.
+--
+-- The tools in this module allow to define the call-site and the main entry
+-- point of a (co-)recursive program.
+--
+-- However, this module does not define 'callback' usages so that implementers
+-- are free to chose the mechanism they want to:
+-- - start the recursive program
+-- - retrieve a return-value (if the recursive program ever returns)
+module System.Process.Corecursive.Base
+    ( App (..)
+    , app
+    , runApp
+    , Self (..)
+    ) where
+
+-- | A datatype representing an instance of the (co-)recursive program.
+--
+-- A reason why the records in this type are separate from 'App' is that a
+-- calling program may need to execute a fair amount of progress
+-- before knowing the right 'executable' (e.g., in the case of a remote
+-- invocation). Also, sometimes one may want to adapt 'Self'.
+data Self t msg arg inst = Self {
+    executable :: t inst
+  -- ^ An  action to retrieve an instance of the (co-)recursive program
+  -- the 'inst' type is leaved as an argument to allow representing cases where
+  -- the execution is actually remote.
+  , unparse    :: arg -> t msg
+  -- ^ An action to unparse arguments. Typically from 'unparseArgs'.
+  }
+instance Functor t => Functor (Self t msg arg) where
+    fmap f (Self e u) = Self (fmap f e) u
+
+-- | A datatype wrapping everything needed to make a (co-)recursive main
+-- function.
+--
+-- Application authors may find this type useful because it has a Functor
+-- instance, allowing to adapt the result of a computation.
+--
+-- See 'app'.
+data App t msg arg inst ret = App {
+    parseArgs          :: msg -> t arg
+  -- ^ Function parsing argument from a serialized message.
+  , unparseArgs        :: arg -> t msg
+  -- ^ Function un-parsing an argument into a serialized message.
+  , corecursiveProgram :: Self t msg arg inst -> arg -> t ret
+  -- ^ Actual program to run from a specification.
+  }
+
+instance Functor t => Functor (App t msg arg inst) where
+    fmap f (App p u cp) =
+        App p u $ \self arg -> fmap f (cp self arg)
+
+-- | Constructor for an App.
+app
+  :: (msg -> m arg)
+  -- ^ Function parsing argument from a serialized message.
+  -> (arg -> m msg)
+  -- ^ Function un-parsing an argument into a serialized message.
+  -> (Self m msg arg inst -> arg -> m ret)
+  -- ^ Actual program to run from a specification.
+  -> App m msg arg inst ret
+app = App
+
+-- | Typical function to run an 'App' with simplifying assumptions:
+--
+-- - locate the Self instance once for the rest of the program
+-- - reads the arguments once
+-- - starts the actual program
+runApp
+  :: Monad m
+  => m inst
+  -- ^ An action to locate the self instance of an applictaion.
+  -- This action is run exactly once and the result is stored in 'Self'.
+  -> m msg
+  -- ^ An action to retrieve the message to start the application with.
+  -- This action is run exactly once, the result is then parsed and discarded.
+  -> App m msg arg inst ret
+  -- ^ The 'App' to run
+  -> m ret
+runApp getInst getMsg (App parse unparse go) = do
+    inst <- getInst
+    let self = Self (pure inst) unparse
+    arg <- parse =<< getMsg
+    go self arg
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
