Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48814c5d42 | |||
| 0eb605a835 | |||
| c32dbb92ac | |||
| 8c3dcacafc | |||
| c680be4817 | |||
| 13f43c3c5f | |||
| aafdc3a119 | |||
| 4053acbbc0 | |||
| 2906352220 | |||
| 1d2a823750 | |||
| 8400ddf6a8 | |||
| 11bf7ecaa4 | |||
| 3d6f13b2bc | |||
| e2a1e3b784 | |||
| e38a6b3166 | |||
| 467b967ced | |||
| 474fdd028c | |||
| a45f89b187 | |||
| 1b60a9364d | |||
| 5208e9a5bb | |||
| 6188583ee9 | |||
| f27ba2710e | |||
| c0e4a88d70 | |||
| 700da3aa0b | |||
| fb80b6dfb2 | |||
| 1d7df94a1d |
@@ -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/
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"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-daltonized",
|
||||
"verbose": true,
|
||||
"tui": "fullscreen",
|
||||
"skipAutoPermissionPrompt": true
|
||||
}
|
||||
+56
-20
@@ -1,33 +1,69 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Print the "best" IP for the tmux status bar.
|
||||
# Preference: DO reserved/floating IP > public egress (ipify) > first local IP.
|
||||
#
|
||||
# Shows a directly-held public/WAN IP when the machine has one on an interface,
|
||||
# otherwise its LAN/private IP. No external "what's my IP" lookup -- a NAT'd box
|
||||
# shows its LAN IP, never the gateway's egress. Works the same everywhere: a box
|
||||
# with a public IP on a NIC (incl. a cloud droplet's eth0) shows that WAN IP; a
|
||||
# NAT'd box shows its LAN IP. The VPN overlay is added separately by tmux-net via
|
||||
# tmux-vpn-ip and is untouched here.
|
||||
#
|
||||
|
||||
set -u
|
||||
|
||||
META="http://169.254.169.254/metadata/v1"
|
||||
CURL="curl -sf --connect-timeout 1 --max-time 2"
|
||||
|
||||
is_digitalocean() {
|
||||
[ -r /sys/class/dmi/id/sys_vendor ] \
|
||||
&& grep -qi digitalocean /sys/class/dmi/id/sys_vendor
|
||||
# This machine's own non-loopback IPv4 addresses, one per line. VPN tunnels are
|
||||
# excluded (tmux-net surfaces the VPN address separately as the ⇡ segment).
|
||||
list_ipv4() {
|
||||
if command -v ip >/dev/null 2>&1; then
|
||||
ip -4 -o addr show scope global 2>/dev/null \
|
||||
| awk '$2 !~ /^(tun|wg|ppp|tap)/ {print $4}' | cut -d/ -f1
|
||||
elif hostname -I >/dev/null 2>&1; then
|
||||
hostname -I 2>/dev/null | tr ' ' '\n'
|
||||
else
|
||||
ifconfig 2>/dev/null | awk '/inet /{print $2}'
|
||||
fi | grep -E '^([0-9]{1,3}\.){3}[0-9]{1,3}$' | grep -v '^127\.'
|
||||
}
|
||||
|
||||
do_anchor_ip() {
|
||||
local kind active ip
|
||||
for kind in reserved_ip floating_ip; do
|
||||
active=$($CURL "$META/$kind/ipv4/active" 2>/dev/null) || continue
|
||||
[ "$active" = "true" ] || continue
|
||||
ip=$($CURL "$META/$kind/ipv4/ip_address" 2>/dev/null) || continue
|
||||
[ -n "$ip" ] && { printf '%s\n' "$ip"; return 0; }
|
||||
done
|
||||
# RFC1918 / link-local / CGNAT -- not a directly-routable WAN address.
|
||||
is_private_ipv4() {
|
||||
case "$1" in
|
||||
10.*|192.168.*|169.254.*) return 0 ;;
|
||||
172.1[6-9].*|172.2[0-9].*|172.3[01].*) return 0 ;;
|
||||
100.6[4-9].*|100.[7-9][0-9].*|100.1[01][0-9].*|100.12[0-7].*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# First directly-held public/WAN IP, if the machine has one on an interface.
|
||||
public_ip() {
|
||||
local ip
|
||||
while IFS= read -r ip; do
|
||||
[ -n "$ip" ] || continue
|
||||
is_private_ipv4 "$ip" || { printf '%s\n' "$ip"; return 0; }
|
||||
done <<EOF
|
||||
$(list_ipv4)
|
||||
EOF
|
||||
return 1
|
||||
}
|
||||
|
||||
if is_digitalocean && do_anchor_ip; then
|
||||
exit 0
|
||||
fi
|
||||
# Fallback: the machine's primary interface IP (covers macOS and odd setups).
|
||||
print_local_ip() {
|
||||
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 } }'
|
||||
}
|
||||
|
||||
curl -s --connect-timeout 3 https://api.ipify.org 2>/dev/null \
|
||||
|| hostname -I | awk '{print $1}'
|
||||
# A directly-held public/WAN IP if the box has one, else the LAN IP.
|
||||
ip=$(public_ip || true)
|
||||
[ -z "${ip:-}" ] && ip=$(print_local_ip)
|
||||
printf '%s\n' "${ip:-}"
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Emit the tmux status-bar network segment.
|
||||
# No VPN: "⌂ <local_ip>"
|
||||
# VPN up: "⌂ <local_ip> / ⇡ <vpn_ip>"
|
||||
# Offline: "✕" (no local IP and no VPN tunnel)
|
||||
#
|
||||
|
||||
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 [ -z "${local_ip:-}" ] && [ -z "${vpn_ip:-}" ]; then
|
||||
printf '\xe2\x9c\x95 \n' # ✕ no active connection (trailing space for padding)
|
||||
elif [ -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
|
||||
Executable
+24
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+17
-4
@@ -2,7 +2,20 @@
|
||||
set -g bell-action any
|
||||
|
||||
# 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
|
||||
bind-key ^D detach-client
|
||||
@@ -66,9 +79,9 @@ 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) '
|
||||
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 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 status-right '#[bold][#[nobold,fg=colour229]#h#[fg=default] / #[fg=colour229]#(~/.local/bin/tmux-net)#[fg=default,bold]]#[nobold,fg=colour255] %-I:%M%P %d-%b-%Y '
|
||||
set -g window-status-format '#[fg=colour235,bg=colour252,nobold] #{?#{==:#{window_index},1},❶,#{?#{==:#{window_index},2},❷,#{?#{==:#{window_index},3},❸,#{?#{==:#{window_index},4},❹,#{?#{==:#{window_index},5},❺,#{?#{==:#{window_index},6},❻,#{?#{==:#{window_index},7},❼,#{?#{==:#{window_index},8},❽,#{?#{==:#{window_index},9},❾,#{?#{==:#{window_index},10},❿,#{window_index}}}}}}}}}}} #{b:pane_current_path} #W '
|
||||
set -g window-status-current-format '#[fg=colour234,bg=colour39,bold] [#[fg=colour232,bold]#{?window_zoomed_flag,#[fg=colour228],} #{?#{==:#{window_index},1},❶,#{?#{==:#{window_index},2},❷,#{?#{==:#{window_index},3},❸,#{?#{==:#{window_index},4},❹,#{?#{==:#{window_index},5},❺,#{?#{==:#{window_index},6},❻,#{?#{==:#{window_index},7},❼,#{?#{==:#{window_index},8},❽,#{?#{==:#{window_index},9},❾,#{?#{==:#{window_index},10},❿,#{window_index}}}}}}}}}}} #{b:pane_current_path} #W #[fg=colour234,bold]] '
|
||||
set-option -g status-interval 60
|
||||
|
||||
# Patch for OS X pbpaste and pbcopy under tmux.
|
||||
|
||||
@@ -102,6 +102,46 @@ On top of stock YADR:
|
||||
- Misc: `.rainbow_config.json` (rainbowstream), `.nanorc`, `.selected_editor`,
|
||||
`.mplayer/config`, `.jigdo-lite`
|
||||
|
||||
## Rainbow output (lolcat)
|
||||
|
||||
`zsh/lolcat.zsh` wires [lolcat](https://github.com/busyloop/lolcat) (Debian's
|
||||
`/usr/games/lolcat`, busyloop's Ruby build — 24-bit truecolor) into a few shell
|
||||
helpers. lolcat auto-detects a tty — it colorizes straight to the terminal but
|
||||
passes text through plain when piped onward, so use `-f`/`--force` to colorize
|
||||
mid-pipeline.
|
||||
|
||||
### Opt-in, per command
|
||||
|
||||
Prefix any command to rainbow its output:
|
||||
|
||||
```sh
|
||||
lol fastfetch
|
||||
lol git log --oneline
|
||||
lol ls -C # -C keeps columns: a piped ls otherwise goes single-column
|
||||
lolf git diff | less -R # force color so it survives down a pipeline
|
||||
```
|
||||
|
||||
### Shortcuts
|
||||
|
||||
```sh
|
||||
rcat file.txt # rainbow cat
|
||||
rls -la # rainbow ls, columns preserved
|
||||
some-cmd | rless # rainbow + pager (less -R)
|
||||
```
|
||||
|
||||
### Session toggle
|
||||
|
||||
Rainbow *all* shell stdout until you turn it off:
|
||||
|
||||
```sh
|
||||
rainbow_on # everything is rainbow now
|
||||
...
|
||||
rainbow_off # back to normal
|
||||
```
|
||||
|
||||
Novelty only: it garbles full-screen/interactive programs (vim, less, htop,
|
||||
fzf, ssh) and the prompt, and buffers streaming output. Doesn't touch stderr.
|
||||
|
||||
## Upstream
|
||||
|
||||
Base is [skwp/dotfiles][yadr] (YADR — Yet Another Dotfiles Repo). All credit
|
||||
|
||||
@@ -210,7 +210,7 @@ def install_term_theme
|
||||
message = "Which theme would you like to apply to your iTerm2 profile?"
|
||||
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")
|
||||
|
||||
@@ -220,6 +220,8 @@ def install_term_theme
|
||||
profiles << 'All'
|
||||
selected = ask message, profiles
|
||||
|
||||
return if selected.nil?
|
||||
|
||||
if selected == 'All'
|
||||
(profiles.size-1).times { |idx| apply_theme_to_iterm_profile_idx idx, color_scheme_file }
|
||||
else
|
||||
@@ -244,7 +246,12 @@ def ask(message, values)
|
||||
puts message
|
||||
while true
|
||||
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
|
||||
puts "ERROR: Invalid selection.\n\n"
|
||||
else
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
# set your user tokens as environment variables, such as ~/.secrets
|
||||
# See the README for examples.
|
||||
[user]
|
||||
name = dissimulo
|
||||
email = connect+gitea@dustin-williams.com
|
||||
[color]
|
||||
ui = true
|
||||
[color "branch"]
|
||||
@@ -126,4 +129,4 @@
|
||||
# http://gitfu.wordpress.com/2008/04/20/git-rerere-rereremember-what-you-did-last-time/
|
||||
enabled = true
|
||||
[include]
|
||||
path = .gitconfig.user
|
||||
path = ~/.gitconfig.user
|
||||
|
||||
+98
-20
@@ -30,9 +30,13 @@ PERSONAL_FILES=(
|
||||
.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=(
|
||||
.fonts .irssi .nano .themes .local .mplayer
|
||||
.fonts .irssi .nano .themes .local .mplayer .claude
|
||||
)
|
||||
|
||||
have() { command -v "$1" >/dev/null 2>&1; }
|
||||
@@ -83,37 +87,104 @@ else
|
||||
fi
|
||||
|
||||
# 3. Deploy personal dotfiles
|
||||
backup_one() {
|
||||
local src_name="$1"
|
||||
local dst="$HOME/$src_name"
|
||||
|
||||
# Move $HOME/<rel> aside into $BACKUP_DIR, preserving its sub-path.
|
||||
backup_one_path() {
|
||||
local rel="$1"
|
||||
local dst="$HOME/$rel"
|
||||
if [ -e "$dst" ] || [ -L "$dst" ]; then
|
||||
mkdir -p "$BACKUP_DIR/$(dirname "$src_name")"
|
||||
mv "$dst" "$BACKUP_DIR/$src_name"
|
||||
mkdir -p "$BACKUP_DIR/$(dirname "$rel")"
|
||||
mv "$dst" "$BACKUP_DIR/$rel"
|
||||
fi
|
||||
}
|
||||
|
||||
deploy_one() {
|
||||
local name="$1"
|
||||
local src="$YADR_DIR/$name"
|
||||
local dst="$HOME/$name"
|
||||
# Returns 0 iff $1 and $2 are equivalent (same symlink target, or identical
|
||||
# regular-file content). Used to make re-runs idempotent: unchanged files get
|
||||
# skipped instead of needlessly backed up.
|
||||
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
|
||||
return
|
||||
fi
|
||||
backup_one "$name"
|
||||
if paths_equivalent "$src" "$dst"; then
|
||||
return
|
||||
fi
|
||||
backup_one_path "$rel"
|
||||
mkdir -p "$(dirname "$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"
|
||||
for f in "${PERSONAL_FILES[@]}"; do deploy_one "$f"; done
|
||||
for d in "${PERSONAL_DIRS[@]}"; do deploy_one "$d"; done
|
||||
for f in "${PERSONAL_FILES[@]}"; do deploy_file "$f"; done
|
||||
for d in "${PERSONAL_DIRS[@]}"; do deploy_dir "$d"; done
|
||||
|
||||
# .local/bin/claude is a relative symlink to ../share/claude/versions/...
|
||||
# If that target isn't present on this machine, remove the dangling link so
|
||||
# Claude Code's own installer (next step) can manage it.
|
||||
if [ -L "$HOME/.local/bin/claude" ] && [ ! -e "$HOME/.local/bin/claude" ]; then
|
||||
rm "$HOME/.local/bin/claude"
|
||||
# .local/bin/claude is a relative symlink to ../share/claude/versions/<version>.
|
||||
# The version baked into the repo snapshot is whatever was current when this
|
||||
# was last committed; on a fresh host that exact version probably isn't
|
||||
# installed. Resolve as follows:
|
||||
# 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
|
||||
|
||||
# 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
|
||||
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
|
||||
log "Done."
|
||||
if [ -d "$BACKUP_DIR" ]; then
|
||||
|
||||
-102
@@ -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'
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../.tmux.conf
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# zsh/lolcat.zsh (drunkendotfiles) — auto-sourced via ~/.zshrc: for f in ~/.yadr/zsh/*.zsh
|
||||
# Rainbow-output helpers built on lolcat = Debian's busyloop Ruby build at
|
||||
# /usr/games/lolcat (upstream github.com/busyloop/lolcat; 24-bit truecolor).
|
||||
# It auto-detects a tty, so use -f/--force-color to colorize mid-pipeline.
|
||||
# This lolcat is truecolor and auto-detects a tty: it colorizes when writing
|
||||
# straight to the terminal, but passes text through UNcolored when piped onward,
|
||||
# so use -f/--force to colorize in the middle of a pipeline.
|
||||
|
||||
# Debian ships lolcat in /usr/games; make sure it's reachable in any shell.
|
||||
[[ ":$PATH:" == *":/usr/games:"* ]] || export PATH="$PATH:/usr/games"
|
||||
|
||||
# --- opt-in: prefix ANY command to rainbow its output on the terminal --------
|
||||
# lol ls -C lol fastfetch lol git log --oneline
|
||||
# (The wrapped command sees a pipe, not a tty, so some tools drop their own
|
||||
# colors/columns -- e.g. use `lol ls -C` to keep ls in columns.)
|
||||
lol() { "$@" | lolcat; }
|
||||
|
||||
# Same, but force color so it survives further down a pipeline:
|
||||
# lolf git diff | less -R
|
||||
lolf() { "$@" | lolcat -f; }
|
||||
|
||||
# --- handy rainbow shortcuts for plain-text output ---------------------------
|
||||
rcat() { lolcat "$@"; } # rcat file.txt (or: some-cmd | rcat)
|
||||
rls() { ls -C "$@" | lolcat; } # rainbow ls, columns preserved
|
||||
rless() { lolcat -f | less -R; } # pipe into me: some-cmd | rless
|
||||
|
||||
# --- whole-session "rainbow everything" toggle (NOVELTY) ---------------------
|
||||
# Pipes the shell's stdout through lolcat until turned off. It WILL garble
|
||||
# full-screen/interactive programs (vim, less, htop, fzf, ssh) and your prompt,
|
||||
# and buffers streaming output. Use it for a burst of plain command output,
|
||||
# then rainbow_off. Does not affect stderr.
|
||||
rainbow_on() { [[ -n $RAINBOW_PIPE ]] && return; exec 3>&1; exec > >(lolcat -f); export RAINBOW_PIPE=1; }
|
||||
rainbow_off() { [[ -z $RAINBOW_PIPE ]] && return; exec 1>&3 3>&-; unset RAINBOW_PIPE; }
|
||||
@@ -1,3 +1,4 @@
|
||||
source $HOME/.zprezto/runcoms/zshrc
|
||||
|
||||
for config_file ($HOME/.yadr/zsh/*.zsh) source $config_file
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
Reference in New Issue
Block a user