Core Library0.xHome

Choose documentation 1

latest

Current version

latest
English

Early release libtmux is released, and its APIs may still change between releases. This site's structure and URLs may change too.

Edit this page on GitHub

tmux client library for Kotlin

Control tmux, connect to and create servers, navigate sessions, windows, and panes, send keys, watch for changes via control mode, capture pane contents.

Install

implementation("io.github.libtmux:libtmux-kotlin:0.1.0")

At a glance

Server → Session → Window → Pane. Each level of the tmux hierarchy has its own entry in the Kotlin API, with the tmux object it wraps.

TypeWraps
io.github.libtmux.kotlin.Server A tmux server
io.github.libtmux.kotlin.Session A session, ID $n
io.github.libtmux.kotlin.Window A window in a session, ID @n
io.github.libtmux.kotlin.Pane A pane in a window, ID %n

What it does

Start with Kotlin

Example details
import io.github.libtmux.ServerConfig
import io.github.libtmux.ServerEndpoint
import io.github.libtmux.TextOutcome
import io.github.libtmux.kotlin.*
import java.nio.file.Path
import java.time.Duration
import java.util.UUID
import kotlinx.coroutines.runBlocking
import kotlin.time.Duration.Companion.seconds
fun main() = runBlocking {
val socket = "libtmux-home-${UUID.randomUUID()}"
val config = ServerConfig.builder()
.endpoint(ServerEndpoint.namedSocket(socket))
.configFile(Path.of("/dev/null"))
.defaultTimeout(Duration.ofSeconds(5))
.build()
withServer(config) { server ->
val session = server.newSession("work")
val pane = session.activeWindow?.activePane
?: error("no active pane")
pane.sendLine("printf '\\nrea%s\\n' dy")
val outcome = pane.awaitText("ready", timeout = 5.seconds)
check(outcome != TextOutcome.TIMED_OUT)
val lines = pane.capture()
check(lines.any { it.trim() == "ready" })
val run = pane.run("echo hi && exit 3", timeout = 5.seconds)
check(run.exitStatus.orNull() == 3)
println("ready; exit ${run.exitStatus.orNull()}")
}
}
import io.github.libtmux.ServerConfig
import io.github.libtmux.ServerEndpoint
import io.github.libtmux.TextOutcome
import io.github.libtmux.kotlin.*
import java.nio.file.Path
import java.time.Duration
import java.util.UUID
import kotlinx.coroutines.runBlocking
import kotlin.time.Duration.Companion.seconds
fun main() = runBlocking {
val socket = "libtmux-home-${UUID.randomUUID()}"
val config = ServerConfig.builder()
.endpoint(ServerEndpoint.namedSocket(socket))
.configFile(Path.of("/dev/null"))
.defaultTimeout(Duration.ofSeconds(5))
.build()
withServer(config) { server ->
try {
val session = server.newSession("work")
val pane = session.activeWindow?.activePane
?: error("no active pane")
pane.sendLine("printf '\\nrea%s\\n' dy")
val outcome = pane.awaitText("ready", timeout = 5.seconds)
check(outcome != TextOutcome.TIMED_OUT)
val lines = pane.capture()
check(lines.any { it.trim() == "ready" })
val run = pane.run("echo hi && exit 3", timeout = 5.seconds)
check(run.exitStatus.orNull() == 3)
println("ready; exit ${run.exitStatus.orNull()}")
} catch (error: Exception) {
throw IllegalStateException(
"tmux quickstart failed", error
)
}
}
}
import io.github.libtmux.ServerConfig
import io.github.libtmux.ServerEndpoint
import io.github.libtmux.TextOutcome
import io.github.libtmux.kotlin.*
import java.nio.file.Path
import java.time.Duration
import java.util.UUID
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.seconds
fun main() = runBlocking {
val socket = "libtmux-home-${UUID.randomUUID()}"
val config = ServerConfig.builder()
.endpoint(ServerEndpoint.namedSocket(socket))
.configFile(Path.of("/dev/null"))
.defaultTimeout(Duration.ofSeconds(5))
.build()
withServer(config) { server ->
try {
val session = server.newSession("work")
val pane = session.activeWindow?.activePane
?: error("no active pane")
pane.sendLine("printf '\\nrea%s\\n' dy")
val outcome = pane.awaitText("ready", timeout = 5.seconds)
check(outcome != TextOutcome.TIMED_OUT)
val lines = pane.capture()
check(lines.any { it.trim() == "ready" })
val run = pane.run("echo hi && exit 3", timeout = 5.seconds)
check(run.exitStatus.orNull() == 3)
println("ready; exit ${run.exitStatus.orNull()}")
} finally {
withContext(NonCancellable) {
server.killServer()
}
}
}
}
import io.github.libtmux.ServerConfig
import io.github.libtmux.ServerEndpoint
import io.github.libtmux.TextOutcome
import io.github.libtmux.kotlin.*
import java.nio.file.Path
import java.time.Duration
import java.util.UUID
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.seconds
fun main() = runBlocking {
val socket = "libtmux-home-${UUID.randomUUID()}"
val config = ServerConfig.builder()
.endpoint(ServerEndpoint.namedSocket(socket))
.configFile(Path.of("/dev/null"))
.defaultTimeout(Duration.ofSeconds(5))
.build()
withServer(config) { server ->
try {
val session = server.newSession("work")
val pane = session.activeWindow?.activePane
?: error("no active pane")
pane.sendLine("printf '\\nrea%s\\n' dy")
val outcome = pane.awaitText("ready", timeout = 5.seconds)
check(outcome != TextOutcome.TIMED_OUT)
val lines = pane.capture()
check(lines.any { it.trim() == "ready" })
val run = pane.run("echo hi && exit 3", timeout = 5.seconds)
check(run.exitStatus.orNull() == 3)
println("ready; exit ${run.exitStatus.orNull()}")
} catch (error: Exception) {
throw IllegalStateException(
"tmux quickstart failed", error
)
} finally {
withContext(NonCancellable) {
server.killServer()
}
}
}
}
Run this example

JDK 25 and tmux on Linux/macOS; Gradle resolves Kotlin 2.4.10

Save the program above as src/main/kotlin/Main.kt in a new directory, along with the files below.

Cleanup is omitted; the private tmux server and its temporary files may remain. Select Cleanup to remove them when the program finishes. The program stops its private tmux server and removes any temporary files it created when it finishes. Error handling adds diagnostics; every version checks required results and deadlines.

build.gradle.kts
plugins {
kotlin("jvm") version "2.4.10"
application
}
repositories { mavenCentral() }
dependencies {
implementation("io.github.libtmux:libtmux-kotlin:0.1.0")
}
java { toolchain { languageVersion.set(JavaLanguageVersion.of(25)) } }
kotlin { jvmToolchain(25) }
application { mainClass.set(providers.gradleProperty("exampleMain")) }
settings.gradle.kts
rootProject.name = "api-example"
gradle.properties
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=768m -Dfile.encoding=UTF-8
kotlin.daemon.jvmargs=-Xmx2g
org.gradle.workers.max=2

Setup and run

# Save the files above at their displayed relative paths.
git clone https://github.com/libtmux/libtmux-java.git libtmux-source
git -C libtmux-source checkout --detach 5c181887918351119bfdb3a046719fa792048e59
./libtmux-source/gradlew --project-dir . --console=plain --no-daemon --max-workers=2 \
installDist -PexampleMain=MainKt
SHELL=/bin/sh build/install/api-example/bin/api-example

Expected output

ready; exit 3

Library revision: 5c1818879183.

Typed API

What you get over the tmux CLI

Esc

Type to search.

Reference previewOpen reference