diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 14746e7..7f9f8e7 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -8,6 +8,8 @@
         
       
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 254a1fc..3efb2d8 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
 
 
   
-    
+    
   
 
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 7060359..867fb6d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,6 @@
 plugins {
     kotlin("jvm") version "2.2.10"
+    kotlin("plugin.serialization") version "2.2.20"
 }
 
 group = "moe.rosa"
@@ -11,6 +12,7 @@ repositories {
 
 dependencies {
     testImplementation(kotlin("test"))
+    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
 }
 
 tasks.test {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 83ad6b3..13d8c79 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,4 +1,6 @@
 plugins {
     id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
 }
-rootProject.name = "planterette"
\ No newline at end of file
+rootProject.name = "planterette"
+include("definition")
+include("host")
\ No newline at end of file
diff --git a/src/main/kotlin/moe/rosa/planterette/Main.kt b/src/main/kotlin/moe/rosa/planterette/Main.kt
index 709234e..aba9c1a 100644
--- a/src/main/kotlin/moe/rosa/planterette/Main.kt
+++ b/src/main/kotlin/moe/rosa/planterette/Main.kt
@@ -1,5 +1,2 @@
 package moe.rosa.planterette
 
-fun main() {
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/moe/rosa/planterette/hakurei/Filesystem.kt b/src/main/kotlin/moe/rosa/planterette/hakurei/Filesystem.kt
new file mode 100644
index 0000000..1959218
--- /dev/null
+++ b/src/main/kotlin/moe/rosa/planterette/hakurei/Filesystem.kt
@@ -0,0 +1,62 @@
+package moe.rosa.planterette.hakurei
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class AbsolutePath(private val path: String) {
+    override fun toString(): String {
+        return path
+    }
+}
+
+interface FSType {
+    val type: String
+}
+data class ApplyState(val autoEtcPrefix: String)
+
+@Serializable
+data class FSBind(
+    val target: AbsolutePath,
+    val source: AbsolutePath,
+    val write: Boolean,
+    val device: Boolean,
+    val ensure: Boolean,
+    val optional: Boolean,
+    val special: Boolean,
+
+    override val type: String = "bind",
+) : FSType
+
+@Serializable
+data class FSEphemeral(
+    val target: AbsolutePath,
+    val write: Boolean,
+    val size: Int,
+    val perm: Int,
+
+    override val type: String = "ephemeral"
+) : FSType
+
+@Serializable
+data class FSLink(
+    val target: AbsolutePath,
+    val linkname: String,
+    val dereference: Boolean,
+
+    override val type: String = "link"
+) : FSType
+
+@Serializable
+data class FSOverlay(
+    val target: AbsolutePath,
+    val lower: List,
+    val upper: AbsolutePath,
+    val work: AbsolutePath,
+
+    override val type: String = "overlay"
+) : FSType
+
+@Serializable
+data class FilesystemConfig(
+    val config: FSType
+)
\ No newline at end of file
diff --git a/src/main/kotlin/moe/rosa/planterette/hakurei/Hakurei.kt b/src/main/kotlin/moe/rosa/planterette/hakurei/Hakurei.kt
new file mode 100644
index 0000000..5c78e9e
--- /dev/null
+++ b/src/main/kotlin/moe/rosa/planterette/hakurei/Hakurei.kt
@@ -0,0 +1,93 @@
+package moe.rosa.planterette.hakurei
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class HakureiConfig(
+    val id: String,
+    val path: AbsolutePath,
+    val args: List,
+    val enablements: Enablements,
+    val sessionBus: DBusConfig,
+    val systemBus: DBusConfig,
+    val directWayland: Boolean,
+    val username: String,
+    val shell: AbsolutePath,
+    val home: AbsolutePath,
+
+    val extraPerms: ExtraPermsConfig,
+    val identity: Int,
+    val groups: List,
+
+    val container: ContainerConfig,
+)
+
+@Serializable
+data class DBusConfig(
+    val see: List,
+    val talk: List,
+    val own: List,
+    val call: Map,
+    val broadcast: Map,
+    val log: Boolean,
+    val filter: Boolean,
+)
+
+@Serializable
+data class Enablements(
+    val wayland: Boolean,
+    val x11: Boolean,
+    val dbus: Boolean,
+    val pulse: Boolean,
+)
+
+@Serializable
+data class ContainerConfig(
+    val hostname: String,
+    val waitDelay: Long,
+    val seccompFlags: Int,
+    val seccompPresets: Int,
+    val seccompCompat: Boolean,
+    val devel: Boolean,
+    val userns: Boolean,
+    val hostNet: Boolean,
+    val hostAbstract: Boolean,
+    val tty: Boolean,
+    val multiarch: Boolean,
+
+    val env: Map,
+
+    val mapRealUid: Boolean,
+    val device: Boolean,
+
+    val filesystem: List,
+)
+@Serializable
+data class ExtraPermsConfig(
+    val ensure: Boolean,
+    val path: AbsolutePath,
+    val read: Boolean,
+    val write: Boolean,
+    val execute: Boolean,
+) {
+    override fun toString(): String {
+        val buffer = StringBuffer(5 + path.toString().length)
+        buffer.append("---")
+        if(ensure) {
+            buffer.append("+")
+        }
+        buffer.append(":")
+        buffer.append(path.toString())
+        if(read) {
+            buffer.setCharAt(0, 'r')
+        }
+        if(write) {
+            buffer.setCharAt(1, 'w')
+        }
+        if(execute) {
+            buffer.setCharAt(2, 'x')
+        }
+        return buffer.toString()
+    }
+}
+
diff --git a/src/test/resources/ChromiumExample.kts b/src/test/resources/ChromiumExample.kts
new file mode 100644
index 0000000..e69de29