groovysh & groovyconsole

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against Apache Groovy 6.0.0 (released 2026-09-22), run on JDK 26 and checked on 2026-10-14. Groovy ships two interactive tools in $GROOVY_HOME/bin. groovysh is a terminal REPL (read-eval-print loop), rebuilt on JLine 3 in Groovy 5.0, with a slash-command system, completion and history. groovyConsole is a Swing window with an editor pane and an output pane, useful for developing a script and for looking at the compiler’s AST. Both are for experimenting; production scripts run with the groovy command described on Running Scripts & the groovy Command.

The groovysh transcripts below were produced by piping the typed lines to groovysh -q -C false (quiet, no colour) and trimming the banner; colours, completion and the line editor need a real terminal. The JVM was started with -Duser.home pointing to a scratch directory so that history and aliases did not touch a real home directory.

groovysh

Start it with groovysh; leave with /exit, because Ctrl+C is trapped by JLine. groovysh --help lists the options of 6.0.0:

Option Meaning

-e, --evaluate=<code>

Evaluate the code first, then stay in the interactive session

-q, --quiet

Suppress the banner and other superfluous output

-C, --color[=<flag>]

Enable or disable ANSI colours

-cp, -classpath, --classpath

Classpath; must be the first argument. Since 6.0 an explicit classpath no longer gets . appended

-D, --define=<name=value>

Define a system property

-c, --encoding=<charset>

Encoding

-d, --debug; -v, --verbose

Debug output; verbose output

-pa, --parameters

Store method parameter names in generated classes

-pr, --enable-preview

Enable JDK preview features; after the classpath, before other arguments

-T, --terminal=<type>

Terminal type

-V, --version; -h, --help

Version; usage

groovysh -q -e 'println 6*7' evaluates the expression and then shows the prompt; the output was 42 followed by groovy>.

The REPL model

groovysh reads a line and decides whether it is a complete expression, statement or definition. If not, it prompts for more; if so, it compiles and runs it and prints the result, then stores that result in the shared variable _. Each input is run in isolation. The exceptions to that rule are what makes the shell usable:

  • import statements are remembered and apply to every later input.

  • Class and other type definitions are remembered.

  • Variables without a type or def (foo = 'bar') are the script binding, called the shell’s shared variables, and persist.

  • What happens to def variables and to methods depends on the interpreter mode.

In interpreter mode the shell behaves as if the remembered definitions were pasted before every input, so local variables and methods survive. With the mode off, a def variable is forgotten at the end of its input, and a method becomes a closure stored in the shared variables. In the installation used for this page, 6.0.0, the mode was on by default, as the GROOVYSH_OPTIONS entry of /show confirms ([interpreterMode:true]). A session in the default mode:

groovy> def soil = 0.27
0.27
groovy> soil * 2
0.54
groovy> class Zone { String name }
groovy> new Zone(name: "bench-1")
Zone@32faa16c
groovy> import java.time.*
groovy> LocalDate.of(2026,10,14).dayOfWeek
WEDNESDAY
groovy> /imports
 import java.time.*
groovy> /types
 class Zone { String name }
groovy> /vars
 def soil = 0.27
groovy> /del soil
groovy> /vars

groovy> throw new RuntimeException("boom")
RuntimeException: boom

The commands /imports, /types, /vars and /methods list what has been remembered, each with a -d option that deletes entries; /del name deletes a name of any kind. An exception is printed in short form, and its details are kept in a shared variable called exception. Setting the mode off changes the behaviour as the documentation describes:

groovy> GROOVYSH_OPTIONS.interpreterMode = false
groovy> def a = 1
1
groovy> a
MissingPropertyException: No such property: a for class: Script5
groovy> b = 2
groovy> b
2
groovy> def hello(n) { "Hello $n" }
groovy> hello("x")
Hello x
groovy> /show
...
b                2
...
hello            [closure:Script10$_run_closure1]
...
GROOVYSH_OPTIONS [interpreterMode:false]

