diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for LiterateMarkdown
+
+## 0.1.0.0 -- 2020-04-11
+
+* First version. Released on an unsuspecting world.
diff --git a/Converter.hs b/Converter.hs
new file mode 100644
--- /dev/null
+++ b/Converter.hs
@@ -0,0 +1,57 @@
+module Converter where
+
+
+-- | converts a files contents from the LHS birdtick style 
+--   to markdown, replacing the code marked by birdticks with ```haskell ... ```
+convertToMd :: String -> String
+convertToMd = unlines . convert' "" . lines
+  where
+    convert' :: String -> [String] -> [String]
+    convert' prev []
+        | isFirstOO prev "<>"          = ["```"]     -- close code tags at the end
+        | otherwise                    = []          
+    convert' prev (h:t)
+        | not (isFirstOO prev "<>") &&                      -- checks for code to stars, inserts newline above code block if needed
+               isFirstOO h    "<>"     = (if prev == "" then [] else [""]) ++ ["```haskell", drop 2 h] ++ rest
+        | isFirstOO      h    "<>"     = (drop 2 h):rest    -- checks for code
+        | isFirstOO      prev "<>"     = ["```"] ++ (if h == "" then [] else [""]) ++ [h] ++ rest    -- checks for code end, insers newline after code block if needed
+        | otherwise                    = h:rest
+        where 
+            rest = convert' h t
+
+-- | converts a files contents from git flavoured markdown 
+--   to literate haskell, replacing code marked with ```haskell ...``` with > birdticks
+--   and  code marked with ``` ... ``` with < birdticks
+--   quotes are converted to `NOTE:` marked lines.
+convertToLhs :: String -> String
+convertToLhs = unlines . convert' False False "" . lines 
+  where
+    convert' :: Bool -> Bool -> String -> [String] -> [String]
+    convert' inCode inSample prev [] = []
+    convert' inCode inSample prev (h:t)
+        | inCode   && h /= "```"       = ["> " ++ h] ++ (convert' True False h t)       -- handles code
+        | inSample && h /= "```"       = ["< " ++ h] ++ (convert' False True h t)       -- handles code sample
+        | headingN h /= 0              = [headingO h ++ (tail $ dropWhile (=='#') h) ++ headingC h] ++ rest   -- converts headings to html
+        | h == "```haskell"            = (if prev == "" then [] else [""]) ++ convert' True False prev t      -- handles code block starts, adds newline if needed
+        | (inCode || inSample) && h == "```" = (if length t > 0 && (head t) == "" then [] else [""]) ++ convert' False False prev t  -- handles code and sample block ends
+        | take 3 h == "```"            = (if prev == "" then [] else [""]) ++ convert' False True prev t      --  handles sample block starts, adds newline if needed
+        | isFirstOO h ">"              = ["NOTE: " ++ drop 2 h] ++ rest                                       -- handles quotes
+        | otherwise                    = h:rest
+        where 
+            headingO h = "<h" ++ show (headingN h) ++ ">"    -- heading open tag
+            headingC h = "</h" ++ show (headingN h) ++ ">"   -- heading close tag
+            headingN h = length $ takeWhile (=='#') h        -- looks for headings
+            rest = convert' False False h t               
+
+-- | uses @isFirst@ to check multiple characters
+isFirstOO :: String -> [Char] -> Bool
+isFirstOO l e = or $ map (isFirst l) e
+
+-- | checks wether the first two characters of a string are 
+--   a given character and ' '
+--   useful to look for code and quotes
+isFirst :: String -> Char -> Bool
+isFirst []        _ = False
+isFirst (h:' ':_) a = a == h
+isFirst (h:_)     a = False
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2020 Fabian Schneider
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LiterateMarkdown.cabal b/LiterateMarkdown.cabal
new file mode 100644
--- /dev/null
+++ b/LiterateMarkdown.cabal
@@ -0,0 +1,97 @@
+cabal-version:       2.2
+
+-- Initial package description 'LiterateMarkdown.cabal' generated by 'cabal
+--  init'.  For further documentation, see
+-- http://haskell.org/cabal/users-guide/
+
+-- The name of the package.
+name:                LiterateMarkdown
+
+-- The package version.  See the Haskell package versioning policy (PVP)
+-- for standards guiding when and how versions should be incremented.
+-- https://pvp.haskell.org
+-- PVP summary:      +-+------- breaking API changes
+--                   | | +----- non-breaking API additions
+--                   | | | +--- code changes with no API change
+version:             0.1.0.0
+
+-- A short (one-line) description of the package.
+synopsis: Converter to convert from .lhs to .md and vice versa.
+
+-- A longer description of the package.
+description: `lhsc` is a program to convert literate haskell files in the 
+             birdtick format to correctly rendered (git flavoured, html containing) markdown files 
+             and vice versa.
+             .
+             It strips away the heading tags #, replacing them with the corresponding html tags,
+             converts the `'''haskell [...]'''` to `> [...]` as recognised by the GHC literate prepocessor.
+             `''' [...] '''` will be converted to `< [...]` and will be discarded by ghc but will still be displayed as code when rendered. 
+             (In both cases `'''` is actually the three md backticks, but its a pain to write md about md.)
+             .
+             Usage:
+             .
+             `lhsc (toLhs|toMd) file1 [file2] [...]`;
+             The `toLhs` and `toMd` commands are not case sensitive. 
+             The program will convert each file from the other format to the specified one, 
+             creating the files `file1.md` `file2.md` ... or `file1.lhs` `file2.lhs` ... in the same directory respectively.
+
+-- A URL where users can report bugs.
+bug-reports: https://github.com/faeblDevelopment/LiterateMarkdown/issues
+ 
+-- The license under which the package is released.
+license:             MIT
+
+-- The file containing the license text.
+license-file:        LICENSE
+
+-- The package author(s).
+author:              Fabian Schneider
+
+-- An email address to which users can send suggestions, bug reports, and
+-- patches.
+maintainer:          faebl.taylor@pm.me
+
+-- A copyright notice.
+-- copyright:
+
+category:            Productivity
+
+-- Extra files to be distributed with the package, such as examples or a
+-- README.
+extra-source-files:  CHANGELOG.md, README.md
+
+source-repository head 
+  type: git
+  location: https://github.com/faeblDevelopment/LiterateMarkdown.git
+  branch: main
+
+library converter
+  exposed-modules:     Converter
+  build-depends:       base ^>=4.12.0.0
+  default-language:    Haskell2010
+
+executable lhsc
+  -- .hs or .lhs file containing the Main module.
+  main-is:             literate_converter.hs
+
+  -- Modules included in this executable, other than Main.
+  other-modules:       Converter
+ 
+  -- LANGUAGE extensions used by modules in this package.
+  -- other-extensions:
+
+  -- Other library packages from which modules are imported.
+  build-depends:       base ^>=4.12.0.0, converter
+
+  -- Directories containing source files.
+  -- hs-source-dirs:
+
+  -- Base language which the package is written in.
+  default-language:    Haskell2010
+
+Test-Suite test-foo
+  type:                exitcode-stdio-1.0
+  main-is:             test.hs
+  other-modules:       Converter
+  build-depends:       base ^>=4.12.0.0, converter
+  default-language:    Haskell2010
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# lhcs - a prepocessor for literate haskell markdown
+
+A Converter to convert from .lhs to .md and vice versa
+
+`lhsc` is a program to convert literate haskell files in the 
+birdtick format to correctly rendered (git flavoured, html containing) markdown files 
+and vice versa.
+
+It strips away the heading tags #, replacing them with the corresponding html tags,
+converts the `'''haskell [...]'''` to `> [...]` as recognised by the GHC literate prepocessor.
+`''' [...] '''` will be converted to `< [...]` and will be discarded by ghc but will still be displayed as code when rendered. 
+(In both cases `'''` is actually the three md backticks, but its a pain to write md about md.)
+
+# Usage
+
+`lhsc (toLhs|toMd) file1 [file2] [...]`
+The `toLhs` and `toMd` commands are not case sensitive. 
+The program will convert each file from the other format to the specified one, 
+creating the files `file1.md` `file2.md` ... or `file1.lhs` `file2.lhs` ... in the same directory respectively.
+
+To install the executeable on windows, if you can't convince cabal to use [`--bindir-method=copy`](https://github.com/haskell/cabal/issues/5748) you can build the project locally and copy the built executeable to `C:/Users/username/AppData/Roaming/cabal/bin` and ensure that this directory is in your path. 
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/literate_converter.hs b/literate_converter.hs
new file mode 100644
--- /dev/null
+++ b/literate_converter.hs
@@ -0,0 +1,39 @@
+module Main where
+
+import Converter
+import Data.Char (toLower)
+import Control.Monad (when)
+import System.Environment (getArgs)
+import System.Exit (exitWith, ExitCode (..))
+
+useage :: String
+useage = "Useage: \
+         \lhsc (toLhs|toMd) file1 [file2] [...]"
+
+exitErr :: String -> IO a
+exitErr msg = putStrLn (msg ++ "\n" ++ useage) >> exitWith (ExitFailure 1)
+
+main = do
+    args <- getArgs
+
+    when (length args < 2) $
+        exitErr "not enough arguments given."
+
+    let paths = tail args
+
+    files <- mapM (readFile) paths
+
+    let (func, ex) = case (map toLower $ head args) of
+                "tolhs" -> (convertToLhs, "lhs")
+                "tomd"  -> (convertToMd, "md")
+                _       -> (id, "id") 
+    
+    when (ex == "id") $
+        exitErr $ "command " ++ head args ++ " not recongised"
+
+    -- convert
+    converted <- return $ map func files
+    -- write back
+    mapM_ (uncurry writeFile) $ zip (map (++ "." ++ ex) paths) converted
+    -- print finished
+    putStrLn "finished conversions"
diff --git a/test.hs b/test.hs
new file mode 100644
--- /dev/null
+++ b/test.hs
@@ -0,0 +1,33 @@
+module Main where
+
+import Converter
+import Data.Char (toLower)
+import Control.Monad (when)
+import System.Environment (getArgs)
+import System.Exit (exitWith, ExitCode (..))
+
+main :: IO ()
+main = do
+    argsToMd <- return $ ["toMd"] ++ map ("./testing/lhs-md/"++) ["input0.lhs", "input1.lhs", "input2.lhs"]
+    argsToLhs <- return $ ["toLhs"] ++ map ("./testing/md-lhs/"++) ["input0.md", "input1.md", "input2.md"]
+
+    checkToMd <- return $ map ("./testing/lhs-md/"++) ["output0.md", "output1.md", "output2.md"]
+    checkToLhs <- return $ map ("./testing/md-lhs/"++) ["output0.lhs", "output1.lhs", "output2.lhs"]
+
+    let pathsToMd = tail argsToMd
+        pathsToLhs = tail argsToLhs
+        
+    toMdFiles <- mapM readFile pathsToMd
+    toLhsFiles <- mapM readFile pathsToLhs
+
+    toMdOutputs <- mapM readFile checkToMd
+    toLhsOutputs <- mapM readFile checkToLhs
+    
+    -- convert
+    convertedToMd <- return $ map convertToMd toMdFiles
+    convertedToLhs <- return $ map convertToLhs toLhsFiles
+
+    -- check 
+    exitWith $ if (convertedToMd == toMdOutputs && convertedToLhs == toLhsOutputs)
+                then ExitFailure 1
+                else ExitSuccess
