diff --git a/BootTidal.hs b/BootTidal.hs
new file mode 100644
--- /dev/null
+++ b/BootTidal.hs
@@ -0,0 +1,57 @@
+:set -XOverloadedStrings
+:set prompt ""
+:set prompt-cont ""
+
+import Sound.Tidal.Context
+
+-- total latency = oLatency + cFrameTimespan
+tidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = "127.0.0.1", oPort = 57120}) (defaultConfig {cFrameTimespan = 1/20})
+
+let p = streamReplace tidal
+let hush = streamHush tidal
+let list = streamList tidal
+let mute = streamMute tidal
+let unmute = streamUnmute tidal
+let solo = streamSolo tidal
+let unsolo = streamUnsolo tidal
+let once = streamOnce tidal
+let asap = once
+let nudgeAll = streamNudgeAll tidal
+let all = streamAll tidal
+let resetCycles = streamResetCycles tidal
+let setcps = asap . cps
+let xfade i = transition tidal True (Sound.Tidal.Transition.xfadeIn 4) i
+let xfadeIn i t = transition tidal True (Sound.Tidal.Transition.xfadeIn t) i
+let histpan i t = transition tidal True (Sound.Tidal.Transition.histpan t) i
+let wait i t = transition tidal True (Sound.Tidal.Transition.wait t) i
+let waitT i f t = transition tidal True (Sound.Tidal.Transition.waitT f t) i
+let jump i = transition tidal True (Sound.Tidal.Transition.jump) i
+let jumpIn i t = transition tidal True (Sound.Tidal.Transition.jumpIn t) i
+let jumpIn' i t = transition tidal True (Sound.Tidal.Transition.jumpIn' t) i
+let jumpMod i t = transition tidal True (Sound.Tidal.Transition.jumpMod t) i
+let mortal i lifespan release = transition tidal True (Sound.Tidal.Transition.mortal lifespan release) i
+let interpolate i = transition tidal True (Sound.Tidal.Transition.interpolate) i
+let interpolateIn i t = transition tidal True (Sound.Tidal.Transition.interpolateIn t) i
+let clutch i = transition tidal True (Sound.Tidal.Transition.clutch) i
+let clutchIn i t = transition tidal True (Sound.Tidal.Transition.clutchIn t) i
+let anticipate i = transition tidal True (Sound.Tidal.Transition.anticipate) i
+let anticipateIn i t = transition tidal True (Sound.Tidal.Transition.anticipateIn t) i
+let forId i t = transition tidal False (Sound.Tidal.Transition.mortalOverlay t) i
+let d1 = p 1
+let d2 = p 2
+let d3 = p 3
+let d4 = p 4
+let d5 = p 5
+let d6 = p 6
+let d7 = p 7
+let d8 = p 8
+let d9 = p 9
+let d10 = p 10
+let d11 = p 11
+let d12 = p 12
+let d13 = p 13
+let d14 = p 14
+let d15 = p 15
+let d16 = p 16
+
+:set prompt "tidal> "
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,24 @@
 # TidalCycles log of changes
 
+## 1.0.11 - as yet unnamed
+
+2019-04-17  Alex McLean  <alex@slab.org>
+	* Add `bite` function for slicing patterns (rather than samples)
+	* Tweak tidal.el to attempt to infer location of default BootTidal.hs
+	* Skip time (forward or backward) if the reference clock jumps suddenly
+	* Fix `fit` - @bgold-cosmos
+	* Remove 'asap'
+	* Add cB for boolean control input
+	* `pickF` for choosing between functions with a pattern of integers
+	* `select` for choosing between list of patterns with a floating point pattern
+	* `squeeze` for choosing between list of patterns with a pattern of integers, where patterns are squeezed into the integer event duration
+	* `splice` for choosing between slices of a pattern, where the slices are squeezed into event duration
+	* Ord and Eq instances for value type @bgold-cosmos
+	* `trigger` - support for resetting envelopes on evaluation
+	* Support for rational event values
+	* Tweak how `*>` and `<*` deal with analog patterns
+	* Caribiner link bridge support
+
 ## 1.0.10 - This machine also kills fascists
 * Add exports to Sound.Tidal.Scales for `getScale` and `scaleTable`
 
