- Shell 38.9%
- Zig 24.1%
- Python 20.5%
- Lua 7.6%
- Makefile 3.7%
- Other 5.2%
| a485/etc/ghostty | ||
| alacritty | ||
| bin | ||
| darwin | ||
| docs/superpowers | ||
| home | ||
| linux | ||
| system | ||
| tools | ||
| .gitignore | ||
| .gitmodules | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Makefile | ||
| opencode.jsonc | ||
| README.md | ||
dotfiles
This repo contains my GNU Stow-managed dotfiles, app configs, and a handful of CLI utilities written in various languages.
This is a living home-directory repo, not a generic starter kit. It is useful as:
- a directly installable Stow setup if you want these exact defaults,
- a reference for stealing individual configs or scripts,
- a source tree for the bundled Zig and Python command-line tools.
Starting points
According to my shell history, here is what I use the most:
bin/xc- Read or write from system clipboard. I use this dozens of times daily to chop up shell pipelines and feed external data through CLI helpers.system/bin/sshq- SSH but with arguments escaped so shell parsing isn't done twicehome/.shenv,home/etc/shrc.d/30-aliases.sh, andhome/etc/zsh/.zshrc.d/git.plugin.zsh- Aliases and helpers I use frequently, especially alias for printing (p,pl), directory listing (l,ll), and git shortcuts (g,gs,ga,gd,gc)tools/zig/src/uniqp.zig,tools/zig/src/xcut.zig,tools/zig/src/trim.zig,tools/zig/src/ncmp.zig,system/bin/hsize, andsystem/bin/urlparam- General purpose, Unix-like command line utilitiestools/python/qrbr.py- If you have a nice braille font, this is nice for generating more compact QR codes than qrencodehome/etc/nvim/,home/etc/mpv/, - Editor and media player configs
Quick paths:
- Start at
Install The Dotfilesif you want the full environment - Jump to
Everyday Toolsif you mainly want the shell utilities - Jump to
Standalone Tool Projectsif you only want the Zig/Python tools - Jump to
Config Guideif you are here to borrow shell, editor, browser, or media config ideas
What Lives Here
home/- The main shared Stow package; top-level dotfiles plusetc/,share/, andvar/bin/- User-specific scripts and wrappers, stowed into$PREFIX/binsystem/bin/- General-purpose tools installed as root-owned copies in/usr/local/binsystem/sbin/- Administrative tools installed as root-owned copies in/usr/local/sbinalacritty/- Build-only Alacritty source config that compiles into generated TOMLdarwin/- macOS-only overlay; directly stowed files plus copied plist snapshots underdarwin/Library/Preferences/a485/- Hostname-specific overlay stowed when the hostname isa485tools/zig/- Standalone Zig CLI project withuniqp,xcut,trim,jshuf, andncmptools/python/- Standalone Python packages and helper CLIs, includingqrbrandalacritty-preprocess
Before You Install
makegenerates the Alacritty config and Zig tool binariesmake installinstalls the user environment into$PREFIX(default~), and on macOS also copies tracked plist snapshots; review withmake dryrunfirstmake stage-systemprepares root-independent system tool artifacts; runsudo make install-systemafterward to install/usr/local/binand/usr/local/sbincopies- Several configs are intentionally personal and need editing before reuse, especially
home/.gitconfig,home/etc/newsboat/config, and qutebrowser secret/search-engine files - Some app configs assume companion tools are already installed (
mpv,qutebrowser,ghostty,alacritty,i3,polybar,dunst,Hammerspoon, and others) - mpv extras live in git submodules under
home/etc/mpv/submodules/; initialize them after cloning - At least one submodule URL uses GitHub SSH, so
git submodule update --init --recursivemay require SSH access
Prerequisites
Common:
gitmake- GNU
stow
macOS-specific:
plutilfor importing app-managed plist state back into the repo
Optional toolchain dependencies:
- Zig
>= 0.16.0if you wantmake build,make test, andmake installto includetools/zig/ - Python
>= 3.12fortools/python/ uvif you wantmake buildto synctools/python/.venvand build Alacritty, ormake installto install the Python toolskcovif you want Zig coverage runs fromzig build -Dcoverage=true test
Build generated files
make
Install dotfiles
Clone and initialize submodules:
git clone --recurse-submodules <your-fork-or-this-repo-url>
cd dotfiles
or,
git clone <your-fork-or-this-repo-url>
cd dotfiles
git submodule update --init --recursive
Preview the filesystem changes:
make dryrun
If you are upgrading from an old commit, run this one-time migration in case any breaking changes have been made:
make migrate
Install into your home directory:
make install
To install into a different prefix instead of ~:
make install PREFIX=/path/to/prefix
What make install does:
- Always Stows
home/into$PREFIX(default~) - Always Stows the user-only
bin/package and the source tools fromsystem/bin/into$PREFIX/bin - Also builds
alacritty/alacritty.ymlintobuild/etc/alacritty/alacritty.tomland Stows that generated file into$PREFIX - Also builds the Zig tools into
tools/zig/zig-out/bin - Also installs the Python tools into
$PREFIX/binwithuv tool install - Does not install the Zig tools into
$PREFIX/bin;make stage-systemandmake install-systeminstall them into/usr/local/bin - On macOS, also Stows
darwin/into$PREFIX, exceptdarwin/Library/Preferences/*.plist - On macOS, also copies
darwin/Library/Preferences/*.plistinto$PREFIX/Library/Preferences/*.plist - When a matching hostname directory exists, also Stows its package into
$PREFIX - macOS preference plists are stored in the repo as XML-format
.plistfiles that mirror their paths under~; they are copied, not symlinked, because apps rewrite them, andmake importsyncs the current installed state back intodarwin/Library/Preferences/ - Does not execute
darwin/.macsettings; that script is stowed, but you run it manually if you want thosedefaults writetweaks
Useful maintenance commands:
make build-python # sync tools/python/.venv
make build-alacritty # generate build/etc/alacritty/alacritty.toml
make build-zig # build tools/zig/zig-out/bin
make build # run all build steps above
make test # run tools/python pytest tests and tools/zig unit tests
make import # import current macOS plist state into darwin/Library/Preferences/
make migrate # migrate old user installs to their current form
make stage-system # stage system/bin and system/sbin plus built tools
sudo make install-system # install root-owned copies under /usr/local
sudo make migrate-system # migrate old /usr/local symlinks if needed
make clean # remove build/ and tools/zig/zig-out, but keep tools/zig/.zig-cache
make uninstall # remove stowed user files and user-installed Python tools
sudo make uninstall-system # remove the manifest-tracked system tools
Use Just The Tools
If you do not want to Stow the whole repo, you can still use the tool projects directly.
Zig tools
In tools/zig, tools can be built with:
zig build
# Run individual tools
zig build run -- uniqp --help
- Built binaries land in
zig-out/bin/ make stage-systemstages them for/usr/local/bin;sudo make install-systeminstalls root-owned copies- Tests are run by
zig build test - Coverage-enabled test runs use
zig build -Dcoverage=true testand write reports underkcov-output/
Python tools
In tools/python, tools can be installed with your preferred package manager:
With pip:
python -m pip install -e .
With pipx:
pipx install .
With uv:
uv tool install .
Usage:
qrbr 'https://example.com'
alacritty-preprocess ../../alacritty/alacritty.yml --xresources ../../home/.Xresources
Repository Layout
.
|- bin/ User-specific scripts stowed into ~/bin
|- system/bin/ General-purpose tools copied into /usr/local/bin
|- system/sbin/ Administrative tools copied into /usr/local/sbin
|- home/ Shared Stow package
| |- etc/ XDG-style app configs
| |- share/ Shared data such as zsh site-functions
| `- .* Top-level dotfiles (~/.gitconfig, ~/.tmux.conf, ...)
|- alacritty/ Build-only Alacritty config source
|- build/ Generated Stow package output
|- darwin/ macOS-only Stow package and copied plist snapshots
|- tools/zig/ Zig CLI project
`- tools/python/ Python CLI project
Everyday Tools
These are the user-facing scripts in the top-level bin/ Stow package that I use the most often. General-purpose pipeline tools live under system/bin/; the alias-heavy side of the same workflow lives in the shell and Git sections under Config Guide.
bin/xc - Clipboard abstraction across platforms
- Wraps X11, Wayland, macOS, WSL, and Termux clipboard commands behind one interface.
- Paste mode (default):
xc(can be explicitly invoked withxc -o). - Copy mode:
xc -i file.txt,printf 'hello' | xc -i,xc -i -e 'literal text'. - Supports primary selection (
-p), target types (-t), whitespace trimming (-T), and explicit trailing-newline policies (-n).
Examples:
xc
printf 'hello\n' | xc -i
xc -i -e 'plain text'
system/bin/ydiff - Diff JSON after normalizing to YAML
- Runs
diffon two JSON/JSONL/NDJSON files after normalizing both throughyqto YAML. - Supports an optional
-ffilter so you can preprocess a document before diffing. - Useful for review of generated config files when raw JSON formatting would create too much noise.
Examples:
ydiff config-a.json config-b.json
ydiff -f '.items[] | {name, value}' before.jsonl after.jsonl
system/bin/hsize - Make byte counts human-readable
- Formats numeric size columns as human-readable values.
- Works well in pipelines from tools like
du,find, or custom tabular output. - Supports selecting a column with
-c, changing the input block size with-B, and choosing IEC vs SI units.
Examples:
printf '123456\n' | hsize
du -s . | hsize -B512
system/bin/urlparam - Inspect or extract URL query parameters
- Reads URLs from stdin.
- With no extra arguments, prints every query parameter pair it finds without unescaping.
- With parameter names, filters to those parameters; with exactly one parameter name, unescapes the value and prints it.
- Useful when processing redirect links, copied browser URLs, or API callbacks.
Examples:
printf '%s\n' 'https://example.com/?a=1&b=2' | urlparam
printf '%s\n' 'https://example.com/?a=1&b=2' | urlparam b
system/bin/sshq - Quote remote ssh commands safely
- Takes a remote command and shell-quotes it before passing it to
ssh. - Useful when you want
sshto behave more likeexec,env, ornohupwithout fighting nested quoting. - Leaves plain
ssh hostbehavior alone when no remote command is supplied.
Examples:
sshq host sh -c 'printf "%s\n" "$@"' sh 'foo $bar \baz' 'Hello, world!'
sshq host env FOO='a b' sh -lc 'printf "%s\n" "$FOO"'
bin/xbrs - Search Void packages with better filtering
- Wraps
xbps-query -Rswith pattern filtering and cleaner aligned output. - Can hide
-devel,-dbg, and32bitpackages, or limit to installed / not-installed packages. - Very specific to my Void Linux workflow.
Examples:
xbrs ripgrep
xbrs -i zsh
xbrs -a llvm
bin/mullvad-exclude - Run a command outside Mullvad split tunnel
- Adds the current process to Mullvad split tunneling, then
execs the requested command. - Extremely small, but a frequent quality-of-life wrapper when Mullvad is enabled.
- Only useful if you use Mullvad and its split-tunnel CLI.
Examples:
mullvad-exclude firefox
mullvad-exclude curl https://ifconfig.me
System Tools
The system packages have separate deployment paths:
system/bin/contains general-purpose tools such assleep_until,pextrace,defrag, and the Zig utilities. Its source tools are also stowed into the user's$PREFIX/binbymake install.system/sbin/contains administrative tools; currently this is onlymake_swap_file, and it remains system-only.make stage-systembuilds a root-independent staging tree underbuild/system/.sudo make install-systemcopies the staged files asroot:rootinto/usr/local/binand/usr/local/sbin.- Installation does not migrate existing symlinks; run
sudo make migrate-systemseparately when upgrading an old system install. make migratehandles old user-bin symlinks;sudo make migrate-systemhandles old system-bin symlinks.
System installation deliberately does not use symlinks into the checkout. Existing unexpected files or symlinks are left untouched and cause installation to fail rather than being overwritten.
Standalone Tool Projects
These are the self-contained tools I use most from the standalone Zig/Python projects. You can build or install them without adopting the whole dotfiles setup.
tools/zig/src/uniqp.zig - Unique-record filter and counter
- Reads newline-delimited input from files or stdin.
uniqpprints only the first occurrence of each unique line.uniqp -ccounts occurrences of each unique line.uniqp --skip-emptyignores empty input lines before filtering or counting.uniqp -lprints the number of unique lines across all input.uniqp -Lprints per-file unique counts
The tool also supports combining -l and -L.
Examples:
printf "%s\n" foo foo bar | uniqp
printf "%s\n" foo foo bar | uniqp -c
printf '\nfoo\n\nbar\n' | uniqp --skip-empty
uniqp -l -L file1.txt file2.txt
tools/zig/src/xcut.zig - Delimiter-aware field cutter
- Similar in spirit to
cut, but built for richer field selection. - Supports custom field delimiters, custom output delimiters, record delimiters, escaped delimiter strings, range syntax, and NUL-terminated mode.
- Requires
-f/--fields.
Examples:
printf "%s\n" "a:b:c" | xcut -d : -f 1,3
printf "%s\n" "a:b:c:d" | xcut -d : -f 2..4
printf "%s\0" a b | xcut -0 -f 1
tools/zig/src/trim.zig - Stream and line trimmer
- Trims leading and trailing characters from whole streams by default.
-lswitches to line-by-line trimming and only prints non-empty lines.-tchooses custom trim characters.-nstrips the final newline;-Npreserves it.
Examples:
printf ' hello \n' | trim
printf ' a \n\n b \n' | trim -l
printf '..hello..\n' | trim -t '.'
tools/zig/src/ncmp.zig - Compare multiple files byte by byte
- Compares two or more files and exits after their first differing byte.
- Prints the one-based byte position by default.
-q/--quietand-s/--silentsuppress comparison output, but not invocation or I/O errors.- Exits 0 for equal inputs, 1 for different inputs, and 2 for errors.
- Accepts one
-operand to compare standard input with files.
Examples:
ncmp first.bin second.bin third.bin
ncmp --silent first.bin second.bin
printf 'payload' | ncmp - saved-payload.bin
tools/python/qrbr.py - Print QR codes as braille
- Turns text from an argument or stdin into a terminal-friendly Unicode braille QR code.
- Depends on
numpyandqrcode[pil]. - Good for sharing links in a terminal without opening an image viewer.
Examples:
qrbr 'https://example.com'
printf 'wifi:ssid=example' | qrbr -e H
tools/python/alacritty_preprocess.py - Build Alacritty TOML from source YAML
- Resolves the custom
!xresourcesYAML tags fromhome/.Xresourcesafter preprocessing it withpcpp. - Emits TOML for
make build, replacing the old live watcher-based preprocessing flow. - Installs as
alacritty-preprocessthroughtools/python/pyproject.toml, andmake buildfirst runsuv sync --project tools/python --lockedbefore invoking it.
Example:
alacritty-preprocess alacritty/alacritty.yml --xresources home/.Xresources
Config Guide
This section starts with the configs that show up most in my day-to-day workflow: shell, Git, editor, browser, and media.
home/.shenv, home/etc/shrc, home/etc/shrc.d/, home/etc/zsh/.zshrc - shell bootstrap stack
- Establishes XDG-style paths such as
XDG_CONFIG_HOME=~/etcandXDG_DATA_HOME=~/var. - Builds
PATH,MANPATH, editor/pager defaults, shell helpers, aliases, prompt setup, completion, and host-specific extras. - Defines many of the high-use helpers and aliases in the history analysis, including
p,pl,l,ll, andvim->nvim. - Bash and POSIX shells flow through
~/.profileandhome/etc/shrc; zsh uses~/.zshenvandhome/etc/zsh/.zshrc. - Also exports many personal environment defaults for Homebrew, pipx, pyenv, Bun, Perl local::lib, cargo, and more.
Notes:
- Very opinionated
- Assumes
~/etc,~/var,~/bin, and related paths are acceptable in your environment
home/.gitconfig - Git aliases, paging, and signing defaults
- Adds short aliases like
git s,git go,git gl, and commit/push/pull wrappers that refresh GPG agent TTY state. I don't really use these anymore, instead preferring the zsh Git aliases. - Pairs with the zsh Git aliases used most in practice:
g,gs,gc,ga, andgd. - Uses
deltaordiff-highlightwhen available. - Enables signing by default, rebasing on pull,
rerere, and some custom diff generators.
Important:
- The checked-in config contains a real user name, email, and signing key
- Change those values before using this file on another machine
home/etc/nvim/ - Lua-based Neovim config
- Bootstraps
lazy.nvimautomatically on first run. - Uses plugin specs under
home/etc/nvim/lua/plugins/for Treesitter, Oil, Mason/LSP, and lightweight editing plugins. - Mason installs LSP servers lazily when matching filetypes are opened.
- Includes many custom mappings, templates, autocmd helpers, and traditional Vim-like defaults.
Notes:
- First launch may clone plugins and install language servers
- If you want a minimal config, copy selectively rather than using this whole tree unchanged
home/etc/qutebrowser/ - Locked-down qutebrowser setup with userscripts
- Disables autoconfig and sets qutebrowser directly from
config.py. - Turns JavaScript off by default, then selectively re-enables it through secret-managed allowlists.
- Loads search engines from
../searchengines.ymland extra settings fromsecrets.yml. - Adds userscript bindings for URL rewriting, alternate download mode, and mpv/umpv launching.
I haven't used qutebrowser for years, so this may be outdated.
Included userscripts:
urlsubrewrites YouTube, Reddit, Twitter, Instagram, and some Quora URLs toward alternative frontends or privacy-friendlier formsdownload-alternatetemporarily flips download prompt/remember settings for hint-driven downloads
Notes:
- Requires
PyYAML - Expects local files that are not in the repo:
searchengines.yml,secrets.yml - Some URL rewrite targets depend on third-party public instances
home/etc/mpv/ - Mpv profiles, keybindings, and Lua scripts
mpv.conftunes streaming, caching, subtitles, screenshots, audio, and a set of named profiles.input.confremaps transport, subtitle, crop, scaling, ontop, and screenshot controls.scripts/mixes custom Lua helpers with third-party submodule scripts.
Notable custom scripts:
chapter_pause.luapauses automatically at chapter boundaries or end-of-file when toggledscale_window.luaresizes the window relative to the monitor or current window sizesmart_ontop.luakeeps the window on top only while actively playing
Notes:
- Initialize submodules for the bundled third-party scripts
- Assumes a fairly advanced mpv setup with extra scripts and external tools already available
home/etc/ghostty/ and platform packages - Ghostty config
- The shared config sets theme, cursor behavior, font features, working directory, and general window behavior.
- Platform-specific files live in
darwin/etc/ghostty/config.d/darwinandlinux/etc/ghostty/config.d/linux; hostname-specific overrides live in matching host packages such asa485/etc/ghostty/a485. - The shared config optionally includes the platform files and the hostname override; matching packages provide the files that exist.
Notes:
- No manual platform symlink is needed after installing with
make install
alacritty/ - Build-only Alacritty config source
alacritty/alacritty.ymlis the source file.tools/python/alacritty_preprocess.pypreprocesseshome/.Xresourceswithpcpp, resolves the custom YAML tags, and writes TOML intobuild/etc/alacritty/alacritty.toml.make cleanremoves the generatedbuild/tree andtools/zig/zig-outbuild output, but leavestools/zig/.zig-cachein place.make buildregenerates the installed Alacritty config; there is no longer a background watcher.make migrateperforms migrations from old installs.
Notes:
- Depends on
uvplus the lockedtools/pythondependencies - Useful if you want terminal colors to track the repo's Xresources palette without runtime preprocessing
home/etc/i3/, home/etc/polybar/, home/etc/dunst/ - Linux desktop stack
- i3 config provides Vim-like navigation, workspace bindings, scratchpad use, and launches Polybar at startup.
- Polybar reads colors from Xresources and exposes modules for i3 workspaces, mpd, filesystem, VPN, wifi, ethernet, memory, CPU, battery, temperature, and date.
bin/polybar-launchreloads Polybar after exporting XRDB-derived colors.- Dunst is configured as the matching lightweight notification daemon.
Notes:
- Strongly tied to X11/Linux
- Network interfaces, Mullvad integration, fonts, and battery names are machine-specific
home/.hammerspoon/init.lua - macOS automation
- Adds hotkeys for window movement and maximizing all windows of the current app.
- Watches Wi-Fi SSIDs and mutes/reduces speaker output on specific networks.
- Launches
mpvorumpvagainst URLs in the clipboard.
Notes:
- Hammerspoon only
- Relies on local shell environment and installed media tools
darwin/Library/Preferences/, darwin/.macsettings, and darwin/.editrc - macOS overlay
darwin/Library/Preferences/com.googlecode.iterm2.pliststores the canonical XML snapshot of the iTerm2 plist at the same path it installs under~..macsettingsis a manual script ofdefaults writetweaks such as screenshot location, key-repeat behavior, and menu bar spacing..editrcadds macOS-specific line editing defaults.
Notes:
make installstowsdarwin/into$PREFIXbut copiesdarwin/Library/Preferences/*.plistinstead of symlinking themmake importconverts installed plist files back into XML indarwin/Library/Preferences/make uninstallremoves stowed macOS files but leaves copied preference plists in place
Other Notable Config Trees
The sections above cover the main pieces. There are also many smaller app configs under home/etc/, including:
ranger/,zathura/,streamlink/,fontconfig/,pulse/,xkb/msmtp/,ncmpcpp/,ncdu/transmission-daemon/,tremc/,yt-dlp/,youtube-dl/sxhkd/,sv/,acpid/,crontab.d/
And many classic top-level dotfiles live directly in home/, such as:
home/.tmux.conf,home/.screenrc,home/.inputrc,home/.Xresourceshome/.emacs,home/.vim/,home/.mutt/,home/.gnupg/home/.bashrc,home/.profile,home/.zshenv
Generated Files And Safe Editing
- Edit source files in
bin/,home/,alacritty/,darwin/, andtools/; avoid hand-editingbuild/ build/,tools/zig/zig-out/,tools/zig/kcov-output*/, andtools/python/build/are generated artifacts
Validation And Maintenance
Useful commands after changes:
make dryrun
make build
make test
When changing uniqp behavior and expected fixture output:
cd tools/zig
./generate-test-output.sh ./zig-out/bin/uniqp
When changing the generated config source under alacritty/:
make build
When changing Darwin plist XML snapshots:
make install
Practical Reuse Advice
- If you are adopting this repo on your own machine, copy selective configs before running
make install - If you do want the full setup, update the personal identity, secrets, and service endpoints first
- The cleanest reuse path is usually: keep the CLI tools, borrow the configs selectively