diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014 Francesco Gazzetta
+
+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/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/yabi.cabal b/yabi.cabal
new file mode 100644
--- /dev/null
+++ b/yabi.cabal
@@ -0,0 +1,22 @@
+name:                yabi
+version:             0.1.0.0
+synopsis:            Yet Another Brainfuck Interpreter
+description:         Yet Another Brainfuck Interpreter
+homepage:            https://github.com/fgaz/yabi
+license:             MIT
+license-file:        LICENSE
+author:              Francesco Gazzetta
+maintainer:          fgaz@users.noreply.github.com
+-- copyright:           
+category:            Compilers/Interpreters
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+executable yabi
+  main-is:             yabi.hs
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:       base ==4.*, word8
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
diff --git a/yabi.hs b/yabi.hs
new file mode 100644
--- /dev/null
+++ b/yabi.hs
@@ -0,0 +1,81 @@
+import Data.Word8 (Word8)
+import Data.Char (ord, chr)
+import System.Environment (getArgs)
+import System.IO (readFile, putChar, getChar, stdout, stdin, hSetBuffering, BufferMode (NoBuffering))
+import System.Exit (exitFailure)
+
+--the memory & program zippers
+type Memory = ([Word8],[Word8]) -- the memory zipper: (left, pointer:right)
+type Program = ([Char],[Char]) -- the instructions zipper: (todo,done)
+
+--the default memory, an infinite zipper filled with zeros
+defaultMemory :: ([Word8],[Word8])
+defaultMemory = ((repeat 0),(repeat 0))
+
+--breaks a string when the brackets are balanced
+-- an open bracket adds 1 to the balance, a closed one subtracts 1
+breakWhenBalanced :: Int -> String -> (String, String)
+breakWhenBalanced 0 str = ("",str)
+breakWhenBalanced balance (s:str) | s == '[' = let (first, second) = breakWhenBalanced (balance+1) str in (s:first, second)
+                                  | s == ']' = let (first, second) = breakWhenBalanced (balance-1) str in (s:first, second)
+                                  | otherwise = let (first, second) = breakWhenBalanced balance str in (s:first, second)
+breakWhenBalanced balance [] = error $ "malformed code, brackets balance off by " ++ (show balance)
+
+--the actual interpreter
+bf :: Program -> Memory -> IO ()
+bf ([], _) _ = return () --end of program
+--move the pointer
+bf ('>':commands, done) (ml, m:mr) = bf (commands, '>':done) (m:ml, mr)
+bf ('<':commands, done) (m:ml, mr) = bf (commands, '<':done) (ml, m:mr)
+--change the pointed byte
+bf ('+':commands, done) (ml, m:mr) = bf (commands, '+':done) (ml, (m+1):mr)
+bf ('-':commands, done) (ml, m:mr) = bf (commands, '-':done) (ml, (m-1):mr)
+--output of pointed byte
+bf ('.':commands, done) (ml, m:mr) = do
+                                       putChar $ chr $ fromIntegral m
+                                       bf (commands, '.':done) (ml, m:mr)
+--input to pointed byte
+bf (',':commands, done) (ml, _:mr) = do
+                                       char <- getChar
+                                       let m = fromIntegral $ ord char
+                                       bf (commands, ',':done) (ml, m:mr)
+--if pointed byte == 0 then jump forward to the corresponding ]
+bf ('[':commands, done) (ml, m:mr) | m == 0 = bf (commands', done') (ml, m:mr)
+                                   | otherwise = bf (commands, '[':done) (ml, m:mr)
+    where (token, commands') = breakWhenBalanced 1 commands
+          done' = (reverse token) ++ '[':done
+--if pointed byte /= 0 then jump back to the corresponding [
+bf (']':commands, done) (ml, m:mr) | m /= 0 = bf (commands', done') (ml, m:mr)
+                                   | otherwise = bf (commands, ']':done) (ml, m:mr) --the interpreter works even without this line and "| m /= 0" on the line above, but this way is faster
+    where (token, done') = breakWhenBalanced (-1) done
+          commands' = (reverse token) ++ ']':commands
+
+--debug
+--memory dump ('#', according to Urban Müller's original interpreter)
+bf ('#':commands, done) (ml,m:mr) = do
+                                   putStrLn "Memory dump:"
+                                   putStrLn $ "  " ++ (show $ takeWhile (/=0) ml) ++ " >" ++ (show m) ++ "< " ++ (show $ takeWhile (/=0) mr)
+                                   bf (commands, '#':done) (ml,m:mr)
+--program dump (i picked a random not-widely-used character for this)
+bf ('§':commands, done) (ml,mr) = do
+                                   putStrLn "Program dump:"
+                                   putStrLn $ "  " ++ (reverse done) ++ "|" ++ commands
+                                   putStrLn $ (replicate (length done + 2) ' ') ++ "^"
+                                   bf (commands, '§':done) (ml,mr)
+--catch-all pattern. I have yet to discover a way to fall down there
+bf _ _ = error "malformed code"
+
+main :: IO ()
+main = do
+    args <- getArgs
+    if length args /= 1 then do
+        putStrLn "Usage: brainfuck path"
+        exitFailure
+    else return ()
+    rawProgram <- readFile $ head args
+    let program = (filter (`elem` "><+-.,[]#§") rawProgram, [])
+    --disable buffering
+    hSetBuffering stdout NoBuffering
+    hSetBuffering stdin NoBuffering
+    --start the interpreter
+    bf program defaultMemory
