diff --git a/.gitignore b/.gitignore
index 747c5a082..a07c8033f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,9 +10,9 @@
 !/.idea/runConfigurations
 !/.idea/codeStyles
 
-/build/
-/out/
-/tmp/
+**/build/
+**/out/
+**/tmp/
 
 *.DS_Store
 
diff --git a/build.gradle.kts b/build.gradle.kts
index 2d68edd8e..deb4b64ab 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -68,6 +68,8 @@ dependencies {
     testImplementation("com.automation-remarks:video-recorder-junit:2.0")
     runtimeOnly("org.antlr:antlr4-runtime:4.9.3")
     antlr("org.antlr:antlr4:4.9.3")
+
+    implementation(project(":vim-engine"))
 }
 
 configurations {
diff --git a/settings.gradle b/settings.gradle
index 172f53e0c..29a1db5a8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,3 @@
 rootProject.name = 'IdeaVIM'
+include 'vim-engine'
+
diff --git a/vim-engine/build.gradle b/vim-engine/build.gradle
new file mode 100644
index 000000000..ffbf684d9
--- /dev/null
+++ b/vim-engine/build.gradle
@@ -0,0 +1,22 @@
+plugins {
+  id 'java'
+  id 'org.jetbrains.kotlin.jvm'
+}
+
+group 'org.jetbrains.ideavim'
+version 'SNAPSHOT'
+
+repositories {
+  mavenCentral()
+}
+
+dependencies {
+  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
+  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
+
+  compileOnly 'org.jetbrains:annotations:23.0.0'
+}
+
+test {
+  useJUnitPlatform()
+}
diff --git a/src/main/java/com/maddyhome/idea/vim/common/TextRange.kt b/vim-engine/src/main/java/com/maddyhome/idea/vim/common/TextRange.kt
similarity index 100%
rename from src/main/java/com/maddyhome/idea/vim/common/TextRange.kt
rename to vim-engine/src/main/java/com/maddyhome/idea/vim/common/TextRange.kt