The lines elided with ... are the shell’s own variables (the console options, the working directory and _). The shared variable b survives, and so does the method hello, but as a closure in the same namespace as the variables; the local a is gone. The advice in the documentation follows: in the non-interpreter mode, treat local variables as immutable, and keep what you need in shared variables. In interpreter mode, remember that each def x = [] is replayed before every later input, so an earlier mutation of x is undone; the documentation gives the example of def fruit = [] followed by fruit << 'peach' and fruit << 'pear', after which fruit is empty again.

Commands

Commands start with a slash and have help text: /help lists them, and /help /name or /name --help explains one. Some have system aliases such as /h. groovysh keeps its own notion of the working directory, so /cd and /pwd affect the file commands but not the JVM’s directory; the shared variable PWD helps when you shell out with /!. In 6.0.0 the commands are:

Group Commands

Shell and state

/help, /exit, /reset (clear the buffer), /show (shared variables), /vars, /methods, /types, /imports, /del, /classloader, /setvar, /setopt, /unsetopt, /keymap, /widget, /highlighter, /colors

Input and output

/echo, /prnt (formatted print), /img (inline image, new in 6.0), /slurp, /load, /save, /history

Files

/ls, /cd, /pwd, /cat, /less, /head, /tail, /wc, /grep, /sort, /nano

Dependencies

/grab

Other tools

/inspect (object browser), /console (open the buffer in groovyConsole), /doc (open documentation in a browser), /date, /ttop (thread view), /pipe, /alias, /unalias, /! (run an operating-system command)

A few of them are worth a closer look.

/slurp and /load

/slurp parses a file into an object without evaluating it. The format comes from the file extension or the content (JSON, XML, YAML, TOML, CSV, Markdown and .properties), and the result lands in _:

groovy> /slurp plants.json
{plants=[{name=tomatoes, everyHours=2, zone=bench-1}, {name=basil, everyHours=12, zone=basket-1}]}
groovy> plants = _
groovy> plants.plants[0].name
tomatoes
groovy> plants.plants*.name
[tomatoes, basil]
groovy> /slurp g.toml
{answer={universe=42}}

JSON, TOML and YAML go through JsonSlurper, TomlSlurper and YamlSlurper and give a lazy map; XML goes through XmlParser and gives a Node; since 6.0 Markdown is handled as well. The options are -e for the encoding and -f for the format. The content-based guess parses and never evaluates. Evaluating a file takes an explicit -f GROOVY, and against a URL that runs whatever the server returns, with your privileges: fetch it without -f and read it first. The JSON, TOML and XML formats are explained on JSON, YAML & TOML and CSV & Markdown.

/save file writes the buffer (the remembered imports, types, methods and variables) to a file, and /load file loads a file into the buffer. For example, /load state.groovy printed Loaded: followed by the path of the file.

/grab

/grab group:module:version adds a Maven dependency to the shell’s classpath at any moment, using Grape (see Grape Dependency Management). Completion offers artifacts already in ~/.m2 and ~/.groovy/grapes:

groovy> /grab org.apache.commons:commons-collections4:4.5.0
groovy> import org.apache.commons.collections4.bidimap.TreeBidiMap
groovy> TreeBidiMap t = [apple: "red"]
{apple=red}
groovy> t.inverseBidiMap()
{red=apple}

The same artifact is available in a script with @Grab('org.apache.commons:commons-collections4:4.5.0'). A dependency fetched this way comes from the network, so the same trust considerations apply as for any download.

/img

New in 6.0, /img draws an image in the terminal through JLine’s terminal-graphics support, which detects Sixel, Kitty or iTerm2 protocols. The argument is a file path, an http(s) URL or a Groovy value referenced as $name, and it accepts --width and --height. Accepted values are a BufferedImage, a RenderedImage, an object with a createBufferedImage(int, int) or toBufferedImage(int, int) method (JFreeChart and Smile figures are the examples in the documentation), and a Swing JComponent:

groovy> /grab org.jfree:jfreechart:1.5.6
groovy> chart = ChartFactory.createBarChart('demo', 'day', 'count', ds)
groovy> /img $chart --width=600 --height=400

This is a fragment from the official documentation, not run here, because it needs a terminal with a graphics protocol.

