cli4clj Version 1.0.0 Released

In this post, I announce the release of version 1.0.0 of cli4clj. Even though I was already fairly happy about the state of cli4clj as posted before, I decided to add some more improvements. In the following, I first provide an overview over the most important features of cli4clj. Subsequently, I outline the improvements since the last release.

The most important features of cli4clj are:

  • Simple configuration via maps
  • Command line history
  • Command line editing
  • Tab-completion
    • For command names
    • Hints for selected commands: based on function arguments and custom hints
  • Aliases can be used to define alternative command names, e.g., for shortcuts.
  • Clojure data types, e.g., vector, list, map, etc., can be used as command arguments.
  • Build-in help
  • Information about function arguments is displayed as help and completion hints.
  • Customizable, similar to the Clojure REPL
  • Functionality for testing CLIs via unit tests

Since the last release, the most important additions are tab-completion and the functionality to extract and display information about function arguments, both in help and tab-completion hints. Following the aim of cli4clj to reduce the effort for implementing a CLI, both features usually do not require additional effort to be used.

Two forms of tab-completion can be distinguished. Firstly, command names can be completed via tab-completion. When multiple completion options exist, a hint with the possible options is shown. Otherwise, the command name is completed.

Secondly, so called “completion hints” can be shown for commands. These completion hints are displayed when the tab-completion is triggered for commands that are already entered. By default, cli4clj tries to display information about function arguments, if such information could be found. In addition, a tab completion hint can be defined in the configuration.

For displaying information about function arguments, in the help and the completion hints, cli4clj extracts the identifiers of the function arguments. It can do this for globally defined functions that were defined via defn and for anonymous functions that were defined with fn when the respective functions and cli4clj configuration options are defined within the (start-cli {…}) expression. Please note that, for the fn-case, it is important that the anonymous functions are defined within the configuration options and that the configuration options are defined directly in the (start-cli {…}) expression and are not stored in a local or global var.

As usual, the new cli4clj version is already available via clojars. In addition, API docs and detailed test results are available via the cli4clj github repository.

This entry was posted in cli4clj, Libs. and tagged , , , . Bookmark the permalink.

5 Responses to cli4clj Version 1.0.0 Released

  1. Knut Hertel says:

    Hi Rüdiger,
    I read your article about cli4clj with great interest and I tried to use cli4clj, but
    it seems not to work on Windows. I get a prompt (cli#)
    and can enter anything, but hitting the return button will not trigger any action.
    Perhaps there is a problem with the jline initialization (it seems to need a DLL)?

    • ruedigergad says:

      Hi Knut,
      thanks a lot for your reply.
      Chances are that it indeed requires something special on Windows. I will try to look into this on the weekend.

      Just in case, if you have the chance to do so, you could give it a try to run the example with jline debugging enabled. For doing this you would need to create the file $HOME/.jline.rc and add a line saying “jline.internal.Log.trace=true”. If you get a trace output, it would be great if you could send it to me, either via e-mail or via a github issue.

      Another thing you can try is to experiment with the Windows specific configuration properties as mentioned here:


      • Knut Hertel says:

        Hi Rüdiger,
        I added the debug line, and now the output loops with:
        [DEBUG] read Windows console input error: ReadConsoleInputW failed
        at org.fusesource.jansi.internal.Kernel32.readConsoleInputHelper(
        at org.fusesource.jansi.internal.Kernel32.readConsoleKeyInput(
        at org.fusesource.jansi.internal.WindowsSupport.readConsoleInput(
        at jline.WindowsTerminal.readConsoleInput(
        at jline.WindowsTerminal.access$000(
        at jline.WindowsTerminal$
        at jline.console.ConsoleReader.readCharacter(
        at jline.console.ConsoleReader.readCharacter(
        at jline.console.ConsoleReader.readBinding(
        at jline.console.ConsoleReader.readLine(
        at jline.console.ConsoleReader.readLine(
        at jline.console.ConsoleReader.readLine(
        at jline.console.ConsoleReader.readLine(
        at cli4clj.cli$create_jline_read_fn$fn__63.invoke(cli.clj:130)
        at clojure.main$repl$read_eval_print__7099$fn__7100.invoke(main.clj:238)
        at clojure.main$repl$read_eval_print__7099.invoke(main.clj:238)

    • ruedigergad says:


      I looked into this issue and I have some good but also some bad news.

      One good news is that I could reproduce your problem here with an ancient virtual machine image running Windows XP (Unfortunately, I do not have any computer around here running Windows nor even a newer Windows VM.).
      Another, hopefully, good news is, that the problem can be “solved” by setting “jline.WindowsTerminal.directConsole=false” in “$HOME/.jline.rc”.

      The bad news is that setting “jline.WindowsTerminal.directConsole=false” disables almost all cool features such as command editing, command history, useful tab completion etc.

      I am still not 100% sure but to me it looks like that this could be a problem with jline or with the jansi library that is used by jline.

      What Windows version did you use?
      Do you, by chance, have the possibility to try this on other Windows versions as well?

      If, by chance, someone else is reading this, it would also be helpful if others could report their results of trying to run the cli4clj example on Windows.


      • Knut Hertel says:

        Hi Rüdiger,

        sorry, I was bogged down by tedious work at the office, so I had no time to respond. I actually use Windows 7 and Windows 8.1 (still), but I will try your workaround.

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.