Wayland, starship, kitty: rebuilding a dev laptop on Ubuntu 26.04
I just rebuilt my dev laptop on a fresh Ubuntu 26.04 install. This post covers the foundation: distro, shell, and terminal. A second post…
Wayland, starship, kitty: rebuilding a dev laptop on Ubuntu 26.04
I just rebuilt my dev laptop on a fresh Ubuntu 26.04 install. This post covers the foundation: distro, shell, and terminal. A second post handles the Claude Code side.
Why Ubuntu 26.04
I only run LTS on my laptops and workstations. Five years of standard support (ten with Pro), no surprise upgrade cycles every six months, and a stable userland that other tooling can target. I’d been waiting for 26.04 since the start of the year, and “Resolute Raccoon” landed on April 23, 2026.
What pulled me in this cycle:
- Linux 7.0 kernel, the first major version bump in a long time
- GNOME 50 on a Wayland-only session (X11 GDM is gone; XWayland still handles legacy apps)
- Toolchains: Python 3.14, GCC 15.2, OpenJDK 25
- systemd 259, cgroup v1 removed entirely
sudo-rs(the Rust rewrite) replaces traditional sudo- TPM 2.0-backed full-disk encryption on by default
- x86–64-v3 package variants for Haswell-and-newer CPUs, with measurable gains on compute-heavy work
- Real-time kernel in
mainwithout Ubuntu Pro
The toolchain refresh and v3 binaries are the practical wins for me. The rest is good to know.
Shell foundation: from Oh My Zsh + Powerlevel10k to starship
I’ve been on Oh My Zsh + Powerlevel10k for years. P10k was the gold standard: fast, beautiful, configurable enough to disappear into the background. Active maintenance has tailed off though, and I’d been hearing for a while that starship was a faster Rust-based alternative. Single-digit milliseconds renders versus p10k’s 30 to 40 with comparable segments.
I switched on this rebuild and so far I’m loving it. Same visual style, faster cold start, one portable config file, no framework wrapping my dotfiles.
sudo apt install -y zsh
chsh -s "$(which zsh)"
curl -sS https://starship.rs/install.sh | sh
The skeleton of my ~/.zshrc:
export EDITOR="code -w"
export PATH="$HOME/.local/bin:$PATH"
export PATH="$PATH:$HOME/.cargo/bin" # rust-installed CLI tools
# History
export HISTSIZE=100000
export SAVEHIST=$HISTSIZE
setopt SHARE_HISTORY HIST_IGNORE_ALL_DUPS HIST_IGNORE_SPACE INC_APPEND_HISTORY
# Sane defaults
setopt AUTO_CD AUTO_PUSHD EXTENDED_GLOB INTERACTIVE_COMMENTS
eval "$(starship init zsh)" # always last
The $HOME/.cargo/bin line matters more than it looks. A lot of the best modern CLI utilities ship via cargo install and won't be on PATH without it. I had it commented out for ages and kept wondering why my newly-installed tools weren't being found.
The starship config
My ~/.config/starship.toml is a Powerlevel10k Classic clone: single-line powerline with directory, git branch, git status, optional kubernetes and python segments, and a right-aligned timestamp plus last-exit-code indicator. add_newline = false keeps it compact.
The pieces worth showing:
add_newline = false
format = """\
[](fg:#3B6E8F)$directory[](fg:#3B6E8F bg:#D7A93C)\
$git_branch$git_status[](fg:#D7A93C)\
$kubernetes$python$cmd_duration """
right_format = "$status$time"
[kubernetes]
disabled = false
symbol = " "
contexts = [
{ context_pattern = ".*prod.*", style = "bg:#BF616A fg:#FFFFFF bold" },
{ context_pattern = ".*staging.*", style = "bg:#D08770 fg:#FFFFFF bold" },
]
[python]
pyenv_version_name = true
detect_files = [".python-version", "requirements.txt", "pyproject.toml"]
[cmd_duration]
format = ' [⏱ $duration](fg:#EBCB8B)'
min_time = 2_000
Two segments earn their keep every shell:
- The kubernetes segment turns red on any context matching
.*prod.*and orange on.*staging.*. It's a visual circuit-breaker. I have to actively notice the colour before I run a destructivekubectlagainst the wrong cluster. cmd_durationwithmin_time = 2_000puts a clock on anything slower than two seconds. Not a hot take, but it makes slow build steps obvious without effort.
zsh plugins I keep
These do what Oh My Zsh’s framework used to do for me. Each one is a single git clone and one source line. No framework, no theme system, no startup-time tax for things I don't use.
mkdir -p ~/.my-custom-zsh && cd ~/.my-custom-zsh
git clone https://github.com/Aloxaf/fzf-tab
git clone https://github.com/zsh-users/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting
sudo apt install -y fzf direnv
cargo install zoxide atuin
Wired into .zshrc in this order (load order matters):
autoload -Uz compinit && compinit
# fzf-tab replaces zsh's tab menu with an fzf picker plus preview.
# Must load AFTER compinit and BEFORE syntax-highlighting / autosuggestions.
source ~/.my-custom-zsh/fzf-tab/fzf-tab.plugin.zsh
# Ghost-text completions from history; Ctrl+Space accepts.
source ~/.my-custom-zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
bindkey '^ ' autosuggest-accept
# Syntax highlighting must be sourced last among ZLE plugins
source ~/.my-custom-zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
eval "$(fzf --zsh)" # Ctrl+R, Ctrl+T, Alt+C
eval "$(atuin init zsh --disable-up-arrow)" # SQLite history; keeps prefix-search on Up/Down
eval "$(zoxide init zsh)" # `z foo` smart cd
eval "$(direnv hook zsh)" # auto-load .envrc per directory
eval "$(starship init zsh)" # always last
What each one earns:
- fzf-tab. Every tab completion becomes an fzf picker with a preview pane.
cd <Tab>shows directory contents;kill <Tab>shows the process command;git checkout <Tab>shows file diffs. Once it's there, going back feels broken. - zsh-autosuggestions. Grey ghost completions from history as you type.
Ctrl+Spaceaccepts. Cuts out mostCtrl+R-then-edit cycles. - zsh-syntax-highlighting. Commands color as you type, so typos and missing files are visible before Enter.
- atuin. Replaces zsh’s flat history file with SQLite, gives you a much richer
Ctrl+R, and syncs across machines if you want.--disable-up-arrowkeeps zsh's prefix-search Up/Down intact. - zoxide.
z foojumps to whichever directory you visit most that matchesfoo. After a week, plaincdfeels archaic. - direnv. Per-project env vars in a checked-in
.envrc. No more sourcing scripts by hand.
Kitty as the terminal
26.04 is Wayland-only by default. X11 GDM is gone. GNOME Terminal works fine, but kitty is built for this world and faster on every input that actually matters: scrolling long buffers, opening lots of panes, rendering ligatures and emoji. I spent some time tuning it on the new install. Here’s what that looked like.
Why kitty specifically:
- GPU-accelerated rendering. Text goes through OpenGL, so scrollback stays smooth even on a 4K display.
- Native Wayland. No XWayland round-trip; runs as a first-class client of the GNOME 50 / Wayland-exclusive session.
- Splits and tabs in one process. No need for tmux for most workflows.
kitty @remote control lets scripts open new tabs in the running terminal. - Image protocol. Display PNGs, SVGs, charts inline with
kitten icat plot.png. Useful for quick previews. - One plain-text config at
~/.config/kitty/kitty.conf, hot-reloadable withCtrl+Shift+F5.
The optimization passes that mattered
Here’s the breakdown of what I tuned and why:

