diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,6 +1,15 @@
 # Change log for cut-the-crap
 
-## Version 2.1.2 - 2020.10.11
+## Version 2.2.0 - 2020.10.28
+
++ Add wrapper for shelly that always flushes stdout
+  This should make the log more consistent
++ Fix scrambling bug.
+  Previously we used the file system to organize fragment order,
+  now we use the silence detection list instead.
+  This is much more robust
+
+## Version 2.1.2 - 2020.10.25
 
 Fix bug where youtube-dl sometimes doesn't write .mkv files
 for certain websites, such as twitch (#52).
diff --git a/Readme.md b/Readme.md
--- a/Readme.md
+++ b/Readme.md
@@ -40,6 +40,21 @@
 result/bin/cut-the-crap
 ```
 
+## Bundle build (staticly linked bundled with runtime deps)
+
+From version 2.1.1 and onwards these nix bundles will be attached to releases on the [release page](https://github.com/jappeace/cut-the-crap/releases).
+These should work on any Linux distribution.
+The cost is that they are large files however (500mb+) because everything is bundled within.
+Including runtime dependencies such as ffmpeg and youtube-dl.
+
+Download the executable from the [release page](https://github.com/jappeace/cut-the-crap/releases).
+
+Releases of this kind trail the main release by a week because we rely on the
+hackage release being merged into nixpkgs.
+At the moment this appears to happen every Friday.
+This approach guarantees nix reproducibility without having to install nix.
+Under the hood we use [nix-bundle](https://github.com/matthewbauer/nix-bundle) for this.
+
 ## Nix/Nixos
 
 + Run `nix-env -iA nixos.haskellPackages.cut-the-crap` or add to systemPackages.
@@ -48,21 +63,6 @@
 This only works for nixpkgs that have cut-the-crap >= 1.4.2 or =< 1.3
 There were some build issues with 1.4.0 and 1.4.1 (now fixed)
 
-## Static build (other linux)
-
-Contact [me](mailto:jappieklooster@hotmail.com)
-if you want this, currently it appears to be broken.
-Or simply add an issue.
-
-Download the executable from the [release page](https://github.com/jappeace/cut-the-crap/releases).
-
-install ffmpeg and youtube-dl, for example:
-
-```
-apt install ffmpeg youtube-dl
-```
-
-Now you can run the executable.
 
 # Usage notes
 
diff --git a/cut-the-crap.cabal b/cut-the-crap.cabal
--- a/cut-the-crap.cabal
+++ b/cut-the-crap.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 43fd63206b4d6b7803776d985132db66faea7470b553bab6c11d67633c015bba
+-- hash: 874f6bde8ebc71a27602d7507482631c4fce2134727e7205c01e989a952cdcaf
 
 name:           cut-the-crap
-version:        2.1.2
+version:        2.2.0
 synopsis:       Cuts out uninteresting parts of videos by detecting silences.
 description:    Cut the crap is an automatic video editing program for streamers. It can cut out uninteresting parts by detecting silences. This was inspired by [jumpcutter](https://github.com/carykh/jumpcutter), where this program can get better quality results by using an (optional) dedicated microphone track. This prevents cutting of [quieter consonants](https://youtu.be/DQ8orIurGxw?t=675) for example. Using ffmpeg more efficiently also produces faster results and is less error prone.
 category:       video
diff --git a/src/Cut/Analyze.hs b/src/Cut/Analyze.hs
--- a/src/Cut/Analyze.hs
+++ b/src/Cut/Analyze.hs
@@ -25,7 +25,7 @@
 import qualified Data.Text               as Text
 import qualified Data.Text.IO            as Text
 import           Data.Text.Lens
-import           Shelly                  hiding (find)
+import           Shelly                  hiding (find, shelly)
 import           Text.Regex.TDFA         hiding (empty)
 
 data Silent
diff --git a/src/Cut/Crap.hs b/src/Cut/Crap.hs
--- a/src/Cut/Crap.hs
+++ b/src/Cut/Crap.hs
@@ -33,7 +33,7 @@
 import           Data.Time
 import           GHC.Generics                 hiding (to)
 import           Options.Applicative
-import           Shelly                       hiding (FilePath)
+import           Shelly                       hiding (FilePath, shelly)
 import           System.IO.Temp
 import Cut.Download
 
@@ -79,15 +79,8 @@
 runEdit :: ListenCutOptions -> [Interval Sound] -> FilePath -> IO ()
 runEdit options parsed tempDir = do
   extract options tempDir parsed
-  shelly $ combineDir options tempDir
+  shelly $ combineDir options tempDir parsed
   getMusic options tempDir
-
-combineDir :: ListenCutOptions -> FilePath -> Sh ()
-combineDir _ tempDir = do
-  res <- lsT $ fromText $ Text.pack (tempDir <> extractDir)
-  let paths = Text.unlines $ flip (<>) "'" . ("file '" <>) <$> res
-  writefile (fromText $ Text.pack $ tempDir <> "/input.txt") paths
-  combine tempDir
 
 readSettings :: IO (ProgramOptions InputSource)
 readSettings = customExecParser (prefs showHelpOnError) $ info
diff --git a/src/Cut/CutVideo.hs b/src/Cut/CutVideo.hs
--- a/src/Cut/CutVideo.hs
+++ b/src/Cut/CutVideo.hs
@@ -1,13 +1,15 @@
 {-# OPTIONS_GHC -Wno-type-defaults #-}
 
+-- | Extract sounded parts, and combine again
 module Cut.CutVideo
   ( extract
+  , extractDir
   , Interval(..)
   , Silent
   , Sound
   , combine
   , combineOutput
-  , extractDir
+  , combineDir
   )
 where
 
@@ -21,27 +23,31 @@
 import           Data.Text           (Text)
 import qualified Data.Text           as Text
 import           Data.Text.Lens
-import           Shelly              hiding (FilePath)
+import           Shelly              hiding (FilePath, shelly)
 import           Text.Printf         (printf)
 
+-- | convert a sounded interval into a filename where we write the temporary extracted file in
+toFileName :: ListenCutOptions -> FilePath -> Interval Sound -> FilePath
+toFileName options tmp inter = tmp
+         </> getOutFileName options
+         <> "-"
+         <> fname
+         <> ".mkv"
+  where
+      fname    = printf "%010d" (truncate $ interval_start inter * 100 :: Integer)
+
 toArgs :: ListenCutOptions -> FilePath -> Interval Sound -> (Interval Sound, [Text])
 toArgs options tmp inter =
   ( inter
   , -- keep ter interval for debugging
     ["-y", "-ss", start, "-t", duration, "-i", options ^. lc_fileio . in_file . packed]
     <> specifyTracks options
-    <> [ Text.pack tmp
-         <> "/"
-         <> Text.pack (getOutFileName options)
-         <> "-"
-         <> fname
-         <> ".mkv"
+    <> [ Text.pack $ toFileName options tmp inter
        ]
   )
  where
   start    = floatToText $ interval_start inter
   duration = floatToText $ interval_duration inter
-  fname    = Text.pack $ printf "%010d" (truncate $ interval_start inter * 100 :: Integer)
 
 extractDir :: FilePath
 extractDir = "/extract"
@@ -82,3 +88,12 @@
     , "copy"
     , Text.pack $ tempDir <> "/" <> combineOutput
     ]
+
+combineDir :: ListenCutOptions -> FilePath -> [Interval Sound] -> Sh ()
+combineDir options tempDir intervals = do
+  let paths = Text.unlines $ flip (<>) "'" . ("file '" <>) <$> res
+  writefile (fromText $ Text.pack $ tempDir <> "/input.txt") paths
+  combine tempDir
+  where
+    res = Text.pack . toFileName options exdir <$> intervals
+    exdir = tempDir <> extractDir
diff --git a/src/Cut/Download.hs b/src/Cut/Download.hs
--- a/src/Cut/Download.hs
+++ b/src/Cut/Download.hs
@@ -19,7 +19,7 @@
 import           Data.Word
 import           Network.URI            (URI)
 import           Options.Applicative
-import           Shelly                 hiding (FilePath)
+import           Shelly                 hiding (FilePath, shelly)
 import           System.Random
 
 -- | Downloads a URI to the filepath returned
diff --git a/src/Cut/Shell.hs b/src/Cut/Shell.hs
--- a/src/Cut/Shell.hs
+++ b/src/Cut/Shell.hs
@@ -7,16 +7,20 @@
   , ffmpeg'
   , floatToText
   , youtube_dl
+  , shelly
   )
 where
 
 import           Data.Text (Text)
 import qualified Data.Text as Text
 import           Numeric
-import           Shelly hiding (run, command)
+import           Shelly(Sh)
+import qualified Shelly as Sh
 import Network.URI(URI)
 import Text.Printf
 import Data.Time
+import System.IO(stdout, hFlush)
+import Control.Monad.IO.Class
 
 -- | Wrap ffmpeg for convenience and logging
 --  technically supports multiple inputs but for convenice we threw that.
@@ -30,6 +34,13 @@
 floatToText :: Double -> Text
 floatToText = Text.pack . flip (showFFloat (Just 10)) ""
 
+-- | Wrapper for shelley that always flushes stdout
+shelly :: MonadIO m => Sh a -> m a
+shelly x = do
+  res <- Sh.shelly x
+  liftIO $ hFlush stdout -- flush stdout per command run
+  pure res
+
 run :: FilePath -> [Text] -> Sh [Text]
 run command args = do
   time' <- liftIO getCurrentTime
@@ -37,9 +48,10 @@
   liftIO $ putStrLn "--- "
   liftIO $ printf "%s: %s %s" format command (Text.unwords args)
   liftIO $ putStrLn "   " -- flush
-  run_ command args
+  Sh.run_ command args
   liftIO $ putStrLn "--- "
-  Text.lines <$> lastStderr
+  result <- Text.lines <$> Sh.lastStderr
+  pure result
 
 youtube_dl :: URI -> FilePath -> Sh [Text]
 youtube_dl uri path' = run "youtube-dl" args
