Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .chezmoiscripts/run_onchange_seed-theme-symlinks.sh.tmpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#!/bin/bash
# Seed Catppuccin theme symlinks to match current macOS appearance — but only
# when they are ABSENT. chezmoi no longer manages these symlinks (sync-theme owns
# them at runtime); this just bootstraps a fresh machine. Existing symlinks are
# left untouched, so a runtime/manual selection is never clobbered.
# (run_onchange: re-runs only if this script's content changes.)
# Seeds Catppuccin theme symlinks for the current appearance, only when ABSENT:
# sync-theme owns them at runtime, so an existing selection is never clobbered.

set -euo pipefail

Expand Down
15 changes: 5 additions & 10 deletions dot_local/bin/executable_dots-setup
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,8 @@ echo "${bold}Profile: ${green}${profile}${reset}"
echo ""

# ── Step 2: State-file + reload package picker ───────────────────────────────
# fzf's change-query is async so change-query+select-all can't reliably filter
# a group. Instead we manage selection state in a file and use execute-silent
# + reload, which is synchronous and works for both individual and group toggles.
# fzf's change-query is async, so group toggles keep state in a file and use
# execute-silent + reload, which is synchronous.

_state_file=$(mktemp /tmp/dots-setup-state.XXXXXX)
_order_file=$(mktemp /tmp/dots-setup-order.XXXXXX)
Expand Down Expand Up @@ -328,10 +327,8 @@ touch_id_sudo=$(printf '%s\n' "${_touch_opts[@]}" | \
--header "Enable Touch ID for sudo? (macOS 14+)")

# ── Step 5: Claude billing ────────────────────────────────────────────────────
# ANTHROPIC_API_KEY is only ever exported (see env.zsh) when you're on
# API-key billing *and* choose to source it from 1Password. Subscription
# (Pro/Max) users get nothing exported, so `claude` always uses subscription
# login — no wrapper/scrubbing needed.
# ANTHROPIC_API_KEY is exported (env.zsh) only for API-key billing sourced
# from 1Password; subscription users get nothing, so `claude` uses its login.
claude_api_key=false
echo ""
_billing_opts=(subscription api_key)
Expand All @@ -355,9 +352,7 @@ if [[ "$_claude_billing" == "api_key" ]]; then
fi

# ── Step 6: Dark-mode location (Hammerspoon darkmode.lua) ────────────────────
# Sun times for the auto light/dark switch are computed locally from lat/long.
# Only prompted when macos_utils (Hammerspoon) is enabled; otherwise defaults
# (or the values already in chezmoi.toml) are kept.
# Sun times come from lat/long. Only asked when macos_utils (Hammerspoon) is on.
darkmode_city=$(_cfg_get darkmode_city); : "${darkmode_city:=Tallinn, Estonia}"
darkmode_lat=$(_cfg_get darkmode_latitude); : "${darkmode_lat:=59.4370}"
darkmode_lon=$(_cfg_get darkmode_longitude); : "${darkmode_lon:=24.7536}"
Expand Down
20 changes: 6 additions & 14 deletions dot_zsh/functions.zsh.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,15 @@ _chezmoi_sync() {
echo "🔄 Fetching origin/main..."
git -C "$src" fetch origin main || { echo "❌ fetch failed"; return 1; }

# checkout -B resets the main branch to origin/main regardless of current state:
# works from any branch, detached HEAD, or after a failed rebase.
# checkout -B works from any branch, detached HEAD, or a failed rebase
git -C "$src" checkout -B main origin/main

chezmoi apply
}

# === Maintenance ===
# Regenerate the static tool-init files (~/.zsh/*_init.zsh) + completions.
# A `brew upgrade` can change a tool's `init` output, leaving the cache stale;
# the run_onchange hash only catches Brewfile/plugin edits, not version bumps.
# brew upgrade can change a tool's init output; the run_onchange hash only sees Brewfile/plugin edits.
_regen_inits() {
bash <(chezmoi execute-template < "$(chezmoi source-path)/.chezmoiscripts/run_onchange_generate-tool-inits.sh.tmpl")
}
Expand Down Expand Up @@ -108,9 +106,8 @@ sh-add() {
}