Highlights from ~/.config/kitty/kitty.conf
# Font
font_family JetBrainsMono Nerd Font
font_size 12.0
disable_ligatures cursor
modify_font cell_height 1px
# Cursor
cursor_shape beam
# Bell
enable_audio_bell no
window_alert_on_bell yes
bell_on_tab "🔔 "
# Scrollback
scrollback_lines 100000
scrollback_pager less --chop-long-lines --RAW-CONTROL-CHARS +INPUT_LINE_NUMBER
scrollback_pager_history_size 10
# Clipboard / selection
copy_on_select clipboard
paste_actions quote-urls-at-prompt,confirm-if-large,replace-dangerous-control-codes
# Wayland
linux_display_server wayland
# Performance
sync_to_monitor yes
repaint_delay 8
input_delay 2
# Splits inside a tab
enabled_layouts splits,stack,tall,fat,grid
# Shell integration
shell_integration enabled
allow_remote_control yes
listen_on unix:/tmp/kitty-${USER}
# Tabs and OS windows: every new spawn inherits cwd
map kitty_mod+t new_tab_with_cwd
map kitty_mod+n new_os_window_with_cwd
map kitty_mod+enter launch --location=split --cwd=current
map kitty_mod+\ launch --location=vsplit --cwd=current
map kitty_mod+- launch --location=hsplit --cwd=current
# Pick any URL on screen via hint
map kitty_mod+e open_url_with_hints
# Run rg via hyperlinked_grep (clickable file:line results)
map kitty_mod+r kitten hyperlinked_grep
# Hot-reload + edit-in-place
map kitty_mod+f5 load_config_file
map kitty_mod+f2 edit_config_file
# Theme: managed by `kitten themes <name>`
# BEGIN_KITTY_THEME
# Catppuccin-Mocha
include current-theme.conf
# END_KITTY_THEME
What kitty’s shell integration buys you
This is the part that surprised me. With shell_integration enabled a fresh shell:
Ctrl+Shift+Z. Jumps the cursor to the previous prompt in scrollback.Ctrl+Shift+X. Selects the entire output of the previous command.- Hold
Ctrland click any file path in the scrollback to open it in$EDITOR(mine iscode -w). Same for line numbers, error stacks, URLs. - New tabs, splits, and OS windows inherit the shell’s current working directory automatically. The shell sends OSC 7; kitty reads it.
Combined, these make scrollback feel structured rather than like a dumb buffer.
Useful kittens (built-in, no extra install)
kitten themes. Browse and apply color schemes; writes tocurrent-theme.confand reloads in place.kitten icat path/to/img.png. Inline images via the kitty graphics protocol.kitten ssh user@host. Copies your kitty config and shell integration over SSH so remote shells feel like local ones.kitten diff a b. Side-by-side diff with image support.kitten clipboard. Read or write the system clipboard from any process:cat token | kitten clipboard.kitten hyperlinked_grep. Wrapsrgso output paths are clickable.
I’m running Catppuccin-Mocha (kitten themes Catppuccin-Mocha); it slots in nicely with the starship colour palette.
Dotfile management
Everything I’ve described is text: ~/.zshrc, ~/.config/starship.toml, ~/.config/kitty/kitty.conf, the ~/.my-custom-zsh/ plugin clones. I keep mine under chezmoi so the next clean install is fifteen minutes, not an afternoon. yadm and plain GNU stow are fine alternatives.
Things I deliberately don’t commit: secrets, anything that contains hostnames I don’t want public, and any state that the system regenerates on its own.
What I left behind
- Oh My Zsh. Served me well for years. After the migration to starship plus a handful of standalone plugins, startup is faster and there’s no framework between me and my dotfiles. I don’t see myself going back.
- Powerlevel10k. Same story: replaced by a starship.toml that does the same job in fewer lines and renders quicker.
- GNOME Terminal. Fine if you want zero config. Kitty’s shell integration alone makes the switch worth it on 26.04’s Wayland-only stack.
- bat, eza -l, tree without depth limits. Pretty in a terminal, noisy in a transcript when something is reading the output.
메타데이터
- post_id
- 2f80de10bb2b
- slug
- wayland-starship-kitty-rebuilding-a-dev-laptop-on-ubuntu-26-04-2f80de10bb2b
- url
- https://medium.com/@harpreet.dhillon/wayland-starship-kitty-rebuilding-a-dev-laptop-on-ubuntu-26-04-2f80de10bb2b
- canonical_url
- https://medium.com/@harpreet.dhillon/wayland-starship-kitty-rebuilding-a-dev-laptop-on-ubuntu-26-04-2f80de10bb2b
- author_url
- https://medium.com/@harpreet.dhillon
- status
- ok
- fetched_at
- 2026-06-24 18:57:25