- Shell 53.5%
- Lua 24.5%
- GLSL 9.7%
- SCSS 6.7%
- Python 5.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| linux | ||
| macos | ||
| shared | ||
| system/etc | ||
| vps | ||
| README.md | ||
| setup_artix.sh | ||
| setup_machine.sh | ||
Dotfiles
My personal dotfiles, managed with GNU Stow. The repo is split into three stow packages so macOS and Linux machines share what they can:
| Package | Contents |
|---|---|
shared/ |
bash, git, nvim, ghostty, ansible, Claude, portable scripts |
macos/ |
Hammerspoon, LaunchAgents, gnupg (PCSC), brew packages, scripts |
linux/ |
the Arcane Ascension Wayfire rice, Linux shell setup |
Files are stowed with per-file symlinks (--no-folding) so app state
written next to stowed files never leaks into the repo. README.md,
setup_machine.sh, setup_artix.sh and the system/ and vps/
trees live outside the packages and are never stowed.
The shared .bashrc sources ~/.config/bash/os.sh, which the macos
and linux packages each provide their own version of — OS-specific
shell setup goes in there, not in the shared file.
New machine setup — macOS
-
Clone the repo to the home folder:
git clone ssh://git@forge.quinlan.cloud:2222/joshquinlan/dotfiles.git ~/.dotfiles -
Run
~/.dotfiles/setup_machine.sh. It is idempotent and handles:- Homebrew (installs if missing, works on Apple Silicon and Intel)
- Stowing
shared+macosinto$HOME(--adoptmeans the repo always wins over any pre-existing files) - All packages, via
get_packages.sh - macOS defaults (Hammerspoon config location)
- Homebrew bash as the login shell
- TouchID for sudo (
/etc/pam.d/sudo_local)
-
Open Neovim once — lazy.nvim installs itself and all plugins on first launch. Versions are pinned in
lazy-lock.json.
New machine setup — Linux (Artix, dinit)
-
Clone the repo to the home folder:
git clone ssh://git@forge.quinlan.cloud:2222/joshquinlan/dotfiles.git ~/.dotfiles -
Run
~/.dotfiles/setup_artix.shas your user (system steps escalate via doas, or sudo on first run if that is all the box has). It is idempotent and handles:- Arch repositories (
artix-archlinux-support+[extra]) - doas as the escalation tool (
system/etc/doas.conf; an existing policy is never overwritten, only diffed) - every rice package: wayfire, kitty, starship, fuzzel, mako, fastfetch, grim, slurp, swaybg, wlsunset, playerctl, greetd with tuigreet, fonts and icons; the AUR bits (wayfire-plugins-extra, eww, swaylock-effects) build directly with makepkg, no AUR helper needed
- un-stowable system files (
system/→/etc), user groups and dinit services (dbus, seatd, greetd) - stowing
shared+linuxand rendering the theme
- Arch repositories (
-
Install the general CLI tools the shared configs expect:
nvim,lsd,most,gpg,gpg-tui,fzf,fd,termscp,libsecret(secret-tool, for weremutt's keyring unlock), and anything else the shell complains about. For ble.sh, either use the distro package or extract the prebuilt nightly tarball to~/.local/share/blesh(see setup_machine.sh for the exact command; the bashrc also checks/usr/share/blesh).
On non-Artix distros there is no setup script; stow manually:
~/.dotfiles/shared/.local/bin/restow --adopt && git -C ~/.dotfiles checkout .
The Arcane Ascension rice (Linux)
A Wayfire desktop themed on the Arcane Ascension books: twilight purples, spire-fire ambers, serif display type. Pieces: eww (bar and cards), fuzzel, mako, kitty with a fastfetch "system augury" greeting, swaylock-effects, greetd + tuigreet.
Keys: Super is the modifier. hjkl focus, Shift+hjkl snap,
1..6 workspaces (Shift carries the window), Enter terminal,
Space launcher, E overview, F fullscreen, M minimise,
Q close, Esc lock, Shift+S region screenshot. The workspace
cube rides on Super+Alt+drag.
Accessibility is non-negotiable: large type everywhere (scale
lives in one file, shared/.config/themes/typeface.sh) and
full-desktop zoom on Super+scroll.
theme-switch <scheme>swaps the whole rice between palettes (arcaneis the committed default,kanagawathe alternative) and live-reloads what can be reloaded.animation-profile <grimoire|swift|toggle>flips between the full effect set (fire open, vortex close, magic-lamp minimise, cube, blur, wobbly) and a fast low-motion profile;--persistmakes it survive a compositor restart.
The wallpaper lives at
linux/.local/share/wallpapers/arcane-serpent-spire.png and is
referenced by the palette (THEME_WALLPAPER), so a scheme can
bring its own image.
Day-to-day
-
After adding or removing files in the repo, run
restow— it stowssharedplus the right OS package automatically.restow -nfor a dry run; extra flags pass through to stow. -
New files go in the most specific package that fits:
sharedunless it genuinely only makes sense on one OS.
Colour schemes
One palette rules every themed tool. The palettes live in
shared/.config/themes/ (hex values plus curated 256-colour
approximations): kanagawa.sh everywhere, arcane.sh as the
Linux rice default. Fonts and the type scale have their own
contract in typeface.sh.
- Runtime consumers (fzf, ble.sh) read the
THEME_*variables directly;.bashrcsources the palette named byDOTFILES_THEME(set from~/.config/themes/rice-themeon Linux, Kanagawa elsewhere). - File-based configs are rendered from
shared/.config/themes/templates/bygen-theme(shared set: lsd, termscp, urlscan, the Ghostty cursor shader) andgen-theme --rice(rice set undertemplates/rice/: wayfire, kitty, starship, eww, mako, fuzzel, swaylock, GTK). Generated files are committed; edit the template or the palette, never the output, then rerun (needsenvsubst, from the gettext package).
A new scheme is a new palette file defining the same variable
set (including the semantic role variables); switch the rice to
it with theme-switch <name>. Switching away from arcane leaves
the rendered files locally dirty by design; git checkout .
restores the committed defaults.
Git identity
- Default identity is
Josh Quinlan <josh@quinlan.cloud>. - Repos with GitHub, GitLab, or sr.ht remotes automatically switch to
the
donquinleoneidentity viaincludeIf→priv.inc.
Gotcha: the global git config is itself a stowed file in this repo. Rebasing here checks out old commits, which silently reverts the global config mid-rebase (identity, signing key, everything). When rewriting history in this repo, set the identity explicitly:
GIT_COMMITTER_NAME="Josh Quinlan" GIT_COMMITTER_EMAIL="josh@quinlan.cloud" \
git commit --amend ...
macOS Gatekeeper
Some apps refuse to open, claiming to be "damaged". That's Gatekeeper. Fix per app with:
xattr -cr /Applications/AppName.app