Aliases and pipes

/alias name fragment defines a command alias, for Groovy code or for another command. The alias is substituted before the command is looked up, so an alias with the name of a built-in command takes precedence over it (the documentation shows /cat replaced by a syntax-highlighting /less -F); /unalias removes one. Aliases are stored on disk. In the scratch run they were written to aliases.json in the .groovy directory of the home directory. /pipe creates and deletes pipe operators. One gotcha from the documentation: the slash starts a comment in Groovy, so quote a path argument that contains a wildcard, as in /ls '/tmp/*.txt'.

History, state and completion

Press Tab to complete class, property, method and command names, including your own types. History persists in the groovysh_history file of the .groovy directory in the home directory, as seen in the scratch run, and /history lists it:

groovy> /history
   27  /grab org.apache.commons:commons-collections4:4.5.0
   ...

The first lines, truncated here, show the earlier entries with their numbers. /show lists shared variables, and /ls and /pwd the working directory.

Widgets

JLine’s widget system is how keys are bound to line-editing actions. groovysh includes the standard ones (word movement, kill and yank) and two optional ones: tailtip, which shows completions and a usage window as you type, and autosuggest, which proposes the rest of a line from your history. They are off by default; /widget -l lists them, /keymap shows the keys bound to the tailtip-toggle and autosuggest-toggle widgets, and both can be on at once.

Embedding groovysh

An application that hosts groovysh (a domain console, say) uses Main.start(GroovyshOptions, String[]) rather than copying Main. The GroovyshOptions builder, which the documentation marks as incubating, sets the banner, prompt, bindings, extra command groups, result and error handlers, history file, and a hook for tuning the JLine reader. The following run hands the shell one variable, evaluates one expression, and collects the printed result instead of printing it:

import org.apache.groovy.groovysh.GroovyshOptions
import org.apache.groovy.groovysh.Main

def results = []
int rc = Main.start(GroovyshOptions.builder()
        .showBanner(false)
        .binding('zone', 'bench-1')
        .resultHandler { printer, result -> results << result }
        .build(), '-e', 'zone.toUpperCase()')
println "rc=$rc results=$results"
rc=0 results=[BENCH-1]

(JLine printed four WARNING lines about restricted native access to standard error when the script started; they are harmless and can be silenced with --enable-native-access=ALL-UNNAMED.) Main.start(Map, String[]) still exists as the binding-only variant. To evaluate with compile-time customizers, create a GroovyEngine from a mutable CompilerConfiguration:

import org.apache.groovy.groovysh.jline.GroovyEngine
import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.ImportCustomizer

def imports = new ImportCustomizer()
imports.addStarImports('java.util.concurrent.atomic')
def config = new CompilerConfiguration()
config.addCompilationCustomizers(imports)
def engine = new GroovyEngine(config)
assert engine.execute('new AtomicInteger(7).get()') == 7
println 'engine ok'

The output was engine ok. Use a copy of the default configuration, because the shared default instance must not be modified; an ASTTransformationCustomizer for @ThreadInterrupt is the usual addition so that Ctrl+C can stop a tight loop. The standard file commands (/ls, /cat, /grep, /wc and others) are in the public ExtraConsoleCommands class.

groovyConsole

groovyConsole opens a Swing window with an input area, where you write a script, and an output area, where whatever the script prints appears together with the value of its last expression if it is not null. Run the whole script from the Actions menu or with Ctrl+Enter or Ctrl+R; if you select part of the text, only the selection runs. The tool is graphical, so it was not run here: its command-line help, which did run, is

Usage: groovyConsole [options] [filename]
The Groovy Swing Console allows a user to enter and run Groovy scripts.
      --configscript=PARAM   A script for tweaking the compiler configuration options
      -cp, -classpath, --classpath
                             Specify where to find the class files - must be first argument
  -D, --define=<name=value>  Define a system property
  -h, --help                 Display this help message
  -pa, --parameters          Generate metadata for reflection on method parameter names
  -pr, --enable-preview      Enable preview Java features (jdk12+ only)
  -V, --version              Display the version

