Personal shell, editor and git config for a Mac and two Omarchy/Arch machines
(charizard, squirtle), from one repo and one branch.
shared/ is linked everywhere; macos/ or linux/ is linked according to
uname. The split is done by which files get linked, not by a runtime OS test
inside the configs — so a per-OS setting is a new file in an OS directory, never
an edit to zshrc.
git clone git@github.com:sublimecoder/dotfiles.git ~/dotfiles
~/dotfiles/install.shinstall.sh symlinks each file into $HOME (e.g. shared/zshrc ->
~/.zshrc, shared/bin/* -> ~/.bin/*). Re-run it any time after adding a new
file — it's safe to run repeatedly, and it won't overwrite a real (non-symlink)
file that's already at the destination.
On macOS it also runs brew bundle against macos/Brewfile. On Linux it
reports anything missing from linux/packages.txt and installs nothing. On
both it runs mise install (global tools from shared/config/mise/config.toml)
and restores the Neovim plugins pinned in shared/config/nvim/lazy-lock.json.
Check a machine any time; it changes nothing and exits non-zero on any failure:
dotfiles-doctor # nvim starts clean, EDITOR, omarchy-provision --check, ssh agent, signed commit./test-install.sh is the repo's own self-check: it runs install.sh against
scratch $HOMEs, offline, with brew/mise/nvim stubbed — including a simulated
Mac run. Run it before committing a change to install.sh or a linked file.
Everything a machine carries beyond a stock Omarchy install lives in
linux/omarchy/common.manifest plus linux/omarchy/hosts/<hostname>.manifest:
packages, AUR packages, Omarchy installers, shell plugins, bar order, web apps,
services and a few in-place settings. The format is documented at the top of
common.manifest. install.sh only reports the count; applying takes sudo:
omarchy-provision --check # what is missing, changes nothing
omarchy-provision # install it (idempotent; re-run after a failure)
sudo ~/dotfiles/linux/bin/restic-setup # nightly restic -> B2; asks for credentialsThen restore data from restic selectively (restic restore latest --target ... --include ~/code and the like), never all of ~/.config over a fresh
install: that overwrites the newer Omarchy defaults the install just wrote.
Order on a dead laptop: install Omarchy, clone this repo, install.sh,
omarchy-provision, restic-setup, restore data. Restic credentials are not in
this repo; keep them somewhere off the machine. When you add something by hand,
add its line to the host manifest, and omarchy-provision --check on the live
machine should say "nothing missing".
It also restores Claude Code: claude/setup.sh merges claude/settings.base.json
into ~/.claude/settings.json (merged, not linked — Claude Code writes that file),
installs the listed plugins, and clones third-party skills. A private second
installer is run afterwards when present; on a fresh machine pass its remote once:
AIOS_VAULT_REMOTE=<git url> ~/dotfiles/install.shDo not run git config --global ... to set anything that belongs in this
repo: ~/.gitconfig is a symlink to shared/gitconfig, so the command rewrites
the tracked file and expands ~ into an absolute /home/... path the Mac does
not have. Edit shared/gitconfig instead. (init.templatedir is already set
there.)
shared/zshrc,shared/aliases,shared/zshenv— shellshared/zsh/— functions, completions, and config fragments loaded byzshrcshared/shellrc— the portable core (functions, aliases, PATH,EDITOR) sourced by both zsh and bashshared/config/nvim/— Neovim (LazyVim); see Editorshared/vimrc,shared/vim/— a plain-vim fallback with no plugins; the old vim-plug/ALE setup is in git historyshared/gitconfig,shared/gitmessage,shared/git_template/— gitshared/bin/— small personal scripts, on$PATHviainstall.sh(dotfiles-doctor,herdr-run-below, thegit-*helpers)shared/config/mise/— global runtime/tool versions for both machinesmacos/— Brewfile, zprofile, and the Homebrew / gcloud / Android / iCloud bits that exist only therelinux/—packages.txt, the Wayland clipboard functions, and the printer setup (linux/bin/setup-printers.sh,linux/cups/lprint-backend)
macos/zsh/configs/ links into the same ~/.zsh/configs/ as the shared ones,
so both halves load through one loader. Linux runs bash, so its per-OS shell
bits are portable functions in linux/shell/functions/ instead.
Neovim on both machines (EDITOR=nvim, set in shared/shellrc), running
LazyVim from shared/config/nvim/:
- Colorscheme:
nanotech/jellybeans.vim, the same one the vimrc used — not the Omarchy theme, soomarchy themechanges do not touch the editor. - Languages: LazyVim extras for Elixir, Ruby, TypeScript, JSON and Markdown,
plus eslint — they replace the old ALE setup. Go is off until
gois inshared/config/mise/config.toml(the extra installs its tools withgo install). Language servers download through Mason on the first open of each language, not duringinstall.sh. - Tests: vim-test. Inside herdr it runs in the pane below the editor (the
terminal pane of
hdl), splitting one off if there is none, viashared/bin/herdr-run-below; outside herdr, in an nvim terminal split. - Plugin versions:
lazy-lock.jsonis tracked and linked, so:Lazy updatewrites the repo copy — commit it. Other machines pick it up on the nextinstall.sh(or:Lazy restore).
Keymaps that differ from the old vimrc (LazyVim owns <leader>s, <leader>l,
<leader>f, <leader>d and <leader>g as groups):
| Old vimrc | Now |
|---|---|
<leader>t / s / l / a / gt |
<leader>tt file, tr nearest, tl last, tT suite, tv visit |
K (grep word) |
K is LSP hover; grep word is <leader>sw |
]r / [r (ALE) |
]d / [d |
,f (ctags) |
gd |
<leader>d todo, <leader>f IEx.pry, <leader>gw WIP push |
dropped (todo shell alias still works) |
Kept as they were: <leader><leader> (alternate file), <C-p> (files), \
(grep), and . / @ over a visual selection.
install.sh moves aside (timestamped, kept) any ~/.config/nvim this repo does
not own — the Mac's old init.vim, or the LazyVim starter a fresh Omarchy
install copies in as real files — so the linked config can take its place.
install.sh does not configure printers — every step needs root. It only
reports the command when no CUPS queue exists:
sudo ~/dotfiles/linux/bin/setup-printers.shThat wires two things on a fresh Omarchy box:
- Canon PIXMA TS4320 (network) — driverless. No Canon package and no PPD: the printer advertises IPP Everywhere over mDNS and stock CUPS drives it. The script discovers any AirPrint printer on the LAN rather than hardcoding one, so a replacement printer needs no edit.
- Yxwl/Labeer Y812BT 4x6 thermal label printer (USB) — via
lprintfrom Archextra/. Its USB device ID reports an emptyCMD:, so nothing auto-detects it; the command language is TSPL, confirmed by probe.
Two things that setup learned the hard way, both written into the script:
lprintclaims the USB device through libusb, which deletes/dev/usb/lp0. Writing to that path afterwards silently creates a regular file and the job disappears with no error. Drive it throughlprint.- Chromium/Brave sends
print-color-mode=coloron every job even when CUPS advertises monochrome-only, andlprintrejects it — jobs land ascanceled-at-devicewith nothing printed and nothing stuck. Not fixable from the browser or the queue defaults, so CUPS reacheslprintthroughlinux/cups/lprint-backend, a nine-line shim that pins monochrome.
The label printer's resolution is per-unit — 203 dpi was confirmed with a
ruler, but the same Yxwl engine ships at 300 dpi under other badges. Verify
before trusting it; re-run with LABEL_DPI=300 if labels print off-scale.
Mac: zsh. Omarchy/Arch: bash, the distribution's default — zsh is not
installed there and is deliberately absent from linux/packages.txt. Nothing is
chsh-ed on either machine. shared/zsh/ is linked on Linux but simply unused.
Reasoning, what bash actually costs, and how to reverse it:
docs/shell-decision.md.
gdm, review and squash compare against git default-branch — origin's
default branch, or main when origin/HEAD is unset (fix that per repo with
git remote set-head origin -a).
A project .env loads through direnv, not a shell function: once per repo,
echo dotenv > .envrc && direnv allow. Nothing loads until you allow it, an
edited .envrc is blocked again until re-allowed, and .env reloads on change
and unloads when you cd out. Edits to .env itself are not re-approved, so
read a cloned repo's .env before the first direnv allow.
If you want to copy any of this, go ahead.