A terminal that does not look like anyone else's: Ghostty with custom shaders, xonsh, a bespoke Starship prompt, and herdr, all in one palette.
It started as a console drawn for a film and was rebuilt as a real terminal: navy glass, one coral accent, and the rule that coral is the only thing that glows.
Shader. One GLSL pass, ember-glass.glsl, runs on the whole terminal. It gives coral shapes a faint halo (the accent is read from palette slot 5, so it follows the theme) and pulses the agent-state signal colours. A window that is not focused cools like banked embers, and a line of light sweeps down it as it warms back up on focus. The cursor does not blink: a halo breathes around it, and it leaves a thread from where it was to where it lands.
Python at the prompt. The shell is xonsh, so a line is either a command or Python, and the two mix: $(...) captures a command's output into a Python value, @(...) drops a Python value into a command, and pg`*.glsl` is a glob that returns Path objects. A readout at the top right of the live prompt flips between -- SHELL -- and -- PYTHON -- as you type.
ember.py adds charts that draw on the character grid: bars, spark, plot (a braille line chart, 2×4 dots per cell), gauge, panel, table. show(fig) draws a matplotlib figure, a PIL image or a PNG inline through the kitty graphics protocol, and ember.mpl() puts matplotlib in the palette first.
The readout stays quiet: a CPU sparkline joins it above 70% load and a memory meter above 80%. Once a line is run the readout clears and the prompt bar collapses to a bare ❯ (red after a failure), so the scrollback is commands and their output.
Workspaces. herdr is themed to match: coral active tab and focus border, a transparent sidebar, panes open xonsh. Agent state is drawn in two signal colours that appear nowhere else in the theme, and the glass shader looks for exactly those colours: working breathes amber on a slow cycle, blocked gives two soft pink-red beats and rests. It is all config; herdr itself is untouched.
Claude Code. A custom theme recolours all of Claude Code's interface in the palette, and its status line repeats the prompt: callsign block, directory, branch, then the model and how full the context is. It is a theme file, a script and two settings; Claude Code itself is untouched.
Codex and omp. Both get an Ember theme through their own theme folders. Codex's covers syntax highlighting, diffs and the footer colours it derives from them; its composer shading and spinners are fixed by Codex and stay as they are. omp's covers its whole interface: borders, messages, tool output, syntax and status line.
Hidden window controls. The title bar is a blank strip in the terminal's own colour. The buttons fade in only while the mouse is over it.
Tools. eza, bat, fzf, delta, fastfetch and btop all use the same colours.
| Hex | Used for | |
|---|---|---|
| glass | #070B16 |
background |
| line | #1E2A44 |
borders, rules, inactive meter |
| dim | #687A9D |
labels, comments (4.5:1 on the glass) |
| text | #C9D3E3 |
body |
| bright | #F4F7FB |
bold, titles |
| coral | #F47853 |
prompt, cursor, focus (ANSI magenta slot) |
| teal | #4FD1C5 |
added, pass |
| amber | #F2B866 |
warnings, strings |
| red | #E5484D |
removed, errors |
Originally built on Ubuntu 24.04 with GNOME, X11 and NVIDIA. Also tested on Ubuntu 26.04.1 with GNOME Shell 50.1, Wayland, GTK 4.22.4, libadwaita 1.9.1 and an NVIDIA RTX 3060 (driver 580.178.04), at 3440×1440/60 Hz. X11 is not required.
| Tool | Version used |
|---|---|
| Ghostty | 1.3.1 (shader colour and focus uniforms need 1.3) |
| xonsh | 0.24.2, with xontrib-term-integrations |
| Starship | 1.26 |
| herdr | 0.9.3 (optional) |
| Claude Code | 2.1.291 (optional; the status line needs jq) |
| Codex CLI | 0.160.1 (optional) |
| omp | 18.6.1 (optional) |
| fastfetch, eza, bat, btop, fzf, zoxide, delta, ripgrep | current releases |
xonsh in its own environment:
uv tool install 'xonsh[full]' --with xontrib-term-integrationsThe font is Space Mono; the installer downloads it if it is missing. Icons come from Ghostty's built-in Nerd Font fallback.
On NVIDIA, __GL_YIELD=USLEEP lets the driver sleep while Ghostty waits in
glFinish(), reducing measured main-thread CPU from 40.47% to 7.67% of one
core on the setup above, with all effects retained.
See NVIDIA's yield setting
and Ghostty 1.3.1's frame completion.
The installer sets this in a systemd user drop-in for
app-com.mitchellh.ghostty.service and reloads unit definitions without restarting
Ghostty. It takes effect on the service's next start. For shell launches, or
packages without that unit, use:
env __GL_YIELD=USLEEP ghosttygit clone https://github.com/vantasnerdan/marbell-ember
cd marbell-ember
./install.shThe installer copies configs and the Ghostty systemd user drop-in into ~/.config
(respecting XDG_CONFIG_HOME), keeps a numbered backup of every file it replaces,
and lists any tools that are missing. It leaves the packaged launcher and unit
alone, installs no packages and does not change your login shell.
If Claude Code is installed, the installer also copies the theme and status line into
~/.claude (or CLAUDE_CONFIG_DIR) and sets theme and statusLine in its
settings.json. Those two keys replace whatever was set before; every other setting
is left as it was, and the previous file is kept as a numbered backup. This step needs
jq: without it the files are still copied and the installer asks you to install jq
and run it again.
If Codex is installed, the theme goes into ~/.codex/themes (or CODEX_HOME) and the
[tui] keys in codex/config.toml are merged into its config.toml: theme is set,
the others are added only where missing, and nothing outside [tui] is touched. If omp
is installed, the theme goes into its themes folder and is selected with
omp config set. Both keep a backup of the config they change. Restart either agent,
or pick the theme again with /theme, to see it.
omp has no theme inheritance, so its theme is a complete colour map: an omp release that adds a required colour may need the theme refreshed.
Ghostty starts xonsh directly, so nothing from ~/.bashrc is inherited. Put your PATH entries and exports in ~/.config/xonsh/local.xsh; the installer creates it from xonsh/local.xsh.example.
xonsh is not bash. Agents are unaffected: $SHELL stays /bin/bash, so Claude Code, Codex and anything else that shells out keeps using bash, and herdr still detects agents started from an xonsh pane. What changes is what a person types or pastes at the prompt:
| bash | here |
|---|---|
export FOO=bar, unset FOO |
work (shimmed in rc.xsh) |
FOO=bar cmd |
$FOO="bar" cmd |
${HOME} |
$HOME |
echo $? |
the prompt shows ✗ <code>; in code, __xonsh__.history.rtns[-1] |
`cmd` |
$(cmd) |
for i in 1 2 3; do ...; done |
a Python for loop, or bash -c '...' |
cat <<EOF heredocs |
bash -c '...', or a Python string |
source script.sh, source venv/bin/activate |
source-bash script.sh; for virtualenvs, xontrib load vox then vox activate |
| pasting several lines | runs after a second Enter |
&&, ||, ;, pipes, redirects, 2>&1, &, Ctrl-C, Ctrl-Z / fg, $(...), ~, tab completion and full-screen programs behave as in bash. ls is eza, but falls back to real ls for flag clusters eza reads differently, such as ls -ltr.
Every optional tool is guarded. On a machine with only xonsh installed the same rc.xsh still loads: a native prompt in the Ember colours replaces Starship, ls is plain ls, and Ctrl-R is xonsh's built-in search.
The optional Ubuntu 26.04 desktop theme carries Ember into window bars, a named GTK3/GTK4 theme and libadwaita user CSS, GNOME Shell through User Themes, and folder icons. It also sets the wallpaper, dock, Space Mono fonts and GNOME Terminal/Ptyxis profiles, adds a Nerd Font fallback for Space Mono, and supplies a GTK override for the Brave snap. Teal navigation, amber headings and blue file details sit against navy; coral marks focus and selection.
GTK/Shell theme bases and folder icons are generated from your installed Yaru at install time. Derived Ubuntu themes are not shipped. The repo supplies the builders, CSS overrides and five ultrawide wallpapers.
With the desktop requirements installed, apply from the checkout:
./gnome/apply.shRestore the saved settings and files, including Shell and icons:
./gnome/revert.shReopen applications to load their CSS. On first installation, User Themes and existing XWayland title bars take effect at the next login. The scripts do not restart the desktop, change the login screen or boot splash, or add blur or animation. See desktop usage for dependencies, backups, browser setup and limits.
ghostty/ config.ghostty, ember.css (hover-only title bar), themes/Marbell Ember, shaders/ember-glass.glsl
ember/ ember.py (charts, inline images, live readout), plate.png, make_plate.py, logo.txt, delta.gitconfig
xonsh/ rc.xsh, local.xsh.example
starship.toml
herdr/ config.toml
claude/ themes/marbell-ember.json, statusline-ember.sh
codex/ themes/marbell-ember.tmTheme, config.toml (the [tui] keys to merge)
omp/ themes/marbell-ember.json, config.yml (the keys the installer sets)
fastfetch/ config.jsonc
bat/ btop/ tool themes
gnome/ desktop builders, CSS, wallpapers, profiles, apply/revert scripts
- The word in the prompt block:
$EMBER_CALLSIGN(defaultMARBELL). - Shader strength and pace: the constants at the top of
ember-glass.glsl.TAPSis the halo's sample count (smoother and costlier as it rises),BANKis how far an unfocused window cools (0.0for none), and the*_PERIODvalues set how slowly the beacons and the cursor breathe. - The full prompt bar on every line:
$EMBER_TRANSIENT = "0"inlocal.xsh. - CPU and memory always in the readout:
$EMBER_CPU_HOT = "0"and$EMBER_MEM_HOT = "0"inlocal.xsh(the defaults are0.70and0.80). - The boot card opens with the first window of a login session;
bootshows it again. - A command that ran for 10 s or more while the window was not focused raises a notification when it ends (
notify-on-command-finishinconfig.ghostty). - A different background plate:
python3 ember/make_plate.py plate.png <seed>(needs numpy and Pillow). - The title bar is an invisible strip at the top (
ghostty/ember.css). Hover it and the window buttons fade in; drag it to move, double-click to maximise, drag the edges to resize.ctrl+shift+dremoves it entirely. ctrl+rsearches history andctrl+tpicks files, both through fzf.- xonsh keeps its own history (SQLite under
~/.local/share/xonsh/); it does not read~/.bash_history.
- The terminal is opaque on purpose. A see-through terminal shows whatever is behind it on a screen share. GNOME has no compositor blur, so the "glass" is a baked plate.
- The prompt shows no user or host name, and the boot card shows no hostname or IP.
- btop's release binaries have no GPU support; build it from source for the GPU panel.
- Starship has no transient prompt for xonsh, so
rc.xshdoes it: the prompt function returns a bare❯on prompt_toolkit's last repaint of a line. - The lens falloff toward the corners is baked into the plate, so it darkens the glass and not the text.
- Images from
show()need a terminal that speaks the kitty graphics protocol, directly: a multiplexer in between may not pass them on. - The optional desktop theme under
gnome/still uses the earlier dim,#5B6B8C.








