Skip to content
Open
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
3 changes: 0 additions & 3 deletions Brewfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ brew "gh"
brew "hashicorp/tap/terraform", trusted: true
brew "htop"
brew "jq"
brew "k9s"
brew "lsd"
brew "lua"
brew "neovim"
brew "mosh"
brew "node"
brew "postgresql@17"
brew "py-spy"
brew "pyenv"
brew "tmux"
brew "tree"
brew "wget"
Expand Down
147 changes: 112 additions & 35 deletions assimilate.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env sh
#!/usr/bin/env bash

set -ex

OS="$(uname -s)"
ARCH="$(uname -m)"

PREFIX="$HOME"
DOTFILES=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
BACKUPS="$PREFIX/backups"
Expand All @@ -24,47 +27,74 @@ function sym () {
ln -s "$src" "$dest"
}

function clone_pinned () {
url="$1"; dir="$2"; sha="$3"
# Fetch only the pinned commit, no full history. Avoids `git clone --revision`
# (git >= 2.49) so this works on older git too, e.g. AL2023's 2.40 on stale AMIs.
# Fetch-by-SHA relies on the server allowing reachable-SHA1-in-want (GitHub does).
if [ ! -d "$dir" ]; then
git init -q "$dir"
git -C "$dir" remote add origin "$url"
fi
git -C "$dir" fetch --depth 1 origin "$sha"
git -C "$dir" checkout -q "$sha"
}

if [ ! -e "$DOTFILES" ]; then
echo "error: dotfiles/ needs to reside in $PREFIX"
exit 1
fi

mkdir -p "$BACKUPS/vim_backups"

sym bashrc .bashrc
# Shared symlinks (work on macOS and Linux)
sym bash_profile .bash_profile
sym gitconfig .gitconfig
sym tmux.conf .tmux.conf
sym zshrc .zshrc
sym nvim .config/nvim
sym hammerspoon .hammerspoon
sym vscode/code_settings.json .vscode/settings.json
sym zed/settings.json .config/zed/settings.json
sym ghostty/config Library/Application\ Support/com.mitchellh.ghostty/config
sym tmux-powerline/config.sh .config/tmux-powerline/config.sh
sym tmux-powerline/config.sh .config/tmux-powerline/config.sh
sym tmux-powerline/themes/theme.sh .config/tmux-powerline/themes/theme.sh
sym claude/statusline.sh .claude/statusline.sh
sym agent-instructions.md .claude/CLAUDE.md
sym agent-instructions.md .codex/AGENTS.md
sym zed/keymap.json .config/zed/keymap.json
sym claude/statusline.sh .claude/statusline.sh
sym agent-instructions.md .claude/CLAUDE.md
sym agent-instructions.md .codex/AGENTS.md

# bashrc: symlinked on macOS; sourced from a stub on Linux.
# On the EC2 dev box, user_data appends a secrets/region block to .bashrc after
# this script runs. If .bashrc were a symlink into the repo, those appends would
# write into the dotfiles repo's tracked file. So on Linux, leave .bashrc as a
# regular file and source the dotfiles bashrc from it.
if [ "$OS" = "Darwin" ]; then
sym bashrc .bashrc
else
if ! grep -Fq 'dotfiles/bashrc' "$PREFIX/.bashrc" 2>/dev/null; then
echo '[ -f "$HOME/dotfiles/bashrc" ] && . "$HOME/dotfiles/bashrc"' >> "$PREFIX/.bashrc"
fi
fi

brew bundle install
# macOS-only symlinks and Homebrew (apps/paths don't exist on Linux)
if [ "$OS" = "Darwin" ]; then
sym hammerspoon .hammerspoon
sym vscode/code_settings.json .vscode/settings.json
sym zed/settings.json .config/zed/settings.json
sym zed/keymap.json .config/zed/keymap.json
sym ghostty/config Library/Application\ Support/com.mitchellh.ghostty/config

"$DOTFILES/claude/sync-settings.sh"
"$DOTFILES/codex/sync-config.sh"
brew bundle install
fi

function clone_pinned () {
url="$1"; dir="$2"; sha="$3"
if [ ! -d "$dir" ]; then
git clone --revision="$sha" "$url" "$dir"
else
# SHA may be missing locally — newer than the last fetch, or absent because
# the prior clone was shallow (--revision pulls only that one commit).
# Fetch it directly.
git -C "$dir" fetch origin "$sha"
git -C "$dir" checkout "$sha"
fi
}
# Sync portable agent settings after Homebrew has supplied jq, yq, and Codex on
# macOS. On Linux, run each sync when its dependencies are already available.
if command -v jq >/dev/null 2>&1; then
"$DOTFILES/claude/sync-settings.sh"
else
echo "WARN: jq is unavailable — skipping Claude settings sync" >&2
fi
if command -v yq >/dev/null 2>&1 && command -v codex >/dev/null 2>&1; then
"$DOTFILES/codex/sync-config.sh"
else
echo "WARN: yq or codex is unavailable — skipping Codex settings sync" >&2
fi

