> ## Documentation Index
> Fetch the complete documentation index at: https://runelite.zip/llms.txt
> Use this file to discover all available pages before exploring further.

# Java Shell

> Runtime Groovy evaluator with RuneLite and n3 API bindings, reflected completions, and a standalone editor window.

# Java Shell

`JavaShellPlugin` operates as a disabled-by-default, hidden developer tool. It provides a lazily-created Groovy evaluator window with pre-bound RuneLite client, n3 `Api.actions.*`, and SDK query bindings.

* **Entrypoint**: `com.n3plugins.javashell.JavaShellPlugin`
* **Descriptor**: `[n3] Java Shell` (`hidden = true`, session/developer console)
* **Config group**: none (no persistent configuration)
* **Enabled by default**: no
* **Break Handler**: none (developer tool, not an automation plugin)

## Architecture

```mermaid theme={null}
flowchart LR
    Plugin["JavaShellPlugin"] -->|sidebar click| Frame["JavaShellFrame"]
    Frame -->|Ctrl+Enter / Run| Executor["GroovyExecutor"]
    Executor -->|clientThread.invokeLater| ClientThread["RuneLite Client Thread"]
    Frame --> Editor["Plain Swing JTextArea"]
```

The plugin registers a sidebar `NavigationButton` on startup. Clicking it lazily creates and toggles a standalone `JavaShellFrame` window. The plugin creates the frame and its Groovy executor on demand and disposes them on shutdown. The editor is a dependency-free Swing `JTextArea`.

## Groovy Evaluator

`GroovyExecutor` evaluates session-only Groovy snippets using Groovy 3.0.17. Each execution:

1. Creates a fresh `GroovyShell` with the plugin's classloader.
2. Binds `client` (RuneLite `Client`) and `clientThread` (`ClientThread`) as instance variables.
3. Binds n3 `Api.actions.*` and `sdk.query.*` types as static API facades.
4. Redirects `System.out` / `System.err` to the output pane for the duration of the snippet.
5. Captures and displays the evaluation result or any caught exception.

Execution happens on the **RuneLite client thread** via `clientThread.invokeLater(...)`. Snippets read live game state directly. Only one script runs at a time; a `running` flag prevents concurrent dispatch.

:::warning\[Caution]

Snippets execute with full access to the RuneLite client and n3 SDK. Arbitrary code can mutate game state, dispatch packets, and interfere with running automation. Use only for developer debugging and inspection.

Tab-dependent requested actions propagate `WIDGET_HIDDEN` and do not select a side tab. Use `tabActions.open(...)`, wait until `tabActions.isOpen(...)` is true, and only then call the inventory, equipment, prayer, magic, or combat action.

:::

### Pre-Bound Variables

| Variable            | Type                    | Kind                                       |
| ------------------- | ----------------------- | ------------------------------------------ |
| `client`            | `Client`                | Instance, the RuneLite client              |
| `clientThread`      | `ClientThread`          | Instance, RuneLite client thread scheduler |
| `bankActions`       | `BankActions`           | Static facade                              |
| `dialogActions`     | `DialogActions`         | Static facade                              |
| `inventoryActions`  | `InventoryActions`      | Static facade                              |
| `magicActions`      | `MagicActions`          | Static facade                              |
| `npcActions`        | `NPCActions`            | Static facade                              |
| `navigationActions` | `NavigationActions`     | Static facade                              |
| `objectActions`     | `ObjectActions`         | Static facade                              |
| `playerActions`     | `PlayerActions`         | Static facade                              |
| `prayerActions`     | `PrayerActions`         | Static facade                              |
| `tileItemActions`   | `TileItemActions`       | Static facade                              |
| `widgetActions`     | `WidgetActions`         | Static facade                              |
| `bank`              | `Bank`                  | Static query builder                       |
| `inventory`         | `Inventory`             | Static query builder                       |
| `npcs`              | `NPCs`                  | Static query builder                       |
| `objects`           | `TileObjects`           | Static query builder                       |
| `players`           | `Players`               | Static query builder                       |
| `tileItems`         | `TileItems`             | Static query builder                       |
| `interactionApi`    | `Map<String, Class<?>>` | All API type bindings                      |

Static bindings expose only static methods in autocompletion. Instance bindings (`client`, `clientThread`) expose all public methods.

## Editor

The editor window currently uses a plain `JTextArea` without syntax highlighting or completions. The execution bindings remain available; richer editor integration is deferred until it can be supplied without the removed FifeSoft runtime jars.

### Controls

| Control                 | Action                             |
| ----------------------- | ---------------------------------- |
| **Ctrl+Enter**          | Execute the current editor content |
| **Run Code** button     | Same as Ctrl+Enter                 |
| **Clear Output** button | Clears the output pane             |

### Output Pane

The output area displays captured `System.out`/`System.err` text, evaluation results prefixed with `=> `, and errors prefixed with `Error: `. The pane caps output at 40,000 characters and trims excess from the beginning.

## Plugin-Manifest Dependencies

The Java Shell does not require external editor or JShell jars. FlatLaf Extras is bundled non-transitively in the distributed suite for Developer Tools Swing inspection and is unrelated to Java Shell execution. RuneLite supplies FlatLaf core.

The fat jar packages Groovy 3.0.17 as a runtime dependency.

## Example Snippets

```groovy theme={null}
// Read current game state
client.getGameState()

// Query inventory for rune essence
inventory.search().withName("Rune essence").result()

// Check if bank is open
bankActions.isOpen()

// Walk to a location
import net.runelite.api.coords.WorldPoint
navigationActions.walkTo(new WorldPoint(3164, 3486, 0))

// List nearby NPCs
npcs.search().result().each { println it.getName() }
```

## Testing

```powershell theme={null}
.\gradlew.bat test --tests com.n3plugins.javashell.* --console plain
```

Break Handlers run active-only.