diff --git a/src/Sound/Tidal/Carabiner.hs b/src/Sound/Tidal/Carabiner.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Tidal/Carabiner.hs
@@ -0,0 +1,66 @@
+module Sound.Tidal.Carabiner where
+
+import Network.Socket hiding (send, sendTo, recv, recvFrom)
+import Network.Socket.ByteString (send, recv)
+import qualified Data.ByteString.Char8 as B8
+import Control.Concurrent (forkIO, threadDelay, takeMVar, putMVar)
+import qualified Sound.Tidal.Stream as S
+import Sound.Tidal.Tempo
+import System.Clock
+import Text.Read (readMaybe)
+import Control.Monad (when, forever)
+import Data.Maybe (isJust, fromJust)
+import qualified Sound.OSC.FD as O
+
+port = 17000
+
+carabiner :: S.Stream -> Int -> Double -> IO Socket
+carabiner tidal bpc latency = do sock <- client tidal bpc latency "127.0.0.1" 17000
+                                 sendMsg sock "status\n"
+                                 return sock
+
+client :: S.Stream -> Int -> Double -> String -> Int -> IO Socket
+client tidal bpc latency host port = withSocketsDo $
+                       do addrInfo <- getAddrInfo Nothing (Just host) (Just $ show port)
+                          let serverAddr = head addrInfo
+                          sock <- socket (addrFamily serverAddr) Stream defaultProtocol
+                          connect sock (addrAddress serverAddr)
+                          _ <- forkIO $ listener tidal bpc latency sock
+                          -- sendMsg sock "status\n"
+                          -- threadDelay 10000000
+                          return sock
+
+listener :: S.Stream -> Int -> Double -> Socket -> IO ()
+listener tidal bpc latency sock =
+  forever $ do rMsg <- recv sock 1024
+               let msg = B8.unpack rMsg
+                   (name:_:ws) = words msg
+                   pairs = pairs' ws
+                   pairs' (a:b:xs) = (a,b):(pairs' xs)
+                   pairs' _ = []
+               act tidal bpc latency name pairs
+
+act :: S.Stream -> Int -> Double -> String -> [(String, String)] -> IO ()
+act tidal bpc latency "status" pairs
+  = do let start = (lookup ":start" pairs >>= readMaybe) :: Maybe Integer
+           bpm   = (lookup ":bpm"   pairs >>= readMaybe) :: Maybe Double
+           beat  = (lookup ":beat"  pairs >>= readMaybe) :: Maybe Double
+       when (and [isJust start, isJust bpm, isJust beat]) $ do
+         nowM <- getTime Monotonic
+         nowO <- O.time
+         let m = (fromIntegral $ sec nowM) + ((fromIntegral $ nsec nowM)/1000000000)
+             d = nowO - m
+             start' = ((fromIntegral $ fromJust start) / 1000000)
+             startO = start' + d
+             cyc = toRational $ (fromJust beat) / (fromIntegral bpc)
+         tempo <- takeMVar (S.sTempoMV tidal)
+         let tempo' = tempo {atTime = startO + latency,
+                             atCycle = 0,
+                             cps = ((fromJust bpm) / 60) / (fromIntegral bpc)
+                            }
+         putMVar (S.sTempoMV tidal) $ tempo'
+act _ _ _ name _ = putStr $ "Unhandled thingie " ++ name
+
+sendMsg :: Socket -> String -> IO ()
+sendMsg sock msg = do send sock $ B8.pack msg
+                      return ()
diff --git a/src/Sound/Tidal/Context.hs b/src/Sound/Tidal/Context.hs
--- a/src/Sound/Tidal/Context.hs
+++ b/src/Sound/Tidal/Context.hs
@@ -4,6 +4,7 @@
 
 import Data.Ratio as C
 
+import Sound.Tidal.Carabiner as C
 import Sound.Tidal.Config as C
 import Sound.Tidal.Control as C
 import Sound.Tidal.Core as C
diff --git a/src/Sound/Tidal/Control.hs b/src/Sound/Tidal/Control.hs
--- a/src/Sound/Tidal/Control.hs
+++ b/src/Sound/Tidal/Control.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings, FlexibleContexts #-}
 
 module Sound.Tidal.Control where
 
@@ -367,10 +367,17 @@
 msec :: Fractional a => Pattern a -> Pattern a
 msec p = ((realToFrac . (/1000)) <$> cF 1 "_cps") *| p
 
+trigger :: Show a => a -> Pattern b -> Pattern b
+trigger k pat = pat {query = q}
+  where q st = query (rotR (offset st) pat) st
+        offset st = fromMaybe 0 $ Map.lookup ctrl (controls st) >>= getR
+        ctrl = "_t_" ++ show k
+
 cI :: String -> Pattern Int
 cI s = Pattern Analog $ \(State a m) -> maybe [] (f a) $ Map.lookup s m
   where f a (VI v) = [Event a a v]
         f a (VF v) = [Event a a (floor v)]
+        f a (VR v) = [Event a a (floor v)]
         f a (VS v) = maybe [] (\v' -> [Event a a v']) (readMaybe v)
 
 _cX :: (Arc -> Value -> [Event a]) -> [a] -> String -> Pattern a
@@ -380,6 +387,7 @@
 _cF :: [Double] -> String -> Pattern Double
 _cF = _cX f
   where f a (VI v) = [Event a a (fromIntegral v)]
+        f a (VR v) = [Event a a (fromRational v)]
         f a (VF v) = [Event a a v]
         f a (VS v) = maybe [] (\v' -> [Event a a v']) (readMaybe v)
 
@@ -390,6 +398,15 @@
 cF_ :: String -> Pattern Double
 cF_ = _cF []
 
+cB :: Bool -> String -> Pattern Bool
+cB b = _cB [b]
+_cB :: [Bool] -> String -> Pattern Bool
+_cB = _cX f
+  where f a (VI v) = [Event a a (v /= 0)]
+        f a (VF v) = [Event a a (v >= 0.5)]
+        f a (VR v) = [Event a a (v >= (1%2))]
+        f a (VS v) = maybe [] (\v' -> [Event a a (v' == "t")]) (readMaybe v)
+
 cT :: Time -> String -> Pattern Time
 cT d = (toRational <$>) . cF (fromRational d)
 cT0 :: String -> Pattern Time
