Skip to content
aniketpantPublic

About

My dotfiles from around :octocat:

Topics

Resources

Stars

9 stars

Watchers

2 watching

Forks

Repository files navigation

dotfiles

Personal Zsh dotfiles managed with GNU Stow.

Structure

.dotfiles/
├── bin/              # git helper scripts (stowed to ~/bin)
├── fonts/            # CommitMono zip for `make fonts`
├── ghostty/
│   └── .config/
│       └── ghostty/
│           ├── config     # terminal config (font, theme, keybindings)
│           └── themes/    # pi-matched light/dark palettes
├── opencode/
│   └── .config/
│       └── opencode/
│           └── cli.json   # TUI settings (theme, session, animations)
├── pi/
│   └── .pi/
│       └── agent/
│           └── settings.json  # pi TUI settings (theme, model, behaviour)
├── git/
│   ├── .gitconfig    # global git config (personal email)
│   ├── .gitignore    # global gitignore
│   └── .gitmessage   # commit message template
├── keyd/
│   ├── default.conf  # global macOS-style Cmd layer (installed to /etc/keyd)
│   └── app.conf      # per-app masks (installed to ~/.config/keyd)
├── scripts/
│   ├── setup-ubuntu.sh      # Ubuntu package & repository installer
│   ├── setup-macos-keys.sh  # GNOME macOS-style keybinding setup
│   └── setup-keyd.sh        # keyd Cmd-layer installer
├── starship/
│   └── .config/
│       └── starship.toml  # prompt config
├── zsh/
│   ├── .zshrc        # main entry point (zinit + turbo mode)
│   ├── aliases.zsh   # shell aliases (auto-sourced)
│   ├── config.zsh    # zsh options, history, key bindings
│   ├── prompt.zsh    # prompt config (Starship handles this)
│   ├── window.zsh    # terminal window title helper (defined, not hooked up)
│   └── functions/    # autoloaded zsh functions
└── Makefile          # install / clean / update / setup / macos-keys / keyd targets

Install

1. Ubuntu Package Setup

On Ubuntu, install system packages, repositories, and modern CLI tools:

git clone https://github.com/aniketpant/dotfiles ~/.dotfiles
cd ~/.dotfiles
make setup-ubuntu

This installs:

  • Terminal & Editors: Ghostty, Neovim, Vim
  • Git & Pagers: git-delta (syntax-highlighted pager), bat (modern cat)
  • Shell & Utilities: zsh, GNU Stow, eza (via official Gierens APT repo), fzf, direnv, starship, zoxide, ripgrep

2. Stow Configurations

make install

make install stows git, zsh, bin, starship, ghostty, opencode, and pi into $HOME.

Theme Sync

Ghostty, pi, and opencode share one palette so moving between the shell and a TUI is not jarring.

App Setting Follows
Ghostty theme = dark:pi-dark,light:pi-light + window-theme = auto GNOME light/dark
pi "theme": "light/dark" terminal appearance
opencode "name": "system", "mode": "system" terminal appearance

ghostty/.config/ghostty/themes/pi-dark and pi-light are generated from pi's own bundled dark.json / light.json colors, so the shell prompt and pi's TUI render from identical hex values. Switching GNOME light/dark moves all three.

To change the palette, edit the two theme files and reload Ghostty with Ctrl+Shift+Comma.

Plugin Manager

Zinit with turbo mode for deferred plugin loading. Shell startup is ~0.6s.

Plugin Purpose
zdharma/fast-syntax-highlighting Syntax highlighting
zsh-users/zsh-autosuggestions Fish-like suggestions
zsh-users/zsh-completions Extended completions
Aloxaf/fzf-tab fzf-powered completions
junegunn/fzf-bin Fuzzy finder binary
zdharma/history-search-multi-word Better Ctrl-R
lukechilds/zsh-nvm Lazy-loaded NVM

Tools

Tool Purpose
starship Cross-shell prompt
zoxide Smart z directory jump
direnv Directory-specific env vars
fzf Fuzzy finder (Ctrl-T, Ctrl-R, Alt-C)
eza Modern ls replacement
bat Modern cat replacement
delta Syntax-highlighted git diff

macOS-style Keybindings

The dotfiles reproduce the macOS "Cmd" workflow across six layers:

make macos-keys   # GNOME: GTK Emacs key theme + free <Super>v
make keyd         # keyd: global Cmd layer + per-app profiles (needs sudo)
Layer What it provides Where
keyd (global) Full Cmd behaviour in every app (Cmd+S/Z/A/F/W/N/O/P/R/T, Cmd+C/V/X, Cmd+←/→, Cmd+Tab) keyd/default.conf
keyd (per-app) Terminal-safe mask for Ghostty (Cmd+T/W/Q/N/F/A/D/K, no Cmd+S/Z footguns) keyd/app.conf
GTK key theme Ctrl+A/E/K/F/B text editing in every GTK app (matches macOS text fields) scripts/setup-macos-keys.sh
GNOME Frees <Super>v so Cmd+V reaches the terminal scripts/setup-macos-keys.sh
Terminal Cmd+C/V, font zoom, Cmd+←/→/⌫ line editing ghostty/.config/ghostty/config
Shell ZLE fallbacks for raw Super escape sequences zsh/config.zsh

