ShellBar is a tool designed to streamline how developers interact with their projects, especially in complex environments such as monorepos. ShellBar is NOT a fork of Ghostty. It uses
libghostty-vtas a library via CMake FetchContent, maintaining complete independence from upstream Ghostty.
ShellBar is a tool designed to streamline how developers interact with their projects, especially in complex environments such as monorepos.
In modern development workflows, terminal commands are often long, repetitive, and hard to remember. They are typically scattered across package.json files or internal documentation, forcing developers to spend valuable time searching for how to run common tasks.
ShellBar solves this by centralizing your most frequently used commands into a dedicated action bar within the shell, turning them into instant, one-click shortcuts.
This becomes especially powerful in monorepos or multi-environment projects (local, staging, production), as well as setups that vary by platform (web, desktop, mobile). Instead of repeatedly consulting documentation or navigating through scripts, developers can immediately trigger the right workflow.
The result is a more focused, efficient, and productive environment where operational friction is reduced, allowing developers to concentrate on what truly matters: building software.
Visually it's a Ghostty-like terminal for Linux (GTK4 + libadwaita, dark theme, inline tabs). The difference is the button bar that you configure to run any command on the active terminal.
- Full terminal with VT100-520, 256 colors, true color, Kitty protocol support
- Configurable toolbar with command buttons from
~/.config/shellbar/config - Text selection with copy-on-select, mouse drag, double-click word, triple-click line
- Copy / Paste (Ctrl+Shift+C / Ctrl+Shift+V) with GTK clipboard, middle-click paste
- Shift+Click and Shift+Arrow keys extend selection
- URL detection with hover underline, pointer cursor, and Ctrl+Click to open
- Smooth animated auto-scroll to bottom on Enter key
- I-beam cursor for text selection areas
- Drag-and-drop reorder in Preferences dialog
- Utility bar — auto-detects installed TUI tools (btop, htop, lazygit, etc.) and launches them in the active terminal
- iOS-style toggle switches for toolbar and utility bar with Cairo-drawn animated controls
- Improved keyboard focus — capture-phase key handler ensures keystrokes reach the terminal even after tab close or dialog interaction
- Minimum terminal size (80×24) enforced to fit tools like btop
- Right-click context menu: Copy, Paste, Select All
- Configurable keybinds in config file
- Tabs with
AdwTabBar+AdwTabView, each with its own shell - Dynamic tab titles (OSC 0/2 from the shell)
- Visual Ghostty clone (dark theme, GTK4/libadwaita, no window title)
- Infinite scrollback (configurable)
- Cairo + Pango rendering (anti-aliasing, unicode, font fallback)
key = valueconfig format (same as Ghostty)- Hot-reload config via
SIGHUP Ctrl+Tshortcut for new tabAlt+1..Alt+0shortcuts for toolbar buttons- Wayland and X11 compatible
curl -LO https://github.com/rendergraf/shellbar/releases/latest/download/shellbar-1.6.0-1.x86_64.rpm
sudo rpm -i shellbar-1.6.0-1.x86_64.rpmOr with dnf:
sudo dnf install https://github.com/rendergraf/shellbar/releases/latest/download/shellbar-1.6.0-1.x86_64.rpmcurl -LO https://github.com/rendergraf/shellbar/releases/latest/download/shellbar_1.6.0_amd64.deb
sudo dpkg -i shellbar_1.6.0_amd64.deb
sudo apt-get install -fcurl -LO https://github.com/rendergraf/shellbar/releases/latest/download/shellbar-1.6.0-1-x86_64.pkg.tar.zst
sudo pacman -U shellbar-1.6.0-1-x86_64.pkg.tar.zstZig (>= 0.15.2) is downloaded automatically during the build process and stored in build/.
git clone https://github.com/rendergraf/shellbar
cd shellbar
cmake -B build -G Ninja
cmake --build build
./build/shellbarRelease build: cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
The build-release.sh script builds Debian, Arch Linux, and Fedora packages:
./build-release.sh 1.6.0 # All packages (.deb + .pkg.tar.zst + .rpm)
./build-release.sh 1.6.0 --deb-only # Debian only
./build-release.sh 1.6.0 --arch-only # Arch only
./build-release.sh 1.6.0 --rpm-only # Fedora onlyPackages are generated in build/:
- Debian/Ubuntu:
shellbar_1.6.0_amd64.deb— install withsudo dpkg -i - Arch Linux:
shellbar-1.6.0-1-x86_64.pkg.tar.zst— install withsudo pacman -U - Fedora/RHEL:
shellbar-1.6.0-1.x86_64.rpm— install withsudo rpm -i
| Dependency | Version | Purpose |
|---|---|---|
| Zig | >= 0.15.2 | Build libghostty-vt (auto-downloaded) |
| C compiler | C11 (gcc/clang) | Build ShellBar |
| CMake | >= 3.19 | Build system |
| Ninja | — | Build backend |
| GTK4 | >= 4.12 | GUI toolkit |
| libadwaita | >= 1.5 | Windows, tabs, styles |
| Pango | — | Terminal text |
| Cairo | — | Terminal rendering |
| git | — | Fetch libghostty-vt |
Debian/Ubuntu 24.04:
sudo apt install build-essential cmake ninja-build \
libgtk-4-dev libadwaita-1-dev libpango1.0-dev \
libcairo2-dev git wgetFedora 41+:
sudo dnf install gcc cmake ninja-build gtk4-devel libadwaita-devel \
pango-devel cairo-devel git wgetArch Linux / EndeavourOS:
sudo pacman -S base-devel cmake ninja gtk4 libadwaita pango cairo git wgetFile: ~/.config/shellbar/config
Format: key = value (same as Ghostty):
# Toolbar buttons
toolbar-button = name="Storybook", command="pnpm storybook", icon="media-playback-start"
toolbar-button = name="Build", command="pnpm build", icon="emblem-system"
toolbar-button = name="Test", command="pnpm test --watch", icon="emblem-default"
toolbar-button = name="Lint", command="pnpm lint --fix", icon="emblem-important"
# Keybinds
keybind = action="copy", key="c", mods="ctrl+shift"
keybind = action="paste", key="v", mods="ctrl+shift"
keybind = action="select_all", key="a", mods="ctrl+shift"If the config file doesn't exist, default buttons and keybinds are used.
kill -HUP $(pidof shellbar)| Shortcut | Action |
|---|---|
Ctrl+T |
New tab |
Ctrl+Shift+C |
Copy selection |
Ctrl+Shift+V |
Paste |
Ctrl+Shift+A |
Select all |
Alt+1..Alt+9, Alt+0 |
Execute toolbar buttons 1–10 |
Shift+Click |
Extend selection to clicked position |
Shift+← Shift+→ Shift+↑ Shift+↓ |
Extend selection by one cell |
Ctrl+Click on URL |
Open URL in default browser |
| Action | Result |
|---|---|
| Drag | Select text (top-to-bottom and bottom-to-top) |
| Double-click | Select word |
| Triple-click | Select entire line |
| Middle-click | Paste from clipboard |
| Right-click | Context menu (Copy / Paste / Select All) |
| Hover over URL | Underline highlight + pointer cursor + "Ctrl+Click" tooltip |
| Hover over text | I-beam cursor for selection |
Keybinds are configurable via ~/.config/shellbar/config:
keybind = action="copy", key="c", mods="ctrl+shift"
keybind = action="paste", key="v", mods="ctrl+shift"
keybind = action="select_all", key="a", mods="ctrl+shift"Available actions: copy, paste, select_all.
Available mods: ctrl, shift, alt, super (combined with +).
AdwTabBaris a standalone top bar insideAdwToolbarView, below the header — never hidden (autohide = FALSE)AdwTabViewis the main content areaadw_tab_view_append()adds each terminal widget as a pageadw_tab_bar_set_view()links the bar to the view so pages sync automatically"notify::selected-page"updates the toolbar's active terminal on tab switch"close-page"destroys the terminal and removes the page- Each tab has its own
forkptyPTY, Ghostty VT state, and Cairo render surface
shellbar/
├── CMakeLists.txt # Build: fetches libghostty-vt + GTK4 + Cairo/Pango
├── shellbar.c # AdwApplication entry point
├── sb_window.c/h # AdwApplicationWindow + AdwTabView + header
├── sb_terminal.c/h # Terminal: PTY + libghostty-vt + Cairo render + input
├── sb_toolbar.c/h # Toolbar with command buttons
├── sb_config.c/h # Config key=value from ~/.config/shellbar/config
├── sb_preferences_dialog.c/h # Preferences dialog for editing buttons
└── README.md # This file
GtkEventControllerKeyonAdwToolbarView(capture phase) catches all keysCtrl+T→ new tab;Alt+1..0→ toolbar shortcuts- Remaining keys are forwarded to
sb_terminal_handle_key() - Configurable keybinds are checked first (copy, paste, select_all)
- If the key maps to a Ghostty key (
gdk_keyval_to_ghostty):ghostty_key_encoder_encode()produces the escape sequence- The result is written to the PTY
- If the key does not map (symbols like
*,!,ñ,ü):- UTF-8 text is written directly to the PTY via
gdk_keyval_to_unicode()
- UTF-8 text is written directly to the PTY via
- If the Ghostty encoder produces no output but UTF-8 text is available, the text is written directly (fallback)
This approach guarantees compatibility with all keyboard characters while using the Ghostty encoder for control keys, function keys, and modifier sequences.
Xavier Araque — xavieraraque@gmail.com — May 2026
MIT © 2026 Xavier Araque