@@ -409,6 +426,7 @@
 _cS = _cX f
   where f a (VI v) = [Event a a (show v)]
         f a (VF v) = [Event a a (show v)]
+        f a (VR v) = [Event a a (show v)]
         f a (VS v) = [Event a a v]
 cS :: String -> String -> Pattern String
 cS d = _cS [d]
@@ -419,7 +437,9 @@
 _cP ds s = innerJoin $ _cX f ds s
   where f a (VI v) = [Event a a (parseBP_E $ show v)]
         f a (VF v) = [Event a a (parseBP_E $ show v)]
+        f a (VR v) = [Event a a (parseBP_E $ show v)]
         f a (VS v) = [Event a a (parseBP_E v)]
+
 cP :: (Enumerable a, Parseable a) => Pattern a -> String -> Pattern a
 cP d = _cP [d]
 cP_ :: (Enumerable a, Parseable a) => String -> Pattern a
@@ -682,3 +702,9 @@
 in126 = cF 0 "126"
 in127 :: Pattern Double
 in127 = cF 0 "127"
+
+splice :: Int -> Pattern Int -> ControlPattern -> Pattern (Map.Map String Value)
+splice bits ipat pat = withEvent f (slice (pure bits) ipat pat) # P.unit "c"
+  where f ev = ev {value = Map.insert "speed" (VF d) (value ev)}
+          where d = sz / (fromRational $ (wholeStop ev) - (wholeStart ev))
+                sz = 1/(fromIntegral bits)
diff --git a/src/Sound/Tidal/Params.hs b/src/Sound/Tidal/Params.hs
--- a/src/Sound/Tidal/Params.hs
+++ b/src/Sound/Tidal/Params.hs
@@ -58,6 +58,11 @@
 accelerate :: Pattern Double -> ControlPattern
 accelerate       = pF "accelerate"
 
+
+-- | Amplitude; like @gain@, but linear.
+amp :: Pattern Double -> ControlPattern
+amp = pF "amp"
+
 -- | a pattern of numbers to specify the attack time (in seconds) of an envelope applied to each sample. Only takes effect if `release` is also specified.
 attack :: Pattern Double -> ControlPattern
 attack = pF "attack"
@@ -160,9 +165,13 @@
 -}
 end :: Pattern Double -> ControlPattern
 end = pF "end"
--- | a pattern of numbers that specify volume. Values less than 1 make the sound quieter. Values greater than 1 make the sound louder.
+
+-- | a pattern of numbers that specify volume. Values less than 1 make
+-- the sound quieter. Values greater than 1 make the sound louder. For
+-- the linear equivalent, see @amp@.
 gain :: Pattern Double -> ControlPattern
 gain = pF "gain"
+
 gate :: Pattern Double -> ControlPattern
 gate = pF "gate"
 hatgrain :: Pattern Double -> ControlPattern
diff --git a/src/Sound/Tidal/Pattern.hs b/src/Sound/Tidal/Pattern.hs
--- a/src/Sound/Tidal/Pattern.hs
+++ b/src/Sound/Tidal/Pattern.hs
@@ -88,6 +88,10 @@
 timeToCycleArc :: Time -> Arc
 timeToCycleArc t = Arc (sam t) (sam t + 1)
 
+-- | Shifts an arc to the equivalent one that starts during cycle zero
+cycleArc :: Arc -> Arc
+cycleArc (Arc s e) = Arc (cyclePos s) (cyclePos s + (e-s))
+
 -- | A list of cycle numbers which are included in the given arc
 cyclesInArc :: Integral a => Arc -> [a]
 cyclesInArc (Arc s e)
@@ -219,9 +223,43 @@
 
 data Value = VS { svalue :: String }
            | VF { fvalue :: Double }
+           | VR { rvalue :: Rational }
            | VI { ivalue :: Int }
-           deriving (Eq,Ord,Typeable,Data)
+           deriving (Typeable,Data)
 
+instance Eq Value where
+  (VS x) == (VS y) = x == y
+  (VF x) == (VF y) = x == y
+  (VI x) == (VI y) = x == y
+  (VR x) == (VR y) = x == y
+  
+  (VF x) == (VI y) = x == (fromIntegral y)
+  (VI y) == (VF x) = x == (fromIntegral y)
+
+  (VF x) == (VR y) = (toRational x) == y
+  (VR y) == (VF x) = (toRational x) == y
+  (VI x) == (VR y) = (toRational x) == y
+  (VR y) == (VI x) = (toRational x) == y
+
+  (VS _) == _ = False
+  _ == (VS _) = False
+  
+instance Ord Value where
+  compare (VS x) (VS y) = compare x y
+  compare (VF x) (VF y) = compare x y
+  compare (VI x) (VI y) = compare x y
+  compare (VR x) (VR y) = compare x y
+  compare (VS _) _ = LT
+  compare _ (VS _) = GT
+  compare (VF x) (VI y) = compare x (fromIntegral y)
+  compare (VI x) (VF y) = compare (fromIntegral x) y
+
+  compare (VR x) (VI y) = compare x (fromIntegral y)
+  compare (VI x) (VR y) = compare (fromIntegral x) y
+
+  compare (VF x) (VR y) = compare x (fromRational y)
+  compare (VR x) (VF y) = compare (fromRational x) y
+
 type ControlMap = Map.Map String Value
 type ControlPattern = Pattern ControlMap
 
