diff --git a/Biobase/Infernal/CM.hs b/Biobase/Infernal/CM.hs
new file mode 100644
--- /dev/null
+++ b/Biobase/Infernal/CM.hs
@@ -0,0 +1,53 @@
+
+-- | Infernal CMs.
+
+module Biobase.Infernal.CM where
+
+import Data.Vector as V
+import Data.Vector.Unboxed as VU
+import Data.ByteString as BS
+
+import Data.PrimitiveArray
+import Data.PrimitiveArray.Ix
+
+
+
+-- | A datatype representing Infernal covariance models. This is a new
+-- representation that is incompatible with the one once found in "Biobase".
+-- The most important difference is that lookups are mapped onto efficient data
+-- structures, currently "PrimitiveArray".
+--
+-- [1] Each "State" of a covariance model has up to 6 transition scores, hence
+-- we need s*6 cells for transitions.
+--
+-- [2] Each "State" of a covariance has up to 16 emission scores, so we have
+-- s*16 cells for emissions, with unused cells set to a really high score.
+--
+-- On top of these basic structures, we then place additional high-level
+-- constructs.
+--
+-- [3] 'paths' are allowed transitions. This can safe a check, if the
+-- transition is encoded with a forbidden score.
+--
+-- [4] 'localBegin' and 'localEnd' are local entry and exit strategies. A
+-- 'localBegin' is a transition score to certain states, all such transitions
+-- are in 'begins'. A 'localEnd' is a transition score to a local end state.
+--
+-- TODO as with other projects, we should not use Double's but "Score" and
+-- "Probability" newtypes.
+
+data CM = CM
+  { name :: ByteString
+  , accession :: Int
+  , ga :: Double
+  , tc :: Double
+  , nc :: Double
+  , transition :: PrimArray (Int,Int) Double
+  , emission :: PrimArray (Int,Int) Double
+  , paths :: V.Vector (VU.Vector Double)
+  , localBegin :: VU.Vector Double
+  , begins :: VU.Vector Int
+  , localEnd :: VU.Vector (Double)
+  , nodes :: V.Vector (VU.Vector Int)
+  }
+  deriving (Show)
diff --git a/Biobase/Infernal/CM/Export.hs b/Biobase/Infernal/CM/Export.hs
new file mode 100644
--- /dev/null
+++ b/Biobase/Infernal/CM/Export.hs
@@ -0,0 +1,12 @@
+
+-- | Transforms the internal representation of a CM back into a version that
+-- can be used by Infernal.
+--
+-- Note that models are transformed into 'ByteString' as-is, the exporter does
+-- not make sure that probabilities add to one, that we write out probabilities
+-- instead of scores, and so on.
+--
+-- TODO some of the notes above will become less problematic once we use
+-- newtypes, as a probability-CM will not be accepted by the exporter by then.
+
+module Biobase.Infernal.CM.Export where
diff --git a/Biobase/Infernal/CM/Import.hs b/Biobase/Infernal/CM/Import.hs
new file mode 100644
--- /dev/null
+++ b/Biobase/Infernal/CM/Import.hs
@@ -0,0 +1,34 @@
+
+-- | Iteratee-based parsing of Infernal covariance models.
+
+module Biobase.Infernal.CM.Import where
+
+import Data.Iteratee as I
+import Data.Iteratee.Char as I
+import Data.Iteratee.IO as I
+import Data.Iteratee.Iteratee as I
+import Data.Iteratee.ListLike as I
+import Data.ByteString as BS
+
+import Biobase.Infernal.CM
+
+
+
+-- * iteratee stuff
+
+-- | 
+
+eneeCM :: (Monad m) => Enumeratee ByteString [CM] m a
+eneeCM = enumLinesBS ><> convStream f where
+  f = do
+    th <- tryHead
+    return undefined
+
+
+-- * convenience functions
+
+-- | Read covariance models from file. This parser reads one or more CMs from
+-- file.
+
+fromFile :: FilePath -> [CM]
+fromFile = undefined
diff --git a/Biobase/Infernal/VerboseHit.hs b/Biobase/Infernal/VerboseHit.hs
--- a/Biobase/Infernal/VerboseHit.hs
+++ b/Biobase/Infernal/VerboseHit.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE RecordWildCards #-}
+{-# OPTIONS_GHC -funbox-strict-fields #-}
 
 -- | Provides a datatype for cmsearch verbose output. The Import/Export system
 -- now allows for primitive annotations using "##" as the first two characters.
@@ -14,20 +15,20 @@
 -- | Captures a complete alignment
 
 data VerboseHit = VerboseHit
-  { vhTarget  :: (Int,Int)  -- ^ part of target sequence (start counting at 1)
-  , vhQuery   :: (Int,Int)  -- ^ which part of the CM/stk do we align to
-  , vhCM      :: ByteString  -- ^ the CM for this alignment
-  , vhStrand  :: Strand     -- ^ should be either '+' or '-'
-  , vhScore   :: Double     -- ^ bit score
-  , vhEvalue  :: Double     -- ^ number of hits we expect to find with 'score' or higher for 'targetSequence' length
-  , vhPvalue  :: Double     -- ^ ?
-  , vhGC      :: Int        -- ^ ?
-  , vhScaffold :: ByteString -- ^ scaffold, chromosome, ... (the name of the sequence, not the sequence data!)
-  , vhWuss :: ByteString -- ^ fancy secondary structure annotation using wuss notation
-  , vhConsensus :: ByteString -- ^ query consensus (upper: highly, lower: weak/no)
-  , vhScoring   :: ByteString -- ^ represents where positive and negative scores come from
-  , vhSequence :: ByteString -- ^ the target sequence which aligns to the model
-  , vhAnnotation :: [ByteString] -- ^ any annotations that could be associated (# lines)
+  { vhTarget      :: !(Int,Int)     -- ^ part of target sequence (start counting at 1)
+  , vhQuery       :: !(Int,Int)     -- ^ which part of the CM/stk do we align to
+  , vhCM          :: !ByteString    -- ^ the CM for this alignment
+  , vhStrand      :: !Strand        -- ^ should be either '+' or '-'
+  , vhScore       :: !Double        -- ^ bit score
+  , vhEvalue      :: !Double        -- ^ number of hits we expect to find with 'score' or higher for 'targetSequence' length
+  , vhPvalue      :: !Double        -- ^ ?
+  , vhGC          :: !Int           -- ^ ?
+  , vhScaffold    :: !ByteString    -- ^ scaffold, chromosome, ... (the name of the sequence, not the sequence data!)
+  , vhWuss        :: !ByteString    -- ^ fancy secondary structure annotation using wuss notation
+  , vhConsensus   :: !ByteString    -- ^ query consensus (upper: highly, lower: weak/no)
+  , vhScoring     :: !ByteString    -- ^ represents where positive and negative scores come from
+  , vhSequence    :: !ByteString    -- ^ the target sequence which aligns to the model
+  , vhAnnotation  :: ![ByteString]  -- ^ any annotations that could be associated (# lines)
   } deriving (Show,Read)
 
 type Strand = Char
diff --git a/Biobase/Infernal/VerboseHit/Export.hs b/Biobase/Infernal/VerboseHit/Export.hs
--- a/Biobase/Infernal/VerboseHit/Export.hs
+++ b/Biobase/Infernal/VerboseHit/Export.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -39,8 +40,9 @@
   f acc = do
     h <- I.head
     let na = newAcc acc h
+    p <- I.peek
     return ( fst na
-           , return . BS.unlines $ snd na ++ P.map (append "## ") (vhAnnotation h)  ++ [showVerboseHit h]
+           , return . BS.unlines $ snd na ++ P.map (append "##") (vhAnnotation h)  ++ [showVerboseHit h] ++ maybe ["//"] (const []) p
            )
 
 -- | Given the current state "a" and verbose hit "h", determine if any state
@@ -48,10 +50,13 @@
 
 newAcc a@(AliGo{..}) h@VerboseHit{..}
   | otherwise = ( AliGo vhCM vhScaffold vhStrand [], ls )
-  where ls = [ "//" | aliCM /= BS.empty && aliCM /= vhCM ] ++
-             [ "CM: " `BS.append` vhCM | aliCM /= vhCM ] ++
-             [ ">" `BS.append` vhScaffold `BS.append` "\n" | aliScaffold /= vhScaffold ] ++
-             [ str `BS.append` " strand results:\n" | aliStrand /= vhStrand ]
+  where ls = [ "//" | aliCM /= BS.empty && bCM ] ++
+             [ "CM: " `BS.append` vhCM | bCM ] ++
+             [ ">" `BS.append` vhScaffold `BS.append` "\n" | bCM || bSc] ++
+             [ str `BS.append` " strand results:\n" | bCM || bSc || bSt ]
+        bCM = aliCM /= vhCM
+        bSc = aliScaffold /= vhScaffold
+        bSt = aliStrand /= vhStrand
         str
           | vhStrand == '+' = "Plus"
           | vhStrand == '-' = "Minus"
@@ -83,14 +88,19 @@
 
 
 {-
-import Biobase.Infernal.VerboseHit.Import
+--import Biobase.Infernal.VerboseHit.Import
 
 test = do
   xs <- fromFile "/home/choener/tmp/infernal-1.0.2/tutorial/tmp.res"
   i <- enumList [xs] $ joinI $ eneeByteString stream2stream
   ys <- run i
+  {-
   BS.putStrLn ys
   print $ BS.length ys
   print $ P.length $ BS.lines ys
+  -}
+  BS.putStrLn $ BS.take 1000 ys
   return ()
 -}
+
+
diff --git a/Biobase/Infernal/VerboseHit/Import.hs b/Biobase/Infernal/VerboseHit/Import.hs
--- a/Biobase/Infernal/VerboseHit/Import.hs
+++ b/Biobase/Infernal/VerboseHit/Import.hs
@@ -41,12 +41,12 @@
     case h' of
       Nothing -> return (acc, [])
       (Just h)
-        | "##"      `isPrefixOf` h -> return (acc{aliAnnotation = aliAnnotation acc ++ [BS.drop 2 h]},[])
-        | "CM: "    `isInfixOf`  h -> return (acc{aliCM = BS.copy $ BS.drop 4 h, aliAnnotation = []}, [])
-        | ">"       `isInfixOf`  h -> return (acc{aliScaffold = BS.copy $ BS.drop 1 h, aliAnnotation = []}, [])
-        | "  Plus"  `isInfixOf`  h -> return (acc{aliStrand = '+', aliAnnotation = []}, [])
-        | "  Minus" `isInfixOf`  h -> return (acc{aliStrand = '-', aliAnnotation = []}, [])
-        | " Query"  `isInfixOf`  h -> do
+        | "##"   `isPrefixOf` h -> return (acc{aliAnnotation = aliAnnotation acc ++ [BS.drop 2 h]},[])
+        | "CM: " `isPrefixOf` h -> return (acc{aliCM = BS.copy $ BS.drop 4 h, aliAnnotation = []}, [])
+        | ">"    `isPrefixOf` h -> return (acc{aliScaffold = BS.copy $ BS.drop 1 h, aliAnnotation = []}, [])
+        | "Plus strand results"  `isInfixOf` h -> return (acc{aliStrand = '+', aliAnnotation = []}, [])
+        | "Minus strand results" `isInfixOf` h -> return (acc{aliStrand = '-', aliAnnotation = []}, [])
+        | " Query" `isInfixOf` h -> do
             x <- qs h (aliCM acc) (aliScaffold acc) (aliStrand acc) (aliAnnotation acc)
             return (acc{aliAnnotation = []},x)
         | otherwise -> return (acc,[])
@@ -130,9 +130,10 @@
 
 -- How to use this enumeratee.
 
+{-
 test = do
   i <- enumFile 8192 "test.vh" $ joinI $ eneeVerboseHit stream2list
   xs <- run i
   P.mapM_ (\x -> print x >> P.putStrLn "\n\n\n") xs
   print $ P.length xs
-
+-}
diff --git a/BiobaseInfernal.cabal b/BiobaseInfernal.cabal
--- a/BiobaseInfernal.cabal
+++ b/BiobaseInfernal.cabal
@@ -1,5 +1,5 @@
 name:           BiobaseInfernal
-version:        0.5.4.0
+version:        0.5.4.1
 author:         Christian Hoener zu Siederdissen
 maintainer:     choener@tbi.univie.ac.at
 homepage:       http://www.tbi.univie.ac.at/~choener/
@@ -22,13 +22,11 @@
                 .
                 .
                 .
-                With the BioHaskell library split, this package is officially
-                back! And the package is not feature-complete yet, take the
-                above as a will-include-soon list.
+                Changes in 0.5.4.1
                 .
-                The taxonomy importer makes use of Iteratee.zip, hence the
-                switch from Enumerator. (See the Biohaskell wiki pages for
-                discussion on Iteratee/Enumerator).
+                * fix-up for VH export
+                .
+                * half-baked CM type (not useful yet)
 
 extra-source-files:
 
@@ -42,12 +40,17 @@
     either-unwrap,
     iteratee,
     transformers,
-    tuple
+    tuple,
+    vector,
+    PrimitiveArray
 
   exposed-modules:
     Biobase.Infernal
     Biobase.Infernal.Clan
     Biobase.Infernal.Clan.Import
+    Biobase.Infernal.CM
+    Biobase.Infernal.CM.Export
+    Biobase.Infernal.CM.Import
     Biobase.Infernal.TabularHit
     Biobase.Infernal.TabularHit.Import
     Biobase.Infernal.Taxonomy
