My personal configuration files for a productive terminal-first Linux development environment.
This repository centralizes my setup for:
- Zsh
- Tmux
- Kitty
- Helix
- Git
- Vim
- Pandoc
- themes and shell utilities
The goal is simple:
identical workflow everywhere.
Whether on:
- a local Debian desktop,
- a remote VPS,
- a headless server,
- a temporary VM,
- or a fresh reinstall,
the experience should remain nearly identical:
- same shell,
- same terminal behavior,
- same keybindings,
- same clipboard workflow,
- same editor,
- same tmux navigation,
- same Git ergonomics.
This repository is intentionally:
- reproducible,
- idempotent,
- modular,
- portable,
- dependency-light,
- and terminal-first.
Current core stack:
- Kitty
- Tmux
- Helix
- Git
- Zsh
Everything else is optional.
Before running the automation, ensure the following are installed:
Essential for general workflows and compiling isolated Python environments with pyenv:
sudo apt update && sudo apt install -y \
curl git zsh tmux kitty xclip yad shfmt \
fonts-noto-color-emoji \
build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev libncursesw5-dev \
xz-utils tk-dev libxml2-dev libxmlsec1-dev \
libffi-dev liblzma-dev# Oh My Zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
β οΈ The Oh My Zsh installer drops you into a temporary zsh session on completion. Typeexitto return to bash, then set zsh as your default shell:chsh -s $(which zsh)Then log out and log back in β closing the terminal is not enough. A full session restart is required for the default shell change to take effect.
# Pyenv & plugins
curl https://pyenv.run | bash
β οΈ pyenv is not available yet in the current session after installation. Either open a new terminal (if zsh is already your default shell), or manually bootstrap it for the current session:export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)"
# NVM (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
β οΈ The NVM installer will append source lines to your.zshrc. Remove them β NVM lazy loading is already handled inexports.zsh. After install, just reload your shell:omz reload
# TypeScript LSP (after NVM + Node are installed)
npm install -g typescript typescript-language-serverThe
install.pyscript automatically symlinkstypescript-language-serverfrom the active NVM Node version into~/.local/binso Helix can find it without loading NVM at startup.
If setting up a headless environment / VPS, flag the machine as a server.
This automatically switches the shell prompt Oh My Zsh theme from:
- local desktop theme β arrow
- server theme β refined
sudo touch /etc/is_serverThe setup intentionally uses the official AppImage instead of distro packages.
Reason:
- distro versions are often outdated,
- AppImage guarantees consistency across machines.
Download the official AppImage: https://github.com/helix-editor/helix/releases
Then place it inside:
~/.local/bin/Example:
mkdir -p ~/.local/bin
mv helix-*.AppImage ~/.local/bin/
chmod +x ~/.local/bin/helix-*.AppImageThe installation script automatically:
- detects the AppImage,
- creates symlinks,
- and extracts it on headless systems when FUSE is unavailable.
π‘ Expected shell state before running
install.py: zsh is your active default shell (verify withecho $SHELL), and pyenv responds topyenv --version. If either is missing, revisit the steps above before continuing.
Clone the repository anywhere:
git clone https://github.com/pfei/dotfiles.git ~/src/dotfiles
cd ~/src/dotfiles
git submodule update --init
./install.pyThe installer dynamically adapts to the environment:
- desktop,
- headless VPS,
- GUI availability,
- terminal capabilities.
It automatically installs/symlinks supported modules and skips incompatible GUI modules on headless systems.
Current modules:
- git
- zsh
- tmux
- kitty
- helix
- vim
- pandoc
- themes
- mate-terminal (legacy)
To complete your Python isolation setup and
make the .zshrc workflow fully operational,
install your target Python version
and initialize virtualenvwrapper hooks inside it:
For example with python 3.13.13:
# 1. Install and set your working Python version
pyenv install 3.13.13
pyenv global 3.13.13
# 2. Bind virtualenvwrapper inside the isolated version
pip install virtualenvwrapper
# 3. Reload your shell configuration
omz reloadGit identity is loaded at install time from a local git/identity.json file (not tracked).
Copy the example and fill in your details:
cp git/identity.json.example git/identity.json
# then edit git/identity.json with your name, email, and SSH signing key pathThe installer will then inject your identity into ~/.gitconfig automatically.
A modular Zsh setup with dynamic environment handling:
- Modular Architecture: Configuration split into exports and functions.
- Adaptive Themes: Uses
refined(e.g.,~ β― user@srvXXXXXX) on servers via/etc/is_server, andarrow(e.g.,~ β€) on local machines. - Language Integration: nvm, pyenv, Go, Deno β all lazy-loaded to keep shell startup fast.
- Python Workflow: pyenv for version management, virtualenvwrapper for lightweight virtual environments. Both use stub functions that defer initialization until first use (~500ms saved on startup).
- Node Workflow: nvm and its ecosystem (node, npm, npx, yarn) are lazy-loaded via stub functions.
- Autoload Functions:
~/.zsh_autoload_functions/hosts private helpers (e.g.,load_google_api_key) not tracked in the repository. - UI: Custom steady yellow underline cursor that resets on exit.
The .zshrc configuration dynamically checks for and sources ~/.zshrc.local
right before initializing the cursor UI. This provides a clean point of extension
to inject private paths, professional/personal aliases, or specific overrides
without polluting the public repository tracking.
Terminal multiplexer configured for ergonomics and speed:
- Prefix: Remapped to
Ctrl-a. - Navigation: Pane switching with
Alt + Arrow Keys, window switching withCtrl + PageUp/Down. - Window Management: Move windows left/right with
Ctrl + Shift + PageUp/Down; windows auto-renumber on close; rename withF2. - Copy Mode: vi keybindings with system clipboard integration (xclip). Mouse drag also copies to clipboard.
- Clipboard: OSC 52 passthrough enabled for seamless clipboard across SSH sessions.
- Persistence: New panes/windows open in the current working directory.
- History: 100,000 lines scrollback.
- Configuration:
kitty/kitty.confβ~/.config/kitty/kitty.conf F11mapped to toggle fullscreen.
- Centralized Config: Settings, keybindings, and snippets in one directory.
- Automation: One-command deployment of symlinks and extensions.
- Smart Formatting: Auto-format shell scripts on save via shfmt, Python via Ruff, JSON/JS/TS/HTML/CSS via Prettier.
- Vim Integration: Optimized Vim keybindings via vscodevim (toggle with
Ctrl+Alt+V). - Spell Checking: English and French, enabled only for Markdown files.
- Extensions: Ruff, Pylance, mypy, ESLint, Prettier, Jupyter, R, Rainbow CS
- Configuration:
helix/config.tomlβ~/.config/helix/config.toml - Language Support:
helix/languages.tomlβ~/.config/helix/languages.tomlβ configures auto-formatting for Python (Ruff), Bash (shfmt), Markdown (mdformat), and JSON (jq), with debugpy integration for Python. - Theme: Custom
my_mochatheme (inherits Catppuccin Mocha with adjusted statusline colors) β~/.config/helix/themes/my_mocha.toml - AppImage Management: Automatically symlinks
hxdirectly to the AppImage on desktop environments, or extracts it cleanly into a FUSE-less standalone wrapper on headless servers. - Hidden Files:
.ignoreensures dotfiles are visible in the file picker (Space + f). - Keybindings:
Space + nhides line numbers,Space + lrestores them.
- Configuration:
git/gitconfigincluded into~/.gitconfigvia[include]β keeps private identity out of the repository. - Identity: Loaded at install time from
git/identity.json(not tracked). Copy fromgit/identity.json.example. - SSH Commit Signing: Configured via
[gpg] format = sshwithallowed_signersauto-setup. The installer appends your public key to~/.ssh/allowed_signersautomatically. - Editor: Helix (
hx) as default commit editor. - Aliases:
lgβ compact, colorized graph log with dates. - Jupyter Support:
nbdimedrivers configured for notebook diff and merge. - Headless optimization: On servers,
credential.helper = storeis set automatically.
- Configuration:
vim/.vimrcβ~/.vimrc - Relative line numbers, persistent undo, Space as leader key.
- Smart case-insensitive search, no swap/backup files.
- Clean Git commit editing (no relative numbers, no cursorline).
- Templates:
pandoc/templates/β~/.local/share/pandoc/templates/ - Clean LaTeX journal template for PDF export.
- Dracula GTK: Dracula theme submodule linked to
~/.themes/Dracula. - Dracula-Yad: Custom Dracula variant for
yaddialogs with high-contrast cyan border and large yellow labels β~/.themes/Dracula-Yad/. - MATE Desktop: Dracula GTK theme, Mint-Y icons, and wallpaper applied automatically via
gsettings. - MATE Terminal (legacy): Catppuccin color profiles (Mocha, Macchiato, FrappΓ©, Latte) loaded via dconf.
h: History search β no args shows last 20, number shows N lines, string greps.lsym: Lists symlinks in current directory with color-coded targets.lst: Shows the 5 most recently modified files.dumpcode: Dumps the full codebase to a text file for LLM analysis, skipping locks and binaries.gitscan: Scans git history for secrets usinggitleaks. It runs in redacted mode to safely display results on public screens.
.
βββ zsh/
β βββ .zshrc # Main entry point
β βββ aliases.zsh # Custom shortcuts
β βββ exports.zsh # PATH and env variables
β βββ functions.zsh # Utilities and helpers
β βββ setup.py # Symlinks + autoload stub
βββ tmux/
β βββ .tmux.conf # Tmux configuration
β βββ setup.py
βββ kitty/
β βββ kitty.conf
β βββ setup.py
βββ vscode/
β βββ settings.json
β βββ keybindings.json
β βββ extensions.txt
β βββ snippets/
β βββ setup.py
βββ helix/
β βββ config.toml
β βββ languages.toml
β βββ themes/
β β βββ my_mocha.toml
β βββ setup.py # Symlinks config + hx AppImage/Wrapper
βββ git/
β βββ gitconfig
β βββ identity.json.example
β βββ setup.py
βββ vim/
β βββ .vimrc
β βββ setup.py
βββ pandoc/
β βββ templates/ # LaTeX templates
β βββ setup.py
βββ themes/
β βββ Dracula/ # GTK theme (submodule)
β βββ Dracula-Yad/ # Custom yad GTK theme
β βββ setup.py
βββ mate-terminal/
β βββ catppucin.dconf
β βββ setup.py
βββ .local/bin/
β βββ dumpcode # Codebase dump utility
βββ install.py # Global installer
βββ .ignore # Show dotfiles in Helix file picker
βββ LICENSE
MIT License β see LICENSE for details.
Last updated: June 2026