@@ -274,41 +312,42 @@
 
 -- | Like <*>, but the structure only comes from the left
 (<*) :: Pattern (a -> b) -> Pattern a -> Pattern b
-(<*) pf@(Pattern Digital _) px = Pattern Digital q
+(<*) pf@(Pattern Analog _) px@(Pattern Analog _) = Pattern Analog q
   where q st = concatMap match $ query pf st
-         where
+          where
             match (Event fWhole fPart f) =
               map
               (Event fWhole fPart . f . value) $
-              query px $ st {arc = xQuery fWhole}
-            xQuery (Arc s _) = pure s -- for discrete events, match with the onset
+              query px st -- for continuous events, use the original query
 
-(<*) pf px = Pattern Analog q
+-- If one of the patterns is digital, treat both as digital.. (TODO - needs extra thought)
+(<*) pf px = Pattern Digital q
   where q st = concatMap match $ query pf st
-          where
+         where
             match (Event fWhole fPart f) =
               map
               (Event fWhole fPart . f . value) $
-              query px st -- for continuous events, use the original query
+              query px $ st {arc = xQuery fWhole}
+            xQuery (Arc s _) = pure s -- for discrete events, match with the onset
 
 -- | Like <*>, but the structure only comes from the right
 (*>) :: Pattern (a -> b) -> Pattern a -> Pattern b
-(*>) pf px@(Pattern Digital _) = Pattern Digital q
+(*>) pf@(Pattern Analog _) px@(Pattern Analog _) = Pattern Analog q
   where q st = concatMap match $ query px st
-         where
+          where
             match (Event xWhole xPart x) =
               map
               (\e -> Event xWhole xPart (value e x)) $
-              query pf $ fQuery xWhole
-            fQuery (Arc s _) = st {arc = pure s} -- for discrete events, match with the onset
+              query pf st -- for continuous events, use the original query
 
-(*>) pf px = Pattern Analog q
+(*>) pf px = Pattern Digital q
   where q st = concatMap match $ query px st
-          where
+         where
             match (Event xWhole xPart x) =
               map
               (\e -> Event xWhole xPart (value e x)) $
-              query pf st -- for continuous events, use the original query
+              query pf $ fQuery xWhole
+            fQuery (Arc s _) = st {arc = pure s} -- for discrete events, match with the onset
 
 infixl 4 <*, *>
 
@@ -380,7 +419,6 @@
           do w' <- subArc oWhole iWhole
              p' <- subArc oPart iPart
              return (Event w' p' v)
-        cycleArc (Arc s e) = Arc (cyclePos s) (cyclePos s + (e-s))
 
 noOv :: String -> a
 noOv meth = error $ meth ++ ": not supported for patterns"
@@ -391,6 +429,7 @@
 instance TolerantEq Value where
          (VS a) ~== (VS b) = a == b
          (VI a) ~== (VI b) = a == b
+         (VR a) ~== (VR b) = a == b
          (VF a) ~== (VF b) = abs (a - b) < 0.000001
          _ ~== _ = False
 
@@ -508,6 +547,7 @@
   show (VS s) = ('"':s) ++ "\""
   show (VI i) = show i
   show (VF f) = show f ++ "f"
