diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+# Changelog for `try-language-spir-v`
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to the
+[Haskell Package Versioning Policy](https://pvp.haskell.org/).
+
+## Unreleased
+
+## 0.1.0.0 - YYYY-MM-DD
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Yoshikuni Jujo (c) 2023
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Yoshikuni Jujo nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+# try-language-spir-v
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/data/ShaderKind.txt b/data/ShaderKind.txt
new file mode 100644
--- /dev/null
+++ b/data/ShaderKind.txt
@@ -0,0 +1,44 @@
+VertexShader
+FragmentShader
+ComputeShader
+GeometryShader
+TessControlShader
+TessEvaluationShader
+GlslVertexShader
+GlslFragmentShader
+GlslComputeShader
+GlslGeometryShader
+GlslTessControlShader
+GlslTessEvaluationShader
+GlslInferFromSource
+GlslDefaultVertexShader
+GlslDefaultFragmentShader
+GlslDefaultComputeShader
+GlslDefaultGeometryShader
+GlslDefaultTessControlShader
+GlslDefaultTessEvaluationShader
+SpirvAssembly
+RaygenShader
+AnyhitShader
+ClosesthitShader
+MissShader
+IntersectionShader
+CallableShader
+GlslRaygenShader
+GlslAnyhitShader
+GlslClosesthitShader
+GlslMissShader
+GlslIntersectionShader
+GlslCallableShader
+GlslDefaultRaygenShader
+GlslDefaultAnyhitShader
+GlslDefaultClosesthitShader
+GlslDefaultMissShader
+GlslDefaultIntersectionShader
+GlslDefaultCallableShader
+TaskShader
+MeshShader
+GlslTaskShader
+GlslMeshShader
+GlslDefaultTaskShader
+GlslDefaultMeshShader
diff --git a/language-spir-v.cabal b/language-spir-v.cabal
new file mode 100644
--- /dev/null
+++ b/language-spir-v.cabal
@@ -0,0 +1,65 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.37.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           language-spir-v
+version:        0.1.0.0
+description:    Please see the README on GitHub at <https://github.com/githubuser/language-spir-v#readme>
+category:       Language
+homepage:       https://github.com/githubuser/language-spir-v#readme
+bug-reports:    https://github.com/githubuser/language-spir-v/issues
+author:         Yoshikuni Jujo
+maintainer:     yoshikuni.jujo@gmail.com
+copyright:      2023 Yoshikuni Jujo
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    CHANGELOG.md
+data-files:
+    data/ShaderKind.txt
+
+source-repository head
+  type: git
+  location: https://github.com/githubuser/language-spir-v
+
+library
+  exposed-modules:
+      Language.SpirV
+      Language.SpirV.Internal
+      Language.SpirV.ShaderKind
+      Language.SpirV.ShaderKind.Core
+  other-modules:
+      Paths_language_spir_v
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
+  pkgconfig-depends:
+      shaderc
+  build-depends:
+      base >=4.7 && <5
+    , bytestring <1
+    , c-enum <1
+    , nowdoc <1
+    , template-haskell <3
+  default-language: Haskell2010
+
+test-suite language-spir-v-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_language_spir_v
+  hs-source-dirs:
+      test
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , bytestring <1
+    , c-enum <1
+    , language-spir-v
+    , nowdoc <1
+    , template-haskell <3
+  default-language: Haskell2010
diff --git a/src/Language/SpirV.hs b/src/Language/SpirV.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/SpirV.hs
@@ -0,0 +1,7 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Language.SpirV (S, writeFile) where
+
+import Prelude hiding (writeFile)
+
+import Language.SpirV.Internal
diff --git a/src/Language/SpirV/Internal.hs b/src/Language/SpirV/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/SpirV/Internal.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Language.SpirV.Internal where
+
+import Data.String
+import Data.ByteString qualified as BS
+
+import Language.SpirV.ShaderKind
+
+newtype S (sknd :: ShaderKind) = S BS.ByteString deriving (Show, IsString)
+
+writeFile :: FilePath -> S sknd -> IO ()
+writeFile fp (S bs) = BS.writeFile fp bs
diff --git a/src/Language/SpirV/ShaderKind.hs b/src/Language/SpirV/ShaderKind.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/SpirV/ShaderKind.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds, KindSignatures #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Language.SpirV.ShaderKind where
+
+import Language.Haskell.TH
+import Data.Traversable
+
+import qualified Language.SpirV.ShaderKind.Core as C
+
+(: []) <$> do
+	enms <- runIO $ lines <$> readFile "data/ShaderKind.txt"
+	dataD (cxt []) (mkName "ShaderKind") [] Nothing
+		((\enm -> normalC (mkName enm) []) <$> enms)
+		[derivClause Nothing [conT ''Show]]
+
+class IsShaderKind (sknd :: ShaderKind) where shaderKind :: C.ShaderKind
+
+do	enms <- runIO $ lines <$> readFile "data/ShaderKind.txt"
+	pairs <- for enms \nm -> do
+		Just foo <- lookupValueName nm
+		Just bar <- lookupValueName $ "C." ++ nm
+		pure (foo, bar)
+	(\(knd, cknd) -> instanceD (cxt []) (conT ''IsShaderKind `appT` promotedT knd)
+		[valD (varP 'shaderKind) (normalB $ conE cknd) []]) `mapM` pairs
diff --git a/src/Language/SpirV/ShaderKind/Core.hsc b/src/Language/SpirV/ShaderKind/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Language/SpirV/ShaderKind/Core.hsc
@@ -0,0 +1,72 @@
+-- This file is automatically generated by the tools/makeShadercShaderKind.hs
+--	% stack runghc --cwd tools/ makeShadercShaderKind
+
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Language.SpirV.ShaderKind.Core where
+
+import Foreign.Storable
+import Foreign.C.Enum
+import Data.Word
+
+#include <shaderc/shaderc.h>
+
+enum "ShaderKind" ''#{type shaderc_shader_kind} [''Show, ''Eq, ''Storable] [
+	("VertexShader", #{const shaderc_vertex_shader}),
+	("FragmentShader", #{const shaderc_fragment_shader}),
+	("ComputeShader", #{const shaderc_compute_shader}),
+	("GeometryShader", #{const shaderc_geometry_shader}),
+	("TessControlShader", #{const shaderc_tess_control_shader}),
+	("TessEvaluationShader", #{const shaderc_tess_evaluation_shader}),
+	("GlslVertexShader", #{const shaderc_glsl_vertex_shader}),
+	("GlslFragmentShader", #{const shaderc_glsl_fragment_shader}),
+	("GlslComputeShader", #{const shaderc_glsl_compute_shader}),
+	("GlslGeometryShader", #{const shaderc_glsl_geometry_shader}),
+	("GlslTessControlShader", #{const shaderc_glsl_tess_control_shader}),
+	("GlslTessEvaluationShader",
+		#{const shaderc_glsl_tess_evaluation_shader}),
+	("GlslInferFromSource", #{const shaderc_glsl_infer_from_source}),
+	("GlslDefaultVertexShader",
+		#{const shaderc_glsl_default_vertex_shader}),
+	("GlslDefaultFragmentShader",
+		#{const shaderc_glsl_default_fragment_shader}),
+	("GlslDefaultComputeShader",
+		#{const shaderc_glsl_default_compute_shader}),
+	("GlslDefaultGeometryShader",
+		#{const shaderc_glsl_default_geometry_shader}),
+	("GlslDefaultTessControlShader",
+		#{const shaderc_glsl_default_tess_control_shader}),
+	("GlslDefaultTessEvaluationShader",
+		#{const shaderc_glsl_default_tess_evaluation_shader}),
+	("SpirvAssembly", #{const shaderc_spirv_assembly}),
+	("RaygenShader", #{const shaderc_raygen_shader}),
+	("AnyhitShader", #{const shaderc_anyhit_shader}),
+	("ClosesthitShader", #{const shaderc_closesthit_shader}),
+	("MissShader", #{const shaderc_miss_shader}),
+	("IntersectionShader", #{const shaderc_intersection_shader}),
+	("CallableShader", #{const shaderc_callable_shader}),
+	("GlslRaygenShader", #{const shaderc_glsl_raygen_shader}),
+	("GlslAnyhitShader", #{const shaderc_glsl_anyhit_shader}),
+	("GlslClosesthitShader", #{const shaderc_glsl_closesthit_shader}),
+	("GlslMissShader", #{const shaderc_glsl_miss_shader}),
+	("GlslIntersectionShader", #{const shaderc_glsl_intersection_shader}),
+	("GlslCallableShader", #{const shaderc_glsl_callable_shader}),
+	("GlslDefaultRaygenShader",
+		#{const shaderc_glsl_default_raygen_shader}),
+	("GlslDefaultAnyhitShader",
+		#{const shaderc_glsl_default_anyhit_shader}),
+	("GlslDefaultClosesthitShader",
+		#{const shaderc_glsl_default_closesthit_shader}),
+	("GlslDefaultMissShader", #{const shaderc_glsl_default_miss_shader}),
+	("GlslDefaultIntersectionShader",
+		#{const shaderc_glsl_default_intersection_shader}),
+	("GlslDefaultCallableShader",
+		#{const shaderc_glsl_default_callable_shader}),
+	("TaskShader", #{const shaderc_task_shader}),
+	("MeshShader", #{const shaderc_mesh_shader}),
+	("GlslTaskShader", #{const shaderc_glsl_task_shader}),
+	("GlslMeshShader", #{const shaderc_glsl_mesh_shader}),
+	("GlslDefaultTaskShader", #{const shaderc_glsl_default_task_shader}),
+	("GlslDefaultMeshShader", #{const shaderc_glsl_default_mesh_shader}) ]
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
