Gregor Lohaus 1f7394d75a add opt-in render profiler instrumentation
Gated behind -Djprototerm.profile=true (or JPROTOTERM_PROFILE=1), accumulates
per-frame nanos into snapshot/fingerprint/draw/frame-total buckets and dumps
to stderr every N renders. Splits the three suspected render costs: native
snapshot marshaling, fingerprint hashing, and canvas draw recording.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 21:04:00 +02:00
2026-05-28 00:33:38 +02:00
2026-05-28 23:52:23 +02:00
2026-05-31 15:45:55 +02:00
2026-05-31 18:51:16 +02:00
2026-05-28 00:33:38 +02:00
2026-05-29 12:33:32 +02:00
2026-05-29 12:33:32 +02:00
2026-05-28 00:33:38 +02:00
2026-05-28 02:07:44 +02:00
2026-05-28 00:33:38 +02:00
2026-05-29 20:37:16 +02:00
2026-05-28 22:18:59 +02:00
2026-05-28 23:52:23 +02:00

jprototerm

JavaFX canvas terminal prototype using jlibghostty for terminal emulation and Nix for the build environment. It builds a plain JavaFX application (JDK 25, JavaFX 25 via Gradle) packaged as a Nix derivation — no GraalVM/GluonFX native image. It supports tiled and floating panes and tabs.

Caution

nix profile add has only been tested on Debian with the proprietary NVIDIA driver. The runtime GL shim hardcodes Debian's /lib/x86_64-linux-gnu driver paths and selects the NVIDIA GLX/EGL vendor, so it likely won't work yet on other distros, Wayland-only setups, or Mesa/AMD/Intel GPUs. I'm happy to accept pull requests that broaden host support.

Build

nix build
./result/bin/jprototerm

Install it into a profile (see the caution above on host support):

nix profile add .
jprototerm

Or install straight from the remote — note the git+https:// scheme (a bare https:// URL is treated as a tarball, not a git repo):

nix profile add git+https://gitea.gregorlohaus.com/gregor/jprototerm

Add ?ref=<branch-or-tag> to pin a revision. The target machine needs Nix with the nix-command and flakes features enabled and network access — the build fetches the jlibghostty/ghostty flake inputs plus the JDK and Gradle from the binary caches.

The flake bundles everything the app needs — the JDK 25 runtime, the Maven JavaFX modules and their native libraries, and the gtk/glib/freetype/X11 libraries they load — except the system OpenGL/graphics drivers. libGL is supplied by the host at runtime through a GL shim in the launcher wrapper, so the same closure runs against NixOS, Mesa, or vendor (e.g. NVIDIA) GPU drivers.

Gradle dependencies are vendored in deps.json for the pure Nix sandbox. Regenerate it after changing dependencies in build.gradle (the update script writes deps.json in the current directory):

$(nix build .#gradleDepsUpdateScript --no-link --print-out-paths)

For development:

nix develop
gradle run

The Gradle project is the source of truth for the JavaFX build.

Config

Configuration is read from:

$XDG_CONFIG_HOME/jprototerm/config.toml

If XDG_CONFIG_HOME is unset, the fallback is:

$HOME/.config/jprototerm/config.toml

If no config file exists, jprototerm writes the default config on startup.

Example, also available in config.example.toml:

[terminal]
columns = 100
rows = 30
shell = "/bin/bash"
font_family = "JetBrainsMono Nerd Font"
font_size = 15

[window]
width = 1200
height = 760

[kitty_graphics]
enabled = true

[scrollback]
editor_command = "vi {file}"

[env.override]
ZELLIJ_SESSION_NAME = ""

[keybindings]
navigate_left = "ALT+H"
navigate_down = "ALT+J"
navigate_up = "ALT+K"
navigate_right = "ALT+L"
toggle_floating = "ALT+F"
new_pane = "ALT+N"
close_pane = "ALT+X"
new_tab = "ALT+A"
previous_tab = "ALT+SHIFT+H"
next_tab = "ALT+SHIFT+L"
open_font_selector = "ALT+T"
open_scrollback = "ALT+S"

Defaults

  • Alt+h/j/k/l: navigate panes
  • Alt+n: new pane — a floating pane when floating panes are shown, otherwise a new tiled pane (tiled panes are split equally across the width)
  • Alt+f: show or hide all floating panes
  • Alt+x: close the active pane; closing a tab's last pane closes the tab, and closing the last pane of the last tab quits
  • Alt+a: new tab
  • Alt+Shift+h / Alt+Shift+l: previous / next tab
  • Alt+t: open the font selector
  • Alt+s: open the active pane scrollback in $EDITOR
  • Font default: JetBrainsMono Nerd Font
  • Kitty graphics protocol parsing is enabled by default

Each tab has its own stack of tiled and floating panes; only the active tab is rendered. A thin tab bar appears at the top when more than one tab is open. Closing the last tiled pane while floating panes exist promotes the most recently active floating pane to a tiled pane.

Description
No description provided
Readme 46 MiB
Languages
Java 96.1%
Nix 3.9%