diff --git a/.chezmoiignore b/.chezmoiignore index ecc0e8a..4c69390 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -5,3 +5,4 @@ CLAUDE.md justfile packages/** secrets/** +macos/** diff --git a/README.md b/README.md index 61b7fd1..4141c1e 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ just apply # apply source -> $HOME just edit ~/.zshrc # edit a managed file just add ~/.config/foo # capture a new dotfile just secrets # edit the encrypted secret store +just macos # apply dev-friendly macOS system defaults (manual, needs sudo) just freeze-packages # re-snapshot Brewfile + devbox after installing something just update # git pull + apply ``` @@ -55,17 +56,26 @@ To enable the CI apply-dry-run, add the age private key as repo secret `SOPS_AGE .chezmoi.toml.tmpl machine vars (prompted on init) .sops.yaml .gitignore .chezmoiignore dot_zshrc dot_zshenv dot_zprofile shell -dot_gitconfig.tmpl git identity (templated, no tokens) +dot_aliases dot_functions modular shell config (sourced by .zshrc) +dot_gitconfig.tmpl git identity + sane defaults (templated, no tokens) +dot_global-gitignore global git excludes (core.excludesFile) dot_npmrc.tmpl npm auth (from sops) dot_config/ starship, ghostty, yazi, htop, gh dot_claude/ Claude Code settings + rules (go/ts/common) secrets/env.enc.yaml sops-encrypted secrets packages/Brewfile devbox.global.json reproducible package sets +macos/set-defaults.sh dev-friendly macOS defaults (manual: just macos) .chezmoiscripts/run_onchange_* idempotent bootstrap .github/workflows/ci.yml gitleaks + apply dry-run justfile task runner ``` +## Credits + +Structure and the macOS-defaults approach are inspired by +[freekmurze/dotfiles](https://github.com/freekmurze/dotfiles), adapted from a +PHP/Laravel workflow to this React/TS · Go · Postgres · chezmoi setup. + ## Security note If a token ever lands in git history, revoke it immediately — history is permanent. diff --git a/dot_aliases b/dot_aliases new file mode 100644 index 0000000..105f73a --- /dev/null +++ b/dot_aliases @@ -0,0 +1,52 @@ +# Sourced from .zshrc. Stack-focused: Go · React/TS · Postgres · devbox/colima · Claude. +# Keep git/kubectl aliases in .zshrc; this file complements them. + +# --- Docker / colima --- +alias dk="docker" +alias dc="docker compose" +alias dps="docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'" +alias cim="colima" +alias cim-start="colima start" +alias cim-stop="colima stop" +alias cim-status="colima status" + +# --- devbox --- +alias db="devbox" +alias dbs="devbox shell" +alias dbr="devbox run" +alias dbg="devbox global" + +# --- Go --- +alias gob="go build ./..." +alias got="go test ./..." +alias gor="go run ." +alias gomt="go mod tidy" +alias gol="golangci-lint run" + +# --- Node / pnpm / bun --- +alias pn="pnpm" +alias pnd="pnpm dev" +alias pnb="pnpm build" +alias pnt="pnpm test" +alias pni="pnpm install" +alias bx="bunx" + +# --- Postgres --- +alias pg="psql" +alias pgl="psql -l" + +# --- Claude Code --- +alias c="claude" +alias cc="claude" + +# --- Modern CLI (installed via Brewfile) --- +command -v eza >/dev/null && alias ls="eza --group-directories-first" && alias ll="eza -la --git --group-directories-first" +command -v bat >/dev/null && alias cat="bat --paging=never" +command -v lazygit >/dev/null && alias lg="lazygit" +command -v yazi >/dev/null && alias y="yazi" +command -v k9s >/dev/null && alias k="k9s" + +# --- Misc --- +alias reload="exec zsh" +alias path='echo -e ${PATH//:/\\n}' +alias ip="curl -fsS ifconfig.me/ip; echo" diff --git a/dot_functions b/dot_functions new file mode 100644 index 0000000..6f3a899 --- /dev/null +++ b/dot_functions @@ -0,0 +1,22 @@ +# Sourced from .zshrc. Small, general-purpose shell functions. + +# Make a directory and cd into it +mkd() { mkdir -p "$@" && cd "$_" || return; } + +# Kill whatever is listening on a port: killport 5432 +killport() { + local pid + pid=$(lsof -ti tcp:"$1") && kill -9 "$pid" && echo "killed $pid on :$1" || echo "nothing on :$1" +} + +# Full dig answer +digga() { dig +nocmd "$1" any +multiline +noall +answer; } + +# git clone and cd into the repo +gclone() { git clone "$1" && cd "$(basename "$1" .git)" || return; } + +# Serve the current dir over HTTP (default :8000) +serve() { python3 -m http.server "${1:-8000}"; } + +# Recursively find + ripgrep helper: f +f() { rg --hidden --glob '!.git' "$@"; } diff --git a/dot_gitconfig.tmpl b/dot_gitconfig.tmpl index dd14b2a..f0c70f9 100644 --- a/dot_gitconfig.tmpl +++ b/dot_gitconfig.tmpl @@ -8,6 +8,18 @@ [user] name = {{ .name }} email = {{ .email }} +[core] + excludesFile = ~/.global-gitignore +[init] + defaultBranch = main +[pull] + rebase = true +[push] + autoSetupRemote = true +[fetch] + prune = true +[diff] + colorMoved = default [credential "https://github.com"] helper = helper = !/opt/homebrew/bin/gh auth git-credential diff --git a/dot_global-gitignore b/dot_global-gitignore new file mode 100644 index 0000000..a97c851 --- /dev/null +++ b/dot_global-gitignore @@ -0,0 +1,58 @@ +# Global gitignore — wired via git config core.excludesFile. +# Project-agnostic junk that should never be committed anywhere. + +# macOS +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +.AppleDouble +Icon? + +# Editors / IDEs +.idea/ +.vscode/ +.zed/ +*.sublime-project +*.sublime-workspace +.*.sw? +*~ + +# Node / JS / TS +node_modules/ +npm-debug.log* +yarn-error.log +.pnpm-debug.log* +.turbo/ +.next/ +dist/ +coverage/ + +# Go +*.test +*.out +/vendor/ +__debug_bin* + +# Python +__pycache__/ +*.py[cod] +.venv/ +.mypy_cache/ +.ruff_cache/ + +# Env & secrets (never commit) +.env +.env.* +!.env.example +*.pem +*.key + +# Tooling +.direnv/ +.devbox/ +.terraform/ + +# Claude Code (machine-local) +.claude/settings.local.json diff --git a/dot_zshrc b/dot_zshrc index c2eb3fe..026fa71 100644 --- a/dot_zshrc +++ b/dot_zshrc @@ -146,3 +146,7 @@ alias claude-mem='bun "/Users/antono/.claude/plugins/marketplaces/thedotmack/plu [[ ":$PATH:" != *":$HOME/.config/kaku/zsh/bin:"* ]] && export PATH="$HOME/.config/kaku/zsh/bin:$PATH" # Kaku PATH Integration [[ -f "$HOME/.config/kaku/zsh/kaku.zsh" ]] && source "$HOME/.config/kaku/zsh/kaku.zsh" # Kaku Shell Integration + +# Modular shell config (managed by chezmoi) +[ -f ~/.aliases ] && source ~/.aliases +[ -f ~/.functions ] && source ~/.functions diff --git a/justfile b/justfile index c2be32f..e870035 100644 --- a/justfile +++ b/justfile @@ -27,6 +27,10 @@ add +files: secrets: sops secrets/env.enc.yaml +# Apply dev-friendly macOS system defaults (manual; needs sudo + logout). +macos: + bash macos/set-defaults.sh + # Refresh package manifests from the current machine. freeze-packages: brew bundle dump --file=packages/Brewfile --force --describe diff --git a/macos/set-defaults.sh b/macos/set-defaults.sh new file mode 100644 index 0000000..1bbaec6 --- /dev/null +++ b/macos/set-defaults.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# macOS developer defaults. Run manually — NOT part of `chezmoi apply`. +# just macos (or) bash macos/set-defaults.sh +# Adapted from https://github.com/freekmurze/dotfiles (dev-safe subset only). +set -euo pipefail + +echo "Configuring macOS defaults… (some changes need a logout/restart)" +# Keep sudo alive for the tweaks that need it. +sudo -v +while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null & + +# --- Keyboard: fast key repeat (great for vim/motions) --- +defaults write NSGlobalDomain KeyRepeat -int 2 +defaults write NSGlobalDomain InitialKeyRepeat -int 15 +defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false +defaults write NSGlobalDomain AppleKeyboardUIMode -int 3 + +# --- Text: stop "smart" substitutions that ruin code/typing --- +defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false + +# --- Panels & save behavior --- +defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true +defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode2 -bool true +defaults write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true +defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false + +# --- Finder: show everything, path/status bars, no .DS_Store on network/USB --- +defaults write com.apple.finder AppleShowAllFiles -bool true +defaults write NSGlobalDomain AppleShowAllExtensions -bool true +defaults write com.apple.finder ShowPathbar -bool true +defaults write com.apple.finder ShowStatusBar -bool true +defaults write com.apple.finder _FXSortFoldersFirst -bool true +defaults write com.apple.finder FXPreferredViewStyle -string "Nlsv" # list view +defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true +defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true + +# --- Screenshots: PNG into ~/Screenshots, no window shadow --- +mkdir -p "${HOME}/Screenshots" +defaults write com.apple.screencapture location -string "${HOME}/Screenshots" +defaults write com.apple.screencapture type -string "png" +defaults write com.apple.screencapture disable-shadow -bool true + +# --- Dock: faster, no auto-rearrange spaces --- +defaults write com.apple.dock autohide-delay -float 0 +defaults write com.apple.dock autohide-time-modifier -float 0.15 +defaults write com.apple.dock mru-spaces -bool false + +# --- Misc developer quality-of-life --- +defaults write NSGlobalDomain NSWindowResizeTime -float 0.001 +defaults write com.apple.LaunchServices LSQuarantine -bool false # no "are you sure you want to open" + +echo "Restarting affected apps…" +for app in Finder Dock SystemUIServer; do killall "$app" >/dev/null 2>&1 || true; done +echo "Done. Log out and back in for everything to take effect."