Author: Xavier Araque xavieraraque@gmail.com — May 2026 Repo: github.com/rendergraf/shellbar
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.
Technically, ShellBar is a terminal emulator based on libghostty-vt (Ghostty's core) that looks and feels like Ghostty, but adds a configurable toolbar with buttons that execute commands on the active terminal.
┌─────────────────────────────────────────────────────────┐
│ shellbar/ ← our own project, independent │
│ │
│ cmake --build . → ./shellbar │
│ │ │
│ ├── uses libghostty-vt (VT emulation C library) │
│ │ (fetched by CMake from the ghostty repo) │
│ │ │
│ └── references ghostling/main.c for patterns │
│ (PTY, input, render) │
│ │
│ shellbar does NOT modify ghostty/ or ghostling/ │
│ shellbar is NOT a fork — it's a new project │
└─────────────────────────────────────────────────────────┘
We never touch the ghostty/ or ghostling/ directories.
Both remain clean upstream repos so we can git pull.
| Layer | Technology | Reason |
|---|---|---|
| Language | C11 | Simple, portable, same as Ghostling |
| GUI | GTK4 + libadwaita | Same toolkit as Ghostty on Linux — identical appearance |
| Terminal core | libghostty-vt (Zig → .so) | Full VT engine, SIMD, scrollback, colors, Kitty protocol |
| PTY | forkpty (glibc) | Standard Unix, same API as Ghostling |
| Render | Cairo (via GtkDrawingArea) | Natural GTK4 integration, software render |
| Text | Pango + FontConfig | Anti-aliasing, unicode, font fallback |
| Build | CMake 3.19+ + Ninja | Same system as Ghostling |
| Config | key = value (like Ghostty) | Familiar to Ghostty users |
| Icons | SVG + GTK icon theme | Scalable, native theme |
Software rendering with Cairo is fast enough for a terminal (~2000–12000 cells per frame). We avoid OpenGL/GLArea complexity in the initial version. GPU rendering can be added later.
shellbar/
├── CMakeLists.txt # Build system
├── shellbar.c # Entry point (main)
├── sb_window.c / .h # Main GTK4 window (Adw.ApplicationWindow)
├── sb_terminal.c / .h # Terminal widget: PTY + VT + render
├── sb_toolbar.c / .h # Command button toolbar
├── sb_config.c / .h # Config file loading + CLI
├── PLAN.md
├── README.md
└── TODO.md
ShellBar looks almost identical to Ghostty on Linux:
┌──────────────────────────────────────────────────┐
│ [+] [≡] │ ← AdwHeaderBar (drag handle + buttons + menu)
├──────────────────────────────────────────────────┤
│ [Terminal 1] [Terminal 2] [*] │ ← AdwTabBar (standalone bar, autohide OFF)
├──────────────────────────────────────────────────┤
│ [▶ cmd1] [▶ cmd2] [▶ cmd3] [+ Add] │ ← ShellBar Toolbar (NEW)
├──────────────────────────────────────────────────┤
│ │
│ ~/projects/myapp $ pnpm storybook │
│ > Storybook 8.0.0 starting... │
│ │ │ ← Terminal area (Ghostty identical)
│ │ │
│ │ │
├──────────────────────────────────────────────────┤
│ [scrollbar] │
└──────────────────────────────────────────────────┘
- HeaderBar: custom
decoration_layout(:minimize,maximize,close), no window title, new tab button and menu button on the right - TabBar: standalone
AdwTabBaras a separate top bar — NOT nested inside the header.adw_tab_bar_set_autohide(FALSE). Connected toAdwTabViewviaadw_tab_bar_set_view(). - Toolbar: our custom command buttons, added as a third top bar
- Content:
AdwTabViewfills the remaining space. Each page is aGtkDrawingArea(terminal widget). - TabBar was moved outside the header because nested inside
adw_header_bar_set_title_widget()caused zero-height allocation on some GTK4 versions.
┌──────────────────────────────────────────────────────────┐
│ shellbar (main) │
├──────────────────────────────────────────────────────────┤
│ GTK4 / libadwaita Event Loop │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ sb_window │ │ sb_toolbar │ │ sb_terminal │ │
│ │ (Adw.AppWin) │ │ (Gtk.Box │ │ (Gtk.DrawingArea│ │
│ │ tabs, nav) │ │ + buttons) │ │ + PTY + VT) │ │
│ └──────┬───────┘ └──────┬───────┘ └───────┬─────────┘ │
│ │ │ │ │
│ └──────────────────┴──────────────────┘ │
│ │ │
│ ┌──────┴───────┐ │
│ │ sb_config │ │
│ │ (key=value) │ │
│ └──────────────┘ │
├──────────────────────────────────────────────────────────┤
│ libghostty-vt (.so) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Terminal │ │ Render │ │ Key/Mouse│ │ Kitty │ │
│ │ State │ │ State │ │ Encoders │ │ Graphics │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├──────────────────────────────────────────────────────────┤
│ Operating System │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ forkpty → /bin/zsh or user's shell │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
- User clicks a toolbar button (e.g. "Storybook")
sb_toolbarcaptures theclickedsignal- Looks up the associated command:
cd /path && pnpm storybook - Gets the PTY fd of the active terminal from
sb_terminal - Writes the command +
\nto the PTY fd viawrite(pty_fd, command, len) - The shell receives the text as if the user typed it
- The command output is rendered in the terminal area
Since we use libghostty-vt via CMake FetchContent:
- Ghostty upstream releases a new version with fixes/features
- In
CMakeLists.txt, change theGIT_TAGto the new commit - Delete
build/and rebuild - If the
libghostty-vtAPI changed, adjust our C code
This works because:
libghostty-vthas a stable, well-documented C API- We never modify Ghostty code
- Our code is independent of Ghostty's GUI
- CMake setup with libghostty-vt fetch
- GTK4 window with Adw.ApplicationWindow
- PTY + shell (forkpty)
- Cairo terminal rendering
- Keyboard and mouse input
- Scrollback and scrollbar
- GTK4 toolbar
- Buttons with icons + text
- Click writes command to PTY
- "+" button to add commands (placeholder)
- Config file
~/.config/shellbar/config - Parse button list from config
- Icon catalog (GTK theme icons)
- Hot reload
- Dark theme
- Minimalist HeaderBar
- Tabs (Adw.TabView)
- Animations and transitions
- HiDPI
- Ghostty-matching CSS
- Keyboard shortcuts for buttons (Alt+1..Alt+0)
- Configurable keybinds
- Drag & drop to reorder buttons
- Button groups (folders)
- Commands with variable arguments
- Split panes
- Command palette (Ctrl+P) with shell history + PATH search
- Inline ghost-text autocomplete with history-first completion
- Configurable button bar position: top / bottom / left / right
- Preferences Settings page with position selector
- Tab slide-in transitions
- Resize overlay (cols × rows chip)
- Tab pills styled as true tabs