Compare commits
15 Commits
d0316e45b5
...
drunkendot
| Author | SHA1 | Date | |
|---|---|---|---|
| 11bf7ecaa4 | |||
| 3d6f13b2bc | |||
| e2a1e3b784 | |||
| e38a6b3166 | |||
| 467b967ced | |||
| 474fdd028c | |||
| a45f89b187 | |||
| 1b60a9364d | |||
| 5208e9a5bb | |||
| 6188583ee9 | |||
| f27ba2710e | |||
| c0e4a88d70 | |||
| 700da3aa0b | |||
| fb80b6dfb2 | |||
| 1d7df94a1d |
33
.claude/.gitignore
vendored
Normal file
33
.claude/.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Never track Claude Code per-machine state, secrets, or chat data.
|
||||||
|
#
|
||||||
|
# settings.json IS tracked (portable user prefs + permissions allowlist).
|
||||||
|
# Everything else under ~/.claude/ stays per-host: credentials, session
|
||||||
|
# logs, project memories, file-edit history, telemetry, caches.
|
||||||
|
|
||||||
|
# Auth — must NEVER be tracked
|
||||||
|
.credentials.json
|
||||||
|
|
||||||
|
# Per-machine settings overrides (by Claude Code convention)
|
||||||
|
settings.local.json
|
||||||
|
|
||||||
|
# Chat and session data
|
||||||
|
history.jsonl
|
||||||
|
sessions/
|
||||||
|
projects/
|
||||||
|
file-history/
|
||||||
|
plans/
|
||||||
|
|
||||||
|
# Caches and ephemeral state
|
||||||
|
cache/
|
||||||
|
downloads/
|
||||||
|
paste-cache/
|
||||||
|
shell-snapshots/
|
||||||
|
session-env/
|
||||||
|
backups/
|
||||||
|
telemetry/
|
||||||
|
mcp-needs-auth-cache.json
|
||||||
|
|
||||||
|
# Plugin marketplace state — known_marketplaces.json IS portable, but the
|
||||||
|
# resolved-plugin caches and the local blocklist are per-machine.
|
||||||
|
plugins/blocklist.json
|
||||||
|
plugins/marketplaces/
|
||||||
57
.claude/settings.json
Normal file
57
.claude/settings.json
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(tmux source-file:*)",
|
||||||
|
"Bash(git:*)",
|
||||||
|
"Bash(curl:*)",
|
||||||
|
"Bash(sudo:*)",
|
||||||
|
"Bash(find:*)",
|
||||||
|
"Bash(ls:*)",
|
||||||
|
"Bash(cat:*)",
|
||||||
|
"Bash(systemctl:*)",
|
||||||
|
"Bash(sysctl:*)",
|
||||||
|
"Bash(crontab:*)",
|
||||||
|
"Bash(dig:*)",
|
||||||
|
"Bash(ulimit:*)",
|
||||||
|
"Bash(python3:*)",
|
||||||
|
"Bash(iptables:*)",
|
||||||
|
"Bash(ip6tables:*)",
|
||||||
|
"Bash(ufw status:*)",
|
||||||
|
"Bash(firewall-cmd:*)",
|
||||||
|
"Bash(apt list:*)",
|
||||||
|
"Bash(apt-get install:*)",
|
||||||
|
"Bash(apt-get upgrade:*)",
|
||||||
|
"Bash(dpkg:*)",
|
||||||
|
"Bash(fail2ban-client status:*)",
|
||||||
|
"Bash(fail2ban-client set:*)",
|
||||||
|
"Bash(aa-status)",
|
||||||
|
"Bash(getenforce)",
|
||||||
|
"Bash(mount)",
|
||||||
|
"Bash(netstat -tuln)",
|
||||||
|
"Bash(netstat -tlnp)",
|
||||||
|
"Bash(openssl x509:*)",
|
||||||
|
"Bash(openssl rand:*)",
|
||||||
|
"Bash(grep -v \"^$\")",
|
||||||
|
"Bash(du -sh /var/log/*)",
|
||||||
|
"Bash(lsmod)",
|
||||||
|
"Bash(xargs ls:*)",
|
||||||
|
"Bash(last:*)",
|
||||||
|
"Bash(nginx:*)",
|
||||||
|
"Bash(redis-cli:*)",
|
||||||
|
"Bash(rkhunter:*)",
|
||||||
|
"Bash(aideinit)",
|
||||||
|
"Bash(npm --version)",
|
||||||
|
"Bash(ruby --version)",
|
||||||
|
"Bash(getent passwd:*)",
|
||||||
|
"Bash(sqlite3:*)",
|
||||||
|
"Read(//home/**)",
|
||||||
|
"Read(//opt/**)",
|
||||||
|
"Read(//etc/nginx/sites-enabled/**)",
|
||||||
|
"Read(//etc/nginx/sites-available/**)"
|
||||||
|
],
|
||||||
|
"defaultMode": "auto"
|
||||||
|
},
|
||||||
|
"theme": "dark",
|
||||||
|
"verbose": true,
|
||||||
|
"skipAutoPermissionPrompt": true
|
||||||
|
}
|
||||||
@@ -29,5 +29,21 @@ if is_digitalocean && do_anchor_ip; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
curl -s --connect-timeout 3 https://api.ipify.org 2>/dev/null \
|
print_local_ip() {
|
||||||
|| hostname -I | awk '{print $1}'
|
local iface ip
|
||||||
|
if command -v ipconfig >/dev/null 2>&1; then
|
||||||
|
for iface in en0 en1 en2; do
|
||||||
|
ip=$(ipconfig getifaddr "$iface" 2>/dev/null) || true
|
||||||
|
[ -n "${ip:-}" ] && { printf '%s\n' "$ip"; return 0; }
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if hostname -I >/dev/null 2>&1; then
|
||||||
|
hostname -I | awk '{print $1}'
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
ifconfig 2>/dev/null | awk '/inet /{ if ($2 != "127.0.0.1") { print $2; exit } }'
|
||||||
|
}
|
||||||
|
|
||||||
|
ip=$(curl -s --connect-timeout 3 https://api.ipify.org 2>/dev/null || true)
|
||||||
|
[ -z "${ip:-}" ] && ip=$(print_local_ip)
|
||||||
|
printf '%s\n' "${ip:-}"
|
||||||
|
|||||||
17
.local/bin/tmux-net
Executable file
17
.local/bin/tmux-net
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Emit the tmux status-bar network segment.
|
||||||
|
# No VPN: "⌂ <local_ip>"
|
||||||
|
# VPN up: "⌂ <local_ip> / ⇡ <vpn_ip>"
|
||||||
|
#
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
local_ip=$("$HOME/.local/bin/tmux-ip" 2>/dev/null || true)
|
||||||
|
vpn_ip=$("$HOME/.local/bin/tmux-vpn-ip" 2>/dev/null || true)
|
||||||
|
|
||||||
|
if [ -n "${vpn_ip:-}" ]; then
|
||||||
|
printf '\xe2\x8c\x82 %s / \xe2\x87\xa1 %s\n' "${local_ip:-}" "$vpn_ip"
|
||||||
|
else
|
||||||
|
printf '\xe2\x8c\x82 %s\n' "${local_ip:-}"
|
||||||
|
fi
|
||||||
24
.local/bin/tmux-vpn-ip
Executable file
24
.local/bin/tmux-vpn-ip
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Print the IPv4 of the first active VPN tunnel interface, if any.
|
||||||
|
# Empty output when no VPN is up.
|
||||||
|
#
|
||||||
|
# macOS: utun* Linux: tun*, wg*, ppp*
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Darwin)
|
||||||
|
ifconfig 2>/dev/null | awk '
|
||||||
|
/^utun[0-9]+:/ { iface=$1; sub(":", "", iface); next }
|
||||||
|
/^[a-z]+[0-9]*:/ { iface="" }
|
||||||
|
iface != "" && $1 == "inet" { print $2; exit }
|
||||||
|
'
|
||||||
|
;;
|
||||||
|
Linux)
|
||||||
|
if command -v ip >/dev/null 2>&1; then
|
||||||
|
ip -4 -o addr show 2>/dev/null \
|
||||||
|
| awk '$2 ~ /^(tun|wg|ppp)[0-9]+/ { sub("/.*","",$4); print $4; exit }'
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
BIN
.local/share/fonts/GALLAUDET.ttf
Normal file
BIN
.local/share/fonts/GALLAUDET.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-Bold.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-Bold.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-BoldItalic.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-Italic.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-Italic.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-Light.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-Light.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-LightItalic.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-LightItalic.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-Medium.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-Medium.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-MediumItalic.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/IntelOneMono-Regular.ttf
Normal file
BIN
.local/share/fonts/IntelOneMono-Regular.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/OpenGorton-Bold.otf
Normal file
BIN
.local/share/fonts/OpenGorton-Bold.otf
Normal file
Binary file not shown.
BIN
.local/share/fonts/OpenGorton-Regular.otf
Normal file
BIN
.local/share/fonts/OpenGorton-Regular.otf
Normal file
Binary file not shown.
BIN
.local/share/fonts/RobotoMono-Italic-VariableFont_wght.ttf
Normal file
BIN
.local/share/fonts/RobotoMono-Italic-VariableFont_wght.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/RobotoMono-VariableFont_wght.ttf
Normal file
BIN
.local/share/fonts/RobotoMono-VariableFont_wght.ttf
Normal file
Binary file not shown.
BIN
.local/share/fonts/code128.ttf
Normal file
BIN
.local/share/fonts/code128.ttf
Normal file
Binary file not shown.
17
.tmux.conf
17
.tmux.conf
@@ -2,7 +2,20 @@
|
|||||||
set -g bell-action any
|
set -g bell-action any
|
||||||
|
|
||||||
# Default termtype. If the rcfile sets $TERM, that overrides this value.
|
# Default termtype. If the rcfile sets $TERM, that overrides this value.
|
||||||
set -g default-terminal screen-256color
|
set -g default-terminal "tmux-256color"
|
||||||
|
|
||||||
|
# Truecolor + clipboard passthrough for outer terminals that advertise RGB
|
||||||
|
# (covers xterm-*, alacritty, kitty, wezterm, iTerm, ghostty, modern Apple Terminal).
|
||||||
|
set -ga terminal-features ",xterm-256color:RGB"
|
||||||
|
set -ga terminal-features ",alacritty:RGB"
|
||||||
|
set -ga terminal-features ",kitty:RGB"
|
||||||
|
set -ga terminal-features ",wezterm:RGB"
|
||||||
|
set -ga terminal-features ",ghostty:RGB"
|
||||||
|
set -ga terminal-features ",screen-256color:RGB"
|
||||||
|
|
||||||
|
# TUI apps (Claude Code, nvim, etc.) want focus events so they can redraw
|
||||||
|
# / refresh state when the pane regains focus.
|
||||||
|
set -g focus-events on
|
||||||
|
|
||||||
# Keep your finger on ctrl, or don't
|
# Keep your finger on ctrl, or don't
|
||||||
bind-key ^D detach-client
|
bind-key ^D detach-client
|
||||||
@@ -66,7 +79,7 @@ set -g pane-border-style fg=colour245
|
|||||||
set -g pane-active-border-style fg=colour39
|
set -g pane-active-border-style fg=colour39
|
||||||
set -g message-style fg=colour16,bg=colour221,bold
|
set -g message-style fg=colour16,bg=colour221,bold
|
||||||
set -g status-left '#[fg=colour235,bg=colour252,bold] ❐ #S #[fg=colour252,bg=colour238,nobold]❯#[fg=colour245,bg=colour238,bold] #(whoami) '
|
set -g status-left '#[fg=colour235,bg=colour252,bold] ❐ #S #[fg=colour252,bg=colour238,nobold]❯#[fg=colour245,bg=colour238,bold] #(whoami) '
|
||||||
set -g status-right '#[bold][#[nobold,fg=colour229]#H#[fg=default] / #[fg=colour229]#(~/.local/bin/tmux-ip)#[fg=default,bold]]#[nobold,fg=colour255] %H:%M %d-%b-%Y '
|
set -g status-right '#[bold][#[nobold,fg=colour229]#h#[fg=default] / #[fg=colour229]#(~/.local/bin/tmux-net)#[fg=default,bold]]#[nobold,fg=colour255] %H:%M %d-%b-%Y '
|
||||||
set -g window-status-format '#[fg=colour235,bg=colour252,nobold] #(~/.local/bin/tmux-window-icon #{window_index}) #(pwd="#{pane_current_path}"; echo ${pwd####*/}) #W '
|
set -g window-status-format '#[fg=colour235,bg=colour252,nobold] #(~/.local/bin/tmux-window-icon #{window_index}) #(pwd="#{pane_current_path}"; echo ${pwd####*/}) #W '
|
||||||
set -g window-status-current-format '#[fg=colour234,bg=colour39,bold] [#[fg=colour232,bold]#{?window_zoomed_flag,#[fg=colour228],} #(~/.local/bin/tmux-window-icon #{window_index}) #(pwd="#{pane_current_path}"; echo ${pwd####*/}) #W #[fg=colour234,bold]] '
|
set -g window-status-current-format '#[fg=colour234,bg=colour39,bold] [#[fg=colour232,bold]#{?window_zoomed_flag,#[fg=colour228],} #(~/.local/bin/tmux-window-icon #{window_index}) #(pwd="#{pane_current_path}"; echo ${pwd####*/}) #W #[fg=colour234,bold]] '
|
||||||
set-option -g status-interval 60
|
set-option -g status-interval 60
|
||||||
|
|||||||
11
Rakefile
11
Rakefile
@@ -210,7 +210,7 @@ def install_term_theme
|
|||||||
message = "Which theme would you like to apply to your iTerm2 profile?"
|
message = "Which theme would you like to apply to your iTerm2 profile?"
|
||||||
color_scheme = ask message, iTerm_available_themes
|
color_scheme = ask message, iTerm_available_themes
|
||||||
|
|
||||||
return if color_scheme == 'None'
|
return if color_scheme.nil? || color_scheme == 'None'
|
||||||
|
|
||||||
color_scheme_file = File.join('iTerm2', "#{color_scheme}.itermcolors")
|
color_scheme_file = File.join('iTerm2', "#{color_scheme}.itermcolors")
|
||||||
|
|
||||||
@@ -220,6 +220,8 @@ def install_term_theme
|
|||||||
profiles << 'All'
|
profiles << 'All'
|
||||||
selected = ask message, profiles
|
selected = ask message, profiles
|
||||||
|
|
||||||
|
return if selected.nil?
|
||||||
|
|
||||||
if selected == 'All'
|
if selected == 'All'
|
||||||
(profiles.size-1).times { |idx| apply_theme_to_iterm_profile_idx idx, color_scheme_file }
|
(profiles.size-1).times { |idx| apply_theme_to_iterm_profile_idx idx, color_scheme_file }
|
||||||
else
|
else
|
||||||
@@ -244,7 +246,12 @@ def ask(message, values)
|
|||||||
puts message
|
puts message
|
||||||
while true
|
while true
|
||||||
values.each_with_index { |val, idx| puts " #{idx+1}. #{val}" }
|
values.each_with_index { |val, idx| puts " #{idx+1}. #{val}" }
|
||||||
selection = STDIN.gets.chomp
|
input = STDIN.gets
|
||||||
|
if input.nil?
|
||||||
|
puts "(no input available — skipping prompt)"
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
selection = input.chomp
|
||||||
if (Float(selection)==nil rescue true) || selection.to_i < 0 || selection.to_i > values.size+1
|
if (Float(selection)==nil rescue true) || selection.to_i < 0 || selection.to_i > values.size+1
|
||||||
puts "ERROR: Invalid selection.\n\n"
|
puts "ERROR: Invalid selection.\n\n"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# set your user tokens as environment variables, such as ~/.secrets
|
# set your user tokens as environment variables, such as ~/.secrets
|
||||||
# See the README for examples.
|
# See the README for examples.
|
||||||
|
[user]
|
||||||
|
name = dissimulo
|
||||||
|
email = connect+gitea@dustin-williams.com
|
||||||
[color]
|
[color]
|
||||||
ui = true
|
ui = true
|
||||||
[color "branch"]
|
[color "branch"]
|
||||||
@@ -126,4 +129,4 @@
|
|||||||
# http://gitfu.wordpress.com/2008/04/20/git-rerere-rereremember-what-you-did-last-time/
|
# http://gitfu.wordpress.com/2008/04/20/git-rerere-rereremember-what-you-did-last-time/
|
||||||
enabled = true
|
enabled = true
|
||||||
[include]
|
[include]
|
||||||
path = .gitconfig.user
|
path = ~/.gitconfig.user
|
||||||
|
|||||||
118
install.sh
118
install.sh
@@ -30,9 +30,13 @@ PERSONAL_FILES=(
|
|||||||
.zprofile .zshenv .zshrc
|
.zprofile .zshenv .zshrc
|
||||||
)
|
)
|
||||||
|
|
||||||
# Directories deployed wholesale to $HOME/<dir>/.
|
# Directories whose contents are merged into $HOME/<dir>/, file by file. Files
|
||||||
|
# the repo provides replace conflicting on-disk versions (with the displaced
|
||||||
|
# version preserved in $BACKUP_DIR); files outside the repo's tree are left
|
||||||
|
# untouched. This deliberately avoids wholesale-replacing $HOME/.local etc.,
|
||||||
|
# which would sweep away unrelated user data (fonts, app state, ...).
|
||||||
PERSONAL_DIRS=(
|
PERSONAL_DIRS=(
|
||||||
.fonts .irssi .nano .themes .local .mplayer
|
.fonts .irssi .nano .themes .local .mplayer .claude
|
||||||
)
|
)
|
||||||
|
|
||||||
have() { command -v "$1" >/dev/null 2>&1; }
|
have() { command -v "$1" >/dev/null 2>&1; }
|
||||||
@@ -83,37 +87,104 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 3. Deploy personal dotfiles
|
# 3. Deploy personal dotfiles
|
||||||
backup_one() {
|
|
||||||
local src_name="$1"
|
# Move $HOME/<rel> aside into $BACKUP_DIR, preserving its sub-path.
|
||||||
local dst="$HOME/$src_name"
|
backup_one_path() {
|
||||||
|
local rel="$1"
|
||||||
|
local dst="$HOME/$rel"
|
||||||
if [ -e "$dst" ] || [ -L "$dst" ]; then
|
if [ -e "$dst" ] || [ -L "$dst" ]; then
|
||||||
mkdir -p "$BACKUP_DIR/$(dirname "$src_name")"
|
mkdir -p "$BACKUP_DIR/$(dirname "$rel")"
|
||||||
mv "$dst" "$BACKUP_DIR/$src_name"
|
mv "$dst" "$BACKUP_DIR/$rel"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
deploy_one() {
|
# Returns 0 iff $1 and $2 are equivalent (same symlink target, or identical
|
||||||
local name="$1"
|
# regular-file content). Used to make re-runs idempotent: unchanged files get
|
||||||
local src="$YADR_DIR/$name"
|
# skipped instead of needlessly backed up.
|
||||||
local dst="$HOME/$name"
|
paths_equivalent() {
|
||||||
|
local a="$1" b="$2"
|
||||||
|
if [ -L "$a" ] && [ -L "$b" ]; then
|
||||||
|
[ "$(readlink "$a")" = "$(readlink "$b")" ]
|
||||||
|
elif [ -L "$a" ] || [ -L "$b" ]; then
|
||||||
|
return 1
|
||||||
|
elif [ -f "$a" ] && [ -f "$b" ]; then
|
||||||
|
cmp -s "$a" "$b"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy one file or symlink at $YADR_DIR/<rel> to $HOME/<rel>. If a different
|
||||||
|
# file/symlink is already at the destination, it's moved into $BACKUP_DIR first.
|
||||||
|
deploy_file() {
|
||||||
|
local rel="$1"
|
||||||
|
local src="$YADR_DIR/$rel"
|
||||||
|
local dst="$HOME/$rel"
|
||||||
if [ ! -e "$src" ] && [ ! -L "$src" ]; then
|
if [ ! -e "$src" ] && [ ! -L "$src" ]; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
backup_one "$name"
|
if paths_equivalent "$src" "$dst"; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
backup_one_path "$rel"
|
||||||
mkdir -p "$(dirname "$dst")"
|
mkdir -p "$(dirname "$dst")"
|
||||||
cp -a "$src" "$dst"
|
cp -a "$src" "$dst"
|
||||||
info "$name"
|
info "$rel"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy a directory by walking its tree and deploying each file/symlink in
|
||||||
|
# turn. Directories get mkdir'd; existing entries inside $HOME/<rel> that the
|
||||||
|
# repo doesn't know about are left alone. This is the merge semantics that
|
||||||
|
# protects e.g. $HOME/.local/share/fonts from being clobbered when the repo
|
||||||
|
# only tracks $HOME/.local/bin.
|
||||||
|
deploy_dir() {
|
||||||
|
local rel="$1"
|
||||||
|
local src="$YADR_DIR/$rel"
|
||||||
|
if [ ! -d "$src" ] || [ -L "$src" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
mkdir -p "$HOME/$rel"
|
||||||
|
local sub sub_rel src_path
|
||||||
|
while IFS= read -r -d '' sub; do
|
||||||
|
sub="${sub#./}"
|
||||||
|
[ "$sub" = "." ] && continue
|
||||||
|
sub_rel="$rel/$sub"
|
||||||
|
src_path="$YADR_DIR/$sub_rel"
|
||||||
|
if [ -d "$src_path" ] && [ ! -L "$src_path" ]; then
|
||||||
|
mkdir -p "$HOME/$sub_rel"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
deploy_file "$sub_rel"
|
||||||
|
done < <(cd "$src" && find . -mindepth 1 -print0)
|
||||||
}
|
}
|
||||||
|
|
||||||
log "Deploying personal dotfiles"
|
log "Deploying personal dotfiles"
|
||||||
for f in "${PERSONAL_FILES[@]}"; do deploy_one "$f"; done
|
for f in "${PERSONAL_FILES[@]}"; do deploy_file "$f"; done
|
||||||
for d in "${PERSONAL_DIRS[@]}"; do deploy_one "$d"; done
|
for d in "${PERSONAL_DIRS[@]}"; do deploy_dir "$d"; done
|
||||||
|
|
||||||
# .local/bin/claude is a relative symlink to ../share/claude/versions/...
|
# .local/bin/claude is a relative symlink to ../share/claude/versions/<version>.
|
||||||
# If that target isn't present on this machine, remove the dangling link so
|
# The version baked into the repo snapshot is whatever was current when this
|
||||||
# Claude Code's own installer (next step) can manage it.
|
# was last committed; on a fresh host that exact version probably isn't
|
||||||
if [ -L "$HOME/.local/bin/claude" ] && [ ! -e "$HOME/.local/bin/claude" ]; then
|
# installed. Resolve as follows:
|
||||||
rm "$HOME/.local/bin/claude"
|
# 1. If the deployed symlink already resolves, leave it alone.
|
||||||
|
# 2. Else, if any other Claude version is present under
|
||||||
|
# ~/.local/share/claude/versions/, repoint the symlink to the highest
|
||||||
|
# one (semver sort) so users get the latest installed binary.
|
||||||
|
# 3. Else, drop the dangling link and let Claude Code's own installer
|
||||||
|
# (next step) recreate it.
|
||||||
|
claude_link="$HOME/.local/bin/claude"
|
||||||
|
claude_versions_dir="$HOME/.local/share/claude/versions"
|
||||||
|
if [ -L "$claude_link" ] && [ ! -e "$claude_link" ]; then
|
||||||
|
latest_claude=""
|
||||||
|
if [ -d "$claude_versions_dir" ]; then
|
||||||
|
latest_claude="$(ls -1 "$claude_versions_dir" 2>/dev/null | sort -V | tail -1)"
|
||||||
|
fi
|
||||||
|
if [ -n "$latest_claude" ] && [ -e "$claude_versions_dir/$latest_claude" ]; then
|
||||||
|
ln -sfn "../share/claude/versions/$latest_claude" "$claude_link"
|
||||||
|
info "Repointed ~/.local/bin/claude -> $latest_claude (latest installed)"
|
||||||
|
else
|
||||||
|
rm "$claude_link"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. Install Claude Code (Anthropic's CLI). Skip if already installed or
|
# 4. Install Claude Code (Anthropic's CLI). Skip if already installed or
|
||||||
@@ -137,6 +208,13 @@ if [ -d "$HOME/.local/bin" ]; then
|
|||||||
find "$HOME/.local/bin" -maxdepth 1 -type f -exec chmod +x {} \; 2>/dev/null || true
|
find "$HOME/.local/bin" -maxdepth 1 -type f -exec chmod +x {} \; 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 5. Refresh font cache so newly-deployed .fonts/ and .local/share/fonts/
|
||||||
|
# entries are visible to apps without a logout/login.
|
||||||
|
if have fc-cache; then
|
||||||
|
log "Refreshing font cache"
|
||||||
|
fc-cache -f >/dev/null 2>&1 || warn "fc-cache returned non-zero; continuing"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
log "Done."
|
log "Done."
|
||||||
if [ -d "$BACKUP_DIR" ]; then
|
if [ -d "$BACKUP_DIR" ]; then
|
||||||
|
|||||||
102
tmux/tmux.conf
102
tmux/tmux.conf
@@ -1,102 +0,0 @@
|
|||||||
# Ring the bell if any background window rang a bell
|
|
||||||
set -g bell-action any
|
|
||||||
|
|
||||||
# Default termtype. If the rcfile sets $TERM, that overrides this value.
|
|
||||||
set -g default-terminal screen-256color
|
|
||||||
|
|
||||||
# Keep your finger on ctrl, or don't
|
|
||||||
bind-key ^D detach-client
|
|
||||||
|
|
||||||
# Create splits and vertical splits
|
|
||||||
bind-key v split-window -h -p 50 -c "#{pane_current_path}"
|
|
||||||
bind-key ^V split-window -h -p 50 -c "#{pane_current_path}"
|
|
||||||
bind-key s split-window -p 50 -c "#{pane_current_path}"
|
|
||||||
bind-key ^S split-window -p 50 -c "#{pane_current_path}"
|
|
||||||
|
|
||||||
# Pane resize in all four directions using vi bindings.
|
|
||||||
# Can use these raw but I map them to shift-ctrl-<h,j,k,l> in iTerm.
|
|
||||||
bind -r H resize-pane -L 5
|
|
||||||
bind -r J resize-pane -D 5
|
|
||||||
bind -r K resize-pane -U 5
|
|
||||||
bind -r L resize-pane -R 5
|
|
||||||
|
|
||||||
# Smart pane switching with awareness of Vim splits.
|
|
||||||
# See: https://github.com/christoomey/vim-tmux-navigator
|
|
||||||
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
|
|
||||||
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
|
|
||||||
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
|
|
||||||
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
|
|
||||||
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
|
|
||||||
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
|
|
||||||
|
|
||||||
tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'
|
|
||||||
if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \
|
|
||||||
"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'"
|
|
||||||
if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \
|
|
||||||
"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'"
|
|
||||||
|
|
||||||
bind-key -T copy-mode-vi 'C-h' select-pane -L
|
|
||||||
bind-key -T copy-mode-vi 'C-j' select-pane -D
|
|
||||||
bind-key -T copy-mode-vi 'C-k' select-pane -U
|
|
||||||
bind-key -T copy-mode-vi 'C-l' select-pane -R
|
|
||||||
bind-key -T copy-mode-vi 'C-\' select-pane -l
|
|
||||||
|
|
||||||
# Use vi keybindings for tmux commandline input.
|
|
||||||
# Note that to get command mode you need to hit ESC twice...
|
|
||||||
set -g status-keys vi
|
|
||||||
|
|
||||||
# Use vi keybindings in copy and choice modes
|
|
||||||
setw -g mode-keys vi
|
|
||||||
|
|
||||||
# easily toggle synchronization (mnemonic: e is for echo)
|
|
||||||
# sends input to all panes in a given window.
|
|
||||||
bind e setw synchronize-panes on
|
|
||||||
bind E setw synchronize-panes off
|
|
||||||
|
|
||||||
# set first window to index 1 (not 0) to map more to the keyboard layout...
|
|
||||||
set-option -g base-index 1
|
|
||||||
set-window-option -g pane-base-index 1
|
|
||||||
set-window-option -g mouse on
|
|
||||||
|
|
||||||
# color scheme (styled as vim-powerline)
|
|
||||||
set -g status-left-length 52
|
|
||||||
set -g status-right-length 451
|
|
||||||
set -g status-style fg=white,bg=colour234
|
|
||||||
set -g pane-border-style fg=colour245
|
|
||||||
set -g pane-active-border-style fg=colour39
|
|
||||||
set -g message-style fg=colour16,bg=colour221,bold
|
|
||||||
set -g status-left '#[fg=colour235,bg=colour252,bold] ❐ #S #[fg=colour252,bg=colour238,nobold]⮀#[fg=colour245,bg=colour238,bold] #(whoami) #[fg=colour238,bg=colour234,nobold]⮀'
|
|
||||||
set -g window-status-format '#[fg=colour235,bg=colour252,bold] #I #(pwd="#{pane_current_path}"; echo ${pwd####*/}) #W '
|
|
||||||
set -g window-status-current-format '#[fg=colour234,bg=colour39]⮀#[fg=black,bg=colour39,noreverse,bold] #{?window_zoomed_flag,#[fg=colour228],} #I #(pwd="#{pane_current_path}"; echo ${pwd####*/}) #W #[fg=colour39,bg=colour234,nobold]⮀'
|
|
||||||
set-option -g status-interval 2
|
|
||||||
|
|
||||||
# Patch for OS X pbpaste and pbcopy under tmux.
|
|
||||||
set-option -g default-command "which reattach-to-user-namespace > /dev/null && reattach-to-user-namespace -l $SHELL || $SHELL"
|
|
||||||
|
|
||||||
# Screen like binding
|
|
||||||
unbind C-b
|
|
||||||
set -g prefix C-a
|
|
||||||
bind a send-prefix
|
|
||||||
|
|
||||||
# No escape time for vi mode
|
|
||||||
set -sg escape-time 0
|
|
||||||
|
|
||||||
# Screen like binding for last window
|
|
||||||
unbind l
|
|
||||||
bind C-a last-window
|
|
||||||
|
|
||||||
# Bigger history
|
|
||||||
set -g history-limit 10000
|
|
||||||
|
|
||||||
# New windows/pane in $PWD
|
|
||||||
bind c new-window -c "#{pane_current_path}"
|
|
||||||
|
|
||||||
# Fix key bindings broken in tmux 2.1
|
|
||||||
set -g assume-paste-time 0
|
|
||||||
|
|
||||||
# force a reload of the config file
|
|
||||||
unbind r
|
|
||||||
bind r source-file ~/.tmux.conf \; display "Reloaded!"
|
|
||||||
|
|
||||||
# Local config
|
|
||||||
if-shell "[ -f ~/.tmux.conf.user ]" 'source ~/.tmux.conf.user'
|
|
||||||
1
tmux/tmux.conf
Symbolic link
1
tmux/tmux.conf
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../.tmux.conf
|
||||||
13
zsh/diff.zsh
Normal file
13
zsh/diff.zsh
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Eagerly define `diff` as a real function instead of relying on prezto's
|
||||||
|
# autoload stub. The autoload stub emits
|
||||||
|
# "(eval):1: diff: function definition file not found"
|
||||||
|
# in non-interactive eval contexts where $fpath doesn't yet include the
|
||||||
|
# prezto utility module's functions directory. Defining a real function
|
||||||
|
# here bypasses the autoload path entirely.
|
||||||
|
function diff {
|
||||||
|
if (( $+commands[colordiff] )); then
|
||||||
|
command diff --unified "$@" | colordiff --difftype diffu
|
||||||
|
else
|
||||||
|
command diff --unified "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
source $HOME/.zprezto/runcoms/zshrc
|
source $HOME/.zprezto/runcoms/zshrc
|
||||||
|
|
||||||
for config_file ($HOME/.yadr/zsh/*.zsh) source $config_file
|
for config_file ($HOME/.yadr/zsh/*.zsh) source $config_file
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|||||||
Reference in New Issue
Block a user