13 Commits
Author SHA1 Message Date
Fabian Ising 874a823d1e [AC] Migrate from brew 2026-09-01 08:29:15 +02:00
Fabian Ising cc90b515c6 [MAC] Add DNS reset 2026-08-28 10:58:53 +02:00
Fabian Ising 13ffdfdb04 [NVIM] Make update checker portable 2026-08-24 09:44:08 +02:00
Fabian Ising 67885075d3 [NVIM] Keep update notices visible 2026-08-24 09:41:11 +02:00
Fabian Ising 9ffe78362e [NVIM] Defer plugin update checks 2026-08-24 09:41:11 +02:00
Fabian Ising f5389de7b8 Fix delzip 2026-08-24 09:34:52 +02:00
Fabian Ising 9e059859c6 [TOOLS] Move color test to tools repo 2026-08-12 17:49:16 +02:00
Fabian Ising 6f9e4910bb [ZSH] Add custom completions 2026-08-11 15:01:20 +02:00
Fabian Ising 104b8e2d8d [ZSH] Venv for agents 2026-08-03 11:02:40 +02:00
Fabian Ising 5cca1956fc [ALC] Fix ctrl-slash in alacritty 2026-08-03 11:02:26 +02:00
Fabian Ising 4c5f988d92 [ZSH] Fix path ordering 2026-08-03 11:02:02 +02:00
Fabian Ising 7afa58f3ec [ZSH] Remove claude venv 2026-07-30 14:43:26 +02:00
Fabian Ising 7d97559b20 [ZSH] Add env file 2026-07-30 14:41:28 +02:00
13 changed files with 545 additions and 113 deletions
+5
View File
@@ -61,3 +61,8 @@ y = 0
key = "Return" key = "Return"
mods = "Shift" mods = "Shift"
chars = "\u001B\r" chars = "\u001B\r"
[[keyboard.bindings]]
key = "Slash"
mods = "Control"
chars = "\u001F"
+3 -3
View File
@@ -8,7 +8,7 @@ This is a personal dotfiles repository targeting macOS (Apple Silicon + Intel) a
Setup is platform-specific and runs from the repo root: Setup is platform-specific and runs from the repo root:
- **macOS:** `./setup_mac.sh` — brews dependencies, creates a `neovim` virtualenv, then calls `./clone_and_link_mac.sh`. Uses GNU coreutils' `gln` (not `ln`), so coreutils must be installed first. - **macOS:** `./setup_mac.sh` — brews dependencies, installs the latest verified upstream Alacritty release, creates a `neovim` virtualenv, then calls `./clone_and_link_mac.sh`. Uses GNU coreutils' `gln` (not `ln`), so coreutils must be installed first.
- **Arch:** `./setup_arch.sh` — pacman deps, then `./clone_and_link.sh` + `./copy_fonts_arch.sh`. - **Arch:** `./setup_arch.sh` — pacman deps, then `./clone_and_link.sh` + `./copy_fonts_arch.sh`.
- `clone_and_link*.sh` create the symlinks (`~/.zsh`, `~/.zshrc`, `~/.tmux`, `~/.tmux.conf`, `~/.config/nvim`, `~/.config/alacritty`, virtualenvwrapper hooks). `link_config.sh` is a simpler standalone variant. - `clone_and_link*.sh` create the symlinks (`~/.zsh`, `~/.zshrc`, `~/.tmux`, `~/.tmux.conf`, `~/.config/nvim`, `~/.config/alacritty`, virtualenvwrapper hooks). `link_config.sh` is a simpler standalone variant.
- `general_setup.sh` switches the login shell to zsh and triggers plugin installs. - `general_setup.sh` switches the login shell to zsh and triggers plugin installs.
@@ -33,5 +33,5 @@ Practical rule: **edit the `.example` source, not the generated symlink target.*
## Maintenance ## Maintenance
- `./update_mac.sh` — macOS update runner. Default (no args) runs `--brew-update --cleanup --diagnostics --update-others`; other flags: `--system-update`, `--permission-fix` (strips Caskroom/App quarantine xattrs). Run `./update_mac.sh --help` for the list. `--update-others` also runs `claude --update` and `Codex --update`. - `./update_mac.sh` — macOS update runner. Default (no args) runs `--brew-update --cleanup --diagnostics --update-others`; other flags: `--system-update`, `--permission-fix` (strips Caskroom/App quarantine xattrs). Run `./update_mac.sh --help` for the list. `--update-others` also updates Alacritty from its verified upstream release, then runs `claude --update` and `Codex --update`.
- `brew_autoupdate`sets up scheduled brew auto-updates. - `brew_autoupdate`runs scheduled brew and Alacritty auto-updates.
+1
View File
@@ -6,5 +6,6 @@ export HOMEBREW_LOGS='/Users/ising/Library/Logs/Homebrew'
export SUDO_ASKPASS='/Users/ising/Library/Application Support/com.github.domt4.homebrew-autoupdate/brew_autoupdate_sudo_gui' export SUDO_ASKPASS='/Users/ising/Library/Application Support/com.github.domt4.homebrew-autoupdate/brew_autoupdate_sudo_gui'
defaults export com.apple.dock "/tmp/dock-layout.plist" defaults export com.apple.dock "/tmp/dock-layout.plist"
/bin/date && /opt/homebrew/bin/brew update && /opt/homebrew/bin/brew upgrade --formula -v && /opt/homebrew/bin/brew upgrade --cask -v && /opt/homebrew/bin/brew cleanup && /usr/bin/open -g /opt/homebrew/Library/Taps/homebrew/homebrew-autoupdate/notifier/brew-autoupdate.app /bin/date && /opt/homebrew/bin/brew update && /opt/homebrew/bin/brew upgrade --formula -v && /opt/homebrew/bin/brew upgrade --cask -v && /opt/homebrew/bin/brew cleanup && /usr/bin/open -g /opt/homebrew/Library/Taps/homebrew/homebrew-autoupdate/notifier/brew-autoupdate.app
/Users/ising/dotfiles/install_alacritty_mac.sh
defaults import com.apple.dock "/tmp/dock-layout.plist" defaults import com.apple.dock "/tmp/dock-layout.plist"
killall dock killall dock
+265
View File
@@ -0,0 +1,265 @@
#!/bin/bash
set -euo pipefail
readonly RELEASE_API="https://api.github.com/repos/alacritty/alacritty/releases/latest"
readonly APPLICATIONS_DIR="/Applications"
readonly APP_NAME="Alacritty.app"
temp_dir=""
mount_point=""
cleanup() {
if [[ -n "$mount_point" && -d "$mount_point" ]]; then
hdiutil detach "$mount_point" >/dev/null 2>&1 || true
fi
if [[ -n "$temp_dir" && -d "$temp_dir" ]]; then
rm -rf "$temp_dir"
fi
}
trap cleanup EXIT INT TERM
die() {
echo "Alacritty update failed: $*" >&2
exit 1
}
require_command() {
command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
}
app_version() {
/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" \
"$1/Contents/Info.plist" 2>/dev/null || true
}
version_is_newer() {
local left="${1%%-*}"
local right="${2%%-*}"
local left_major left_minor left_patch
local right_major right_minor right_patch
IFS=. read -r left_major left_minor left_patch <<< "$left"
IFS=. read -r right_major right_minor right_patch <<< "$right"
[[ "$left_major" =~ ^[0-9]+$ && "$left_minor" =~ ^[0-9]+$ && "$left_patch" =~ ^[0-9]+$ ]] || return 1
[[ "$right_major" =~ ^[0-9]+$ && "$right_minor" =~ ^[0-9]+$ && "$right_patch" =~ ^[0-9]+$ ]] || return 1
(( 10#$left_major > 10#$right_major )) && return 0
(( 10#$left_major < 10#$right_major )) && return 1
(( 10#$left_minor > 10#$right_minor )) && return 0
(( 10#$left_minor < 10#$right_minor )) && return 1
(( 10#$left_patch > 10#$right_patch ))
}
run_for_applications() {
if [[ -w "$APPLICATIONS_DIR" ]]; then
"$@"
else
sudo "$@"
fi
}
safe_link() {
local source="$1"
local destination="$2"
if [[ -e "$destination" && ! -L "$destination" ]]; then
die "will not replace non-symlink: $destination"
fi
ln -sfn "$source" "$destination"
}
assert_linkable() {
local destination="$1"
if [[ -e "$destination" && ! -L "$destination" ]]; then
die "will not replace non-symlink: $destination"
fi
}
validate_shell_artifacts() {
local app="$1"
local brew_prefix="$2"
local resources="$app/Contents/Resources"
local source manpage section
for source in \
"$app/Contents/MacOS/alacritty" \
"$resources/completions/alacritty.bash" \
"$resources/completions/alacritty.fish" \
"$resources/completions/_alacritty" \
"$resources/61/alacritty" \
"$resources/61/alacritty-direct"; do
[[ -f "$source" ]] || die "required artifact is missing: ${source#"$app/"}"
done
assert_linkable "$brew_prefix/bin/alacritty"
assert_linkable "$brew_prefix/etc/bash_completion.d/alacritty"
assert_linkable "$brew_prefix/share/fish/vendor_completions.d/alacritty.fish"
assert_linkable "$brew_prefix/share/zsh/site-functions/_alacritty"
assert_linkable "$HOME/.terminfo/61/alacritty"
assert_linkable "$HOME/.terminfo/61/alacritty-direct"
for section in 1 5 7; do
for manpage in "$resources"/*."$section".gz; do
[[ -e "$manpage" ]] || continue
assert_linkable "$brew_prefix/share/man/man$section/${manpage##*/}"
done
done
}
install_shell_artifacts() {
local app="$APPLICATIONS_DIR/$APP_NAME"
local resources="$app/Contents/Resources"
local brew_prefix="$1"
local manpage section
mkdir -p \
"$brew_prefix/bin" \
"$brew_prefix/etc/bash_completion.d" \
"$brew_prefix/share/fish/vendor_completions.d" \
"$brew_prefix/share/zsh/site-functions" \
"$brew_prefix/share/man/man1" \
"$brew_prefix/share/man/man5" \
"$brew_prefix/share/man/man7" \
"$HOME/.terminfo/61"
safe_link "$app/Contents/MacOS/alacritty" "$brew_prefix/bin/alacritty"
safe_link "$resources/completions/alacritty.bash" "$brew_prefix/etc/bash_completion.d/alacritty"
safe_link "$resources/completions/alacritty.fish" "$brew_prefix/share/fish/vendor_completions.d/alacritty.fish"
safe_link "$resources/completions/_alacritty" "$brew_prefix/share/zsh/site-functions/_alacritty"
safe_link "$resources/61/alacritty" "$HOME/.terminfo/61/alacritty"
safe_link "$resources/61/alacritty-direct" "$HOME/.terminfo/61/alacritty-direct"
for section in 1 5 7; do
for manpage in "$resources"/*."$section".gz; do
[[ -e "$manpage" ]] || continue
safe_link "$manpage" "$brew_prefix/share/man/man$section/${manpage##*/}"
done
done
}
restore_previous_app() {
local destination="$1"
local backup="$2"
run_for_applications rm -rf "$destination"
if [[ -d "$backup" ]]; then
run_for_applications /usr/bin/ditto "$backup" "$destination"
fi
}
main() {
local destination="$APPLICATIONS_DIR/$APP_NAME"
local release_json latest_tag latest_version asset_name asset_url asset_digest
local expected_sha actual_sha dmg staged_app staged_version installed_version
local previous_app brew_prefix brew_managed=false
[[ "$(uname -s)" == "Darwin" ]] || die "this installer only supports macOS"
require_command brew
require_command curl
require_command jq
require_command hdiutil
require_command codesign
brew_prefix="$(brew --prefix)"
if brew list --cask alacritty >/dev/null 2>&1; then
brew_managed=true
fi
temp_dir="$(mktemp -d "${TMPDIR:-/tmp}/alacritty-update.XXXXXX")"
release_json="$temp_dir/release.json"
curl --fail --location --silent --show-error --retry 3 \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"$RELEASE_API" -o "$release_json"
latest_tag="$(jq -er '.tag_name' "$release_json")"
latest_version="${latest_tag#v}"
asset_name="Alacritty-${latest_tag}.dmg"
asset_url="$(jq -er --arg asset "$asset_name" \
'.assets[] | select(.name == $asset) | .browser_download_url' "$release_json")"
asset_digest="$(jq -er --arg asset "$asset_name" \
'.assets[] | select(.name == $asset) | .digest' "$release_json")"
[[ "$asset_digest" == sha256:* ]] || die "GitHub did not provide a SHA-256 digest for $asset_name"
expected_sha="$(printf '%s' "${asset_digest#sha256:}" | tr '[:upper:]' '[:lower:]')"
[[ "$expected_sha" =~ ^[[:xdigit:]]{64}$ ]] || die "invalid SHA-256 digest for $asset_name"
installed_version=""
if [[ -d "$destination" ]]; then
installed_version="$(app_version "$destination")"
fi
if [[ "$installed_version" == "$latest_version" && "$brew_managed" == false ]]; then
validate_shell_artifacts "$destination" "$brew_prefix"
install_shell_artifacts "$brew_prefix"
echo "Alacritty $installed_version is already up to date."
return
fi
if [[ -n "$installed_version" ]] && version_is_newer "$installed_version" "$latest_version"; then
echo "Installed Alacritty $installed_version is newer than stable $latest_version; leaving it unchanged."
return
fi
echo "Installing Alacritty $latest_version from the upstream release."
dmg="$temp_dir/$asset_name"
curl --fail --location --silent --show-error --retry 3 "$asset_url" -o "$dmg"
actual_sha="$(shasum -a 256 "$dmg" | awk '{print $1}')"
[[ "$actual_sha" == "$expected_sha" ]] || die "SHA-256 mismatch for $asset_name"
mount_point="$temp_dir/mount"
mkdir -p "$mount_point"
hdiutil attach "$dmg" -nobrowse -readonly -mountpoint "$mount_point" >/dev/null
[[ -d "$mount_point/$APP_NAME" ]] || die "$APP_NAME is missing from $asset_name"
staged_app="$temp_dir/$APP_NAME"
/usr/bin/ditto "$mount_point/$APP_NAME" "$staged_app"
hdiutil detach "$mount_point" >/dev/null
mount_point=""
staged_version="$(app_version "$staged_app")"
[[ "$staged_version" == "$latest_version" ]] || die "release metadata says $latest_version, app says $staged_version"
codesign --verify --deep --strict "$staged_app" || die "the staged app has an invalid ad-hoc signature"
xattr -dr com.apple.quarantine "$staged_app" 2>/dev/null || true
validate_shell_artifacts "$staged_app" "$brew_prefix"
previous_app="$temp_dir/previous/$APP_NAME"
if [[ -d "$destination" ]]; then
mkdir -p "${previous_app%/*}"
/usr/bin/ditto "$destination" "$previous_app"
fi
if [[ "$brew_managed" == true ]]; then
echo "Migrating Alacritty away from the disabled Homebrew cask."
if ! brew uninstall --cask alacritty; then
restore_previous_app "$destination" "$previous_app"
install_shell_artifacts "$brew_prefix" || true
die "Homebrew could not uninstall its Alacritty cask"
fi
fi
if ! run_for_applications rm -rf "$destination" || \
! run_for_applications /usr/bin/ditto "$staged_app" "$destination"; then
restore_previous_app "$destination" "$previous_app"
die "could not install $destination"
fi
if ! codesign --verify --deep --strict "$destination" || \
[[ "$(app_version "$destination")" != "$latest_version" ]]; then
restore_previous_app "$destination" "$previous_app"
die "installed app validation failed; restored the previous app"
fi
install_shell_artifacts "$brew_prefix"
echo "Alacritty $latest_version installed successfully."
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
main "$@"
fi
+130 -3
View File
@@ -32,9 +32,6 @@ let g:loaded_perl_provider = 0
call plug#begin() call plug#begin()
if !exists('g:vscode') if !exists('g:vscode')
" Warn about plugin updates
Plug 'semanser/vim-outdated-plugins'
" Powerline replacement " Powerline replacement
Plug 'vim-airline/vim-airline' Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes' Plug 'vim-airline/vim-airline-themes'
@@ -112,6 +109,136 @@ endif
call plug#end() call plug#end()
" Check for plugin updates after the editor is responsive.
lua << EOF
local function check_plugin_updates()
local plugins = {}
for name, plugin in pairs(vim.g.plugs or {}) do
if vim.fn.isdirectory(plugin.dir) == 1 then
table.insert(plugins, { name = name, dir = plugin.dir })
end
end
table.sort(plugins, function(a, b) return a.name < b.name end)
local next_plugin = 1
local active = 0
local finished = 0
local failures = 0
local updates = {}
local concurrency = 2
local function git_command(args)
local command = {}
if vim.fn.executable('ionice') == 1 then
vim.list_extend(command, { 'ionice', '-c', '3' })
end
if vim.fn.executable('nice') == 1 then
vim.list_extend(command, { 'nice', '-n', '10' })
end
table.insert(command, 'git')
vim.list_extend(command, args)
return command
end
local function set_airline_status(message)
vim.g.plugin_update_status = message
local marker = '%{get(g:,"plugin_update_status","")}'
local warning = vim.g.airline_section_warning or ''
if not string.find(warning, 'plugin_update_status', 1, true) then
vim.g.airline_section_warning = warning .. ' ' .. marker
end
if vim.fn.exists(':AirlineRefresh') == 2 then
vim.cmd('AirlineRefresh')
end
end
local function report()
if #updates > 0 then
set_airline_status(string.format('[updates: %d]', #updates))
local message = string.format(
'%d plugin update%s available: %s',
#updates,
#updates == 1 and '' or 's',
table.concat(updates, ', ')
)
if failures > 0 then
message = message .. string.format(' (%d check%s failed)', failures, failures == 1 and '' or 's')
end
vim.notify(message, failures > 0 and vim.log.levels.WARN or vim.log.levels.INFO)
elseif failures > 0 then
set_airline_status('[update check failed]')
vim.notify(
string.format('Plugin update check incomplete: %d check%s failed', failures, failures == 1 and '' or 's'),
vim.log.levels.WARN
)
else
set_airline_status('')
vim.notify('All plugins up-to-date', vim.log.levels.INFO)
end
end
local pump
local function complete_one()
active = active - 1
finished = finished + 1
if finished == #plugins then
report()
else
pump()
end
end
local function check_one(plugin)
active = active + 1
vim.system(
git_command({ '-C', plugin.dir, 'fetch', '--quiet', '--no-tags', 'origin' }),
{ text = true, timeout = 20000 },
vim.schedule_wrap(function(fetch_result)
if fetch_result.code ~= 0 then
failures = failures + 1
complete_one()
return
end
vim.system(
git_command({ '-C', plugin.dir, 'rev-list', '--count', 'HEAD..@{upstream}' }),
{ text = true, timeout = 5000 },
vim.schedule_wrap(function(count_result)
local count = tonumber(vim.trim(count_result.stdout or ''))
if count_result.code ~= 0 or count == nil then
failures = failures + 1
elseif count > 0 then
table.insert(updates, plugin.name)
end
complete_one()
end)
)
end)
)
end
pump = function()
while active < concurrency and next_plugin <= #plugins do
local plugin = plugins[next_plugin]
next_plugin = next_plugin + 1
check_one(plugin)
end
end
if #plugins > 0 then
pump()
end
end
vim.api.nvim_create_autocmd('VimEnter', {
group = vim.api.nvim_create_augroup('plugin_update_check', { clear = true }),
once = true,
callback = function()
vim.defer_fn(check_plugin_updates, 1500)
end,
})
EOF
" Run PlugInstall if there are missing plugins " Run PlugInstall if there are missing plugins
autocmd VimEnter * if len(filter(values(g:plugs), '!isdirectory(v:val.dir)')) autocmd VimEnter * if len(filter(values(g:plugs), '!isdirectory(v:val.dir)'))
\| PlugInstall --sync | source $MYVIMRC \| PlugInstall --sync | source $MYVIMRC
+6 -4
View File
@@ -6,14 +6,16 @@
# Distributed under terms of the MIT license. # Distributed under terms of the MIT license.
# #
brew install neovim tmux alacritty coreutils cmake golang npm virtualenvwrapper brew install neovim tmux coreutils cmake golang jq npm virtualenvwrapper
source /opt/homebrew/bin/virtualenvwrapper.sh ./install_alacritty_mac.sh
BREW_PREFIX="$(brew --prefix)"
source "$BREW_PREFIX/bin/virtualenvwrapper.sh"
mkvirtualenv neovim mkvirtualenv neovim
pip3 install pynvim pip3 install pynvim
npm install -g neovim npm install -g neovim
echo For alacritty to work seemlessly with tmux, we will have to add '/usr/local/bin'\ echo For alacritty to work seamlessly with tmux, we will add the Homebrew bin directory\
to the path. This will require your root password. to the path. This will require your root password.
sudo launchctl config user path /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin sudo launchctl config user path /usr/bin:/bin:/usr/sbin:/sbin:"$BREW_PREFIX/bin":/usr/local/bin
cp $PWD/nvim/scheme.vim.template $PWD/nvim/scheme.vim cp $PWD/nvim/scheme.vim.template $PWD/nvim/scheme.vim
cp $PWD/.config/alacritty/schemes.yml.template $PWD/.config/alacritty/schemes.yml cp $PWD/.config/alacritty/schemes.yml.template $PWD/.config/alacritty/schemes.yml
./clone_and_link_mac.sh ./clone_and_link_mac.sh
-99
View File
@@ -1,99 +0,0 @@
#!/bin/bash
#
# This file echoes a bunch of 24-bit color codes
# to the terminal to demonstrate its functionality.
# The foreground escape sequence is ^[38;2;<r>;<g>;<b>m
# The background escape sequence is ^[48;2;<r>;<g>;<b>m
# <r> <g> <b> range from 0 to 255 inclusive.
# The escape sequence ^[0m returns output to default
setBackgroundColor()
{
echo -en "\x1b[48;2;$1;$2;$3""m"
}
resetOutput()
{
echo -en "\x1b[0m\n"
}
# Gives a color $1/255 % along HSV
# Who knows what happens when $1 is outside 0-255
# Echoes "$red $green $blue" where
# $red $green and $blue are integers
# ranging between 0 and 255 inclusive
rainbowColor()
{
let h=$1/43
let f=$1-43*$h
let t=$f*255/43
let q=255-t
if [ $h -eq 0 ]
then
echo "255 $t 0"
elif [ $h -eq 1 ]
then
echo "$q 255 0"
elif [ $h -eq 2 ]
then
echo "0 255 $t"
elif [ $h -eq 3 ]
then
echo "0 $q 255"
elif [ $h -eq 4 ]
then
echo "$t 0 255"
elif [ $h -eq 5 ]
then
echo "255 0 $q"
else
# execution should never reach here
echo "0 0 0"
fi
}
for i in `seq 0 127`; do
setBackgroundColor $i 0 0
echo -en " "
done
resetOutput
for i in `seq 255 128`; do
setBackgroundColor $i 0 0
echo -en " "
done
resetOutput
for i in `seq 0 127`; do
setBackgroundColor 0 $i 0
echo -n " "
done
resetOutput
for i in `seq 255 128`; do
setBackgroundColor 0 $i 0
echo -n " "
done
resetOutput
for i in `seq 0 127`; do
setBackgroundColor 0 0 $i
echo -n " "
done
resetOutput
for i in `seq 255 128`; do
setBackgroundColor 0 0 $i
echo -n " "
done
resetOutput
for i in `seq 0 127`; do
setBackgroundColor `rainbowColor $i`
echo -n " "
done
resetOutput
for i in `seq 255 128`; do
setBackgroundColor `rainbowColor $i`
echo -n " "
done
resetOutput
+11
View File
@@ -1,5 +1,13 @@
#!/bin/bash #!/bin/bash
SCRIPT_SOURCE="${BASH_SOURCE[0]}"
while [[ -L "$SCRIPT_SOURCE" ]]; do
SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_SOURCE")" >/dev/null 2>&1 && pwd)"
SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")"
[[ "$SCRIPT_SOURCE" != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE"
done
SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_SOURCE")" >/dev/null 2>&1 && pwd)"
ARCH=`uname -m` ARCH=`uname -m`
if [[ $ARCH == "arm64" ]]; then if [[ $ARCH == "arm64" ]]; then
PREFIX="/opt/homebrew/" PREFIX="/opt/homebrew/"
@@ -55,6 +63,9 @@ function update_others {
echo "Update other stuff" echo "Update other stuff"
echo "----------" echo "----------"
echo "-- ALACRITTY"
"$SCRIPT_DIR/install_alacritty_mac.sh" || echo "Alacritty update failed." >&2
if [ -x "$(command -v claude)" ]; then if [ -x "$(command -v claude)" ]; then
echo "-- CLAUDE" echo "-- CLAUDE"
claude --update claude --update
+1
View File
@@ -3,3 +3,4 @@
.p10k.zsh .p10k.zsh
.p10k.mac.zsh .p10k.mac.zsh
antigen/ antigen/
.env.local
+2 -1
View File
@@ -35,9 +35,10 @@ fi
export DYLD_FALLBACK_LIBRARY_PATH="$HOMEBREW_PREFIX/lib${DYLD_FALLBACK_LIBRARY_PATH:+:$DYLD_FALLBACK_LIBRARY_PATH}" export DYLD_FALLBACK_LIBRARY_PATH="$HOMEBREW_PREFIX/lib${DYLD_FALLBACK_LIBRARY_PATH:+:$DYLD_FALLBACK_LIBRARY_PATH}"
export GI_TYPELIB_PATH="$HOMEBREW_PREFIX/lib/girepository-1.0${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}" export GI_TYPELIB_PATH="$HOMEBREW_PREFIX/lib/girepository-1.0${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}"
export PKG_CONFIG_PATH="$HOMEBREW_PREFIX/lib/pkgconfig:$HOMEBREW_PREFIX/share/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" export PKG_CONFIG_PATH="$HOMEBREW_PREFIX/lib/pkgconfig:$HOMEBREW_PREFIX/share/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
alias claude="workon claude; claude; deactivate"
alias python="python3" alias python="python3"
# Tahoe 26 WindowServer bug: windows stay interactive but can't be moved by # Tahoe 26 WindowServer bug: windows stay interactive but can't be moved by
# mouse or API until the window-management daemon is restarted (no logout). # mouse or API until the window-management daemon is restarted (no logout).
alias unstick-windows="killall WindowManager" alias unstick-windows="killall WindowManager"
alias resetdns="sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder"
+46
View File
@@ -27,3 +27,49 @@ _venv_track_precmd() {
} }
autoload -Uz add-zsh-hook autoload -Uz add-zsh-hook
add-zsh-hook precmd _venv_track_precmd add-zsh-hook precmd _venv_track_precmd
# Which venv an agent shell should use: nearest .venv/venv walking up from $1
# (default $PWD, stopping above $HOME), else the shared fallback env.
_agent_venv_path() {
local d=${1:-$PWD} c
while [[ $d == */* && $d != $HOME ]]; do
for c in "$d/.venv" "$d/venv"; do
[[ -f $c/bin/activate ]] && { print -r -- "$c"; return 0 }
done
d=${d%/*}
done
[[ -f $HOME/python-envs/claude/bin/activate ]] && print -r -- "$HOME/python-envs/claude"
}
# Agent shells source this file once per session, rooted at the project dir, and
# snapshot the result: CLAUDECODE marks Claude Code, CODEX_SHELL the ChatGPT/Codex
# desktop app. Only VIRTUAL_ENV is set here; the block at the end of .zshrc turns it
# into an activation once PATH is fully built. Terminal launches use the wrappers below.
if [[ -n ${CLAUDECODE:-} || -n ${CODEX_SHELL:-} ]] && [[ -z ${VIRTUAL_ENV:-} ]]; then
_venv=$(_agent_venv_path)
[[ -n $_venv ]] && export VIRTUAL_ENV=$_venv
unset _venv
fi
# Claude Code takes PATH from its own process env: its shell snapshot writes
# `export PATH=` last, discarding whatever .zshrc built. So the venv has to be
# active *before* launch. The subshell keeps this shell's PATH untouched.
claude() {
if [[ -n ${VIRTUAL_ENV:-} ]]; then
command claude "$@"
return
fi
local v=$(_agent_venv_path)
( [[ -n $v ]] && source "$v/bin/activate"; exec command claude "$@" )
}
# Codex captures the profile's own PATH, so hand it VIRTUAL_ENV only and let the
# activation block at the end of .zshrc order PATH correctly. Pre-activating here
# would leave venv/bin behind gnubin and homebrew, same as tmux-inherited venvs.
codex() {
if [[ -n ${VIRTUAL_ENV:-} ]]; then
command codex "$@"
else
VIRTUAL_ENV=$(_agent_venv_path) command codex "$@"
fi
}
+6 -1
View File
@@ -3,10 +3,15 @@
[[ -f ~/.zsh/.user_config ]] && source ~/.zsh/.user_config [[ -f ~/.zsh/.user_config ]] && source ~/.zsh/.user_config
[[ -f ~/.zsh/.virtual_env_config.zsh ]] && source ~/.zsh/.virtual_env_config.zsh [[ -f ~/.zsh/.virtual_env_config.zsh ]] && source ~/.zsh/.virtual_env_config.zsh
[[ -f ~/.zsh/.local_config ]] && source ~/.zsh/.local_config [[ -f ~/.zsh/.local_config ]] && source ~/.zsh/.local_config
[[ -f ~/.zsh/.env.local ]] && source ~/.zsh/.env.local
source "${ZDOTDIR:-$HOME}/.zsh/lib/updates.zsh" source "${ZDOTDIR:-$HOME}/.zsh/lib/updates.zsh"
export LC_OSC52=1 export LC_OSC52=1
# Completions for tools installed under ~/.local (e.g. tools-repo's safe*
# wrappers). Must precede antidote, whose completion plugin runs compinit.
fpath=("$HOME/.local/share/zsh/site-functions" $fpath)
plugins_txt=${ZDOTDIR:-$HOME}/.zsh/.zsh_plugins.txt plugins_txt=${ZDOTDIR:-$HOME}/.zsh/.zsh_plugins.txt
static_file=${ZDOTDIR:-$HOME}/.cache/zsh/.zsh_plugins.zsh static_file=${ZDOTDIR:-$HOME}/.cache/zsh/.zsh_plugins.zsh
source "${ZDOTDIR:-$HOME}/.zsh/lib/antidote.zsh" source "${ZDOTDIR:-$HOME}/.zsh/lib/antidote.zsh"
@@ -66,7 +71,7 @@ fi
typeset -U path PATH typeset -U path PATH
[[ -z "${VIRTUAL_ENV:-}" ]] && unset VIRTUAL_ENV [[ -z "${VIRTUAL_ENV:-}" ]] && unset VIRTUAL_ENV
if [[ -n "$VIRTUAL_ENV" && -f "$VIRTUAL_ENV/bin/activate" ]]; then if [[ -n "$VIRTUAL_ENV" && -f "$VIRTUAL_ENV/bin/activate" ]]; then
if [[ ":$PATH:" != *":$VIRTUAL_ENV/bin:"* ]]; then if [[ ${PATH%%:*} != "$VIRTUAL_ENV/bin" ]]; then
source "$VIRTUAL_ENV/bin/activate" source "$VIRTUAL_ENV/bin/activate"
fi fi
fi fi
+69 -2
View File
@@ -21,10 +21,77 @@ alias ls='ls --color=always'
alias cgrep='grep --color=always' alias cgrep='grep --color=always'
alias cdiff='git diff --color-words --no-index' alias cdiff='git diff --color-words --no-index'
# Remove the files an archive extracted into the current directory.
# Lists what it will delete and asks first; -f skips the prompt, -n dry-runs.
# Directories are only removed if they end up empty.
delzip() { delzip() {
unzip -Z -1 "$@" | xargs -I{} rm -rf {} emulate -L zsh
setopt local_options
local dry=0 force=0
while [[ $1 == -[nf] ]]; do
[[ $1 == -n ]] && dry=1 || force=1
shift
done
(( $# )) || { print -ru2 "usage: delzip [-n|-f] <archive.zip>..."; return 2 }
local zip entry parent
local -a entries files dirs
for zip in "$@"; do
[[ -f $zip ]] || { print -ru2 "delzip: no such file: $zip"; return 1 }
entries=("${(f)$(unzip -Z -1 -- $zip)}") || return 1
for entry in $entries; do
[[ -n $entry ]] || continue
# zip-slip guard: never touch anything outside the cwd
if [[ $entry == (/|~)* || $entry == (|*/)..(|/*) ]]; then
print -ru2 "delzip: refusing unsafe path: $entry"
return 1
fi
[[ $entry == */ ]] && dirs+=(${entry%/}) || files+=($entry)
# many archives omit directory entries, so infer them from the
# paths as well; unzip creates those dirs regardless
parent=${entry%/}
while [[ $parent == */* ]]; do
parent=${parent%/*}
dirs+=($parent)
done
done
done
dirs=(${(u)dirs})
# only keep what is actually on disk, so the list reflects reality;
# -L catches broken symlinks, which -e alone misses
local -a present
present=(); for entry in $files; do [[ -e $entry || -L $entry ]] && present+=($entry); done
files=($present)
present=(); for entry in $dirs; do [[ -d $entry ]] && present+=($entry); done
dirs=($present)
(( $#files + $#dirs )) || { print -ru2 "delzip: nothing to remove here (already gone?)"; return 1 }
if (( dry )); then
print -rl -- ${files} ${(O)dirs}
return 0
fi
if (( ! force )); then
[[ -t 0 ]] || { print -ru2 "delzip: not a terminal, use -f to skip the prompt"; return 1 }
print -r -- "delzip: remove ${#files} file(s) under ${PWD}:"
print -rl -- " "${^files[1,20]}
(( $#files > 20 )) && print -r -- " ... and $(( $#files - 20 )) more"
(( $#dirs )) && print -r -- "plus ${#dirs} directory/ies, if they end up empty."
read -q "?Proceed? [y/N] " || { print -r -- $'\naborted'; return 1 }
print
fi
(( $#files )) && rm -f -- $files
# deepest first, so parents can empty out; rmdir refuses non-empty dirs
for entry in ${(O)dirs}; do
[[ -d $entry ]] && rmdir -- $entry 2>/dev/null
done
return 0
} }
export MITMPROXY_SSLKEYLOGFILE='~/.mitmproxy/sslkeylogfile.txt' export MITMPROXY_SSLKEYLOGFILE="$HOME/.mitmproxy/sslkeylogfile.txt"
unset ZSH_AUTOSUGGEST_USE_ASYNC unset ZSH_AUTOSUGGEST_USE_ASYNC
export LANG='en_US.UTF-8' export LANG='en_US.UTF-8'