# Install oh-my-zsh (clone repo directly; install.sh is just `git clone` once
# its zshrc/runzsh/chsh side-effects are disabled)
Expand All @@ -79,27 +109,74 @@ if [ ! -d "$HOME/.cargo" ]; then
| sh -s -- -y --no-modify-path --default-toolchain 1.95.0
fi

# Install git-delta from a pinned GitHub release tarball (sidesteps brew bottle ABI drift)
# Install git-delta from a pinned GitHub release tarball (sidesteps brew bottle ABI drift).
# Tarball target and SHA256 are platform-specific.
DELTA_VERSION=0.19.2
DELTA_SHA256=9be36612a5a13e9e386dc498fb8e50dc87c72ee42b63db0ea05b32f99a72a69a
DELTA_BIN="$HOME/.local/bin/delta"
if [ ! -x "$DELTA_BIN" ] || [ "$("$DELTA_BIN" --version 2>/dev/null | awk '{print $2}')" != "$DELTA_VERSION" ]; then

case "$OS-$ARCH" in
Darwin-arm64)
DELTA_TARGET=aarch64-apple-darwin
DELTA_SHA256=9be36612a5a13e9e386dc498fb8e50dc87c72ee42b63db0ea05b32f99a72a69a
;;
Linux-x86_64)
DELTA_TARGET=x86_64-unknown-linux-gnu
DELTA_SHA256=8e695c5f586a8c53d6c3b01be0b4a422ed218bfed2a56191caebe373a1c18ab2
;;
*)
echo "WARN: no delta build pinned for $OS-$ARCH — skipping delta install" >&2
DELTA_TARGET=""
;;
esac

if [ -n "$DELTA_TARGET" ] && { [ ! -x "$DELTA_BIN" ] || [ "$("$DELTA_BIN" --version 2>/dev/null | awk '{print $2}')" != "$DELTA_VERSION" ]; }; then
tmp=$(mktemp -d)
curl -fsSL "https://github.com/dandavison/delta/releases/download/${DELTA_VERSION}/delta-${DELTA_VERSION}-aarch64-apple-darwin.tar.gz" -o "$tmp/delta.tar.gz"
echo "${DELTA_SHA256} $tmp/delta.tar.gz" | shasum -a 256 -c -
curl -fsSL "https://github.com/dandavison/delta/releases/download/${DELTA_VERSION}/delta-${DELTA_VERSION}-${DELTA_TARGET}.tar.gz" -o "$tmp/delta.tar.gz"
if [ -n "$DELTA_SHA256" ]; then
if command -v sha256sum >/dev/null; then
echo "${DELTA_SHA256} $tmp/delta.tar.gz" | sha256sum -c -
else
echo "${DELTA_SHA256} $tmp/delta.tar.gz" | shasum -a 256 -c -
fi
else
echo "WARN: no DELTA_SHA256 pinned for $OS-$ARCH — integrity check skipped" >&2
fi
mkdir -p "$HOME/.local/bin"
tar -xzf "$tmp/delta.tar.gz" -C "$tmp"
install -m 755 "$tmp/delta-${DELTA_VERSION}-aarch64-apple-darwin/delta" "$DELTA_BIN"
install -m 755 "$tmp/delta-${DELTA_VERSION}-${DELTA_TARGET}/delta" "$DELTA_BIN"
rm -rf "$tmp"
fi

# Install tmux plugin manager and plugins declared in tmux.conf
clone_pinned https://github.com/tmux-plugins/tpm "$HOME/.tmux/plugins/tpm" 7bdb7ca33c9cc6440a600202b50142f401b6fe21 # v3.1.0
clone_pinned https://github.com/erikw/tmux-powerline "$HOME/.tmux/plugins/tmux-powerline" 6079ace8d534a01d4d964b8b854b223f72edaf4b # v3.2.0

