name: dotfiles-domain description: Use when working in the dotfiles repository (${HOME}/.config/dotfiles), personal bin (${HOME}/personal/dev/bin), or personal configs (${HOME}/personal/dev/configs). Covers shell scripting rules, Ruby conventions, zsh startup optimization, fresh-install idempotency, antidote plugin manager, and all coding decisions from prior sessions.
Dotfiles Domain Skill
This skill provides context for working in the personal dotfiles repository and companion script directories.
Absolute Rules
- NEVER push to any remote (
git push,git push --force,git push --force-with-lease, or any variant). This is unconditional — no exceptions, no user prompts. Only the user pushes. - NEVER commit, amend, or create a PR unless explicitly requested by the user. This includes
git commit,git commit --amend, andgh pr create. Only the user decides when to record history.
Quick Reference: The Three Directories
| Variable | Path |
|---|---|
$DOTFILES_DIR |
${HOME}/.config/dotfiles |
$PERSONAL_BIN_DIR |
${HOME}/personal/dev/bin |
$PERSONAL_CONFIGS_DIR |
${HOME}/personal/dev/configs |
Key Files
| File | Purpose |
|---|---|
files/--HOME--/.shellrc |
Core shell utilities, functions, env vars |
files/--HOME--/.aliases |
Higher-level aliases; sources .shellrc |
files/--ZDOTDIR--/.zshrc |
Interactive zsh config |
files/--ZDOTDIR--/.zshenv |
Env vars for all shell types |
files/--ZDOTDIR--/.zlogin |
Post-startup work (compilation, etc.) |
scripts/fresh-install-of-osx.sh |
Bootstrap: vanilla OS + idempotent re-run |
scripts/utilities/logging.rb |
Ruby logging module |
scripts/utilities/string.rb |
String color extensions |
scripts/utilities/cli_parser.rb |
Ruby CLI option parser |
scripts/utilities/hash_ext.rb |
Hash extensions (deep_sort) |
scripts/utilities/path_utils.rb |
Path utility functions |
Critical Rules (Never Violate)
fresh-install-of-osx.shmust be idempotent — works on vanilla OS AND pre-configured machine. CheckFIRST_INSTALLenv var for first-run-only logic.Do not use bare
echoin scripts — useinfo/warn/success/error/debug.Do not use raw test switches (
-f,-z,-n, etc.) — use.shellrcutility functions.Do not use
.empty?in Ruby — usenil_or_empty?custom helper.Do not replace
nil_or_empty?with.empty?— it is intentional.Encapsulation: guards that belong inside a function/file must NOT be repeated across multiple files. The
.shellrcre-source guard is inside.shellrcitself viais_shellrc_sourcedsentinel.Source tightest file: source
.shellrcif only.shellrcfunctions needed; source.aliasesif.aliasesfunctions needed (it auto-sources.shellrc). Never source both.Ruby 2.6 compat:
$DOTFILES_DIR/scripts/code must work with system Ruby 2.6 (vanilla macOS).Private naming: prefix internal/private functions/methods with
_.mainfunction: all shell scripts (except*-common.sh) must have amain()function as the entry point.Quoting: always quote variable expansions (
"${var}"). Use single quotes for static strings with no variable expansion. Always use${var}brace notation — never bare$var.
Antidote (Replaces OMZ)
Antidote is the zsh plugin manager (replaced oh-my-zsh):
- Installed via Homebrew.
ANTIDOTE_HOME=~/Library/Caches/antidote(macOS-specific).- Generated bundle file is checked into home git repo.
update_antidote_and_regenerate_plugin_bundledefined in.shellrc.- Run
antidote bundleinzsh --no-rcs -c "..."to avoid ANSI code leaks. - Guard
--unshallowwith shallow-repo check before calling. ZSHandZSH_CUSTOMenv vars from OMZ era must be unset.
Cron Split Architecture
Cron functions are split intentionally:
.shellrc:suspend_cron,resume_cron— needed before dotfiles cloned..aliases:_create_crontab,recron, higher-level helpers — only needed after dotfiles installed.
Scripts that need cron functions: source the tightest file that has them.
Color / Logging Architecture
Shell color functions (blue, red, green, etc.) apply ${1//${HOME}/~}
inline for performance (avoids a subshell fork). This is intentional — do
not refactor into a separate replace_home_with_tilde call inside each color
function.
The same pattern applies in Ruby: color methods on String apply the tilde
substitution internally.
Logging functions (info, warn, success) do NOT apply the substitution —
it is applied by the color functions they call.
RUBYLIB Setup
.shellrc sets RUBYLIB to include $DOTFILES_DIR/scripts/utilities. This
allows require 'logging' without require_relative.
On vanilla OS during fresh-install, RUBYLIB may not be set. Scripts that
run early must handle this.
.envrc Architecture
.envrc files are evaluated by direnv in a bash subshell:
- Source
.shellrcunconditionally (notypeguard needed). - POSIX syntax only — no zsh-specific constructs.
- Functions from
.shellrcare available after sourcing.
Shell Formatting Tools
- Shell scripts:
shfmt(installed via Homebrew). Runshfmt -w <file>after every edit. No inline ignore directive exists — exclude whole files via.shfmtignoreonly (two valid reasons: zsh-only syntax parse failures, or shfmt bug with one-liners in loop/push bodies). - Ruby scripts:
rufo— run from$HOME(uses mise-managed Ruby), NOT from$DOTFILES_DIR(which is pinned to system Ruby 2.6).
Documentation Update Routine
Run this routine proactively at the end of every session and at least once per day when multiple sessions occur. Do not wait to be asked.
Trigger conditions
Run the routine whenever any of the following occurred during the session:
- A new design decision was made or an existing one was revised
- A bug was discovered and fixed (especially if the fix reveals a general rule)
- A new pattern, constraint, or naming convention was established
- A new script or function was added or significantly changed
- An existing rule in the instructions was found to be incorrect or incomplete
- A new adopter-facing workflow step was introduced
Routing: what goes where
Scan the session context and apply each piece of pertinent information to the tightest file that owns it. Never duplicate the same rule across files — put it in one place and cross-reference from broader files where needed.
| Type of information | Primary file | Cross-reference if significant |
|---|---|---|
| Shell scripting rule, pattern, or pitfall | shell-scripting.instructions.md |
copilot-instructions.md summary bullets |
| Zsh startup optimisation or startup-path constraint | zsh-startup.instructions.md |
copilot-instructions.md summary bullets |
| Git config alias pattern or delta/diff rule | git-config.instructions.md |
copilot-instructions.md summary bullets |
| Ruby scripting pattern or convention | ruby-scripting.instructions.md |
— |
| Fresh-install idempotency guard or bootstrap constraint | fresh-install.instructions.md |
copilot-instructions.md if affects general readers |
| Naming convention, global state variable, or sourcing rule | copilot-instructions.md (primary) |
TechnicalDeepDive.md § 2 or § 3 if architectural |
| Architectural explanation (why a design exists) | TechnicalDeepDive.md |
link from adopter docs if user-visible |
| New or changed script behaviour | Extras.md |
link to TechnicalDeepDive.md for internals |
| Adopter workflow change (fork, upgrade, import/export steps) | README.md |
GettingStarted.md if affects first-run |
| Bug fix or behavioural change with adoption steps | CHANGELOG.md under current version |
— |
| Inaccuracy found in any doc | Fix in-place in the affected file | Fix all files that carry the same error |
Process
- Scan the full session for decisions, fixes, and patterns not yet reflected in any doc.
- For each item, identify the tightest owning file from the routing table.
- Draft the addition in the style of the surrounding content in that file
(see the code comment rules in
copilot-instructions.md§ Code Comments: explain why, not what; no temporal language; no changelog phrasing). - Apply the edit. If a broader file needs a cross-reference or summary bullet, add that too.
- If the item belongs in
CHANGELOG.md, add it under the current### x.y.zversion using the####sub-section format. Check whether an unpushed commit exists (git log @{u}..HEAD) before deciding whether to create a new version entry or extend the existing one. 5a. When creating a commit, use the####sub-section goal headings from the current CHANGELOG entry as the commit message, joined with semicolons. OmitAdopting these changes— it is not a code change. Usegit next-versionto confirm the version before finalising the CHANGELOG entry. - After all updates, verify no file now contains a stale or contradicted version of the same rule.
What does NOT belong in documentation
- Changelog-style phrasing in code comments ("Added X to fix Y").
- Temporal language ("currently", "as of this session", "now uses").
- Implementation details that are already self-evident from reading the code.
- Redundant duplication of a rule already present in the tightest file.