diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt
index 03cff61a0027e633c7121ed4c2ae91ddd552de6d..5ce2466813013061f1228bcda978b97deb48c8ac 100644
--- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt
+++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt
@@ -145,6 +145,7 @@ class OpenApiGeneratorPlugin : Plugin<Project> {
                     skipValidateSpec.set(generate.skipValidateSpec)
                     generateAliasAsModel.set(generate.generateAliasAsModel)
                     engine.set(generate.engine)
+                    cleanupOutput.set(generate.cleanupOutput)
                 }
             }
         }
diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt
index 6fbb11d45d2ace1a42489ff2969cc3db99a96c81..f70a7c06603085ce39dc55a428421371578cb3ee 100644
--- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt
+++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt
@@ -17,6 +17,8 @@
 package org.openapitools.generator.gradle.plugin.extensions
 
 import org.gradle.api.Project
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
 import org.gradle.kotlin.dsl.listProperty
 import org.gradle.kotlin.dsl.mapProperty
 import org.gradle.kotlin.dsl.property
@@ -336,6 +338,12 @@ open class OpenApiGeneratorGenerateExtension(project: Project) {
      */
     val engine = project.objects.property<String?>()
 
+    /**
+     * Defines whether the output dir should be cleaned up before generating the output.
+     *
+     */
+    val cleanupOutput = project.objects.property<Boolean>()
+
     init {
         applyDefaults()
     }
@@ -357,5 +365,6 @@ open class OpenApiGeneratorGenerateExtension(project: Project) {
         enablePostProcessFile.set(false)
         skipValidateSpec.set(false)
         generateAliasAsModel.set(false)
+        cleanupOutput.set(false)
     }
 }
diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
index 82fe7e761e848bfdb3ed0b4ca6cb8fd0d375d158..42394f7d85b4fdea4b7a53610cf3ceeb82607953 100644
--- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
+++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
@@ -478,6 +478,14 @@ open class GenerateTask : DefaultTask() {
     @Input
     val engine = project.objects.property<String?>()
 
+    /**
+     * Defines whether the output dir should be cleaned up before generating the output.
+     *
+     */
+    @Optional
+    @Input
+    val cleanupOutput = project.objects.property<Boolean>()
+
     private fun <T : Any?> Property<T>.ifNotEmpty(block: Property<T>.(T) -> Unit) {
         if (isPresent) {
             val item: T? = get()
@@ -500,6 +508,12 @@ open class GenerateTask : DefaultTask() {
     @Suppress("unused")
     @TaskAction
     fun doWork() {
+        cleanupOutput.ifNotEmpty { cleanup ->
+            if (cleanup) {
+                project.delete(outputDir)
+            }
+        }
+
         val configurator: CodegenConfigurator = if (configFile.isPresent) {
             CodegenConfigurator.fromFile(configFile.get())
         } else createDefaultCodegenConfigurator()
diff --git a/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt b/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt
index 4d5a96fd95ca1d474b0d0b32a70c64620428d7f8..3e8073d3dcafb4054211842b5890bc244f132255 100644
--- a/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt
+++ b/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt
@@ -69,6 +69,91 @@ class GenerateTaskDslTest : TestBase() {
                 "Expected a successful run, but found ${result.task(":openApiGenerate")?.outcome}")
     }
 
+    @Test
+    fun `openApiGenerate should not cleanup outputDir by default`() {
+        // Arrange
+        val projectFiles = mapOf(
+            "spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml")
+        )
+        withProject(defaultBuildGradle, projectFiles)
+
+        val oldFile = File(temp, "build/kotlin/should-be-removed")
+        oldFile.mkdirs()
+        oldFile.createNewFile()
+
+        // Act
+        val result = GradleRunner.create()
+            .withProjectDir(temp)
+            .withArguments("openApiGenerate")
+            .withPluginClasspath()
+            .build()
+
+        // Assert
+        assertTrue(
+            result.output.contains("Successfully generated code to"),
+            "User friendly generate notice is missing."
+        )
+
+        assertTrue(oldFile.exists(), "Old files should have been removed")
+
+        assertEquals(
+            TaskOutcome.SUCCESS, result.task(":openApiGenerate")?.outcome,
+            "Expected a successful run, but found ${result.task(":openApiGenerate")?.outcome}"
+        )
+    }
+
+    @Test
+    fun `openApiGenerate should cleanup outputDir`() {
+        // Arrange
+        val projectFiles = mapOf(
+            "spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml")
+        )
+        withProject(
+            """
+        plugins {
+          id 'org.openapi.generator'
+        }
+        openApiGenerate {
+            generatorName = "kotlin"
+            inputSpec = file("spec.yaml").absolutePath
+            outputDir = file("build/kotlin").absolutePath
+            apiPackage = "org.openapitools.example.api"
+            invokerPackage = "org.openapitools.example.invoker"
+            modelPackage = "org.openapitools.example.model"
+            configOptions = [
+                    dateLibrary: "java8"
+            ]
+            cleanupOutput = true
+        }
+    """.trimIndent(),
+            projectFiles
+        )
+
+        val oldFile = File(temp, "build/kotlin/should-be-removed")
+        oldFile.mkdirs()
+        oldFile.createNewFile()
+
+        // Act
+        val result = GradleRunner.create()
+            .withProjectDir(temp)
+            .withArguments("openApiGenerate")
+            .withPluginClasspath()
+            .build()
+
+        // Assert
+        assertTrue(
+            result.output.contains("Successfully generated code to"),
+            "User friendly generate notice is missing."
+        )
+
+        assertFalse(oldFile.exists(), "Old files should have been removed")
+
+        assertEquals(
+            TaskOutcome.SUCCESS, result.task(":openApiGenerate")?.outcome,
+            "Expected a successful run, but found ${result.task(":openApiGenerate")?.outcome}"
+        )
+    }
+
     @Test
     fun `should apply prefix & suffix config parameters`() {
         // Arrange
@@ -314,4 +399,4 @@ class GenerateTaskDslTest : TestBase() {
         assertEquals(TaskOutcome.FAILED, result.task(":openApiGenerate")?.outcome,
             "Expected a failed run, but found ${result.task(":openApiGenerate")?.outcome}")
     }
-}
\ No newline at end of file
+}