Personal configuration references and standalone maintenance tools for macOS
and Linux hosts. This repository reports drift and missing capabilities. It
does not automatically overwrite $HOME or rebuild an entire machine.
reference/contains the intended examples compared with live files under$HOME.mackup/declares which application paths belong to each reference.scripts/implements typed inspection tasks and explicit maintenance tasks; every mutating task previews by default and writes only with--apply.modules/bin/contains independent user commands.modules/<tool>/contains substantial tools that own their installation and removal.generated/is optional shell runtime state. A missing generated directory is a host-health warning, not a reason to mutate the repository.inventory/contains per-host software snapshots written only bymise run inventory.
Agent-specific rules live in AGENTS.md. Files under modules/ also inherit
modules/AGENTS.md.
Git and mise are the only bootstrap requirements. On a machine without mise, install it first and expose its user binary to the current bootstrap process:
curl -fsSL https://mise.run | sh
export PATH="$HOME/.local/bin:$PATH"
git clone https://github.com/ipruning/dotfiles.git ~/dotfiles
cd ~/dotfiles
mise trust
mise install
mise exec -- uv sync --locked
mise tasksmise trust is required because this repository declares a project virtual
environment. mise install provides the pinned Python and uv versions, then
mise exec -- uv sync --locked materializes the locked project dependencies,
including the pinned Mackup fork, before shell activation makes uv directly
available. Task auto-install is disabled: these two commands form the explicit
bootstrap boundary, and a later mise run ... does not quietly download a
missing task tool or project dependency.
mise tasks is the authoritative command list. The main inspection interface
is:
mise run diff
mise run check
mise run lint
mise run verifyOn Linux, diff and check automatically select the small linux-lite
profile. macOS selects macos. Use --profile full when deliberately auditing
every stored reference:
mise run diff -- --profile full
mise run check -- --profile fullChoose the operation by intent; mise tasks and each task's --help remain the
authoritative command interfaces:
| Intent | Documentation |
|---|---|
| Bootstrap a small Linux host | Linux Lite setup |
| Compare, restore, or adopt configuration | Configuration drift |
| Inspect host and repository health | Host health |
| Update installed tools | Host updates |
| Refresh generated shell state | Generated runtime |
| Record installed software | Host inventory |
| Operate a self-installing module | Standalone tools |
| Inspect Skillshare ownership | Skillshare |
Inspection remains read-only. The explicit setup task is the only repository task that edits shell and Git bootstrap configuration in place; like every mutating task it previews by default:
mise run setup -- --profile linux-lite
mise run setup -- --profile linux-lite --apply
exec bashIt preserves the existing ~/.bashrc, adds one marked block that loads
modules/bash/init.bash, and adds ~/.private.gitconfig to Git's includes. It
does not create an identity, install optional tools, clone private repositories,
or synchronize Skillshare extras. The Bash module adds ~/.local/bin and mise's
shim directory to PATH, then activates mise in interactive shells. It does not
expose modules/bin or generated/bin on Linux. The managed block is placed
before Ubuntu's non-interactive early return, so direct SSH commands also receive
the user and mise paths without interactive shell initialization.
The Linux Lite drift profile observes only Git and Skillshare configuration. Skillshare remains optional: a missing executable, configuration, or source is a warning for a human or AI operator to evaluate, not a setup action.
Linux Lite targets Bash, but the full Zsh reference is deliberately safe to
restore on a Linux host as well, so mise run restore -- zsh is supported
there. The contract is a split between experience and commands:
- The Zsh experience loads on Linux.
.zshrcsourcesmodules/zsh/(aliases, environment, completions, plugins) and the generated completion directory regardless of platform; the Homebrew block is macOS-only and the clash block is Linux-only. - The user bin and mise shim directories load on every platform. The repository
command directories do not:
.zshenvprependsmodules/binandgenerated/bintoPATHonly underdarwin*, so a Linux host never gains repository commands and can never shadow a system tool — most importantly iproute2ss, whose repository namesake isskillshare-source. - The mise configuration reinforces this: it carries no repository bins, and its
lockfile_platformscovers bothmacos-arm64andlinux-x64, so restoring the macOS mise config onto Linux cannot expose a repository command either.
What is not promised: optional tools (atuin, starship, tv) are host-managed and
their integrations degrade silently when the tool is absent. mise run shell
reflects the same asymmetry — it syntax-checks Zsh files only where zsh is
installed and marks them not-applicable elsewhere rather than failing.
mise run diff compares profile-relevant files under reference/ with the
corresponding paths under the current $HOME. It reports locations and file
kinds, never file contents. Ordinary drift exits successfully; an incomplete
inspection, such as an unreadable path or invalid Mackup response, exits
non-zero.
mise run diff
mise run diff -- git
mise run diff -- --json
mise run diff -- --profile fullThe command runs the immutable Mackup fork pinned as a locked git dependency in
pyproject.toml and recorded in uv.lock. The bootstrap command mise exec -- uv sync --locked provisions it, so no Mackup fetch happens during inspection.
It loads application definitions directly from mackup/applications/ and does
not install ~/.mackup links or change either side.
Restore is deliberately application-scoped. It defaults to the same read-only
plan; --apply first moves each changed live path into
~/.local/state/dotfiles/restore-backups/, then links the live path to its
reference. There is no implicit restore-all operation.
mise run restore -- git
mise run restore -- git --json
mise run restore -- git --applyWhen a live configuration should become the reference, adopt is the mirror of
restore: it is application-scoped, defaults to the same read-only plan, and
--apply copies the live truth into reference/ (and removes reference files
whose live counterpart is gone). It writes only inside the repository, never
under $HOME, and refuses to run while the affected reference paths have
uncommitted changes, so Git can always revert an adoption.
mise run adopt -- mise
mise run adopt -- mise --json
mise run adopt -- mise --applyGit protects repository changes; restore backups protect the replaced live paths.
mise run check reports required executables and optional capabilities
separately. The selected profile determines the current check set, which the
plain or JSON report lists directly. On macOS, the report also consumes
macos-session-health status --format json to detect an unavailable collector
or notification path.
mise run check
mise run check -- --json
mise run check -- --strictWarnings do not fail the normal command because different hosts intentionally
have different capabilities. --strict treats warnings as failures.
When Skillshare is present, check also runs skillshare doctor --json. It
does not treat the executable, YAML file, and source directory alone as proof
that synchronization is healthy. Missing or empty generated shell directories
are likewise reported as not ready.
mise run lint inspects repository paths, Mackup mappings, and dangling
symlinks. Its path.* findings are host-relative: a machine-specific path
referenced by tracked configuration is reported OK where it exists and as a
warning on hosts where it does not, so warning counts legitimately differ
between machines running the same commit. mise run verify adds Python formatting, type checking, behavior
tests, the standalone module suites on macOS, and the shell gate: mise run shell
runs Bash syntax checks and ShellCheck for Bash files. Zsh files receive syntax
checking when zsh is available.
Updating installed tools is an explicit mutation, separate from configuration inspection. Preview the exact commands first:
mise run update
mise run update -- --json
mise run update -- --applyThe task discovers supported updaters on PATH, reports missing tools as
skipped, applies available updates in a stable order, and continues independent
steps after a failure. Its preview is the authoritative list of supported
updaters and the exact commands available on the current host. Any failed step
makes the command exit non-zero. It deliberately does not run brew cleanup,
brew autoremove, or mise prune; removal and pruning require a separate,
explicit operation.
For mise, the preview first reads the active installed versions and passes that
explicit list to mise upgrade; a configured but missing mise tool is not
installed. Other missing CLIs are skipped rather than bootstrapped. Package
managers may still replace package dependencies as part of an ordinary upgrade.
update does not pull this repository, run Skillshare, or write live
configuration back into reference/. Inspect the resulting host state
separately:
mise run runtimeReview the runtime preview and apply it only when it plans relevant Zsh changes.
If the apply reports refreshed Zsh state, open a new Zsh or run exec zsh to
load the new functions, completions, and plugins:
mise run runtime -- --apply
exec zshFrom the refreshed shell, inspect the resulting host and configuration state:
mise run check
mise run diffShell runtime is maintained separately from tool updates and configuration restore. Preview the owned operations, then apply them explicitly:
mise run runtime
mise run runtime -- --json
mise run runtime -- --applyThe runtime task owns generated shell functions, completions, plugins, caches,
and other declared runtime artifacts. Its preview is the authoritative list of
planned operations on the current host. --offline limits an apply to local
generation and cache maintenance. It never runs Skillshare or writes host
inventory; snapshots have their own explicit task (see Host inventory).
Repository-owned source builds are an explicit, slower sub-operation:
mise run runtime -- --build
mise run runtime -- --build --applyThis refreshes the sources named by the runtime plan under the ignored
generated/sources/, builds them with their declared commands, and atomically
installs the artifacts into generated/bin/. Any other binary placed there
must name its own owner; mise run check reports unknown binaries.
Inventory snapshots record which software a host had installed at one point in
time. They are tracked under inventory/<host>/ so history stays reviewable,
and they are only ever written by the explicit task:
mise run inventory
mise run inventory -- --json
mise run inventory -- --applyThe preview is the authoritative list of collectors, destinations, and skipped host capabilities. A failed collector or an invalid empty result makes the command exit non-zero and leaves the existing snapshot untouched. Collectors whose domain permits zero items instead write an empty snapshot, replacing any stale non-empty result. Nothing regenerates these files implicitly — a snapshot is as old as its last committed run, never a claim about current host truth.
bag-mode, macos-session-health, and macos-maxfiles are self-installing
modules. Each executable owns its command interface, installation, removal,
tests, and generated launchd configuration. Their local runbooks own the
module-specific operating and recovery decisions:
bag-mode: closed-lid operation, restoration, and safe removal;macos-session-health: incident diagnosis and guarded recovery;macos-maxfiles: machine-wide limit lifecycle, rollback, and reboot behavior.
Ordinary commands under modules/bin/ are independent of the dotfiles
inspection tasks. Linux Lite deliberately does not add them to PATH. The macOS
shell configuration currently expects this repository at ~/dotfiles; mise run lint reports when that assumption is false.
Global harness prompts and AI skills remain owned by the Skillshare source repository. This repository stores only the reference Skillshare configuration and reports when its executable, configuration, or source directory is absent. It does not install or synchronize Skillshare automatically.
The default skillshare sync operation synchronizes skills. The stored
configuration also declares opt-in extras targets under ~/.config/amp,
~/.codex, and ~/.claude; an explicit extras sync writes those global
harness directories. Before that external write, inspect the exact affected
files:
skillshare diff --json
skillshare sync extras --dry-run --force --jsonInstalling Skillshare, choosing a source repository, and synchronizing skills are separate operator decisions. Linux Lite reports the missing capability and stops there; use the Skillshare source repository's current instructions if the host should gain that capability.
See LICENSE.