Repository navigation
Conversation
3 of 4 tasks
why: Only test code could start and own a tmux server, so every API example ran inside a 99-line shell launcher that made the socket directory, scrubbed TMUX, stopped the server and checked for leaks. That is the work the library exists to take off a caller. Part of #142. what: - Add Server.start and ServerLaunch: a foreground daemon in a directory of its own, an empty config unless one is given, none of the caller's TMUX, TMUX_PANE or LIBTMUX_SOCKET*, and a TMUX_TMPDIR inside the directory - Make close on such a server stop tmux, wait until it no longer answers, stop any server a program left under the directory, remove it, and throw when one still answers or was left - Reap servers whose owning JVM is gone, once per root, moved here from the JUnit extension with its tests - Test start, close, the scrubbed environment, both failures and a start that cannot finish; each fails when the code it covers breaks
why: The extension carried its own copy of the directory naming, reaping, readiness probe and exit wait that Server.start now owns. Part of #142. what: - Start each fixture server through Server.start under the test root - Drop the extension's reaping, directory naming and exit wait, and the test of the exit wait that no longer exists
why: A Kotlin caller should scope a private server the way it scopes any other, with a block that ends it however the block ends. Part of #142. what: - Add Server.start and withPrivateServer, which closes under NonCancellable like withServer - Test that the server and its directory are gone after a block and after a block that throws
why: Scala callers scope with Using in the direct facade and a Resource in the Cats one. Part of #142. what: - Add Server.start to the direct facade, so Using.resource ends the server - Add Server.start[F] to the Cats facade as a Resource with the facade's operation bound - Test that the directory is gone after each
why: A reader who copied an example got a program that could not run without a shell script beside it. The programs should show the library doing the work. Part of #142. what: - Start every Java, Kotlin, Scala Direct and Scala Cats API program's server with Server.start and create work-one and work-two in the programs that read them - Delete api/run.sh and its sandbox test, whose checks now live in the library's tests, and drop the launcher from the manifest and README - Run the programs with the matrix's tmux first on PATH - Match Capture's markers at the end of a line, since a prompt may come before the output
why: The new entry point and the removed launcher change what a reader of the examples and a caller of the library see. Part of #142. what: - Add entries to the libtmux, Kotlin, Scala and Scala Cats changelogs - Add the examples change to the root changelog
why: The Clojure facade copied the shell launcher to own a server, and a Clojure caller should get the same entry point as Java's Server.start, in the facade's own shape. Part of #142. what: - Add libtmux.core/start!, which takes an option map like open! and returns the Server for with-open; closing it stops tmux and removes its directory - Reject unknown options before anything starts - Regenerate the API reference and fix the README's launcher sentence - Test a started server's close and the rejected options against real tmux
why: The Clojure programs still ran through examples/api/run.sh, which this change deletes, and took three arguments from it. Part of #142. what: - Start every Clojure program's server with start! and drop its arguments; create work-one and work-two in the programs that read them - Drop run.sh from the Clojure manifest and README, and run the programs with the matrix's tmux first on PATH - Make Connect assert the snapshot has a session list rather than a session, since a fresh server has none
tony
force-pushed
the
feat/private-server-142
branch
from
November 8, 2026 03:45
21cae20 to
ee3a836
Compare
This was referenced Nov 8, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Server.start(ServerLaunch)andServer.start(): a private tmux server with its own directory underServerLaunch.root(/tmp/libtmux-java-devby default), an empty config unless one is given, none of the caller'sTMUX,TMUX_PANEorLIBTMUX_SOCKET*, and aTMUX_TMPDIRinside the directory. It runs as a foreground child (tmux -D), so its exit is observed on the process.close()on that server stops tmux, waits until it no longer answers, stops any server a program left under the directory, removes the directory, and throwsIllegalStateExceptionif a server still answers (the directory stays) or one was left.libtmux-junit5'sTmuxExtensionstarts its fixtures withServer.start; the directory naming, the abandoned-server reaping and the exit wait moved into the library with the reaping tests.NamedServerFixturestays: it authenticates and ends a server another process started, which is not this entry point's job.Server.startandwithPrivateServer { }, Scala directServer.start()forUsing.resource, and Scala CatsServer.start[F]as aResource.work-oneandwork-twothemselves where they read them.examples/api/run.sh,ApiRunnerSandboxTest, the launcher manifest entries and the README's launcher section are removed.libtmux.core/start!, which takes an option map likeopen!and returns the Server forwith-open; its thirteen example programs start their own server and take no arguments. The facade has no public macros, so there is nowith-server.Closes #142
Docs site (not changed here):
packages/api-model/src/languages/jvm-examples.tsin libtmux/docs requires exactly four setup files includingrun.sh, labels it as a launcher, says the program opens a client for the launcher's server, and printssh run.sh build/install/api-example/bin/api-example;site/test/jvm-api-examples.test.tsexpects five files per example. All of that needs to droprun.shonce this lands.Test plan
./gradlew :libtmux:test --tests '*PrivateServerTest'failed to compile beforeServer.startexisted, then passed; breaking the environment scrub and the directory removal makes five of its eleven cases fail:libtmux:check :libtmux-junit5:check :libtmux-kotlin:check :libtmux-scala:check :libtmux-scala-cats:check :examples:checkPrivateServerTestandPrivateServerSuiteagainst the real tmux 3.8a on PATH:integration-tests:clojureIntegrationTest,:libtmux-clojure:check,:libtmux-clojure-core-async:check