+  show (VR r) = show r ++ "r"
 
 instance {-# OVERLAPPING #-} Show ControlMap where
   show m = intercalate ", " $ map (\(name, v) -> name ++ ": " ++ show v) $ Map.toList m
@@ -626,9 +666,10 @@
 applyFIS f _ _ (VF f') = VF $ f f'
 applyFIS _ f _ (VI i ) = VI $ f i
 applyFIS _ _ f (VS s ) = VS $ f s
+applyFIS _ _ _ v = v
 
 -- | Apply one of two functions to a Value, depending on its type (int
--- or float; strings are ignored)
+-- or float; strings and rationals are ignored)
 fNum2 :: (Int -> Int -> Int) -> (Double -> Double -> Double) -> Value -> Value -> Value
 fNum2 fInt _      (VI a) (VI b) = VI $ fInt a b
 fNum2 _    fFloat (VF a) (VF b) = VF $ fFloat a b
@@ -647,6 +688,10 @@
 getS :: Value -> Maybe String
 getS (VS s) = Just s
 getS _  = Nothing
+
+getR :: Value -> Maybe Rational
+getR (VR r) = Just r
+getR _  = Nothing
 
 compressArc :: Arc -> Pattern a -> Pattern a
 compressArc (Arc s e) p | s > e = empty
diff --git a/src/Sound/Tidal/Stream.hs b/src/Sound/Tidal/Stream.hs
--- a/src/Sound/Tidal/Stream.hs
+++ b/src/Sound/Tidal/Stream.hs
@@ -14,6 +14,7 @@
 -- import qualified Data.Bifunctor as BF
 -- import qualified Data.Bool as B
 -- import qualified Data.Char as C
+import           System.IO (hPutStrLn, stderr)
 
 import qualified Sound.OSC.FD as O
 
@@ -232,16 +233,24 @@
 streamReplace :: Show a => Stream -> a -> ControlPattern -> IO ()
 streamReplace s k pat
   = E.catch (do let x = queryArc pat (Arc 0 0)
+                tempo <- readMVar $ sTempoMV s
+                input <- takeMVar $ sInput s
+                -- put change time in control input
+                now <- O.time
+                let cycle = T.timeToCycles tempo now
+                putMVar (sInput s) $
+                  Map.insert ("_t_all") (VR cycle) $ Map.insert ("_t_" ++ show k) (VR cycle) input
+                -- update the pattern itself
                 pMap <- seq x $ takeMVar $ sPMapMV s
                 let playState = updatePS $ Map.lookup (show k) pMap
                 putMVar (sPMapMV s) $ Map.insert (show k) playState pMap
                 calcOutput s
                 return ()
           )
-    (\(e :: E.SomeException) -> putStrLn $ "Error in pattern: " ++ show e
+    (\(e :: E.SomeException) -> hPutStrLn stderr $ "Error in pattern: " ++ show e
     )
   where updatePS (Just playState) = do playState {pattern = pat, history = pat:(history playState)}
-        updatePS Nothing = PlayState pat False False []
+        updatePS Nothing = PlayState pat False False [pat]
 
 streamMute :: Show a => Stream -> a -> IO ()
 streamMute s k = withPatId s (show k) (\x -> x {mute = True})
@@ -258,14 +267,12 @@
 streamUnsolo :: Show a => Stream -> a -> IO ()
 streamUnsolo s k = withPatId s (show k) (\x -> x {solo = False})
 
-streamOnce :: Stream -> Bool -> ControlPattern -> IO ()
-streamOnce st asap p
+streamOnce :: Stream -> ControlPattern -> IO ()
+streamOnce st p
   = do cMap <- readMVar (sInput st)
        tempo <- readMVar (sTempoMV st)
        now <- O.time
-       let latency target | asap = 0
-                          | otherwise = oLatency target
-           fakeTempo = T.Tempo {T.cps = T.cps tempo,
+       let fakeTempo = T.Tempo {T.cps = T.cps tempo,
                                 T.atCycle = 0,
                                 T.atTime = now,
                                 T.paused = False,
@@ -280,7 +287,7 @@
            on e = sched tempo $ start $ whole e
            cpsChanges = map (\e -> (on e - now, Map.lookup "cps" $ value e)) es
            messages target =
-             catMaybes $ map (\e -> do m <- toMessage (at e + (latency target)) target fakeTempo e
+             catMaybes $ map (\e -> do m <- toMessage (at e + (oLatency target)) target fakeTempo e
                                        return $ (at e, m)
                              ) es
        mapM_ (\(Cx target udp) ->
@@ -310,7 +317,7 @@
 
 streamHush :: Stream -> IO ()
 streamHush s = do modifyMVar_ (sOutput s) $ return . const silence
-                  modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {pattern = silence})
+                  modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {pattern = silence, history = silence:history x})
 
 streamUnmuteAll :: Stream -> IO ()
 streamUnmuteAll s = do modifyMVar_ (sPMapMV s) $ return . fmap (\x -> x {mute = False})
diff --git a/src/Sound/Tidal/Tempo.hs b/src/Sound/Tidal/Tempo.hs
--- a/src/Sound/Tidal/Tempo.hs
+++ b/src/Sound/Tidal/Tempo.hs
@@ -98,19 +98,24 @@
              tempo <- readMVar tempoMV               
              t <- O.time
              let frameTimespan = cFrameTimespan config
-                 delta = logicalNow - t
-                 -- 'now' comes from clock ticks, nothing to do with cycles
                  logicalT ticks' = start st + fromIntegral ticks' * frameTimespan
                  logicalNow = logicalT $ ticks st + 1
-                 -- the tempo is just used to convert logical time to cycles
+                 -- Wait maximum of two frames
+                 delta = min (frameTimespan * 2) (logicalNow - t)
                  e = timeToCycles tempo logicalNow
                  s = if starting st && synched tempo
                      then timeToCycles tempo (logicalT $ ticks st)
                      else P.stop $ nowArc st
-                 st' = st {ticks = ticks st + 1, nowArc = P.Arc s e,
+             when (t < logicalNow) $ threadDelay (floor $ delta * 1000000)
+             t' <- O.time
+             let actualTick = floor $ (t' - start st) / frameTimespan
+                 -- reset ticks if ahead/behind by 4 or more
+                 newTick | (abs $ actualTick - ticks st) > 4 = actualTick
+                         | otherwise = (ticks st) + 1
+                 st' = st {ticks = newTick,
+                           nowArc = P.Arc s e,
                            starting = not (synched tempo)
                           }
-             when (t < logicalNow) $ threadDelay (floor $ delta * 1000000)
              callback tempoMV st'
              loop tempoMV st'
 
diff --git a/src/Sound/Tidal/Transition.hs b/src/Sound/Tidal/Transition.hs
--- a/src/Sound/Tidal/Transition.hs
+++ b/src/Sound/Tidal/Transition.hs
@@ -20,27 +20,36 @@
 import Sound.Tidal.Utils (enumerate)
 
 -- Evaluation of pat is forced so exceptions are picked up here, before replacing the existing pattern.
-transition :: Show a => Stream -> (Time -> [ControlPattern] -> ControlPattern) -> a -> ControlPattern -> IO ()
-transition stream f patId !pat = do pMap <- takeMVar (sPMapMV stream)
-                                    let playState = updatePS $ Map.lookup (show patId) pMap
-                                    pat' <- transition' $ history playState
-                                    let pMap' =
-                                          Map.insert (show patId) (playState {pattern = pat'}) pMap
-                                    putMVar (sPMapMV stream) pMap'
-                                    calcOutput stream
-                                    return ()
+-- the "historyFlag" determines if the new pattern should be placed on the history stack or not
+transition :: Show a => Stream -> Bool -> (Time -> [ControlPattern] -> ControlPattern) -> a -> ControlPattern -> IO ()
+transition stream historyFlag f patId !pat =
+  do pMap <- takeMVar (sPMapMV stream)
+     let playState = updatePS $ Map.lookup (show patId) pMap
+     pat' <- transition' $ appendPat (not historyFlag) (history playState)
+     let pMap' = Map.insert (show patId) (playState {pattern = pat'}) pMap
+     putMVar (sPMapMV stream) pMap'
+     calcOutput stream
+     return ()
   where
-    updatePS (Just playState) = playState {history = pat:(history playState)}
+    appendPat flag = if flag then (pat:) else id
+    updatePS (Just playState) = playState {history = (appendPat historyFlag) (history playState)}
     updatePS Nothing = PlayState {pattern = silence,
                                   mute = False,
                                   solo = False,
-                                  history = pat:silence:[]
+                                  history = (appendPat historyFlag) (silence:[])
                                  }
     transition' context = do tempo <- readMVar $ sTempoMV stream
                              now <- O.time
                              let c = timeToCycles tempo now
                              return $ f c context
 
+mortalOverlay :: Time -> Time -> [Pattern a] -> Pattern a
+mortalOverlay _ _ [] = silence
+mortalOverlay t now (pat:ps) = overlay (pop ps) (playFor s (s+t) pat) where
+  pop [] = silence
+  pop (x:xs) = x
+  s = sam (now - fromIntegral (floor now `mod` floor t)) + sam t
+
 {-| Washes away the current pattern after a certain delay by applying a
     function to it over time, then switching over to the next pattern to
     which another function is applied.
@@ -114,7 +123,7 @@
 
 -- | Sharp `jump` transition at next cycle boundary where cycle mod n == 0
 jumpMod :: Int -> Time -> [ControlPattern] -> ControlPattern
-jumpMod n now = jumpIn ((n-1) - ((floor now) `mod` n)) now
+jumpMod n now = jumpIn' ((n-1) - ((floor now) `mod` n)) now
 
 -- | Degrade the new pattern over time until it ends in silence
 mortal :: Time -> Time -> Time -> [ControlPattern] -> ControlPattern
diff --git a/src/Sound/Tidal/UI.hs b/src/Sound/Tidal/UI.hs
--- a/src/Sound/Tidal/UI.hs
+++ b/src/Sound/Tidal/UI.hs
@@ -161,7 +161,7 @@
 {- | Like @choose@, but works on an a list of tuples of values and weights
 
 @
-sound "superpiano(3,8)" # note (choose [("a",1), ("e",0.5), ("g",2), ("c",1)])
+sound "superpiano(3,8)" # note (wchoose [("a",1), ("e",0.5), ("g",2), ("c",1)])
 @
 
 In the above example, the "a" and "c" notes are twice as likely to
@@ -1101,7 +1101,7 @@
 stretch :: Pattern a -> Pattern a
 -- TODO - should that be whole or part?
 stretch p = splitQueries $ p {query = q}
-  where q st = query (zoomArc (enclosingArc $ map whole $ query p (st {arc = Arc (sam s) (nextSam s)})) p) st
+  where q st = query (zoomArc (cycleArc $ enclosingArc $ map whole $ query p (st {arc = Arc (sam s) (nextSam s)})) p) st
           where s = start $ arc st
 
 {- | `fit'` is a generalization of `fit`, where the list is instead constructed by using another integer pattern to slice up a given pattern.  The first argument is the number of cycles of that latter pattern to use when slicing.  It's easier to understand this with a few examples:
@@ -1388,7 +1388,6 @@
   where a = filterValues id stitch
         b = filterValues not stitch
 
-
 stutter :: Integral i => i -> Time -> Pattern a -> Pattern a
 stutter n t p = stack $ map (\i -> (t * fromIntegral i) `rotR` p) [0 .. (n-1)]
 
@@ -1599,13 +1598,12 @@
     maskedWeft = mask (every 2 rev $ _fast (n % 2) $ fastCat [silence, pure True]) weftP
     maskedWarp = mask (every 2 rev $ _fast (n % 2) $ fastCat [pure True, silence]) warpP
 
-_select :: Double -> [Pattern a] -> Pattern a
-_select f ps =  ps !! floor (max 0 (min 1 f) * fromIntegral (length ps - 1))
-
 -- | chooses between a list of patterns, using a pattern of floats (from 0-1)
 select :: Pattern Double -> [Pattern a] -> Pattern a
 select = tParam _select
 
+_select :: Double -> [Pattern a] -> Pattern a
+_select f ps =  ps !! floor (max 0 (min 1 f) * fromIntegral (length ps - 1))
 
 -- | chooses between a list of functions, using a pattern of floats (from 0-1)
 selectF :: Pattern Double -> [Pattern a -> Pattern a] -> Pattern a -> Pattern a
@@ -1614,6 +1612,13 @@
 _selectF :: Double -> [Pattern a -> Pattern a] -> Pattern a -> Pattern a
 _selectF f ps p =  (ps !! floor (max 0 (min 0.999999 f) * fromIntegral (length ps))) p
 
+-- | chooses between a list of functions, using a pattern of integers
+pickF :: Pattern Int -> [Pattern a -> Pattern a] -> Pattern a -> Pattern a
+pickF pi fs pat = innerJoin $ (\i -> _pickF i fs pat) <$> pi
+
+_pickF :: Int -> [Pattern a -> Pattern a] -> Pattern a -> Pattern a
+_pickF i fs p =  (fs !!! i) p
+
 -- | @contrast p f f' p'@ splits controlpattern @p'@ in two, applying
 -- the function @f@ to one and @f'@ to the other. This depends on
 -- whether events in it contains values matching with those in @p@.
@@ -1729,7 +1734,7 @@
 swap :: Eq a => [(a, b)] -> Pattern a -> Pattern b
 swap things p = filterJust $ (`lookup` things) <$> p
 
-{- @coat@ | 
+{- @soak@ | 
     applies a function to a pattern and cats the resulting pattern,
     then continues applying the function until the depth is reached
     this can be used to create a pattern that wanders away from 
@@ -1740,14 +1745,30 @@
 soak depth f pattern = cat $ take depth $ iterate f pattern
 
 deconstruct :: Int -> Pattern String -> String
-deconstruct n p = intercalate " " $ map showStep $ toList n p
+deconstruct n p = intercalate " " $ map showStep $ toList p
   where 
     showStep :: [String] -> String
     showStep [] = "~"
     showStep [x] = x
     showStep xs = "[" ++ (intercalate ", " xs) ++ "]"
-    toList :: Int -> Pattern a -> [[a]]
-    toList n pat = map (\(s,e) -> map value $ queryArc (_segment n' pat) (Arc s e)) arcs
+    toList :: Pattern a -> [[a]]
+    toList pat = map (\(s,e) -> map value $ queryArc (_segment n' pat) (Arc s e)) arcs
       where breaks = [0, (1/n') ..]
             arcs = zip (take n breaks) (drop 1 breaks)
             n' = fromIntegral n
+
+{- @bite@ n ipat pat |
+  slices a pattern `pat` into `n` pieces, then uses the `ipat` pattern of integers to index into those slices.
+  So `bite 4 "0 2*2" (run 8)` is the same as `"[0 1] [4 5]*2"`.
+-}
+
+bite :: Int -> Pattern Int -> Pattern a -> Pattern a
+bite n ipat pat = squeezeJoin $ zoompat <$> ipat
+  where zoompat i = zoom (i'/(fromIntegral n), (i'+1)/(fromIntegral n)) pat
+           where i' = fromIntegral $ i `mod` n
+
+{- @squeeze@ ipat pats | uses a pattern of integers to index into a list of patterns.
+-}
+squeeze :: Pattern Int -> [Pattern a] -> Pattern a
+squeeze _ [] = silence
+squeeze ipat pats = squeezeJoin $ (pats !!!) <$> ipat
diff --git a/src/Sound/Tidal/Version.hs b/src/Sound/Tidal/Version.hs
--- a/src/Sound/Tidal/Version.hs
+++ b/src/Sound/Tidal/Version.hs
@@ -1,4 +1,4 @@
 module Sound.Tidal.Version where
 
 tidal_version :: String
-tidal_version = "1.0.7"
+tidal_version = "1.0.11"
diff --git a/test/Sound/Tidal/UITest.hs b/test/Sound/Tidal/UITest.hs
--- a/test/Sound/Tidal/UITest.hs
+++ b/test/Sound/Tidal/UITest.hs
@@ -237,3 +237,8 @@
           (wedge (0) (s "ho ho:2 ho:3 hc") (rev $ s "ho ho:2 ho:3 hc"))
           (rev $ s "ho ho:2 ho:3 hc")
 
+    describe "bite" $ do
+      it "can slice a pattern into bits" $ do
+        compareP (Arc 0 4)
+          (bite 4 "0 2*2" (Sound.Tidal.Core.run 8))
+          ("[0 1] [4 5]*2" :: Pattern Int)
diff --git a/tidal.cabal b/tidal.cabal
--- a/tidal.cabal
+++ b/tidal.cabal
@@ -1,5 +1,5 @@
 name:                tidal
-version:             1.0.10
+version:             1.0.11
 synopsis:            Pattern language for improvised music
 -- description:
 homepage:            http://tidalcycles.org/
@@ -13,6 +13,7 @@
 build-type:          Simple
 cabal-version:       >=1.10
 tested-with:         GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.3
+data-files:          BootTidal.hs
 
 Extra-source-files: README.md CHANGELOG.md tidal.el
 
@@ -26,6 +27,7 @@
   default-language:    Haskell2010
 
   Exposed-modules:     Sound.Tidal.Bjorklund
+                       Sound.Tidal.Carabiner
                        Sound.Tidal.Chords
                        Sound.Tidal.Config
                        Sound.Tidal.Control
@@ -59,6 +61,8 @@
     , bifunctors < 5.6
     , transformers < 0.5.7
     , template-haskell >= 2.10.0.0 && < 2.15
+    , bytestring < 0.11
+    , clock < 0.8
 
   if !impl(ghc >= 8.4.1)
     build-depends: semigroups == 0.18.*
diff --git a/tidal.el b/tidal.el
--- a/tidal.el
+++ b/tidal.el
@@ -57,6 +57,14 @@
   ()
   "*Arguments to the haskell interpreter (default=none).")
 
+(defvar tidal-boot-script-path
+  (concat (substring
+           (shell-command-to-string
+            "ghc-pkg describe $(ghc-pkg latest tidal) | grep data-dir | cut -f2 -d' '") 0 -1)
+          "/BootTidal.hs")
+  "*Full path to BootTidal.hs (inferred by introspecting ghc-pkg package db)."
+  )
+
 (defvar tidal-literate-p
   t
   "*Flag to indicate if we are in literate mode (default=t).")
@@ -87,60 +95,7 @@
      nil
      tidal-interpreter-arguments)
     (tidal-see-output))
-  (tidal-send-string ":set prompt \"\"")
-  (if (string< tidal-interpreter-version "8.2.0")
-      (tidal-send-string ":set prompt2 \"\"")
-    (tidal-send-string ":set prompt-cont \"\""))
-  (tidal-send-string ":set -XOverloadedStrings
-import Sound.Tidal.Context
-tidal <- startMulti [superdirtTarget {oLatency = 0.1, oAddress = \"127.0.0.1\", oPort = 57120}] (defaultConfig {cFrameTimespan = 1/20, cCtrlListen = True})
-let p = streamReplace tidal
-let hush = streamHush tidal
-let list = streamList tidal
-let mute = streamMute tidal
-let unmute = streamUnmute tidal
-let solo = streamSolo tidal
-let unsolo = streamUnsolo tidal
-let once = streamOnce tidal False
-let asap = streamOnce tidal True
-let nudgeAll = streamNudgeAll tidal
-let all = streamAll tidal
-let resetCycles = streamResetCycles tidal
-let setcps = asap . cps
-let xfade i = transition tidal (Sound.Tidal.Transition.xfadeIn 4) i
-let xfadeIn i t = transition tidal (Sound.Tidal.Transition.xfadeIn t) i
-let histpan i t = transition tidal (Sound.Tidal.Transition.histpan t) i
-let wait i t = transition tidal (Sound.Tidal.Transition.wait t) i
-let waitT i f t = transition tidal (Sound.Tidal.Transition.waitT f t) i
-let jump i = transition tidal (Sound.Tidal.Transition.jump) i
-let jumpIn i t = transition tidal (Sound.Tidal.Transition.jumpIn t) i
-let jumpIn' i t = transition tidal (Sound.Tidal.Transition.jumpIn' t) i
-let jumpMod i t = transition tidal (Sound.Tidal.Transition.jumpMod t) i
-let mortal i lifespan release = transition tidal (Sound.Tidal.Transition.mortal lifespan release) i
-let interpolate i = transition tidal (Sound.Tidal.Transition.interpolate) i
-let interpolateIn i t = transition tidal (Sound.Tidal.Transition.interpolateIn t) i
-let clutch i = transition tidal (Sound.Tidal.Transition.clutch) i
-let clutchIn i t = transition tidal (Sound.Tidal.Transition.clutchIn t) i
-let anticipate i = transition tidal (Sound.Tidal.Transition.anticipate) i
-let anticipateIn i t = transition tidal (Sound.Tidal.Transition.anticipateIn t) i
-let d1 = p 1
-let d2 = p 2 . (|< orbit 1)
-let d3 = p 3 . (|< orbit 2)
-let d4 = p 4 . (|< orbit 3)
-let d5 = p 5 . (|< orbit 4)
-let d6 = p 6 . (|< orbit 5)
-let d7 = p 7 . (|< orbit 6)
-let d8 = p 8 . (|< orbit 7)
-let d9 = p 9 . (|< orbit 8)
-let d10 = p 10
-let d11 = p 11
-let d12 = p 12
-let d13 = p 13
-let d14 = p 14
-let d15 = p 15
-let d16 = p 16
-  ")
-  (tidal-send-string ":set prompt \"tidal> \"")
+  (tidal-send-string (concat ":script " tidal-boot-script-path))
 )
 
 (defun tidal-see-output ()