# === Brew Drift Detection ===
# Two-way sync: promote untracked packages into dot_Brewfile.tmpl and remove
# stale entries (in Brewfile but no longer installed). Skipped packages are
# persisted to .brewsync_skip so they are never prompted again.
# Two-way sync: add untracked packages to dot_Brewfile.tmpl, drop uninstalled
# ones. Skips persist in .brewsync_skip.
brewsync() {
local src brewfile tmp skip_file
src="$(chezmoi source-path)/dot_Brewfile.tmpl"
Expand All @@ -123,7 +120,6 @@ brewsync() {
touch "$skip_file"

# ── Stale detection ──────────────────────────────────────────────────────
# Find packages listed in ~/.Brewfile that are no longer installed.
local formula_list cask_list
formula_list=$(brew list --formula 2>/dev/null)
cask_list=$(brew list --cask 2>/dev/null)
Expand Down Expand Up @@ -162,11 +158,8 @@ brewsync() {
fi

# ── Untracked detection ──────────────────────────────────────────────────
# Use the short name (strip tap prefix) for matching: brew leaves may return
# "siderolabs/tap/talosctl" or just "talosctl"; brew list --cask always returns the
# short form (e.g. "airbattery") even when the Brewfile has the tap-qualified
# form (e.g. cask "lihaoyun6/tap/airbattery"). The regex ([^"'/]+/)* matches
# zero or more leading tap path components so both forms are detected.
# Match on the short name: brew leaves may or may not include the tap, casks
# never do, and the Brewfile may be tap-qualified; ([^"'/]+/)* covers both.
local -a untracked=()
while IFS= read -r pkg; do
local short="${pkg##*/}"
Expand All @@ -177,7 +170,6 @@ brewsync() {
command grep -qE "^cask [\"']([^\"'/]+/)*${short}[\"']" "$brewfile" || untracked+=("cask:::$cask")
done < <(brew list --cask 2>/dev/null)

# Filter out permanently skipped entries
local -a pending=()
for entry in "${untracked[@]}"; do
command grep -qxF "$entry" "$skip_file" || pending+=("$entry")
Expand Down
4 changes: 1 addition & 3 deletions dot_zshrc.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ unset HISTFILE
setopt HIST_IGNORE_SPACE AUTO_CD CORRECT

# 8. Async compile (background, does not block startup)
# Only (re)compile when the source is newer than its .zwc — `-nt` is true when
# the target is missing too, so fresh files compile on first run. zsh updates a
# file's mtime whenever chezmoi rewrites it, so edits are always picked up.
# compile when source is newer than its .zwc (-nt is also true when .zwc is missing)
{
[[ ~/.zshrc -nt ~/.zshrc.zwc ]] && zcompile ~/.zshrc
for f in ~/.zsh/*.zsh(N); do
Expand Down
8 changes: 3 additions & 5 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,14 @@ if ! command -v chezmoi &>/dev/null; then
fi

# --- Phase 1: init + base apply ---
# chezmoi init clones the repo and writes ~/.config/chezmoi/chezmoi.toml with
# safe defaults (all feature flags off). The first apply installs only base
# packages — importantly including fzf, which dots-setup needs.
# init writes chezmoi.toml with all flags off; the first apply installs base
# packages only, including fzf, which dots-setup needs.
echo "Initialising dotfiles from ${DOTFILES_REPO} (base pass)..."
chezmoi init "$DOTFILES_REPO"
chezmoi apply

# --- Phase 2: interactive machine setup ---
# dots-setup runs the profile wizard, writes the real chezmoi.toml, then calls
# chezmoi apply again to install the selected packages.
# dots-setup writes the real chezmoi.toml and applies again with the selection.
echo ""
echo "Launching machine setup wizard..."
~/.local/bin/dots-setup
Loading