if type brew &>/dev/null; then
FPATH=$(brew --prefix)/share/zsh-completions:$FPATH
autoload -Uz compinit
compinit
fi
#compdef gt
###-begin-gt-completions-###
#
# yargs command completion script
#
# Installation: gt completion >> ~/.zshrc
# or gt completion >> ~/.zprofile on OSX.
#
_gt_yargs_completions()
{
local reply
local si=$IFS
IFS=$'
' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" gt --get-yargs-completions "${words[@]}"))
IFS=$si
_describe 'values' reply
}
compdef _gt_yargs_completions gt
###-end-gt-completions-###
# gh completions
fpath=($HOME/.zsh/completions $fpath)
autoload -Uz compinit
compinit
# Determine defaultBranch once per repo, store it if not set
get_default_branch() {
local branch
branch=$(git config --get bakert.defaultBranch 2>/dev/null)
if [[ -z "$branch" ]]; then
branch=$(git remote show origin 2>/dev/null | awk '/HEAD branch/ {print $NF}')
branch=${branch:-master}
git config --local bakert.defaultBranch "$branch"
echo "Set bakert.defaultBranch to '$branch' in local git config" >&2
fi
echo "$branch"
}
# Perform an operation that might fail if the current branch is implicated in a way that won't fail
# Leaves you on default branch after if your current branch ceased to exist.
with_default_branch() {
local current_branch=$(git rev-parse --abbrev-ref HEAD)
local default_branch=$(get_default_branch)
if [[ "$current_branch" != "$default_branch" ]]; then
git switch "$default_branch"
fi
"$@"
if [[ "$current_branch" != "$default_branch" ]] && git show-ref --verify --quiet "refs/heads/$current_branch"; then
git switch "$current_branch"
fi
}
## Functions not aliases to allow completions
ga() { git add "$@"; }; compdef _git ga=git-add
gaa() { git add . "$@"; }; compdef _git gaa=git-add
# Equivlent to `git add !$`
gal() {
emulate -L zsh
setopt noglob
local cmd last
cmd=$(fc -ln -1) || return 1
local -a words
words=(${(z)cmd})
(( ${#words} )) || { echo "No history."; return 1; }
last=${words[-1]}
last=${(Q)last} # remove surrounding quotes if any
# Expand ~ / ~user without enabling globbing
if [[ $last == "~"* ]]; then
last=${~last}
fi
[[ -n $last ]] || { echo "No last arg."; return 1; }
git add -- "$last"
}; compdef _git gal=git-add
gap() { git add -p "$@"; }; compdef _git gap=git-add
gb() { git branch "$@"; }; compdef _git gb=git-branch
gbd() { with_default_branch git branch -D "$@"; }; compdef _git gbd=git-branch
gbl() { git blame "$@"; }; compdef _git gbl=git-blame
gc() { git commit "$@"; }; compdef _git gc=git-commit
gca() { git commit --amend "$@"; }; compdef _git gca=git-commit
gcae() { git commit --amend --no-edit "$@"; }; compdef _git gcae=git-commit
gcan() { git commit --amend -n "$@"; }; compdef _git gcan=git-commit
gcane() { git commit --amend -n --no-edit "$@"; }; compdef _git gcane=git-commit
gclb() { gpru && gded }; compdef _git gclb=git-branch
gclfd() { git clean -fd "$@" }; compdef _git gclfd=git-clean
gcp() { git cherry-pick "$@" }; compdef _git gcp=git-cherry-pick
gcpa() { git cherry-pick --abort "$@" }; compdef _git gcpa=git-cherry-pick
gcpc() { git cherry-pick --continue "$@" }; compdef _git gcpa=git-cherry-pick
glc() { git clone "$@"; }; compdef _git glc=git-clone
gcm() { git commit -m "$@"; }; compdef _git gcm=git-commit
gcn() { git commit -n "$@"; }; compdef _git gcn=git-commit
gco() { git checkout "$@"; }; compdef _git gco=git-checkout
gd() { git diff "$@"; }; compdef _git gd=git-diff
gdc() { git diff --cached "$@"; }; compdef _git gdc=git-diff
gdd() { git diff $(get_default_branch) "$@"; }; compdef _git gdd=git-diff
# Delete all local branches that don't have changes not already in default branch
gded() {
local default_branch=$(get_default_branch)
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
if [[ "$branch" != "$default_branch" ]]; then
local count=$(git rev-list --count "$branch" --not "$default_branch")
if [[ "$count" -eq 0 ]]; then
echo "Deleting branch: $branch"
git branch -D "$branch"
fi
fi
done
}
gfo() { git fetch origin $(get_default_branch):$(get_default_branch) "$@"; }; compdef _git gfo=git-fetch
# Make a gist, guessing exactly what you want a gist of based on state of repo
gg() {
local target=$1
local desc=""
local filename=""
local url=""
if [[ -z $target ]]; then
if [[ -n $(git status --porcelain) ]]; then
desc="Working copy diff"
filename="working.diff"
url=$((git diff HEAD && git ls-files --others --exclude-standard | xargs -I {} git diff /dev/null {}) | gh gist create -f "$filename" -d "$desc" - | tail -n1)
else
desc="Top commit diff (HEAD)"
filename="head.diff"
url=$(git show HEAD | gh gist create -f "$filename" -d "$desc" - | tail -n1)
fi
elif [[ $target == "develop" ]]; then
desc="Diff from develop"
filename="develop.diff"
url=$(git diff develop...HEAD | gh gist create -f "$filename" -d "$desc" - | tail -n1)
else
desc="Diff of $target"
filename="$target.diff"
url=$(git diff "$target...HEAD" | gh gist create -f "$filename" -d "$desc" - | tail -n1)
fi
echo "$url"
open "$url"
}; compdef _git gg=git-show
# Make a gist of the difference between working copy and default branch
ggd() { gg "$(get_default_branch)"; }; compdef _git ggd=git-show
gl() { git log "$@"; }; compdef _git gl=git-log
# Pretty one-liner log
glp() {
local git_args=()
if [[ $1 =~ ^-[0-9]+$ ]] || [[ $1 =~ ^--max-count=[0-9]+$ ]] || [[ $1 =~ ^-n$ && $2 =~ ^[0-9]+$ ]]; then
git_args=("$@")
else
git_args=("$@")
fi
git log --pretty="tformat:$FORMAT" "${git_args[@]}" |
column -t -s '{' |
less -XRS --quit-if-one-screen
}; compdef _git glp=git-log
gm() { git mv "$@"; }; compdef _git gm=git-mv
gp() { git pull "$@"; }; compdef _git gp=git-pull
gpf() { git push --force-with-lease "$@"; }; compdef _git gpf=git-push
gpr() { gh pr create "$@"; }; compdef _gh gpr=gh-pr
gprb() { gh pr create -B "$@"; }; compdef _gh gprb=gh-pr
gprd() { gh pr create -d "$@"; }; compdef _gh gprd=gh-pr
gprdb() { gh pr create -d -B "$@"; }; compdef _gh gprdb=gh-pr
# Remove local branches that aren't on remote any more
gpru() {
cleanup_gone_branches() {
git remote update origin --prune
local gone_branches=$(git branch -vvv | grep gone | cut -d' ' -f3)
if [[ -n "$gone_branches" ]]; then
echo "$gone_branches" | xargs -I{} git branch -D '{}'
fi
}
with_default_branch cleanup_gone_branches
}
gpso() { git push --set-upstream origin "${@:-$(git branch --show-current)}"; }; compdef _git gpso=git-push
grb() { git rebase "$@"; }; compdef _git grb=git-rebase
grba() { git rebase --abort "$@"; }; compdef _git grba=git-rebase
grbc() { git rebase --continue "$@"; }; compdef _git grbc=git-rebase
grbd() { git rebase $(get_default_branch) "$@"; }; compdef _git grbd=git-rebase
grbdo() { gfo && git rebase $(get_default_branch) "$@"; }; compdef _git grbd=git-rebase
grbi() { git rebase -i $(get_default_branch) "$@"; }; compdef _git grbi=git-rebase
grl() { git reflog "$@"; }; compdef _git grl=git-reflog
grs() { git reset "$@"; }; compdef _git grs=git-reset
grsh1() { git reset HEAD~1 "$@"; }; compdef _git grsh1=git-reset
grsh2() { git reset HEAD~2 "$@"; }; compdef _git grsh2=git-reset
grsh3() { git reset HEAD~3 "$@"; }; compdef _git grsh3=git-reset
grsh4() { git reset HEAD~4 "$@"; }; compdef _git grsh4=git-reset
grsh5() { git reset HEAD~5 "$@"; }; compdef _git grsh5=git-reset
grsh6() { git reset HEAD~6 "$@"; }; compdef _git grsh6=git-reset
grsh7() { git reset HEAD~7 "$@"; }; compdef _git grsh7=git-reset
grsh8() { git reset HEAD~8 "$@"; }; compdef _git grsh8=git-reset
grsh9() { git reset HEAD~8 "$@"; }; compdef _git grsh9=git-reset
grt() { git restore "$@"; }; compdef _git grt=git-restore
grta() { git restore . "$@"; }; compdef _git grt=git-restore
grts() { git restore --staged "$@"; }; compdef _git grt=git-restore
grtsa() { git restore --staged . "$@"; }; compdef _git grt=git-restore
grm() { git rm "$@"; }; compdef _git grm=git-rm
gs() { git status "$@"; }; compdef _git gs=git-status
gsh() { git show "$@"; }; compdef _git gsh=git-show
gshn() { git show --name-only "$@"; }; compdef _git gsh=git-show
gst() { git stash "$@"; }; compdef _git gst=git-stash
gstd() { git stash drop "$@"; }; compdef _git gstd=git-stash
gstl() { git stash list "$@"; }; compdef _git gstl=git-stash
gstp() { git stash pop "$@"; }; compdef _git gstp=git-stash
gsts() { git stash show -p "$@"; }; compdef _git gsts=git-stash
gstu() { git stash -u "$@"; }; compdef _git gstu=git-stash
gsw() { git switch "$@"; }; compdef _git gsw=git-switch
gswc() { git switch -c "$@"; }; compdef _git gswc=git-switch
gswcd() { git switch -c "$1" $(get_default_branch); }; compdef _git gswcd=git-switch
gswd() { git switch $(get_default_branch); }; compdef _git gswd=git-switch
gswp() { git switch - "$@"; }; compdef _git gswd=git-switch
gtc() { gt create "$@"; }
gtl() { gt log "$@"; }
gtm() { gt move "$@"; }
gtr() { gt restack "$@"; }
gts() { gt submit "$@"; }
gtsy() { gt sync "$@"; }
gtt() { gt track "$@"; }
alias gwip='git add . && git commit -m "WIP" -n'
Sort committers by average length of commit message
git log --no-merges --pretty=format:'COMMIT_START|%an|%B|COMMIT_END' | \
awk '
BEGIN { RS = "COMMIT_END\n"; FS = "|" }
/COMMIT_START/ {
author = $2
message = ""
for (i = 3; i <= NF; i++) {
if (i > 3) message = message "|"
message = message $i
}
len = length(message)
authors[author] += len
counts[author]++
if (!min[author] || len < min[author]) min[author] = len
if (len > max[author]) max[author] = len
}
END {
for (author in authors) {
avg = authors[author] / counts[author]
printf "%6.1f|%-30s|(min: %d, max: %d, commits: %d)\n",
avg, author, min[author], max[author], counts[author]
}
}' | sort -t'|' -k1 -nr | awk -F'|' '{printf "%-30s %s chars %s\n", $2, $1, $3}'
Gradient Borders with Transparent Background

<html lang="en">
<head>
<title>Gradient borders with transparent background</title>
<meta charset="utf-8">
<style>
* {
box-sizing: border-box;
}
body {
background-color: black;
color: white;
}
.card {
background-color: gray;
color: black;
}
.gradient-border-mask {
display: flow-root;
position: relative;
padding: 1.3rem;
}
.gradient-border-mask::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 5px;
border: 5px solid transparent;
background: linear-gradient(45deg, purple, orange) border-box;
-webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: destination-out;
mask-composite: exclude;
}
</style>
</head>
<body>
<div class="gradient-border-mask">
<p>Lorem ipsum dolor sit amet consectetur</p>
</div>
<div class="card">
<p>Lorem ipsum dolor sit amet consectetur</p>
<div class="gradient-border-mask">
<p>Lorem ipsum dolor sit amet consectetur</p>
</div>
</div>
</body>
</html>
How to keep your input and dismiss/cancel atuin
The normal behavior of atuin is to put either the command you matched onto your commandline, or nothing. So if you Ctrl-r and type something with no good match and exit, you “lose” what you have typed. You can Ctrl-g to get back what you had when you pressed Ctrl-r but anything you typed after that is lost.
To get what I think is superior behavior set exit_mode = "return_query" in ~/.config/atuin/config.toml. Now whatever is in the atuin buffer is now on your commandline if you hit Esc. You can still Ctrl-g to get what you had before Ctrl-r or Ctrl-c to exit to an empty commandline.
Starting more than one dev webserver each in its own terminal window (Mac)
#!/usr/bin/env zsh
# Script to start monorepo development processes in separate terminals
open_position_run() {
local dir=$1
local cmd=$2
# Start the server
osascript -e 'tell application "Terminal"
do script "cd '"$dir"' && nvm use 20 && '"$cmd"' &" in window 1
end tell'
}
open_position_run "/Users/bakert/monorepo/apps/app1 "pnpm dev"
open_position_run "/Users/bakert/monorepo/apps/app2 "pnpm dev"
History (Fourth Time)
I did this in 2008, 2011 and 2015 but forgot to do it for ten years.
[zarniwoop ~] history 0 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
34675 git
5294 composer
4376 cd
3761 vi
3076 pnpm
2914 python
2188 m
1917 ls
1822 python3
1717 ssh
Compared to 2015. New: composer, pnpm, python/python3, m (run scripts for an app I work on). Climbers: git, cd. Fallers: ssh, ls. Old: c, php, pass, sudo, ruby.
COUNT(*) OVER () in Drizzle
In general I like to use COUNT(*) OVER () to get the total count for a query when retrieving a slice with OFFSET and LIMIT (very useful for pagination) rather than issuing a separate query for the total count. This is not super well supported in Drizzle but you can do it like this:
const data = await db.query.tableName.findMany({
…
extras: {
// Weird cast here because COUNT(*) is a bigint which is handled as a string in js
// https://orm.drizzle.team/docs/guides/count-rows
total: sql<number>`CAST(COUNT(*) OVER() AS INTEGER)`.as("total"),
},
…
Set Up a New Mac (May 2025 Edition)
Previously: July 2019, July 2022, August 2023
- Upgrade to latest MacOS
- Restore from Blackblaze backup: u directory, dotfiles, .atuin dir, .config dir, .cursor dir, .nvm-zsh dir, .ssh dir, .vim dir, any other dot dirs that look useful, ~/Library/Application Support/Alfred
- Set perms on .ssh
$ cd ~ && chmod 600 ~/.ssh/* && chmod 700 ~/.ssh && chmod 644 ~/.ssh/*.pub
- Set perms on ~/u/bin
$ chmod u+x ~/u/bin/*
- Hide Desktop icons
$ defaults write com.apple.finder CreateDesktop false $ killall Finder
- Show hidden files in Finder with Cmd-Shift-.
- 1Password
- Dock: remove everything, hiding on, magnification on
- Alfred (and give it Accessibility access, add license key)
- System Settings, Mouse, set Trackpad speed to max and enable right-click
- Sublime Text 4 (add license key, set
"trim_trailing_white_space_on_save": "all"in sublime prefs, install Package Control, install Nord Theme via Package Control) - subl commandline sublime.
$ ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" ~/u/bin/subl
- sublime git-ignorer. (1) add Package Control repo https://github.com/apc999/sublime-text-gitignore (2)
install package sublime-text-gitignore (3) use menu item : File->Exclude Git-ignored (4) Give this a keyboard shortcut in Sublime, Preferences, Key Bindings with{ "keys": ["super+shift+i"], "command": "exclude_ignored" } - Keyboard shortcut to toggle word wrap in Sublime Text. Preferences, Key Bindings
{ "keys": ["super+shift+w"], "command": "toggle_setting", "args": { "setting": "word_wrap" } } - Install FiraCode and add it to Sublime Text prefs with
"font_face": "Fira Code". - Nord theme for Terminal and make default in preferences.
- Polar theme for terminal when ssh’ing to remotes
- For both Nord and Polar themes: “Use Option as Meta Key” in Terminal to make left Alt work as Esc. And Terminal, Settings, Advanced, un-check “Audible bell” and “Only when sound is muted”. And Shell, (When the shell exits) “Close the window”.
- System Preferences, Sound, turn “Alert volume” all the way down
- Use Ctrl-f7 to enable keyboard navigation of dialogs
- Homebrew. (Installs OSX commandline tools)
- Discord
- Change all .txt to open with Sublime Text
- Chrome. Sign in to Chrome to get extensions, then tell it you really do want uBlock Origin via “Keep for Now” under Extensions in Settings. Uninstall Chrome if they’ve finally locked it down entirely
- Firefox. Sign in to sync extensions. Set as default browser. Settings, search for “Autoplay”, Settings, Allow Audio and Video. Visit each extension you want in Private Browsing and select Run in Prviate Windows
- Skitch
- Backblaze. Choose to inherit the previous backup (it won’t copy anything down). Give System Settings, Privacy & Security, Full Disk Access
- Parallels Desktop + Windows + MTGO
- Disable Ask Siri in System Preferences, Siri
- Turn on “tap to click” in System Preferences, Trackpad
- Disable long-press (it’s annoying when selecting text in Chrome):
defaults write -g ApplePressAndHoldEnabled -bool false - Spotify
- Slack
- Rectangle Pro
- DaisyDisk
- ChatGPT
- Claude
- Linear
- Zed
- Notion
brew install nvimbrew install mariadbbrew install npmbrew install pnpm@9brew install apache2.brew install php. Enable in Apache with LoadModule, FilesMatch and DirectoryIndex directives as per homebrew output andbrew services restart apache2.brew install ghbrew install composerbrew install batbrew install atuin && atuin import autobrew install deltabrew install vercel-clinpm install -g rtm-cligit cloneimportant repos (ff, pd, monorepo)- Restore any local databases for dev (ff, decksite, logsite)
ln -s ~/ff/src/www /opt/homebrew/var/www/ffGRANT ALL ON ff.* TO ff@localhost IDENTIFIED BY *REDACTED*- pd setup
- Check open but unsaved files in Sublime Text in case there’s anything you need to preserve
git statusin any recent repos and check for uncommitted work.
zsh “shortcuts”
$ cat ~/.config/zsh/nav.zsh
───────┬─────────────────────────────────────────────────────────────────────
│ File: /Users/bakert/.config/zsh/nav.zsh
───────┼─────────────────────────────────────────────────────────────────────
1 │ export MONOREPO_ROOT="/Users/bakert/cardeio-monorepo-v2"
2 │ export ORGANIZED_PLAY="$MONOREPO_ROOT/apps/organized-play"
3 │ export PLAY_NEXT="$MONOREPO_ROOT/apps/play-next"
4 │ export LUDWIG="$MONOREPO_ROOT/apps/ludwig"
5 │ export CARD_SEARCH_DEMO="$MONOREPO_ROOT/apps/card-search-demo"
6 │ export DECK_BUILDER="$MONOREPO_ROOT/packages/deck-builder"
7 │
8 │ hash -d mr="$MONOREPO_ROOT"
9 │ hash -d op="$ORGANIZED_PLAY"
10 │ hash -d pn="$PLAY_NEXT"
11 │ hash -d lw="$LUDWIG"
12 │ hash -d cs="$CARD_SEARCH_DEMO"
13 │ hash -d db="$DECK_BUILDER"
───────┴──────────────────────────────────────────────────────────────────────
Use prefixed with ~ anywhere you need a path:
$ cd ~mr $ vi ~lw/src/index.ts
Git – You’re Doing It Wrong
| Instead of | Do this |
git checkout {file} | git restore {file} |
git checkout {branch} | git switch {branch} |
git checkout -b {newbranch} | git switch -c {newbranch} |
git push --force | git push --force-with-lease |
git rebase | git rebase --update-refs |
