Dotfiles
nathan-roberts/dotfiles, private, cloned to ~/.dotfiles.
How it loads
~/.zshrc sources ~/.dotfiles/setup.init, which then runs in this order:
| Order | What | Note |
|---|---|---|
| 1 | .zshenv | Environment variables |
| 2 | Adds $DOTFILES/bin to PATH | Makes project-setup available |
| 3 | Symlinks AI skills into ~/.claude/skills | See below |
| 4 | Every zsh/*.zsh | |
| 5 | .zsh_aliases | Loads after zsh/, so aliases here win |
| 6 | .nr-bash-commands | Nearly empty |
| 7 | .zshrc.local | Gitignored, machine-specific, beats everything |
Skills are symlinked on every shell start
Step 3 is the surprising one. Each folder in ai/skills/ is symlinked individually into ~/.claude/skills/<name>.
Individually, not as one folder symlink, so skills installed by other tools can sit in ~/.claude/skills without ending up in the repo. It also prunes dead symlinks and refuses to overwrite a real directory.
This is why editing a SKILL.md in the repo takes effect immediately. No install step.
Commands worth remembering
| Command | Does |
|---|---|
scan | Interactive UpdraftPlus restore picker. See below |
skill-new <name> | Scaffolds ai/skills/<name>/SKILL.md plus references/, opens it. Refuses if it exists |
skill-edit, skill-cat, skills, skills-ls | Open, print, cd to, list skills |
sslcerts <domain> | Certificate validity window, subject and issuer |
mkcd <dir> | Make a directory and cd into it |
backup <file> | Copy to <file>.bak |
wpinit | New WordPress project from scratch, creates the private GitHub repo too |
project-setup | Bootstraps an existing WordPress directory |
dlud | Downloads UpdraftPlus Premium from a Dropbox link |
dev | Opens three things at once: Surf, Tower, and ddev launch |
scan
The most substantial thing in here, 616 lines of Python behind a one-word command, and nothing about the name says "restore".
Run scan anywhere inside a DDEV project. It walks up to find .ddev/config.yaml, reads docroot: from it, lists backups in <docroot>/wp-content/updraft, and gives an arrow-key picker for the backup and which components to restore. Then it runs ddev wp updraftplus rescan-storage local and restore <nonce> --components=....
Solves "which of these forty zips do I restore, and what's the nonce" without opening wp-admin.
wpinit vs project-setup
Easy to reach for the wrong one.
wpinit | project-setup | |
|---|---|---|
| Starting from | Nothing | An existing WordPress directory |
| Creates GitHub repo | Yes, private, via gh | No |
| Branches | main then dev | Current only |
| UpdraftPlus | Premium, from Dropbox | Free, from wordpress.org |
| Finishes | Prints commands for you to run manually | Fully automatic |
wpinit not finishing on its own is the bit that catches you out.
Known problems
| Problem | Detail |
|---|---|
gp commits the wrong date | Defined with double quotes, so $(date) is evaluated once at shell start. Every gp commit is stamped with when the shell opened. Single quotes fix it |
| oh-my-zsh may be dead config | source $ZSH/oh-my-zsh.sh is commented out at zsh/ohmyzsh.zsh:70, so the whole plugins=(...) array and the powerlevel10k theme do nothing from this file |
l and la broken on macOS | Redefined at .zsh_aliases:195 using GNU --color, clobbering the earlier correct ${colorflag} versions |
wpsetup likely broken | Points at ~/scripts/wp-setup.sh, which isn't in this repo |
precmd overridden wholesale | .zshenv:43 replaces the hook, which can quietly break a powerlevel10k prompt |
| Fourteen aliases defined twice | gs, l, la, ll, localip, map, myip, o, p, qc, reload, show, sniff, t. The later ones win |
c is surf ., not code . | WARP.md says otherwise |
Docs in here are stale
README.md and WARP.md both describe a repo that no longer exists. README omits ai/skills/, wp-scripts/, scripts/, most of zsh/, and says nothing about skills symlinking. It still has github.com/yourusername/dotfiles placeholder text. WARP.md gets c, dev and scan wrong.
Treat this page as the accurate one until those are fixed.
Global Claude preferences
~/.claude/CLAUDE.md is a symlink to ai/CLAUDE.md in this repo, so it's version controlled rather than a loose file in the home directory.
setup.init recreates the symlink on every shell start, the same way it does for skills. If a real file is already sitting at ~/.claude/CLAUDE.md it refuses to overwrite it and says so, so on a new machine move that file into ai/ first.