How it works

keyd's [cmd:C] layer makes Cmd behave as Ctrl for every key without an explicit mapping, so Cmd+S saves, Cmd+Z undoes, Cmd+A selects all, Cmd+W closes, Cmd+Q quits, etc. Exceptions:

  • Cmd+C/V/X → Ctrl+Insert / Shift+Insert / Shift+Delete, so copy/paste/cut work in both GTK apps and terminals while Ctrl+C stays SIGINT.
  • Cmd+←/→ → Home/End; Cmd+↑/↓ → Ctrl+Home/End.
  • Cmd+Tab → Super+Tab (app switcher); Cmd+` → Alt+F6 (cycle app windows).
  • Cmd+M → Super+H (minimise); Cmd+Space → Super+A (app grid).

Tapping Super alone still opens GNOME Activities.

Trade-offs

Because Super is redefined, GNOME's own Super shortcuts are replaced: Super+1-9 (dash) becomes Ctrl+1-9 (browser tab switching, macOS-like), and Super+A/S/N/D/H are gone (Super+A is reachable as Cmd+Space). In the terminal, unmapped Cmd+keys arrive as Ctrl+keys. That is handled by the per-app profile below.

Per-app profiles

keyd/app.conf is read by keyd-application-mapper. When a matching window is focused it layers a mask over the global rules, so Ghostty keeps its terminal-level shortcuts while every other app gets the full Cmd behaviour:

In keyd's notation M- is Meta/Super and A- is Alt, so M-k below arrives at Ghostty as Super+K.

Chord Sends Action Wired in Ghostty?
Cmd+T Ctrl+Shift+T new tab yes
Cmd+W Ctrl+Shift+W close tab yes
Cmd+K Super+K clear screen yes
Cmd+[ / ] Super+[ / ] prev / next tab no — Ghostty binds Super+Shift+[, so the chords differ by a Shift
Cmd+Q Ctrl+Shift+Q quit no — unbound
Cmd+N Ctrl+Shift+N new window no — unbound
Cmd+F Ctrl+Shift+F search no — unbound, and Ghostty has no search action
Cmd+A Ctrl+Shift+A select all no — unbound, and Ghostty has no select-all action
Cmd+D Ctrl+Shift+O split right no — Ghostty splits on Ctrl+Shift+\ and Ctrl+Shift+H/J/K/L
Cmd+S — (noop) avoids Ctrl+S (XOFF) n/a
Cmd+Z — (noop) avoids Ctrl+Z (suspend) n/a

Six of these rows do not work as written: five are unbound, and the bracket pair disagrees by a Shift. Cmd+F and Cmd+A cannot be fixed by adding a keybind at all, because Ghostty has no search or select-all action — they need to send something else. The Super+ bindings already in that file are unreachable while keyd is running, because keyd overloads the physical Super key into the cmd layer and never emits a bare Super — except where app.conf maps back to M-, as cmd.k does.

Window classes are normalised by the mapper (com.mitchellh.ghostty → com-mitchellh-ghostty); discover others with tail -f ~/.config/keyd/app.log.

A fresh session is required after make keyd: the keyd group membership and the keyd GNOME extension (auto-patched for your GNOME version) only take effect on the next login.

If the mapper still logs Failed to connect to "/var/run/keyd.socket" after logging back in, reboot. With KillUserProcesses=no (the default), a logout does not restart user@1000.service while other user processes exist, so the new session inherits the old group list. To test without rebooting:

sudo setfacl -m u:$USER:rw /var/run/keyd.socket   # temporary; lost on keyd restart

keyd remaps at the evdev layer, so it works on Wayland. This is why it's used instead of Kinto, whose Linux backend (xkeysnail) is X11-only.

Revert with:

./scripts/setup-keyd.sh --revert
./scripts/setup-macos-keys.sh --revert

Work Machine Setup

The .gitconfig uses includeIf to conditionally include ~/.gitconfig-work when working inside ~/work/. Create that file on work machines with work-specific user, credentials, and URL rewrites.

Local Overrides

Add machine-specific config to ~/.localrc (not version-controlled):

export WORK_TOKEN=...

Profiling Startup Time

Uncomment the two zprof lines in .zshrc:

zmodload zsh/zprof  # top of .zshrc
zprof               # bottom of .zshrc

Then run zsh -i -c exit and read the report.

About

My dotfiles from around :octocat:

Topics

Resources

Stars

9 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages