Koodies 1.5: Execute Commands, Scripts & Containers the Kotlin-way

Koodies 1.5 is out now and allows you to run command lines and shell scripts, either on your host or in a Docker container of your choice, synchronously or asynchronously, optionally logging and even while interacting with the created process—all of this with zero boilerplate.


The Java’s Development Kit allows developers to execute native OS processes using Runtime.exec since its first release. As of Java 1.5/5.0 the newly introduced ProcessBuilder rendered process handling easier; as did subsequent feature additions like ProcessHandle.

Apache Commons Exec was somewhat a breakthrough as it took away one of the biggest challenges programmers face with processes—reading their standard output and error. Furthermore Apache Commons Exec supports parameter substitution and helps coping with concurrency (e.g. DefaultExecutor, ExecuteWatchdog). Yet, a couple of everyday tasks are still not easily achievable.

ZT Process Executor is a process executor that makes a lot of things better. It has meta logging, which greatly helps at debugging and provides “one-liners” (that are rather “one-line-ishs” because of line length and exception handling boilerplate), as one can see in the following example:

String output;
boolean success = false;
try {
    output = new ProcessExecutor().command("java", "-version")
    success = true;
} catch (InvalidExitValueException e) {
    System.out.println("Process terminated with " + e.getExitValue());
    output = e.getResult().outputUTF8();

Unfortunately when it comes to script, no simple solutions seem to exist at all. Also libraries taking advantage of Kotlin features are not known.

This is where Koodies Exec jumps in.
The following snippet provides the same functionality as the code from:

val exec = CommandLine("java", "-version").exec()
     .apply { if(state is Failed) println(exitCode) }
val (output, success) = to exec.successful


Execute Command Lines on Host

CommandLine("printenv", "HOME")
  .exec() // .exec.logging() // .exec.processing { io -> … }

Execute Shell Scripts on Host

ShellScript {
  "printenv | grep HOME | perl -pe 's/.*?HOME=//'"
}.exec() // .exec.logging() // .exec.processing { io -> … }

Execute Command Lines in Docker Container

CommandLine("printenv", "HOME")
  .dockerized{ "ubuntu" }
  .exec() // .exec.logging() // .exec.processing { io -> … }

Execute Shell Scripts in Docker Container

ShellScript {
  "printenv | grep HOME | perl -pe 's/.*?HOME=//'"
}.dockerized{ "ubuntu" }
 .exec() // .exec.logging() // .exec.processing { io -> … }

Logging and Interaction

As you can see in the above examples, three execution variants exist:

▶️ executing-only

ShellScript { … }.exec()

📝 logging

ShellScript { … }.exec.logging()

If things go wrong, it’s also logged:

Process {PID} terminated with exit code {…}
➜ A dump has been written to:
  - {WorkDir}/koodies.dump.{}.log
  - {WorkDir}/koodies.dump.{}.ansi-removed.log
➜ The last 10 lines are:

🧠 processing

ShellScript { … }.exec.processing { io -> 

io is typed; simply use io is IO.Output to filter out errors and meta information.

Asynchronous Execution

Processes are executed synchronously by default. Simply add async to the exec call to run the process asynchronously:

  • ShellScript { … }.exec.async()
  • ShellScript { … }.exec.async.logging()
  • ShellScript { … }.exec.async.processing { io -> doSomething(io) }

Automatically Captured I/O

Whatever variant you choose, life-cycle events, sent input, the process’s output and errors are stored for you:

  • CommandLine(…).exec().io
  • CommandLine(…).exec().io.output
  • CommandLine(…).exec().io.error.ansiRemoved

Typed (Exit) State

  • Access the state with state, which is either an instance of RunningExited (with the sub states Succeeded and Failed) or Excepted.
  • All states print nicely and provide a copy of all logged I/O, and state-dependent information such as the exit code.
  • By default, processes are killed on VM shutdown, which can be configured.
  • Life-cycle callbacks can be registered.

Ready to run Docker commands

with(tempDir()) {

    // convert SVG to PNG using command line-style docker command
    docker("minidocks/librsvg", "-z", 5, "--output", "koodies.png", "koodies.svg")

    // convert PNG to ASCII art using shell script-style docker command
    docker("rafib/awesome-cli-binaries", logger = null) {
           /opt/bin/chafa -c full -w 9 koodies.png
    }.io.output.ansiKept.let { println(it.resetLines()) }


R3vvvvvvvvvvvvvvvvvvvvvv\. .▝▜MMMMMMMMMMMMMMMMMM
vvvvvvvvvvvvvvvvvvvvvv\. .▝▜MMMMMMMMMMMMMMMM
vvvvvvvvvvvvvvvvvvvv\. .▝▜MMMMMMMMMMMMMM
uxvvvvvvvvvvvvvvvvz3x_ ▝▜MMMMMMMMMMMM
▁3uxvvvvvvvvvvvv▁▅&▆▂gx` ▝▜MMMMMMMMMM
Z▅▁3uxvvvvvvvvz▆WWRZ&▆▂gv. `▀WMMMMMMMM
WR&▄▁3uxvvvvvuk▀BWWWRZ&▆▂gv. .\vvz▀WMMMMMM
WWWRZ▅▁3ux▁▂Zg33k▀BWWWRZ&▆▂g}. .\vvvvvvz▀WMM0W
000WWRZ▅▃▆MM▆▂Zg33k▀BWWWRZ&▆▂g}. .\vvvvvvvvvvx▀BBR
  • All docker commands (dockerubuntubusyboxcurldownload, …) use the path in the receiver to
    • set the working directory of both the host command and the docker container
    • map the host working directory to the container’s working directory,
    • that is, all files of that directory are equally available in your container instance.
  • Low-level docker commands: startrunstopkillremovesearchimageps
  • Object-oriented design
    • DockerengineRunninginfoimagescontainerssearchexec
    • DockerImagelistisPulledpulltagsOnDockerHub
    • DockerContainerstartstopstatekillremove
  • See ExecutionIntegrationTest.kt and Docker.kt for more examples.


Koodies is a Kotlin Multiplatform Library, using the hierarchical project structure, a minimal set of dependencies, and is hosted on GitHub with releases provided on Maven Central.





WordPress Web Service

You are an enthusiastic WordPress user?
You want to implement a Flash based WordPress front end / theme?
You want to use WordPress as a back end for you software?

My new WordPress Web Service plugin is your solution!

WPWS allows you to access your WordPress installation via WSDL/SOAP. In contrast to classical RESTful services WSDL/SOAP is type safe meaning that you always get what you expect. RESTful services can change their normally not explicitly defined API from one day to the other and … BANG! You web application crashes.

After you have installed WPWS you can simply open your blog and append ?/wpws to your blog’s url.
My plugin for example is accessible through
The following screenshot shows what the plugin’s homepage looks like.

Continue reading…

generic ISOCUBE

Zachary Johnson and Paul Hayes showed some really nice examples of the CSS 2D transformation capabilites (isocube, 3D isocube using 2D CSS).

What I missed was the math behind it. Both (and every other isocube I could find on the net) statically positioned the three rectangles that form the isocube.

So what I did was to implement a generic isocube that renders based on the dimensions w, h and a degree α. The sources can be downloaded as a jQuery Plugin.

The math is mainly based on the Pythagorean theorem. In order to geometrically verify some hypotheses that came up I used Cinderella.

Continue reading…

Client-Server Communication for Humanoid Robots

Last month I finished my Bachelor thesis with the German title Client-Server-Kommunikation für humanoide Roboter (engl. “Client-Server Communication for Humanoid Robots”).

Within the framework of this work I implemented an application based on the Eclipse Rich Client Platform (RCP) that allows for the communication with humanoid soccer playing robots – namely FUmanoids – developed at the Freie Universität Berlin.

Continue reading…