diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for vehicle
+
+## 0.1.0.0 -- 10-27-2026
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 David Cox
+
+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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,25 @@
+# vehicle
+Standard Classification for Space Launch &amp; Reentry Vehicles
+
+[ASTM F3388-23](https://store.astm.org/f3388-23.html)
+
+Usage
+```
+vhcl --help
+vhcl w | vhcl r
+```
+
+Install
+
+```
+cabal install vehicle
+```
+
+Development
+
+```
+cabal build
+cabal haddock
+cabal test
+cabal run vhcl -- --help
+```
diff --git a/exe/Main.hs b/exe/Main.hs
new file mode 100644
--- /dev/null
+++ b/exe/Main.hs
@@ -0,0 +1,187 @@
+module Main (main) where
+
+import Data.Binary
+import Data.Binary.Get
+import Data.Binary.Put
+import qualified Data.ByteString.Lazy as BS
+import Data.Vehicle
+import Data.Version
+import Options.Applicative
+import Paths_vehicle
+
+main :: IO ()
+main = do
+  cli <- customExecParser prefs' $ pinfo $ showVersion version
+  case cli of
+    ReadVehicle fM ->
+      print . runGet (get :: Get Vehicle) =<< maybe BS.getContents BS.readFile fM
+    WriteVehicle v fM -> maybe BS.putStr BS.writeFile fM $ runPut $ put v
+
+prefs' :: ParserPrefs
+prefs' = prefs $ showHelpOnError <> showHelpOnEmpty
+
+pinfo :: String -> ParserInfo CLI
+pinfo v = info (parser <**> simpleVersioner v <**> helper) $
+  progDesc "Space Launch & Reentry Vehicles"
+
+data CLI = ReadVehicle (Maybe FilePath) | WriteVehicle Vehicle (Maybe FilePath)
+
+parser :: Parser CLI
+parser = hsubparser $ mconcat
+  [command "r" $ info (fmap ReadVehicle $
+    optional $ fileArg "Optional binary input file otherwise stream STDIN") $
+    progDesc "Read vehicle data"
+  , command "w" $ info (WriteVehicle <$> parseVehicle <*>
+    optional (fileArg "Optional binary output file otherwise stream STDOUT")) $
+    progDesc "Write vehicle data"]
+
+fileArg :: String -> Parser FilePath
+fileArg h = strArgument $ metavar "FILE" <> completer (bashCompleter "file") <> help h
+
+parseVehicle :: Parser Vehicle
+parseVehicle = Vehicle <$> parseReg <*> parseMissnTy <*> parseCat <*> many parseClass
+  <*> parseMode <*> many parseCap <*> many parseSiz <*> many parseProp
+  <*> many parsePayld <*> many parseMissn
+
+parseReg :: Parser Reg
+parseReg = parserOptionGroup "Regulatory type" $
+  fmap Gov (strOption $ long "gov" <> metavar "STR" <> value "" <> showDefault
+    <> help "Government") <|>
+  fmap Com (strOption $ long "com" <> metavar "STR" <> help "Commerical")
+
+parseMissnTy :: Parser MissnTy
+parseMissnTy = parserOptionGroup "Mission Type" $ asum
+  [ fmap GovGov $ strOption $ long "gov-gov" <> metavar "STR" <> value "" <> showDefault
+    <> help "Government for Government"
+  , fmap ComGov $ strOption $ long "com-gov" <> metavar "STR" <>
+    help "Commerical for Government"
+  , fmap ComCom $ strOption $ long "com-com" <> metavar "STR" <>
+    help "Commerical for Commercial"
+  , fmap GovCom $ strOption $ long "gov-com" <> metavar "STR" <>
+    help "Government for Commerical"
+  ]
+
+parseCat :: Parser Cat
+parseCat = parserOptionGroup "Category" $ asum
+  [ flag Rocket Rocket $ long "rocket" <>
+    help "propelled and steered by combustion regardless or launch orien or method, default"
+  , flag' Spaceplane $ long "spaceplane" <>
+    help "winged vehicle, self-propelled, steered by aerodynmic flight ctl in atmosphere, \
+         \can also operate above atmosphere"
+  , flag' LiftingBody $ long "lifting-body" <> help "winged, reenters as unpowered glider"
+  , flag' Capsule $ long "capsule" <> help "aerodynamic stable reentry with\
+    \ negligible steering capability"
+  , flag' Balloon $ long "balloon" <> help "gas propelled lighter-than-air,\
+    \ hovers in stratosphere"]
+
+parseClass :: Parser Class
+parseClass = parserOptionGroup "Class" $ asum
+  [ LnchOri <$> asum
+    [ flag' VertLnch $ long "vlnch" <> help "vertical launch orientation"
+    , flag' HorizLnch $ long "hlnch" <> help "horizontal launch orientation"
+    , flag' PayldLnch $ long "plnch" <> help "payload launch orientation"]
+  , LnchDom <$> asum
+    [ flag' Air $ long "air" <> help "air launch domain"
+    , flag' Gnd $ long "gnd" <> help "ground launch domain"
+    , flag' Sea $ long "sea" <> help "sea launch domain"
+    , flag' Spce $ long "spce" <> help "space launch domain"]
+  , LndOri <$> asum
+    [ flag' VertLand $ long "vlnd" <> help "vertical landing orientation"
+    , flag' HorizLand $ long "hlnd" <> help "horizontal landing orientation"]
+  , Recov <$> asum
+    [ flag' AirRec $ long "air-rec" <> help "air recovery"
+    , flag' GndRec $ long "gnd-rec" <> help "ground recovery"
+    , flag' SeaRec $ long "sea-rec" <> help "sea recovery"]]
+
+parseMode :: Parser Mode
+parseMode = parserOptionGroup "Mode" $ asum
+  [ flag Piloted Piloted $ long "piloted" <> help "flight ctl by human default"
+  , flag' UnguidedBallistic $ long "unguided-ballistic" <>
+    help "flight path det by environ factors"
+  , flag' AutoGuided $ long "auto-guided" <> help "flight ctl by onboard computa"
+  , flag' GuidedExtCmds $ long "guided-ext" <>
+    help "flight guided by computer & external cmds"
+  , flag' AutoPilotHybrid $ long "auto-pilot-hybrid" <>
+    help "flight ctl by human and/or computer"
+  ]
+
+parseCap :: Parser Cap
+parseCap = parserOptionGroup "Capability" $ asum
+  [ flag' AntiColisn $ long "acolisn" <> help "anti-collision sense & avoid"
+  , flag' Proplsv $ long "proplsv" <> help "propulsive mode other than attitude ctl"
+  , fmap StatPwrFlight $ option auto $ long "spf" <> metavar "DBL"
+    <> help "Stationary powered flight duration seconds"
+  , FastSlowApprchLndingSpd
+    <$> strOption (long "aprch" <> metavar "STR" <> help "approach descriptor")
+    <*> parsePlot (option auto (short 'a' <> metavar "DBL" <> help "approach altitude"))
+        (option auto (short 's' <> metavar "DBL" <> help "approach speed"))
+    <*> option auto (long "lnding-spd" <> metavar "DBL" <> help "final landing speed")
+  , GearCfg <$> strOption (long "gear-cfg" <> metavar "STR" <> help "landing gear config")
+  , JetiBdy <$> strOption (long "jeti-bdy" <> metavar "STR" <> help "jettison body")
+  , Stge <$> option auto (long "stge" <> metavar "INT" <> help "stage num") <*>
+    switch (long "ctl-rntry" <> help "controlled reentry") <*>
+    optional (flag' True (long "reuse" <> help "reusable") <|>
+      flag' False (long "no-reuse" <> help "non-reusable"))
+  , TermSys <$> asum
+    [ flag' Thrustt $ long "thrst" <> help "thrust termination system"
+    , flag' OrdFTS $ long "ofts" <> help "ordnance flight termination system (FTS)"
+    , flag' FlightCtlManip $ long "fcm" <> help "flight control manipulation termination system"
+    , fmap Ots $ strOption $ long "ots" <> metavar "STR" <>
+      help "other termination system"]]
+
+parseSiz :: Parser Size
+parseSiz = parserOptionGroup "Size" $ asum
+  [ LnchSz <$> option auto (long "lnch-stg" <> metavar "INT" <> help "launch stage")
+    <*> option auto (long "lnch-bgn" <> metavar "DBL" <> help "launch weight begin kg")
+    <*> option auto (long "lnch-end" <> metavar "DBL" <> help "launch weight end kg")
+  , RntrySz <$> option auto (long "rntry-stg" <> metavar "INT" <> help "reentry stage")
+    <*> option auto (long "rntry-bgn" <> metavar "DBL" <> help "reentry weight begin kg")
+    <*> option auto (long "rntry-end" <> metavar "DBL" <> help "reentry weight end kg")
+  , Explosv <$> option auto (long "explo-bgn" <> metavar "DBL" <> help "explosive begin TNT")
+    <*> option auto (long "explo-end" <> metavar "DBL" <> help "explosive end TNT")
+  , Thrustp <$> strOption (long "thrst-prof" <> metavar "STR" <> help "thrust profile descriptor")
+    <*> parsePlot (option auto (short 't' <> metavar "DBL" <> help "thrust profile time"))
+        (option auto (short 'n' <> metavar "DBL" <> help "thrust profile N"))]
+
+parseProp :: Parser Prop
+parseProp = parserOptionGroup "Propellant" $ asum
+  [ fmap Sys $ strOption $ long "sys" <> metavar "STR" <> help "system type"
+  , Fuel <$> strOption (long "fuel" <> metavar "STR" <> help "fuel type")
+    <*> option auto (long "fuel-cap" <> metavar "DBL" <> help "fuel capacity kg")
+  , Oxidizr <$> strOption (long "oxid" <> metavar "STR" <> help "oxidizer type")
+    <*> option auto (long "oxid-cap" <> metavar "DBL" <> help "oxidizer capacity kg")
+  , OtherProp <$> strOption (long "other-prop" <> metavar "STR" <> help "other propellant type")
+    <*> option auto (long "other-cap" <> metavar "DBL" <> help "other propellant capacity kg")
+  ]
+
+parsePayld :: Parser Payld
+parsePayld = parserOptionGroup "Payload" $ asum
+  [ fmap Human $ strOption $ long "human" <> metavar "STR" <> help "humans"
+  , fmap Animal $ strOption $ long "animal" <> metavar "STR" <> help "animals"
+  , fmap Biologic $ strOption $ long "biologic" <> metavar "STR" <> help "plants etc."
+  , fmap Cargo $ strOption $ long "cargo" <> metavar "STR" <> help "non-hazard cargo"
+  , fmap Hazard $ strOption $ long "hazard" <> metavar "STR" <> help "hazardous cargo"]
+
+parseMissn :: Parser Missn
+parseMissn = parserOptionGroup "Mission" $ asum
+  [ Orb <$> strOption (long "orb" <> metavar "STR" <> help "orbital plot descriptor")
+    <*> parsePlot (option auto (short 'b' <> metavar "DBL" <> help "orbital time"))
+    (option auto (short 'o' <> metavar "DBL" <> help "orbital altitude"))
+  , Suborb <$> strOption (long "suborb" <> metavar "STR" <> help "suborbital plot descriptor")
+    <*> parsePlot (option auto (short 'c' <> metavar "DBL" <> help "suborbital altitude"))
+    (option auto (short 'd' <> metavar "DBL" <> help "suborbital time"))
+  , NASUsage <$> strOption (long "nas-desc" <> metavar "STR" <> help "NAS descriptor")
+    <*> option auto (long "nas-strt" <> metavar "INT" <> help "NAS start MET")
+    <*> option auto (long "nas-end" <> metavar "INT" <> help  "NAS end MET")
+    <*> parsePlot (option auto (long "lon" <> metavar "DBL" <> help "NAS longitude"))
+    (option auto (long "lat" <> metavar "DBL" <> help "NAS latitude"))
+  , Windw <$> option auto (long "windw" <> metavar "STR" <> help "window descriptor")
+    <*> option auto (long "hs" <> metavar "INT" <> help "window duration hours")
+    <*> option auto (long "ms" <> metavar "INT" <> help "window duration minutes")
+  , Flex <$> strOption (long "flex-op" <> metavar "STR" <> help "flex operation")
+    <*> option auto (long "flex-val" <> metavar "INT" <> help "flex value")
+  , AdvNoticeOp <$> strOption (long "note-op" <> metavar "STR" <> help "advance notice operation")
+    <*> option auto (long "note-time" <> metavar "DBL" <> help "advance notice time")]
+
+parsePlot :: (Alternative f, Applicative f) => f a -> f b -> f [(a, b)]
+parsePlot fa fb = many $ (,) <$> fa <*> fb
diff --git a/lib/Data/Vehicle.hs b/lib/Data/Vehicle.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Vehicle.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
+
+module Data.Vehicle (Vehicle(..), Reg(..), MissnTy(..), Cat(..), Class(..)
+  , LnchOri(..), LnchDom(..), LndOri(..), Recov(..), Mode(..), Cap(..)
+  , TSys(..), Size(..), Prop(..), Payld(..), Missn(..), Plot
+  ) where
+
+import Data.Binary
+import GHC.Generics
+
+data Vehicle = Vehicle{reg :: Reg, missnTy :: MissnTy, cat :: Cat
+  , clas :: [Class], mode :: Mode, caps :: [Cap], sizs :: [Size], props :: [Prop]
+  , payld :: [Payld], missn :: [Missn]}
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data Reg = Gov String | Com String deriving (Binary, Eq, Generic, Read, Show)
+
+data MissnTy = GovGov String | ComGov String | ComCom String | GovCom String
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data Cat = Rocket | Spaceplane | LiftingBody | Capsule | Balloon
+  deriving (Binary, Bounded, Enum, Eq, Generic, Read, Show)
+
+data Class = LnchOri LnchOri | LnchDom LnchDom | LndOri LndOri | Recov Recov
+  deriving (Binary, Eq, Generic, Read, Show)
+
+-- | Launch Orientation
+data LnchOri = VertLnch | HorizLnch | PayldLnch
+  deriving (Binary, Bounded, Enum, Eq, Generic, Read, Show)
+
+-- | Launch domain
+data LnchDom = Air | Gnd | Sea | Spce
+  deriving (Binary, Bounded, Enum, Eq, Generic, Read, Show)
+
+-- | Landing Orientation
+data LndOri = VertLand | HorizLand
+  deriving (Binary, Bounded, Enum, Eq, Generic, Read, Show)
+
+-- | Recovery
+data Recov = AirRec | GndRec | SeaRec
+  deriving (Binary, Bounded, Enum, Eq, Generic, Read, Show)
+
+data Mode = Piloted | UnguidedBallistic | AutoGuided | GuidedExtCmds
+  | AutoPilotHybrid deriving (Binary, Bounded, Enum, Eq, Generic, Read, Show)
+
+data Cap = AntiColisn | Proplsv | StatPwrFlight Double |
+  FastSlowApprchLndingSpd String Plot Double | GearCfg String | JetiBdy String |
+  Stge Int Bool (Maybe Bool) | TermSys TSys
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data TSys = Thrustt | OrdFTS | FlightCtlManip | Ots String
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data Size = LnchSz Int Double Double | RntrySz Int Double Double
+  | Explosv Double Double | Thrustp String Plot
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data Prop = Sys String | Fuel String Double | Oxidizr String Double | OtherProp String Double
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data Payld = Human String | Animal String | Biologic String | Cargo String
+  | Hazard String
+  deriving (Binary, Eq, Generic, Read, Show)
+
+data Missn = Orb String Plot | Suborb String Plot
+  | NASUsage String Int Int Plot | Windw String Int Int
+  | Flex String Int | AdvNoticeOp String Double
+  deriving (Binary, Eq, Generic, Read, Show)
+
+type Plot = [(Double, Double)]
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,63 @@
+module Main (main) where
+
+import Data.Binary
+import Data.Vehicle
+import Hedgehog
+import qualified Hedgehog.Gen as Gen
+import qualified Hedgehog.Range as Range
+import Test.Tasty
+import Test.Tasty.Hedgehog
+
+main :: IO ()
+main = defaultMain $ testGroup "Data.Vehicle" [binTripTest]
+
+binTripTest :: TestTree
+binTripTest = testProperty "BinTrip" $ property $ do
+  v <- forAll genVehicle
+  tripping v encode $ \bs -> case decodeOrFail bs of
+    Left  (_, _, er) -> Left er
+    Right (_, _, v') -> Right (v' :: Vehicle)
+
+genVehicle :: MonadGen m => m Vehicle
+genVehicle = Vehicle
+  <$> Gen.choice [Gov <$> genStr, Com <$> genStr]
+  <*> Gen.choice [GovGov <$> genStr, ComGov <$> genStr, ComCom <$> genStr
+    , GovCom <$> genStr]
+  <*> Gen.enumBounded
+  <*> genList (Gen.choice [LnchOri <$> Gen.enumBounded
+    , LnchDom <$> Gen.enumBounded, LndOri <$> Gen.enumBounded
+    , Recov <$> Gen.enumBounded])
+  <*> Gen.enumBounded
+  <*> genList (Gen.choice [pure AntiColisn, pure Proplsv
+    , StatPwrFlight <$> genDbl, FastSlowApprchLndingSpd <$> genStr <*> genPlot <*> genDbl
+    , GearCfg <$> genStr, JetiBdy <$> genStr, Stge <$> genInt <*> Gen.bool
+      <*> Gen.maybe Gen.bool, TermSys <$> Gen.choice [pure Thrustt, pure OrdFTS
+      , pure FlightCtlManip, Ots <$> genStr]])
+  <*> genList (Gen.choice [LnchSz <$> genInt <*> genDbl <*> genDbl
+    , RntrySz <$> genInt <*> genDbl <*> genDbl, Explosv <$> genDbl <*> genDbl
+    , Thrustp <$> genStr <*> genPlot])
+  <*> genList (Gen.choice [Sys <$> genStr, Fuel <$> genStr <*> genDbl
+    , Oxidizr <$> genStr <*> genDbl, OtherProp <$> genStr <*> genDbl])
+  <*> genList (Gen.choice [Human <$> genStr, Animal <$> genStr
+    , Biologic <$> genStr, Cargo <$> genStr, Hazard <$> genStr])
+  <*> genList (Gen.choice [Orb <$> genStr <*> genPlot
+    , Suborb <$> genStr <*> genPlot, Windw <$> genStr <*> genInt <*> genInt
+    , Flex <$> genStr <*> genInt, AdvNoticeOp <$> genStr <*> genDbl])
+
+genPlot :: MonadGen m => m Plot
+genPlot = genList $ (,) <$> genDbl <*> genDbl
+
+genInt :: MonadGen m => m Int
+genInt = Gen.int $ Range.linearFrom 0 (-(2^(29 :: Integer))) (2^(29 :: Integer)-1)
+
+genDbl :: MonadGen m => m Double
+genDbl = Gen.double $ Range.linearFracFrom 0 (-999999999999999) 999999999999999
+
+genStr :: MonadGen m => m String
+genStr = Gen.string rangeList Gen.unicode
+
+genList :: MonadGen m => m a -> m [a]
+genList = Gen.list rangeList
+
+rangeList :: Range Int
+rangeList = Range.linearFrom 0 0 256
diff --git a/vehicle.cabal b/vehicle.cabal
new file mode 100644
--- /dev/null
+++ b/vehicle.cabal
@@ -0,0 +1,56 @@
+cabal-version:      3.0
+name:               vehicle
+version:            0.1.0.0
+synopsis:           Standard Classification for Space Launch & Reentry Vehicles
+description:        ASTM F3388-23
+homepage:           https://github.com/dopamane/vehicle
+license:            MIT
+license-file:       LICENSE
+author:             dopamane
+maintainer:         dwc1295@gmail.com
+copyright:          David Cox
+category:           Data
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+                    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/dopamane/vehicle
+
+library
+  default-language: Haskell2010
+  ghc-options:      -Wall -O2
+  hs-source-dirs:   lib
+  exposed-modules:  Data.Vehicle
+  build-depends:
+    base < 5,
+    binary,
+
+executable vhcl
+  default-language: Haskell2010
+  ghc-options:      -Wall -O2 -threaded
+  hs-source-dirs:   exe
+  main-is:          Main.hs
+  other-modules:    Paths_vehicle
+  autogen-modules:  Paths_vehicle
+  build-depends:
+    base < 5,
+    binary,
+    bytestring,
+    optparse-applicative,
+    vehicle
+
+test-suite test
+  default-language: Haskell2010
+  ghc-options:      -Wall -O2 -threaded
+  hs-source-dirs:   test
+  type:             exitcode-stdio-1.0
+  main-is:          Main.hs
+  build-depends:
+    base < 5,
+    binary,
+    hedgehog,
+    tasty,
+    tasty-hedgehog,
+    vehicle
