Updated dotfiles
This commit is contained in:
parent
a797c569af
commit
70e8f9a8a2
7 changed files with 277 additions and 19 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -88,3 +88,9 @@ id_*
|
||||||
rustdesk/
|
rustdesk/
|
||||||
*_scan_*.txt
|
*_scan_*.txt
|
||||||
*.m4a
|
*.m4a
|
||||||
|
|
||||||
|
# Git templates (contains private commit hooks)
|
||||||
|
git-templates/
|
||||||
|
|
||||||
|
# Taskwarrior config (contains private task data references)
|
||||||
|
task/
|
||||||
|
|
|
||||||
23
scripts/bin/rpi-flasher
Executable file
23
scripts/bin/rpi-flasher
Executable file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Script Name: rpi-flasher
|
||||||
|
# Description: Launch Raspberry Pi Imager via XWayland
|
||||||
|
# AppImage only bundles xcb (X11) plugin, needs XWayland on Wayland sessions
|
||||||
|
|
||||||
|
export DISPLAY="${DISPLAY:-:0}"
|
||||||
|
|
||||||
|
# Find XWayland auth file if XAUTHORITY isn't set
|
||||||
|
if [ -z "${XAUTHORITY:-}" ]; then
|
||||||
|
for f in /run/user/"$(id -u)"/xauth_*; do
|
||||||
|
[ -f "$f" ] && export XAUTHORITY="$f" && break
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Allow root to connect (needed when imager escalates via pkexec to write SD card)
|
||||||
|
xhost +si:localuser:root 2>/dev/null || true
|
||||||
|
|
||||||
|
# Copy xauth cookie to ~/.Xauthority so pkexec'd root process can find it
|
||||||
|
xauth extract - "$DISPLAY" 2>/dev/null | xauth -f "$HOME/.Xauthority" merge - 2>/dev/null || true
|
||||||
|
|
||||||
|
QT_QPA_PLATFORM=xcb /home/e/opt/raspberrypi/imager_2.0.6_amd64.AppImage "$@"
|
||||||
68
scripts/bin/zzz
Executable file
68
scripts/bin/zzz
Executable file
|
|
@ -0,0 +1,68 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# zzz - Sleep timer with notification
|
||||||
|
# Usage: zzz -s 5 (5 seconds)
|
||||||
|
# zzz -m 2 (2 minutes)
|
||||||
|
# zzz 30 (30 seconds, default unit)
|
||||||
|
# zzz -q -s 10 (quiet - no voice, just ding)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
QUIET=false
|
||||||
|
SECONDS_TOTAL=0
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: zzz [-s seconds] [-m minutes] [-q] [seconds]"
|
||||||
|
echo " -s SEC Sleep for SEC seconds"
|
||||||
|
echo " -m MIN Sleep for MIN minutes"
|
||||||
|
echo " -q Quiet mode (ding only, no voice)"
|
||||||
|
echo " NUM Bare number = seconds"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse args
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-s) SECONDS_TOTAL="$2"; shift 2 ;;
|
||||||
|
-m) SECONDS_TOTAL=$(( $2 * 60 )); shift 2 ;;
|
||||||
|
-q) QUIET=true; shift ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*)
|
||||||
|
if [[ "$1" =~ ^[0-9]+$ ]]; then
|
||||||
|
SECONDS_TOTAL="$1"; shift
|
||||||
|
else
|
||||||
|
echo "Unknown argument: $1" >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$SECONDS_TOTAL" -le 0 ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Display what we're doing
|
||||||
|
if [[ "$SECONDS_TOTAL" -ge 60 ]]; then
|
||||||
|
MINS=$(( SECONDS_TOTAL / 60 ))
|
||||||
|
SECS=$(( SECONDS_TOTAL % 60 ))
|
||||||
|
if [[ "$SECS" -gt 0 ]]; then
|
||||||
|
echo "💤 Sleeping ${MINS}m ${SECS}s..."
|
||||||
|
else
|
||||||
|
echo "💤 Sleeping ${MINS}m..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "💤 Sleeping ${SECONDS_TOTAL}s..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep "$SECONDS_TOTAL"
|
||||||
|
|
||||||
|
# Notification
|
||||||
|
paplay /usr/share/sounds/Oxygen-Im-New-Mail.ogg 2>/dev/null &
|
||||||
|
|
||||||
|
if [[ "$QUIET" == false ]]; then
|
||||||
|
echo "Sleep finished" | piper -m ~/.local/share/piper-voices/en_US-lessac-medium.onnx --output-raw 2>/dev/null \
|
||||||
|
| aplay -r 22050 -f S16_LE -t raw -q 2>/dev/null \
|
||||||
|
|| spd-say -w "Sleep finished" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "⏰ Done!"
|
||||||
|
|
@ -546,8 +546,10 @@ bind g display-popup -E -w 45% -h 50% -T " Prices " "bash -c '~/.local/bin/price
|
||||||
bind v display-popup -E -w 80% -h 80% -T " Vitals " "btop"
|
bind v display-popup -E -w 80% -h 80% -T " Vitals " "btop"
|
||||||
# notes (prefix + n) - opens helix scratchpad
|
# notes (prefix + n) - opens helix scratchpad
|
||||||
bind n display-popup -E -w 80% -h 80% -T " Notes " "hx ~/.claude/scratchpad/notes.md"
|
bind n display-popup -E -w 80% -h 80% -T " Notes " "hx ~/.claude/scratchpad/notes.md"
|
||||||
# docker (prefix + d)
|
# detach (prefix + d) - restore default that was accidentally overwritten
|
||||||
bind d display-popup -E -w 80% -h 80% -T " Docker " "lazydocker"
|
bind d detach-client
|
||||||
|
# docker (prefix + D) - capital D to preserve detach on lowercase d
|
||||||
|
bind D display-popup -E -w 80% -h 80% -T " Docker " "lazydocker"
|
||||||
# weather (prefix + w)
|
# weather (prefix + w)
|
||||||
bind w display-popup -E -w 60% -h 70% -T " Weather " "bash -c 'curl -s wttr.in?0; echo; echo \" Press any key...\"; read -n1'"
|
bind w display-popup -E -w 60% -h 70% -T " Weather " "bash -c 'curl -s wttr.in?0; echo; echo \" Press any key...\"; read -n1'"
|
||||||
# agenda (prefix + a) - cal.com events
|
# agenda (prefix + a) - cal.com events
|
||||||
|
|
|
||||||
88
zsh/.aliases
88
zsh/.aliases
|
|
@ -93,10 +93,14 @@ ide() {
|
||||||
# TMUX-RECON Aliases
|
# TMUX-RECON Aliases
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# Clipboard (conditional on xsel or xclip)
|
# Clipboard (Wayland-first, fallback to X11)
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
|
|
||||||
if command -v xsel &> /dev/null; then
|
if command -v wl-copy &> /dev/null && [[ -n "$WAYLAND_DISPLAY" ]]; then
|
||||||
|
# Wayland - use wl-clipboard
|
||||||
|
alias pbcopy='wl-copy'
|
||||||
|
alias pbpaste='wl-paste'
|
||||||
|
elif command -v xsel &> /dev/null; then
|
||||||
alias pbcopy='xsel --input --clipboard'
|
alias pbcopy='xsel --input --clipboard'
|
||||||
alias pbpaste='xsel --output --clipboard'
|
alias pbpaste='xsel --output --clipboard'
|
||||||
elif command -v xclip &> /dev/null; then
|
elif command -v xclip &> /dev/null; then
|
||||||
|
|
@ -119,7 +123,7 @@ cpy() {
|
||||||
cat "$1" | pbcopy
|
cat "$1" | pbcopy
|
||||||
}
|
}
|
||||||
alias d='docker'
|
alias d='docker'
|
||||||
alias dc='docker-compose'
|
alias dc='docker compose'
|
||||||
# alias h='history'
|
# alias h='history'
|
||||||
alias f='fabric'
|
alias f='fabric'
|
||||||
#f() {
|
#f() {
|
||||||
|
|
@ -130,7 +134,7 @@ alias j='journalctl -f'
|
||||||
# Note: jj is now a script in ~/scripts/ (upgraded from alias)
|
# Note: jj is now a script in ~/scripts/ (upgraded from alias)
|
||||||
# For quick clipboard pretty-print, still use: pbpaste | jq . | pbcopy
|
# For quick clipboard pretty-print, still use: pbpaste | jq . | pbcopy
|
||||||
alias jjj='pbpaste | jq .' # Quick view (no copy back)
|
alias jjj='pbpaste | jq .' # Quick view (no copy back)
|
||||||
alias k='kill $(ps aux | fzf | awk '\''{print $2}'\'')'
|
alias kill='kill $(ps aux | fzf | awk '\''{print $2}'\'')'
|
||||||
# alias k9='kill -9 **'
|
# alias k9='kill -9 **'
|
||||||
alias nano='hx'
|
alias nano='hx'
|
||||||
alias nf='fzf -m --preview="bat --color=always --style=numbers --line-range:300 {}" --bind "enter:become(hx {+})"'
|
alias nf='fzf -m --preview="bat --color=always --style=numbers --line-range:300 {}" --bind "enter:become(hx {+})"'
|
||||||
|
|
@ -149,6 +153,7 @@ elif [[ -n "$BASH_VERSION" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
alias sa='source ~/.aliases'
|
alias sa='source ~/.aliases'
|
||||||
|
alias snaabu="sudo /home/$USER/.pdtm/go/bin/naabu"
|
||||||
|
|
||||||
alias ta='tmux attach -t'
|
alias ta='tmux attach -t'
|
||||||
alias trim="awk '{\$1=\$1;print}'"
|
alias trim="awk '{\$1=\$1;print}'"
|
||||||
|
|
@ -373,6 +378,7 @@ alias gc='git commit'
|
||||||
alias gco='git checkout'
|
alias gco='git checkout'
|
||||||
alias ga='git add'
|
alias ga='git add'
|
||||||
alias gst='git rev-parse --git-dir > /dev/null 2>&1 && git status || eza'
|
alias gst='git rev-parse --git-dir > /dev/null 2>&1 && git status || eza'
|
||||||
|
alias grv='git remote -v'
|
||||||
|
|
||||||
|
|
||||||
copy-line() {
|
copy-line() {
|
||||||
|
|
@ -727,6 +733,14 @@ alias run-backup='sudo ~/.claude/context/personal/scripts/full-system-backup.sh
|
||||||
|
|
||||||
alias vpn-help='bat ~/.local/share/doc/protonvpn-automation-quickref.md 2>/dev/null || cat ~/.local/share/doc/protonvpn-automation-quickref.md'
|
alias vpn-help='bat ~/.local/share/doc/protonvpn-automation-quickref.md 2>/dev/null || cat ~/.local/share/doc/protonvpn-automation-quickref.md'
|
||||||
|
|
||||||
|
# Kill stale ProtonVPN connections (fixes zombie openvpn after Plasma partial shutdown)
|
||||||
|
vpn-kill() {
|
||||||
|
nmcli connection show --active | grep -i proton | while read -r line; do
|
||||||
|
name=$(echo "$line" | awk '{print $1" "$2}')
|
||||||
|
nmcli connection down "$name" 2>/dev/null && echo "Disconnected: $name"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# TabMan - Browser tab manager
|
# TabMan - Browser tab manager
|
||||||
alias tabman="bun ~/github/tabman/index.ts"
|
alias tabman="bun ~/github/tabman/index.ts"
|
||||||
|
|
@ -741,4 +755,68 @@ alias reddit-dl="bun /home/e/opt/redlib/reddit-dl.ts"
|
||||||
alias inotify-check='echo "Instances: $(find /proc/*/fd -lname "anon_inode:inotify" 2>/dev/null | wc -l) / $(cat /proc/sys/fs/inotify/max_user_instances)"'
|
alias inotify-check='echo "Instances: $(find /proc/*/fd -lname "anon_inode:inotify" 2>/dev/null | wc -l) / $(cat /proc/sys/fs/inotify/max_user_instances)"'
|
||||||
|
|
||||||
# SimpleX Bot - E2EE automation
|
# SimpleX Bot - E2EE automation
|
||||||
alias simplex='~/opt/simplex-bot/simplex'
|
alias sbot='~/opt/simplex-bot/simplex'
|
||||||
|
|
||||||
|
# ----------------------------
|
||||||
|
# GPG Encryption Helpers
|
||||||
|
# ----------------------------
|
||||||
|
# Simple file encryption/decryption using your default GPG key
|
||||||
|
# Usage: gpg-encrypt notes.md → creates notes.md.gpg
|
||||||
|
# gpg-decrypt notes.md.gpg → creates notes.md
|
||||||
|
|
||||||
|
gpg-encrypt() {
|
||||||
|
local file="$1"
|
||||||
|
if [[ -z "$file" ]]; then
|
||||||
|
echo "Usage: gpg-encrypt <file>" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
echo "Error: File '$file' not found" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
gpg --output "${file}.gpg" --encrypt --default-recipient-self "$file" \
|
||||||
|
&& echo "✅ Encrypted: ${file}.gpg"
|
||||||
|
}
|
||||||
|
|
||||||
|
gpg-decrypt() {
|
||||||
|
local file="$1"
|
||||||
|
if [[ -z "$file" ]]; then
|
||||||
|
echo "Usage: gpg-decrypt <file.gpg>" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
echo "Error: File '$file' not found" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
local output="${file%.gpg}"
|
||||||
|
if [[ "$output" == "$file" ]]; then
|
||||||
|
output="${file}.decrypted"
|
||||||
|
fi
|
||||||
|
gpg --decrypt "$file" > "$output" \
|
||||||
|
&& echo "✅ Decrypted: $output"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Standard Notes (AppImage in Downloads)
|
||||||
|
alias standard-notes='/home/$USER/Downloads/standard-notes-3.201.2-linux-x86_64.AppImage'
|
||||||
|
|
||||||
|
alias dailies='~/.claude/context/personal/scripts/daily-reminders.sh'
|
||||||
|
|
||||||
|
# ---- Meshtastic -----
|
||||||
|
mesh-nodes() {
|
||||||
|
for port in /dev/ttyUSB*; do
|
||||||
|
[ -e "$port" ] || continue
|
||||||
|
echo "=== $port ==="
|
||||||
|
timeout 5 meshtastic --port "$port" --info 2>&1 | grep -iE "Owner|Short Name|Role|Hardware" || echo "No Meshtastic device"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh-send() {
|
||||||
|
local port="${1:-/dev/ttyUSB0}"
|
||||||
|
shift
|
||||||
|
meshtastic --port "$port" --sendtext "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh-listen() {
|
||||||
|
local port="${1:-/dev/ttyUSB0}"
|
||||||
|
meshtastic --port "$port" --listen
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,3 +86,8 @@ export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
|
||||||
# [[ -n "$_xauth" ]] && export XAUTHORITY="$_xauth"
|
# [[ -n "$_xauth" ]] && export XAUTHORITY="$_xauth"
|
||||||
# unset _xauth
|
# unset _xauth
|
||||||
# fi
|
# fi
|
||||||
|
|
||||||
|
# Disable SSH password popups
|
||||||
|
export SSH_ASKPASS=""
|
||||||
|
export SSH_ASKPASS_REQUIRE=never
|
||||||
|
export PATH=$PATH:/opt/zeek/bin
|
||||||
|
|
|
||||||
100
zsh/.zshrc
100
zsh/.zshrc
|
|
@ -9,6 +9,12 @@ fi
|
||||||
# Don't export - each shell instance should load fresh
|
# Don't export - each shell instance should load fresh
|
||||||
ZSHRC_LOADED=1
|
ZSHRC_LOADED=1
|
||||||
|
|
||||||
|
# Import X11/Wayland display vars from systemd (for KDE Wayland)
|
||||||
|
# XAUTHORITY has a randomized filename each session, so pull from systemd
|
||||||
|
# if [ -z "$DISPLAY" ] || [ -z "$XAUTHORITY" ]; then
|
||||||
|
# eval $(systemctl --user show-environment | grep -E '^DISPLAY=|^XAUTHORITY=' 2>/dev/null)
|
||||||
|
# fi
|
||||||
|
|
||||||
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
|
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
|
||||||
# Initialization code that may require console input (password prompts, [y/n]
|
# Initialization code that may require console input (password prompts, [y/n]
|
||||||
# confirmations, etc.) must go above this block; everything else may go below.
|
# confirmations, etc.) must go above this block; everything else may go below.
|
||||||
|
|
@ -109,10 +115,10 @@ zstyle ':fzf-tab:complete:more:*' fzf-preview 'bat --color=always $realpath 2>/d
|
||||||
eval "$(zoxide init zsh)"
|
eval "$(zoxide init zsh)"
|
||||||
|
|
||||||
# Atuin setup - smart history search
|
# Atuin setup - smart history search
|
||||||
eval "$(atuin init zsh)"
|
eval "$(atuin init zsh --disable-up-arrow)"
|
||||||
|
|
||||||
# Sourcing
|
# Sourcing
|
||||||
source $HOME/.cargo/env
|
[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env"
|
||||||
[ -f ~/.aliases ] && source ~/.aliases
|
[ -f ~/.aliases ] && source ~/.aliases
|
||||||
[ -f ~/.exports ] && source ~/.exports
|
[ -f ~/.exports ] && source ~/.exports
|
||||||
# source /usr/share/doc/pkgfile/command-not-found.zsh
|
# source /usr/share/doc/pkgfile/command-not-found.zsh
|
||||||
|
|
@ -206,24 +212,94 @@ export PATH="$BUN_INSTALL/bin:$PATH"
|
||||||
# Removed redundant .local/bin addition (already in ~/.exports)
|
# Removed redundant .local/bin addition (already in ~/.exports)
|
||||||
|
|
||||||
# SSH Agent for persistent tunnel (Baserow, etc.)
|
# SSH Agent for persistent tunnel (Baserow, etc.)
|
||||||
export SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket
|
# TEMPORARILY DISABLED - Testing if this breaks session during login
|
||||||
|
# export SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket
|
||||||
|
|
||||||
# SSH keys - auto-add if agent is running but keys not loaded
|
# Reminder to add SSH key after reboot
|
||||||
# Load main key (check by fingerprint, not email - OPSEC)
|
# TEMPORARILY DISABLED - Testing if this breaks session during login
|
||||||
ssh-add -l 2>/dev/null | grep -q "Tq/46I0GfFmme7/tyb/BFhj" || {
|
# if ! ssh-add -l &>/dev/null; then
|
||||||
ssh-add ~/.ssh/id_ed25519 2>/dev/null || echo "🔑 Run: ssh-add ~/.ssh/id_ed25519"
|
# echo "🔑 Reminder: Add your Vultr SSH key for blog automation:"
|
||||||
}
|
# echo " ssh-add ~/.ssh/id_ed25519_vultr"
|
||||||
# Load additional keys from local config (not committed - contains infra-specific paths)
|
# fi
|
||||||
[[ -f ~/.ssh/autoload ]] && source ~/.ssh/autoload
|
|
||||||
|
|
||||||
# Deduplicate PATH at the end (after all PATH modifications)
|
# Deduplicate PATH at the end (after all PATH modifications)
|
||||||
export PATH=$(echo "$PATH" | tr ':' '\n' | awk '!seen[$0]++' | paste -sd:)
|
export PATH=$(echo "$PATH" | tr ':' '\n' | awk '!seen[$0]++' | paste -sd:)
|
||||||
|
|
||||||
# Make PATH available to GUI applications (Ulauncher, etc.)
|
# Make PATH available to GUI applications (Ulauncher, etc.)
|
||||||
# This ensures apps launched outside terminal sessions can find bun, custom bins, etc.
|
# This ensures apps launched outside terminal sessions can find bun, custom bins, etc.
|
||||||
systemctl --user import-environment PATH
|
# TEMPORARILY DISABLED - Testing if this breaks systemd user session during login
|
||||||
|
# systemctl --user import-environment PATH
|
||||||
|
|
||||||
[ -f ~/.env ] && source ~/.env
|
[ -f ~/.env ] && source ~/.env
|
||||||
|
|
||||||
# Port reference quick access
|
# Port reference quick access
|
||||||
alias ports='cat ~/.claude/context/infrastructure/ports-reference.md | less'
|
|
||||||
|
# VPN Switcher - alias to private script (not in git)
|
||||||
|
alias vpn-switch='/home/e/.claude/context/personal/scripts/vpn-switch'
|
||||||
|
|
||||||
|
# GPG-based SSH authentication
|
||||||
|
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
|
||||||
|
gpgconf --launch gpg-agent
|
||||||
|
|
||||||
|
# Foundry (Ethereum development toolkit)
|
||||||
|
export PATH="$HOME/.foundry/bin:$PATH"
|
||||||
|
|
||||||
|
# SSH key status check - run `ssh-keys` to see what's loaded
|
||||||
|
ssh-keys() {
|
||||||
|
local -A KEYS=(
|
||||||
|
[x1]="$HOME/.ssh/id_ed25519_x1"
|
||||||
|
[forge]="$HOME/.ssh/id_ed25519"
|
||||||
|
[contabo]="$HOME/.ssh/vps2"
|
||||||
|
[vps3]="$HOME/.ssh/id_ed25519"
|
||||||
|
)
|
||||||
|
local loaded=$(ssh-add -l 2>/dev/null)
|
||||||
|
echo "SSH Keys:"
|
||||||
|
for host in x1 forge contabo vps3; do
|
||||||
|
local keyfile="${KEYS[$host]}"
|
||||||
|
local fp=$(ssh-keygen -lf "$keyfile" 2>/dev/null | awk '{print $2}')
|
||||||
|
if echo "$loaded" | grep -q "$fp" 2>/dev/null; then
|
||||||
|
echo " $host ✓ loaded"
|
||||||
|
else
|
||||||
|
echo " $host ✗ ssh-add $keyfile"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show missing SSH keys on new shell (quiet if all loaded)
|
||||||
|
_ssh_key_check() {
|
||||||
|
local loaded=$(ssh-add -l 2>/dev/null)
|
||||||
|
local missing=()
|
||||||
|
local -A KEYS=(
|
||||||
|
[x1]="$HOME/.ssh/id_ed25519_x1"
|
||||||
|
[forge/vps3]="$HOME/.ssh/id_ed25519"
|
||||||
|
[contabo]="$HOME/.ssh/vps2"
|
||||||
|
)
|
||||||
|
for label in x1 "forge/vps3" contabo; do
|
||||||
|
local keyfile="${KEYS[$label]}"
|
||||||
|
local fp=$(ssh-keygen -lf "$keyfile" 2>/dev/null | awk '{print $2}')
|
||||||
|
if ! echo "$loaded" | grep -q "$fp" 2>/dev/null; then
|
||||||
|
missing+=("$label → ssh-add $keyfile")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if (( ${#missing[@]} > 0 )); then
|
||||||
|
echo "🔑 Missing SSH keys:"
|
||||||
|
for m in "${missing[@]}"; do
|
||||||
|
echo " $m"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
_ssh_key_check
|
||||||
|
|
||||||
|
# Post-reboot: remind to refresh security baseline
|
||||||
|
_reboot_baseline_check() {
|
||||||
|
local stamp="$HOME/.cache/.last-baseline-boot-id"
|
||||||
|
local current_boot=$(cat /proc/sys/kernel/random/boot_id 2>/dev/null)
|
||||||
|
local last_boot=$(cat "$stamp" 2>/dev/null)
|
||||||
|
if [[ "$current_boot" != "$last_boot" ]]; then
|
||||||
|
echo "🛡️ New boot detected — security baseline may be stale"
|
||||||
|
echo " Run: ~/.claude-user/scripts/upgrade-pai.sh --manifest"
|
||||||
|
mkdir -p "$(dirname "$stamp")"
|
||||||
|
echo "$current_boot" > "$stamp"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
_reboot_baseline_check
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue