Contributing to Forgetty

April 21, 2026 · View on GitHub

Thanks for your interest in contributing! This guide gets you from clone to running the terminal, and helps you make your first contribution.

Building from source

Prerequisites

ToolVersionInstall
Ruststablerustup.rs
Zig0.15+ziglang.org/download — builds libghostty-vt
GTK4 + libadwaita4.9+See below

Install GTK4 development libraries:

# Debian/Ubuntu
sudo apt install libgtk-4-dev libadwaita-1-dev

# Fedora
sudo dnf install gtk4-devel libadwaita-devel

# Arch
sudo pacman -S gtk4 libadwaita

Clone and build

git clone --recursive https://github.com/vikgmdev/forgetty.git
cd forgetty
cargo build --release

The --recursive flag is required — libghostty-vt is a git submodule under crates/forgetty-vt/ghostty/. If you cloned without it:

git submodule update --init --recursive

First build takes a few minutes because Zig compiles libghostty-vt from source. Subsequent builds are fast.

Run

cargo run --release

Or with flags:

cargo run --release -- --working-directory ~/projects -e htop

Project structure

Forgetty is a Cargo workspace with 10 crates. The design principle is thin native shell + thick shared core — the GTK4 shell is ~7,400 lines, but ~70% of the code is platform-independent Rust that will be shared across future platform targets.

forgetty/
├── src/                    # Binary entry point (main.rs, cli.rs)
├── crates/
│   ├── forgetty-core/      # Shared types, errors, coordinate types
│   ├── forgetty-vt/        # libghostty-vt FFI — VT parsing, screen state
│   │   └── ghostty/        # Git submodule (Ghostty source for Zig build)
│   ├── forgetty-pty/       # PTY spawn/lifecycle, I/O multiplexing
│   ├── forgetty-config/    # TOML config, 486 bundled themes, defaults
│   ├── forgetty-gtk/       # GTK4 platform shell — rendering, input, UI
│   ├── forgetty-watcher/   # Filesystem watcher for config hot reload
│   ├── forgetty-workspace/ # Session save/restore, workspace persistence
│   ├── forgetty-session/   # Daemon session manager (panes, tabs, routing)
│   ├── forgetty-sync/      # iroh QUIC transport for cross-device sync
│   └── forgetty-socket/    # JSON-RPC 2.0 over Unix socket
├── resources/themes/       # 486 bundled theme TOML files
├── assets/icons/           # App icon (SVG)
├── dist/linux/             # Desktop entry, man page, DEB build script
├── scripts/                # convert-iterm-themes.py (theme maintenance)
├── tests/
│   ├── stress/             # 25-scenario stress test suite
│   ├── integration/        # Integration tests
│   └── fixtures/           # Test fixtures
└── docs/
    └── architecture/       # Technical docs and design decisions

Key crates

forgetty-gtk — Where most UI work happens. app.rs is the GTK4 application (tabs, splits, menus, shortcuts), terminal.rs handles per-pane rendering and state, input.rs maps GDK events to ghostty key/mouse encoders, clipboard.rs has the smart copy pipeline.

forgetty-vt — Safe Rust wrappers around libghostty-vt's C API. If you're adding a new terminal capability, this is where the FFI binding goes. Read the FFI section in the docs before touching this crate — there are hard-won rules from weeks of debugging.

forgetty-config — Config loading, theme system, and the bundled theme registry. Note: bundled_themes.rs is auto-generated by scripts/convert-iterm-themes.py — don't edit it by hand.

forgetty-pty — PTY management. Spawns the user's shell, handles resize, I/O channels.

Running checks

# Compile check (fast feedback)
cargo check --workspace

# Lint — must pass clean
cargo clippy --workspace -- -D warnings

# Run tests
cargo test --workspace

# Full release build
cargo build --release

Always run cargo clippy and cargo test before submitting a PR.

How we develop

Every feature goes through three phases:

  1. Plan — Write a spec with acceptance criteria (what does "done" look like?)
  2. Build — Implement, commit, verify no regressions
  3. QA — Test every acceptance criterion, verify behavior

For small fixes you can skip straight to a PR. For new features, writing clear acceptance criteria before you start coding will save time and make review faster.

Pull request guidelines

  • One feature or fix per PR. Small, focused PRs get reviewed faster.
  • Describe what changed and why. For bug fixes, include how to reproduce.
  • Run checks locally before pushing: cargo clippy --workspace && cargo test --workspace
  • Test manually — launch Forgetty and verify your change works. For UI changes, test with splits, multiple tabs, and at least one theme switch.
  • Don't break existing features. If your change touches input handling, test that vim, htop, and basic shell usage still work.
  • Match existing patterns. The codebase uses Rc<RefCell<>> for shared state, try_borrow_mut() instead of borrow_mut() to avoid panics, and GTK4 actions for keyboard shortcuts.

Branch naming

feat/quake-mode
fix/search-highlight-zoom
docs/config-reference

Commit messages

Use conventional prefixes:

feat: add quake/dropdown mode with global hotkey
fix: search highlights misaligned after font zoom
perf: reduce allocation in screen sync hot path
docs: add configuration reference
test: stress test for concurrent splits

Good first issues

Concrete, scoped tasks suitable for a first contribution:

  1. Shift+Click to extend selection — Currently Shift+Click clears the selection instead of extending it to the click position. The selection code is in crates/forgetty-gtk/src/terminal.rs. Look at how double-click-drag extends by word — similar logic, but from the existing selection anchor to the clicked cell.

  2. Auto-scroll during drag selection — When drag-selecting text and the mouse moves past the top or bottom edge of the viewport, the terminal should auto-scroll. The drag handling is in terminal.rs.

  3. Tab reordering via drag-and-dropadw::TabBar supports drag-to-reorder natively, but it needs to be wired up so the underlying TabStateMap stays in sync.

  4. Custom cursor color in config — Add a cursor_color key to config.toml that overrides the theme cursor color. Parsing in forgetty-config, rendering in forgetty-gtk/src/terminal.rs.

  5. Man page improvements — The man page at dist/linux/forgetty.1 could cover more CLI flags, environment variables, and config options.

Look for issues labeled good first issue on GitHub for the latest list.

Reporting bugs

Open a GitHub issue with:

  • Forgetty version (forgetty --version)
  • Linux distribution and version
  • Display server (Wayland or X11): echo $XDG_SESSION_TYPE
  • Steps to reproduce
  • Expected vs actual behavior
  • Terminal output or screenshots if relevant

Code of conduct

Be kind, be constructive, be welcoming. We're building this in the open and want contributions from everyone. Harassment, discrimination, and personal attacks have no place here.

License

By contributing to Forgetty, you agree that your contributions will be licensed under the MIT License, the same license that covers the project.

Questions?

Open a GitHub Discussion or file an issue. Happy to help you find the right place to start.