(The two longer option descriptions are shown unwrapped.) The rest of this section follows the official documentation.

Feature How it works

Files

File > Open (Ctrl+O), Save (Ctrl+S) and New File (Ctrl+Q); you can drag a Groovy file onto the text area

Output

"Capture System.out" in the Actions menu switches the capture of standard output on and off

History

the last ten runs are kept; Next and Previous in the Edit menu (Ctrl+N, Ctrl+P) move through them

Results

the last non-null result is bound to _; the result of every run in the history is in the list variable __, where __[-1] is the last run

Inspector

"Inspect Last" in the Actions menu opens a GUI inspector on the last non-null result, convenient for lists and maps

Classpath

Script menu: add a jar or a directory to the classpath of the running script

Script arguments

Script > Set Script Arguments: space-separated arguments passed to the script (6.0); before 6.0 you had to assign args in the script

Run as Java

Script > Run as Java (Alt+R), Run Selection as Java and Compile as Java treat the input as one public Java class and invoke its main, using the arguments from the same dialog

Fonts and errors

Smaller and Larger Font; compile errors and exceptions in the output are hyperlinks to the source line

Themes

light, dark, follow-system and custom themes, new in 6.0, applied to the editor, the output and the surrounding window and remembered between sessions

Interrupting a script

The dialog that appears while a script runs has an interrupt button. Interrupting only sets the thread’s interrupt flag, so a script stuck in a plain loop may go on running. Tick Script > Allow interruption to make the console apply the @ThreadInterrupt AST transformation to your script, which checks the flag in loops and method entries. The price is extra execution time for the checks. @ThreadInterrupt is one of the transformations on AST Transformations: Logging, Safety, Concurrency & Directives.

Visualising results

With View > Visualize Script Results ticked, a result that is a java.awt.Image, a javax.swing.Icon, or a parent-less java.awt.Component is displayed rather than shown as text. You can add your own transformations in ~/.groovy/OutputTransforms.groovy, a script that the console runs on startup with a transforms list in its binding. This example, from the documentation, shows a map as a table:

import javax.swing.*
transforms << { result ->
    if (result instanceof Map) {
        def table = new JTable(
            result.collect{ k, v ->
                [k, v?.inspect()] as Object[]
            } as Object[][],
            ['Key', 'Value'] as Object[])
        table.preferredViewportSize = table.preferredSize
        return new JScrollPane(table)
    }
}

It was not run here, because it needs a display. The console remembers all of its settings with the Java Preferences API.

The AST and CST browsers

The AST browser, opened from the Script menu, shows the syntax tree of the script being edited, together with the generated source and the bytecode. It is the quickest way to see what an AST transformation produced. The documentation’s example is a class annotated with @Immutable, whose generated equals appears in the Source tab, and the bytecode of the expression LocalDate.parse('2020/02/10', 'yyyy/MM/dd'). The CST browser shows the concrete syntax tree from the first parse and is mainly of use to people working on the parser. Writing your own transformations is covered on Writing AST Transformations & Macros.

Embedding the console

A Java or Groovy application can embed the console, preload variables and open it:

import groovy.ui.Console;

Console console = new Console();
console.setVariable("var1", getValueOfVar1());
console.setVariable("var2", getValueOfVar2());
console.run();

The code is from the documentation and was not run here, as it opens a window. The variables are available to scripts typed into the console. The console is in the groovy-console module; see Integrating Groovy into Java Applications for the general mechanisms.

Where the book is outdated

The first edition of the reference book (Groovy 1.0, 2007) treats groovysh as a simple line reader. Since Groovy 5.0 it is a JLine 3 shell with slash commands, completion, history, widgets and a configurable working directory, and since 6.0 it also shows inline images with /img and slurps Markdown. The book’s groovyConsole predates the history, the result inspector, the script arguments dialog (6.0), the light and dark themes (6.0), the AST browser and the Java mode described above. The book’s examples of loading a script into a session are replaced by /load and /save, and its way of adding libraries by /grab. The collected list of changes is on What’s New & Migrating from Older Versions.