diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index be4bb8e..c261620 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -13,6 +13,7 @@
+
diff --git a/kommand-examples/timeout/build.gradle.kts b/kommand-examples/timeout/build.gradle.kts
new file mode 100644
index 0000000..7b253f5
--- /dev/null
+++ b/kommand-examples/timeout/build.gradle.kts
@@ -0,0 +1,79 @@
+import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
+
+val currentPlatform: Platform = when {
+ DefaultNativePlatform.getCurrentOperatingSystem().isMacOsX && DefaultNativePlatform.getCurrentArchitecture().isAmd64 -> Platform.MACOS_X64
+ DefaultNativePlatform.getCurrentOperatingSystem().isMacOsX && DefaultNativePlatform.getCurrentArchitecture().isArm64 -> Platform.MACOS_ARM64
+ DefaultNativePlatform.getCurrentOperatingSystem().isLinux && DefaultNativePlatform.getCurrentArchitecture().isAmd64 -> Platform.LINUX_X64
+ DefaultNativePlatform.getCurrentOperatingSystem().isLinux && DefaultNativePlatform.getCurrentArchitecture().isArm64 -> Platform.LINUX_ARM64
+ DefaultNativePlatform.getCurrentOperatingSystem().isWindows && DefaultNativePlatform.getCurrentArchitecture().isAmd64 -> Platform.MINGW_X64
+ else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
+}
+
+plugins {
+ kotlin("multiplatform")
+}
+
+repositories {
+ mavenCentral()
+ gradlePluginPortal()
+}
+
+kotlin {
+ jvm {
+ compilations.all {
+ kotlinOptions.jvmTarget = "17"
+ }
+ withJava()
+ testRuns["test"].executionTask.configure {
+ useJUnitPlatform()
+ }
+ }
+
+ val nativeTarget = when (currentPlatform) {
+ Platform.MACOS_X64 -> macosX64()
+ Platform.MACOS_ARM64 -> macosArm64()
+ Platform.LINUX_X64 -> linuxX64()
+ Platform.LINUX_ARM64 -> linuxArm64()
+ Platform.MINGW_X64 -> mingwX64()
+ }
+
+ nativeTarget.apply {
+ binaries {
+ executable {
+ entryPoint = "com.kgit2.kommand.main"
+ }
+ }
+ }
+
+ applyDefaultHierarchyTemplate()
+
+ sourceSets {
+ // add opt-in
+ all {
+ languageSettings.optIn("kotlinx.cinterop.UnsafeNumber")
+ languageSettings.optIn("kotlinx.cinterop.ExperimentalForeignApi")
+ languageSettings.optIn("kotlin.experimental.ExperimentalNativeApi")
+ languageSettings.optIn("kotlin.native.runtime.NativeRuntimeApi")
+ languageSettings.optIn("kotlin.ExperimentalStdlibApi")
+ }
+
+ commonMain {
+ dependencies {
+ implementation(rootProject)
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0-RC2")
+ implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0")
+ }
+ }
+ }
+}
+
+enum class Platform(
+ val archName: String
+) {
+ MACOS_X64("x86_64-apple-darwin"),
+ MACOS_ARM64("aarch64-apple-darwin"),
+ LINUX_X64("x86_64-unknown-linux-gnu"),
+ LINUX_ARM64("aarch64-unknown-linux-gnu"),
+ MINGW_X64("x86_64-pc-windows-gnu"),
+ ;
+}
diff --git a/kommand-examples/timeout/src/appleMain/kotlin/com/kgit2/kommand/Main.kt b/kommand-examples/timeout/src/appleMain/kotlin/com/kgit2/kommand/Main.kt
new file mode 100644
index 0000000..bceba8a
--- /dev/null
+++ b/kommand-examples/timeout/src/appleMain/kotlin/com/kgit2/kommand/Main.kt
@@ -0,0 +1,60 @@
+package com.kgit2.kommand
+
+import com.kgit2.kommand.process.Command
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.IO
+import kotlinx.coroutines.async
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import kotlinx.datetime.Clock
+
+fun main() = runBlocking(Dispatchers.Default) {
+ // Sleep with regular
+ val start = Clock.System.now()
+ val status = Command("sleep").arg("5").status()
+ println("status: $status elapsed: ${Clock.System.now() - start}")
+
+ // Sleep with timeout detection and timeout determination
+ val start2 = Clock.System.now()
+ val child = Command("sleep").arg("5").spawn()
+ val childJob = async(Dispatchers.IO) {
+ runCatching {
+ child.wait()
+ }.onFailure {
+ println("child result: $it")
+ }.getOrNull()
+ }
+ runCatching {
+ withTimeout(3000) {
+ childJob.await()
+ }
+ }.onSuccess {
+ println("status: $it elapsed: ${Clock.System.now() - start2}")
+ }.onFailure {
+ child.kill()
+ println("status: $it elapsed: ${Clock.System.now() - start2}")
+ }
+
+ // Sleep with timeout detection and determination that it will not timeout
+ val start3 = Clock.System.now()
+ val child2 = Command("sleep").arg("2").spawn()
+ val childJob2 = async(Dispatchers.IO) {
+ runCatching {
+ child2.wait()
+ }.onFailure {
+ println("child result: $it")
+ }.getOrNull()
+ }
+ runCatching {
+ withTimeout(3000) {
+ childJob2.await()
+ }
+ }.onSuccess {
+ println("status: $it elapsed: ${Clock.System.now() - start3}")
+ }.onFailure {
+ child2.kill()
+ println("status: $it elapsed: ${Clock.System.now() - start3}")
+ }
+
+ Unit
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index d5c3a30..e5c99df 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -25,3 +25,4 @@ include(":kommand-examples")
include(":kommand-examples:example1")
include(":kommand-examples:example2")
include(":kommand-examples:example3")
+include(":kommand-examples:timeout")