# Install Packer (nvim plugin manager) and run PackerSync
clone_pinned https://github.com/wbthomason/packer.nvim "$HOME/.local/share/nvim/site/pack/packer/start/packer.nvim" ea0cc3c59f67c440c5ff0bbe4fb9420f4350b9a3 # 2023-08-24, matches plugins.lua pin
# Install neovim on Linux from a pinned upstream tarball (macOS gets it via Brewfile).
# AL2023 doesn't ship neovim in its default dnf repos. Lands in $HOME/.local so no
# root needed, and runs before the PackerSync block below so the plugin sync works.
NVIM_VERSION=0.9.5
NVIM_SHA256=44ee395d9b5f8a14be8ec00d3b8ead34e18fe6461e40c9c8c50e6956d643b6ca
if [ "$OS" = "Linux" ] && [ "$ARCH" = "x86_64" ] && ! command -v nvim >/dev/null; then
tmp=$(mktemp -d)
curl -fsSL "https://github.com/neovim/neovim/releases/download/v${NVIM_VERSION}/nvim-linux64.tar.gz" -o "$tmp/nvim.tar.gz"
if command -v sha256sum >/dev/null; then
echo "${NVIM_SHA256} $tmp/nvim.tar.gz" | sha256sum -c -
else
echo "${NVIM_SHA256} $tmp/nvim.tar.gz" | shasum -a 256 -c -
fi
mkdir -p "$HOME/.local/share" "$HOME/.local/bin"
tar -xzf "$tmp/nvim.tar.gz" -C "$HOME/.local/share"
ln -sf "$HOME/.local/share/nvim-linux64/bin/nvim" "$HOME/.local/bin/nvim"
rm -rf "$tmp"
# Make nvim visible to the rest of this script (PackerSync below)
export PATH="$HOME/.local/bin:$PATH"
fi

# Install Packer (nvim plugin manager) and run PackerSync — only if nvim is available
if command -v nvim >/dev/null; then
clone_pinned https://github.com/wbthomason/packer.nvim "$HOME/.local/share/nvim/site/pack/packer/start/packer.nvim" ea0cc3c59f67c440c5ff0bbe4fb9420f4350b9a3 # 2023-08-24, matches plugins.lua pin

nvim --headless -c 'autocmd User PackerComplete quitall' -c 'PackerSync' || true
nvim --headless -c 'autocmd User PackerComplete quitall' -c 'PackerSync' || true
fi

echo "> Assimilation successful!"
8 changes: 5 additions & 3 deletions bashrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export LANG='en_US.UTF-8'
alias config="/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME"
alias vi=nvim
alias vim=nvim
alias ls="lsd -al"
# lsd comes from the Brewfile on macOS; guard so a Linux box without it keeps
# a working `ls`
command -v lsd >/dev/null 2>&1 && alias ls="lsd -al"

# Docker
alias d='docker'
Expand Down Expand Up @@ -75,7 +77,7 @@ alias kuc='kubectl config'

# nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" --no-use # Load nvm without auto-use (auto-use errors with "N/A" when no .nvmrc is set)
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

# PYTHONPATH
Expand Down Expand Up @@ -104,7 +106,7 @@ alias dbtr="dbt run"
alias cb="cargo build"
alias cr="cargo run"
alias ct="cargo test"
. "$HOME/.cargo/env"
[ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env"

# modal
alias md="modal deploy"
Expand Down
3 changes: 3 additions & 0 deletions zed/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"project_panel": {
"dock": "left"
},
"cursor_blink": false,
"terminal": {
"cursor_shape": "bar"
Expand Down
18 changes: 13 additions & 5 deletions zshrc
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ else
fi

export PATH="$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH"
source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh

# zsh-autosuggestions (installed via brew on macOS, may be missing elsewhere)
if command -v brew >/dev/null 2>&1; then
_zsh_autosug="$(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh"
[ -f "$_zsh_autosug" ] && source "$_zsh_autosug"
unset _zsh_autosug
fi

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" --no-use # Load nvm without auto-use (auto-use errors with "N/A" when no .nvmrc is set)
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

. "$HOME/.cargo/env"
[ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env"
alias snowsql=/Applications/SnowSQL.app/Contents/MacOS/snowsql

# The next line updates PATH for the Google Cloud SDK.
Expand All @@ -62,8 +68,10 @@ if [ -f "$HOME/Downloads/google-cloud-sdk/path.zsh.inc" ]; then . "$HOME/Downloa
# The next line enables shell command completion for gcloud.
if [ -f "$HOME/Downloads/google-cloud-sdk/completion.zsh.inc" ]; then . "$HOME/Downloads/google-cloud-sdk/completion.zsh.inc"; fi

# .zsh syntax highlighting
source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
# .zsh syntax highlighting (installed via brew on macOS, may be missing elsewhere)
if [ -f /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
fi

# Prepend so pinned overrides in assimilate.sh (e.g. delta) win over brew bottles with ABI drift
export PATH="$HOME/.local/bin:$PATH"
Expand Down