3 Commits

Author SHA1 Message Date
Claude
7444f5b97b Remove pointless exports from ssh/rc, add process-model comment
ssh/rc runs as a sshd child process so exports never reach the user's
shell. SSH_REMOTE_AUTH_SOCK was set and exported but never used (a
leftover from a prior failed fix attempt). SSH_AUTH_SOCK was reassigned
to the symlink path and exported, also to no effect. Remove both.

https://claude.ai/code/session_01RhXaFzxJA5D2BcGcz18ipA
2026-04-19 02:19:05 +00:00
Claude
c5e1157f47 Fix shenv clobbering forwarded SSH socket with local agent in tmux
ssh/rc env changes (including SSH_REMOTE_AUTH_SOCK) are lost because
ssh/rc runs as a sshd child process, not the user's shell. The shell
always receives SSH_AUTH_SOCK set to the raw forwarded socket path.

Fresh SSH login worked fine (step 1 catches the raw socket). The bug
was in tmux new windows: SSH_AUTH_SOCK there is our stable symlink, so
step 1 fails, then steps 2/3 look up the system agent and overwrite the
symlink that ssh/rc just set to the forwarded socket.

Fix: only run the system agent lookup when the stable symlink is already
broken. A valid symlink means ssh/rc (or a previous shenv run) already
set it correctly; don't clobber it.

https://claude.ai/code/session_01RhXaFzxJA5D2BcGcz18ipA
2026-04-19 01:47:36 +00:00
Claude
6b50be84a9 Fix SSH agent forwarding clobbered by local agent in shenv
ssh/rc saves the raw forwarded socket in SSH_REMOTE_AUTH_SOCK before
rewriting SSH_AUTH_SOCK to the stable symlink. shenv was ignoring that
variable, so it saw SSH_AUTH_SOCK as "our link" and fell through to the
systemd lookup, which could overwrite the symlink with a local agent
socket and silently drop the forwarded one.

Now shenv checks SSH_REMOTE_AUTH_SOCK first, giving forwarded sockets
priority over any local agent.

https://claude.ai/code/session_01RhXaFzxJA5D2BcGcz18ipA
2026-04-19 01:43:12 +00:00
62 changed files with 406 additions and 1713 deletions

View File

@@ -1,7 +1,5 @@
tap "dart-lang/dart", trusted: true tap "dart-lang/dart"
tap "espressif/eim" tap "sass/sass"
tap "holtwick/tap", trusted: true
tap "sass/sass", trusted: true
brew "ack" brew "ack"
brew "acme.sh" brew "acme.sh"
@@ -10,50 +8,37 @@ brew "autoconf"
brew "automake" brew "automake"
brew "b2-tools" brew "b2-tools"
brew "bat" brew "bat"
brew "bazelisk"
brew "binwalk" brew "binwalk"
brew "cask" brew "cask"
brew "ccache" brew "ccache"
brew "certbot" brew "certbot"
brew "cloudflared"
brew "cmake" brew "cmake"
brew "colima" brew "colima"
brew "devcontainer" brew "devcontainer"
brew "dfu-util" brew "dfu-util"
brew "difftastic" brew "difftastic"
brew "direnv" brew "direnv"
brew "dua-cli"
brew "duck" brew "duck"
brew "dust" brew "earthly"
brew "espressif/eim/eim", trusted: true
brew "esptool" brew "esptool"
brew "fish"
brew "fq"
brew "gh" brew "gh"
brew "ghidra", link: false brew "ghidra", link: false
brew "git" brew "git"
brew "git-delta" brew "git-delta"
brew "git-lfs" brew "git-lfs"
brew "git-xet"
brew "glib"
brew "gnupg" brew "gnupg"
brew "go" brew "go"
brew "gradle" brew "gradle"
brew "hashcat"
brew "hf" brew "hf"
brew "holtwick/tap/bx", trusted: true
brew "htop" brew "htop"
brew "httpie" brew "httpie"
brew "huggingface-cli"
brew "hugo" brew "hugo"
brew "imagemagick" brew "imagemagick"
brew "john-jumbo" brew "john-jumbo"
brew "jq" brew "jq"
brew "kubeconform"
brew "kubectx"
brew "libgcrypt"
brew "librsvg"
brew "libslirp"
brew "lima" brew "lima"
brew "minikube"
brew "mise" brew "mise"
brew "mosh" brew "mosh"
brew "neovim" brew "neovim"
@@ -63,27 +48,22 @@ brew "ollama"
brew "p7zip" brew "p7zip"
brew "pipenv" brew "pipenv"
brew "pipx" brew "pipx"
brew "pixman"
brew "pkgconf" brew "pkgconf"
brew "protobuf" brew "protobuf"
brew "pwgen" brew "pwgen"
brew "pwntools" brew "pwntools"
brew "python@3.13"
brew "python@3.14"
brew "qemu" brew "qemu"
brew "restic" brew "restic"
brew "ripgrep" brew "ripgrep"
brew "ruby", link: false brew "ruby"
brew "ruby@3.3" brew "ruby@3.3"
brew "rustup" brew "rustup"
brew "sass/sass/migrator" brew "sass/sass/migrator"
brew "sass/sass/sass" brew "sass/sass/sass"
brew "sdl2-compat"
brew "shellcheck" brew "shellcheck"
brew "smartmontools" brew "smartmontools"
brew "starship" brew "starship"
brew "tmux" brew "tmux"
brew "todoist-cli"
brew "uv" brew "uv"
brew "virtualenvwrapper" brew "virtualenvwrapper"
brew "wget" brew "wget"
@@ -112,7 +92,7 @@ cask "raycast"
cask "rectangle" cask "rectangle"
cask "scroll-reverser" cask "scroll-reverser"
cask "temurin" cask "temurin"
cask "wezterm" cask "veracrypt"
cask "zulu@17" cask "zulu@17"
def is_corp? def is_corp?
@@ -120,23 +100,13 @@ def is_corp?
`profiles status -type enrollment 2>/dev/null`.include?("Enrolled via DEP: Yes") `profiles status -type enrollment 2>/dev/null`.include?("Enrolled via DEP: Yes")
end end
if is_corp?
brew "bazelisk", link: false
end
# non-corp # non-corp
if !is_corp? if !is_corp?
brew "bazelisk" brew "bazel"
brew "openssh" brew "openssh"
brew "virt-manager"
cask "claude-code" cask "claude-code"
cask "codex"
cask "cryptomator" cask "cryptomator"
cask "keepassxc"
cask "gcloud-cli" cask "gcloud-cli"
cask "keybase" cask "google-cloud-sdk"
cask "orbstack" cask "orbstack"
cask "jordanbaird-ice@beta"
cask "veracrypt"
end end

View File

@@ -1 +0,0 @@
AGENTS.md

View File

@@ -4,12 +4,7 @@ set -ueo pipefail
shopt -s extglob shopt -s extglob
# get libraries # get libraries
if [[ -f "${HOME}/.local/lib/bash/tui.sh" ]]; then . ${HOME}/.local/lib/bash/tui.sh
. "${HOME}/.local/lib/bash/tui.sh"
else
echo "Error: ${HOME}/.local/lib/bash/tui.sh not found!" >&2
exit 1
fi
COMMANDS=( COMMANDS=(
gctx gctx
@@ -48,7 +43,7 @@ _gctx_choose() {
--format='value(is_active, name, format("{} (as {})", properties.core.project, properties.core.account))') --format='value(is_active, name, format("{} (as {})", properties.core.project, properties.core.account))')
local choice local choice
if choice=$(printf "%-${maxnamelen}s %s\n" "${lines[@]}" | select_entry "gcloud config" "$default") ; then if choice=$(printf "%-${maxnamelen}s %s\n" "${lines[@]}" | select_entry "gcloud config" "$default") ; then
_gctx_set "$(echo "${choice}" | awk '{print $1}')" _gctx_set "${choice}"
else else
echo "No option selected, leaving unchanged." echo "No option selected, leaving unchanged."
fi fi
@@ -73,7 +68,7 @@ _gctx_clone() {
local oldconfig=() local oldconfig=()
local line local line
while IFS= read -r line ; do while IFS= read -r line ; do
oldconfig+=("$line") old_config+=("$line")
done < <(gcloud config configurations describe "$(_gctx_name)" --format='multi(properties:format="flattened[separator=\" \"]")') done < <(gcloud config configurations describe "$(_gctx_name)" --format='multi(properties:format="flattened[separator=\" \"]")')
# create new # create new

View File

@@ -1,22 +1,8 @@
#!/bin/sh #!/bin/sh
set -o nounset env > ${TMPDIR}/env-pre
. ${HOME}/.shenv
TMP_DIR="${TMPDIR:-/tmp}" env > ${TMPDIR}/env-post
TMP_DIR="${TMP_DIR%/}" for VAR in $(env | cut -d'=' -f1) ; do
/bin/launchctl setenv "${VAR}" "$(eval echo \$${VAR})"
env > "${TMP_DIR}/env-pre" 2>/dev/null || true
if [ -f "${HOME}/.shenv" ]; then
. "${HOME}/.shenv"
fi
env > "${TMP_DIR}/env-post" 2>/dev/null || true
if [ -x "/bin/launchctl" ]; then
for VAR in $(env | awk -F= '/^[a-zA-Z_][a-zA-Z0-9_]*=/ {print $1}') ; do
case "${VAR}" in
_|""|*[!a-zA-Z0-9_]*|[0-9]*) continue ;;
esac
eval "val=\${${VAR}:-}"
/bin/launchctl setenv "${VAR}" "${val}"
done done
fi

View File

@@ -12,17 +12,8 @@ fi
trap "test -f ${FILENAME} && rm -f ${FILENAME}" EXIT trap "test -f ${FILENAME} && rm -f ${FILENAME}" EXIT
IOENGINE="libaio"
DIRECT=1
if [ "$(uname)" = "Darwin" ]; then
IOENGINE="posixaio"
# macOS doesn't support O_DIRECT in the same way, but fio's direct=1
# handles it via F_NOCACHE if supported.
DIRECT=1
fi
fio --loops=5 --size=${BENCHMARK_SIZE} --filename=${FILENAME} \ fio --loops=5 --size=${BENCHMARK_SIZE} --filename=${FILENAME} \
--stonewall --ioengine=${IOENGINE} --direct=${DIRECT} \ --stonewall --ioengine=libaio --direct=1 \
--name=Seqread --bs=1m --rw=read \ --name=Seqread --bs=1m --rw=read \
--name=Seqwrite --bs=1m --rw=write \ --name=Seqwrite --bs=1m --rw=write \
--name=512Kread --bs=512k --rw=randread \ --name=512Kread --bs=512k --rw=randread \

View File

@@ -47,7 +47,7 @@ shift $((OPTIND - 1)) # Remove the parsed options
# --- Set target directory --- # --- Set target directory ---
# Use the first remaining argument as the target directory. # Use the first remaining argument as the target directory.
if [ "$#" -gt 0 ]; then if [ -n "$1" ]; then
TARGET_DIR="$1" TARGET_DIR="$1"
fi fi
@@ -75,7 +75,7 @@ find "${TARGET_DIR}" -type l ! -exec test -e {} \; -print0 | while IFS= read -r
continue continue
fi fi
# Ask the user for confirmation. # Ask the user for confirmation.
read -p "Remove broken symlink '${link}'? [y/N] " -n 1 -r < /dev/tty read -p "Remove broken symlink '${link}'? [y/N] " -n 1 -r
echo # Move to a new line after input. echo # Move to a new line after input.
if [[ $REPLY =~ ^[Yy]$ ]]; then if [[ $REPLY =~ ^[Yy]$ ]]; then

View File

@@ -1,10 +1,6 @@
#!/bin/bash #!/bin/bash
CHROME_BINS="google-chrome-beta google-chrome" CHROME_BINS="google-chrome-beta google-chrome"
if [ "$(uname)" = "Darwin" ]; then
CHROME_BINS="${CHROME_BINS} /Applications/Google\ Chrome\ Beta.app/Contents/MacOS/Google\ Chrome\ Beta /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
fi
for bin in ${CHROME_BINS} ; do for bin in ${CHROME_BINS} ; do
if command -v ${bin} >/dev/null 2>&1 ; then if command -v ${bin} >/dev/null 2>&1 ; then
CHROME=$(command -v ${bin}) CHROME=$(command -v ${bin})
@@ -22,4 +18,4 @@ export HOME=${HOME}/.chrome-pentest
mkdir -p ${HOME} mkdir -p ${HOME}
# Launch chrome for burp # Launch chrome for burp
exec "${CHROME}" --user-data-dir=${HOME}/chrome-pentest --proxy-server=127.0.0.1:8080 exec ${CHROME} --user-data-dir=${HOME}/chrome-pentest --proxy-server=127.0.0.1:8080

View File

@@ -3,7 +3,7 @@
# Installs Ansible, trying user-space methods first before falling back to sudo. # Installs Ansible, trying user-space methods first before falling back to sudo.
# This script is designed to be idempotent and safe to run multiple times. # This script is designed to be idempotent and safe to run multiple times.
set -euo pipefail # Exit immediately if a command exits with a non-zero status, undefined variable, or pipe failure. set -e # Exit immediately if a command exits with a non-zero status.
# --- Helper Functions --- # --- Helper Functions ---
info() { echo "[INFO] $1"; } info() { echo "[INFO] $1"; }
@@ -44,8 +44,8 @@ fi
# Try Python's venv module if pipx failed or wasn't present # Try Python's venv module if pipx failed or wasn't present
VENV_PATH="${HOME}/.local/share/ansible_venv" VENV_PATH="${HOME}/.local/share/ansible_venv"
# Create a temp path securely to avoid clobbering a failed install # Create a temp path to avoid clobbering a failed install
VENV_TEST_PATH="$(mktemp -d "${TMPDIR:-/tmp}/ansible_venv_test.XXXXXX")" VENV_TEST_PATH="/tmp/ansible_venv_test_$$"
if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then
rm -rf "${VENV_TEST_PATH}" # Clean up test rm -rf "${VENV_TEST_PATH}" # Clean up test
info "Python's venv module is available. Creating a virtual environment at ${VENV_PATH}..." info "Python's venv module is available. Creating a virtual environment at ${VENV_PATH}..."
@@ -55,7 +55,7 @@ if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then
info "Ansible installed successfully into a virtual environment." info "Ansible installed successfully into a virtual environment."
info "To use it, run: '${VENV_PATH}/bin/ansible'" info "To use it, run: '${VENV_PATH}/bin/ansible'"
info "To make it available everywhere, add its bin directory to your PATH:" info "To make it available everywhere, add its bin directory to your PATH:"
info " echo 'export PATH=\"${VENV_PATH}/bin:\$PATH\"' >> ~/.profile" info " echo 'export PATH="${VENV_PATH}/bin:$PATH"' >> ~/.profile"
info "(You may need to source ~/.profile or restart your shell)." info "(You may need to source ~/.profile or restart your shell)."
exit 0 exit 0
else else
@@ -63,7 +63,6 @@ if python3 -m venv "${VENV_TEST_PATH}" >/dev/null 2>&1; then
rm -rf "${VENV_PATH}" # Clean up failed attempt rm -rf "${VENV_PATH}" # Clean up failed attempt
fi fi
else else
rm -rf "${VENV_TEST_PATH}" # Clean up test after failure
info "Python's venv module not available or failed to create a test environment." info "Python's venv module not available or failed to create a test environment."
fi fi

View File

@@ -1,11 +1,9 @@
#!/bin/bash #!/bin/bash
set -ueo pipefail set -ue
SYS_TMPDIR="${TMPDIR:-/tmp}" TMPDIR=$(mktemp -d)
TMPDIR="$(mktemp -d "${SYS_TMPDIR%/}/install_tool.XXXXXX")"
trap 'rm -rf -- "${TMPDIR}"' EXIT trap 'rm -rf -- "${TMPDIR}"' EXIT
export -n TMPDIR 2>/dev/null || true
REINSTALL=0 REINSTALL=0
PACKAGES=1 PACKAGES=1
@@ -40,7 +38,7 @@ shift $((OPTIND-1))
function list_tools { function list_tools {
echo "Options:" >/dev/stderr echo "Options:" >/dev/stderr
awk 'BEGIN {s=0;FS=")"};/main tool selection/{s=1};/^\s+[a-zA-Z0-9_.-]+)$/{if(s==1){print $1}}' "$0" | sort | while read -r opt; do awk 'BEGIN {s=0;FS=")"};/main tool selection/{s=1};/^\s+\w+)$/{if(s==1){print $1}}' "$0" | sort | while read -r opt; do
echo -e "\\t${opt}" >/dev/stderr echo -e "\\t${opt}" >/dev/stderr
done done
} }
@@ -126,13 +124,11 @@ function get_latest_github_release_url {
local repo="$1" local repo="$1"
local glob="$2" local glob="$2"
curl -s "https://api.github.com/repos/${repo}/releases/latest" | \ curl -s "https://api.github.com/repos/${repo}/releases/latest" | \
jq -r --arg rx "${glob}" '.assets[] | select(.name | test($rx)) | .browser_download_url' jq -r ".assets[] | select(.name|test(\"${glob}\")) | .browser_download_url"
} }
function require { function require_pipx {
local cmd="${1}" command -v pipx >/dev/null 2>&1 || die "Requires pipx"
local msg="${2:-Requires ${cmd}}"
command -v "${cmd}" >/dev/null 2>&1 || die "${msg}"
} }
# Begin main tool selection # Begin main tool selection
@@ -292,7 +288,10 @@ case ${TOOL} in
git clone "${src}" "${DESTDIR}" git clone "${src}" "${DESTDIR}"
;; ;;
pwndbg) pwndbg)
require gdb "No gdb available!" if ! command -v gdb > /dev/null 2>&1 ; then
echo 'No gdb available!' >/dev/stderr
exit 1
fi
git clone --depth 1 -b stable https://github.com/pwndbg/pwndbg.git "${DESTDIR}" git clone --depth 1 -b stable https://github.com/pwndbg/pwndbg.git "${DESTDIR}"
PY_PACKAGES=${DESTDIR}/vendor PY_PACKAGES=${DESTDIR}/vendor
mkdir -p "${PY_PACKAGES}" mkdir -p "${PY_PACKAGES}"
@@ -312,7 +311,10 @@ case ${TOOL} in
;; ;;
gef) gef)
makedest_or_die makedest_or_die
require gdb "No gdb available!" if ! command -v gdb > /dev/null 2>&1 ; then
echo 'No gdb available!' >/dev/stderr
exit 1
fi
download \ download \
https://github.com/hugsy/gef/raw/master/gef.py \ https://github.com/hugsy/gef/raw/master/gef.py \
"${DESTDIR}/gef.py" "${DESTDIR}/gef.py"
@@ -439,19 +441,25 @@ EOF
add_bin_symlink docker-compose add_bin_symlink docker-compose
;; ;;
tldr) tldr)
require pipx require_pipx
pipx install tldr pipx install tldr
;; ;;
blint) blint)
require pipx require_pipx
pipx install blint pipx install blint
;; ;;
dust) dust)
require cargo "This needs cargo (for rust)!" if ! command -v cargo >/dev/null 2>&1 ; then
echo "This needs cargo (for rust)!" >/dev/stderr
exit 1
fi
cargo install du-dust cargo install du-dust
;; ;;
bottom) bottom)
require cargo "This needs cargo (for rust)!" if ! command -v cargo >/dev/null 2>&1 ; then
echo "This needs cargo (for rust)!" >/dev/stderr
exit 1
fi
cargo install bottom cargo install bottom
;; ;;
delta) delta)
@@ -468,8 +476,7 @@ EOF
ropper) ropper)
deb_only deb_only
install_pkgs python3-z3 install_pkgs python3-z3
require pipx pip3 install --user pyvex ropper
pipx install ropper
;; ;;
kubeconform) kubeconform)
go install github.com/yannh/kubeconform/cmd/kubeconform@latest go install github.com/yannh/kubeconform/cmd/kubeconform@latest
@@ -520,11 +527,14 @@ EOF
sh "${rustup_init}" --no-modify-path -y sh "${rustup_init}" --no-modify-path -y
;; ;;
igrep) igrep)
require cargo "This needs cargo (for rust)!" if ! command -v cargo >/dev/null 2>&1 ; then
echo "This needs cargo (for rust)!" >/dev/stderr
exit 1
fi
cargo install igrep cargo install igrep
;; ;;
unblob) unblob)
require pipx require_pipx
pipx install unblob pipx install unblob
;; ;;
fq) fq)
@@ -545,37 +555,6 @@ EOF
fi fi
fi fi
;; ;;
speckit)
require uv
latest_version=$(curl -s "https://api.github.com/repos/github/spec-kit/releases/latest" | jq -r '.tag_name')
if [ -z "${latest_version}" ] || [ "${latest_version}" = "null" ]; then
die "Failed to determine latest release version for speckit."
fi
uv tool install specify-cli --from "git+https://github.com/github/spec-kit.git@${latest_version}"
;;
ssh-agent-mux)
makedest_or_die
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$(uname -m)" in
x86_64|amd64)
arch="amd64"
;;
aarch64|arm64)
arch="arm64"
;;
*)
die "Unsupported architecture: $(uname -m)"
;;
esac
tar_url=$(get_latest_github_release_url "overhacked/ssh-agent-mux" ".*${os}-${arch}\\.tar\\.gz$")
if [ -z "${tar_url}" ]; then
die "Could not find ssh-agent-mux release for ${os}-${arch}"
fi
download "${tar_url}" "${TMPDIR}/ssh-agent-mux.tar.gz"
tar zxf "${TMPDIR}/ssh-agent-mux.tar.gz" --strip-components=1 -C "${DESTDIR}"
chmod +x "${DESTDIR}/ssh-agent-mux"
add_bin_symlink ssh-agent-mux
;;
*) *)
echo "Unknown tool: ${TOOL}" >/dev/stderr echo "Unknown tool: ${TOOL}" >/dev/stderr
list_tools list_tools

View File

@@ -251,13 +251,7 @@ def main(args):
if last_type and e.pkg_type != last_type: if last_type and e.pkg_type != last_type:
output_lines.append("") output_lines.append("")
last_type = e.pkg_type last_type = e.pkg_type
output_lines.extend(e.to_lines())
lines = e.to_lines()
# If we just added a blank line, and the new lines start with one, skip the first new line
if output_lines and output_lines[-1] == "" and lines and lines[0] == "":
output_lines.extend(lines[1:])
else:
output_lines.extend(lines)
new_content = "\n".join(output_lines) new_content = "\n".join(output_lines)
if footer: if footer:

View File

@@ -1,213 +0,0 @@
#!/usr/bin/env bash
# Exit on error, undefined variables, and pipe failures
set -euo pipefail
show_help() {
cat << EOF
Usage: $(basename "$0") [options] <note_name_or_path>
Create a new note in your Obsidian vault.
Options:
-v, --vault <dir> Specify the Obsidian vault directory.
--overwrite Overwrite the file if it already exists.
-h, --help Show this help message.
EOF
}
VAULT_DIR=""
OVERWRITE="false"
NOTE_PATH=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-v|--vault)
if [[ -z "${2:-}" ]]; then
echo "Error: --vault requires a directory path." >&2
exit 1
fi
VAULT_DIR="$2"
shift 2
;;
--overwrite)
OVERWRITE="true"
shift
;;
-h|--help)
show_help
exit 0
;;
-*)
echo "Error: Unknown option: $1" >&2
show_help
exit 1
;;
*)
if [[ -n "$NOTE_PATH" ]]; then
echo "Error: Multiple note paths provided: $NOTE_PATH and $1" >&2
exit 1
fi
NOTE_PATH="$1"
shift
;;
esac
done
if [[ -z "$NOTE_PATH" ]]; then
echo "Error: Missing note path/name." >&2
show_help
exit 1
fi
# 1. Find the Obsidian vault.
if [[ -n "$VAULT_DIR" ]]; then
# -v/--vault was passed. Check that the directory exists and contains a .obsidian directory.
if [[ ! -d "$VAULT_DIR" ]]; then
echo "Error: Specified vault directory does not exist: $VAULT_DIR" >&2
exit 1
fi
if [[ ! -d "$VAULT_DIR/.obsidian" ]]; then
echo "Error: Specified directory is not an Obsidian vault (missing .obsidian): $VAULT_DIR" >&2
exit 1
fi
VAULT_DIR="$(cd "$VAULT_DIR" && pwd)"
else
# Search directories upward for a parent (or current) directory containing a .obsidian subdirectory.
# Stop at the user's home directory or a filesystem boundary.
CURRENT_DIR="$PWD"
FOUND_VAULT=""
get_device_id() {
local dir="$1"
if [[ "$(uname)" == "Darwin" ]]; then
stat -f '%d' "$dir" 2>/dev/null || echo ""
else
stat -c '%d' "$dir" 2>/dev/null || echo ""
fi
}
CURRENT_DEV="$(get_device_id "$CURRENT_DIR")"
while [[ "$CURRENT_DIR" != "/" && "$CURRENT_DIR" != "$HOME" ]]; do
if [[ -d "$CURRENT_DIR/.obsidian" ]]; then
FOUND_VAULT="$CURRENT_DIR"
break
fi
PARENT_DIR="$(dirname "$CURRENT_DIR")"
if [[ "$PARENT_DIR" == "$CURRENT_DIR" ]]; then
break
fi
# Check filesystem boundary
PARENT_DEV="$(get_device_id "$PARENT_DIR")"
if [[ -n "$CURRENT_DEV" && -n "$PARENT_DEV" && "$CURRENT_DEV" != "$PARENT_DEV" ]]; then
break
fi
CURRENT_DIR="$PARENT_DIR"
CURRENT_DEV="$PARENT_DEV"
done
# Check the last checked directory (could be HOME or /)
if [[ -z "$FOUND_VAULT" && -d "$CURRENT_DIR/.obsidian" ]]; then
FOUND_VAULT="$CURRENT_DIR"
fi
if [[ -n "$FOUND_VAULT" ]]; then
VAULT_DIR="$FOUND_VAULT"
else
# Fallback paths in order: ~/Notes, ~/Obsidian/Notes, ~/Personal/Notes, ~/Projects/Notes.
FALLBACKS=(
"$HOME/Notes"
"$HOME/notes"
"$HOME/Obsidian/Notes"
"$HOME/Obsidian/notes"
"$HOME/Personal/Notes"
"$HOME/Personal/notes"
"$HOME/Projects/Notes"
"$HOME/Projects/notes"
)
for path in "${FALLBACKS[@]}"; do
if [[ -d "$path" && -d "$path/.obsidian" ]]; then
VAULT_DIR="$(cd "$path" && pwd)"
break
fi
done
fi
fi
if [[ -z "$VAULT_DIR" ]]; then
echo "Error: Could not find an Obsidian vault. Please specify one with -v/--vault." >&2
exit 1
fi
# Strip leading slash from NOTE_PATH to handle relative paths properly
NOTE_PATH="${NOTE_PATH#/}"
# 2. Determine if current working directory is within the vault.
# Resolve physical paths to handle symlinks cleanly.
RESOLVED_PWD="$(pwd -P)"
RESOLVED_VAULT="$(cd "$VAULT_DIR" && pwd -P)"
if [[ "$RESOLVED_PWD" == "$RESOLVED_VAULT" || "$RESOLVED_PWD" == "$RESOLVED_VAULT"/* ]]; then
# Within the vault, treat relative to CWD
TARGET_FILE="$PWD/$NOTE_PATH"
else
# Not within the vault, treat relative to vault root
TARGET_FILE="$VAULT_DIR/$NOTE_PATH"
fi
TARGET_DIR="$(dirname "$TARGET_FILE")"
TARGET_BASE="$(basename "$TARGET_FILE")"
# If there's no file extension on the argument, add .md.
if [[ "$TARGET_BASE" != *.* ]]; then
TARGET_BASE="$TARGET_BASE.md"
fi
TARGET_FILE="$TARGET_DIR/$TARGET_BASE"
# If the necessary directory components don't exist, create them.
if [[ ! -d "$TARGET_DIR" ]]; then
mkdir -p "$TARGET_DIR"
fi
# 3. If the file exists and there's no --overwrite argument, throw an error.
if [[ -f "$TARGET_FILE" && "$OVERWRITE" != "true" ]]; then
echo "Error: File already exists: $TARGET_FILE (use --overwrite to replace it)" >&2
exit 1
fi
# 4. If the path ends in .md (case-insensitive), generate appropriate YAML front matter and write it to the new file.
if [[ "$TARGET_BASE" =~ \.[mM][dD]$ ]]; then
NOTE_TITLE="${TARGET_BASE%.*}"
NOTE_TITLE_ESCAPED="${NOTE_TITLE//\"/\\\"}"
CURRENT_DATE="$(date +"%Y-%m-%d %H:%M")"
cat << EOF > "$TARGET_FILE"
---
title: "$NOTE_TITLE_ESCAPED"
date: $CURRENT_DATE
tags: []
---
EOF
else
# Just touch the file to ensure it exists
touch "$TARGET_FILE"
fi
# 5. Open the user's $EDITOR (falling back to vim/vi if unset) pointing to the new file.
EDITOR="${EDITOR:-}"
if [[ -z "$EDITOR" ]]; then
if command -v vim >/dev/null 2>&1; then
EDITOR="vim"
else
EDITOR="vi"
fi
fi
exec "$EDITOR" "$TARGET_FILE"

View File

@@ -1,63 +0,0 @@
#!/bin/bash
set -euo pipefail
# QUARTZ_DIR search logic
if [ -z "${QUARTZ_DIR:-}" ]; then
if [ -f "quartz.config.ts" ]; then
QUARTZ_DIR="$PWD"
elif [ -d "$HOME/Personal/notes-quartz" ]; then
QUARTZ_DIR="$HOME/Personal/notes-quartz"
elif [ -d "$HOME/Projects/notes-quartz" ]; then
QUARTZ_DIR="$HOME/Projects/notes-quartz"
else
echo "Error: QUARTZ_DIR could not be found." >&2
exit 1
fi
fi
if [ ! -d "$QUARTZ_DIR" ]; then
echo "Error: QUARTZ_DIR '$QUARTZ_DIR' is not a directory." >&2
exit 1
fi
# NOTES_DIR search logic
PARSE_NOTES_DIR=""
# Use a copy of args to find -d/--directory
ARGS=("$@")
for ((i=0; i<${#ARGS[@]}; i++)); do
if [[ "${ARGS[i]}" == "-d" || "${ARGS[i]}" == "--directory" ]]; then
if [[ $((i+1)) -lt ${#ARGS[@]} ]]; then
PARSE_NOTES_DIR="${ARGS[i+1]}"
fi
break
fi
done
if [ -n "$PARSE_NOTES_DIR" ]; then
NOTES_DIR="$PARSE_NOTES_DIR"
elif [ -z "${NOTES_DIR:-}" ]; then
if [ -d "$HOME/Notes" ]; then
NOTES_DIR="$HOME/Notes"
elif [ -d "$HOME/Personal/notes" ]; then
NOTES_DIR="$HOME/Personal/notes"
elif [ -d "$HOME/Projects/notes" ]; then
NOTES_DIR="$HOME/Projects/notes"
else
echo "Error: NOTES_DIR could not be found." >&2
exit 1
fi
fi
if [ ! -d "$NOTES_DIR" ]; then
echo "Error: NOTES_DIR '$NOTES_DIR' is not a directory." >&2
exit 1
fi
cd "$QUARTZ_DIR"
# Run npx quartz
# Following the prompt's structure but using NOTES_DIR for the flag
# npx quartz ${argv[1]} --directory ${NOTES_DIR} "$@"
# We use ${1:-} for argv[1] to handle cases with no arguments.
npx quartz "${1:-}" --directory "$NOTES_DIR" "$@"

View File

@@ -18,7 +18,7 @@ HOST_SPECIFIC_SCRIPT="${RESTIC_SCRIPTS_DIR}/${HOSTNAME}"
# Check if the script exists and is executable # Check if the script exists and is executable
if [[ -f "${HOST_SPECIFIC_SCRIPT}" && -x "${HOST_SPECIFIC_SCRIPT}" ]]; then if [[ -f "${HOST_SPECIFIC_SCRIPT}" && -x "${HOST_SPECIFIC_SCRIPT}" ]]; then
echo "Executing restic script for hostname: ${HOSTNAME}" echo "Executing restic script for hostname: ${HOSTNAME}"
"${HOST_SPECIFIC_SCRIPT}" "$@" "${HOST_SPECIFIC_SCRIPT}"
else else
echo "Error: No executable restic script found for hostname '${HOSTNAME}' at '${HOST_SPECIFIC_SCRIPT}'." >&2 echo "Error: No executable restic script found for hostname '${HOSTNAME}' at '${HOST_SPECIFIC_SCRIPT}'." >&2
echo "Please create an executable script at that path if you want to use this functionality." >&2 echo "Please create an executable script at that path if you want to use this functionality." >&2

View File

@@ -12,8 +12,8 @@ set -o pipefail
# For this script, we assume the user's home directory. # For this script, we assume the user's home directory.
SOURCE_DIR="${HOME}" SOURCE_DIR="${HOME}"
# Exclude file location. # Exclude file location. We'll create a default one next to the script.
EXCLUDE_FILE="${HOME}/.restic_exclude.darwin" EXCLUDE_FILE="$HOME/.restic_exclude.darwin"
# --- Functions --- # --- Functions ---
usage() { usage() {
@@ -34,7 +34,7 @@ EOF
# --- Main Script --- # --- Main Script ---
# Check if restic is installed # Check if restic is installed
if ! command -v restic >/dev/null 2>&1; then if ! command -v restic &> /dev/null; then
echo "Error: restic command not found." >&2 echo "Error: restic command not found." >&2
echo "Please install restic first: https://restic.net/" >&2 echo "Please install restic first: https://restic.net/" >&2
exit 1 exit 1
@@ -57,7 +57,7 @@ while getopts ":l:bu:h" opt; do
;; ;;
b) b)
BACKUP_MODE="b2" BACKUP_MODE="b2"
if [[ ${OPTIND} -le $# && "${!OPTIND:-}" != -* ]]; then if [[ ${OPTIND} -le $# && "${!OPTIND}" != -* ]]; then
REPO="b2:${!OPTIND}:" REPO="b2:${!OPTIND}:"
OPTIND=$((OPTIND + 1)) OPTIND=$((OPTIND + 1))
fi fi
@@ -91,19 +91,18 @@ fi
if [[ "${BACKUP_MODE}" == "b2" ]]; then if [[ "${BACKUP_MODE}" == "b2" ]]; then
if [[ -f "${HOME}/.resticb2" ]] ; then if [[ -f "${HOME}/.resticb2" ]] ; then
# shellcheck disable=SC1090
. "${HOME}/.resticb2" . "${HOME}/.resticb2"
fi fi
export B2_ACCOUNT_ID="${B2_ACCOUNT_ID:-}" export B2_ACCOUNT_ID
export B2_ACCOUNT_KEY="${B2_ACCOUNT_KEY:-}" export B2_ACCOUNT_KEY
export B2_BUCKET_NAME="${B2_BUCKET_NAME:-}" export B2_BUCKET_NAME
if [[ -z "${B2_ACCOUNT_ID}" || -z "${B2_ACCOUNT_KEY}" ]]; then if [[ -z "${B2_ACCOUNT_ID:-}" || -z "${B2_ACCOUNT_KEY:-}" ]]; then
echo "Error: For Backblaze B2 backups, you must set the B2_ACCOUNT_ID and B2_ACCOUNT_KEY environment variables." >&2 echo "Error: For Backblaze B2 backups, you must set the B2_ACCOUNT_ID and B2_ACCOUNT_KEY environment variables." >&2
exit 1 exit 1
fi fi
if [[ -z "${REPO}" ]]; then if [[ -z "${REPO:-}" ]]; then
if [[ -n "${B2_BUCKET_NAME}" ]]; then if [[ -n "${B2_BUCKET_NAME:-}" ]]; then
REPO="b2:${B2_BUCKET_NAME}:" REPO="b2:${B2_BUCKET_NAME}:"
else else
echo "Error: Backup mode is B2 but no bucket name was provided and the B2_BUCKET_NAME environment variable is not set." >&2 echo "Error: Backup mode is B2 but no bucket name was provided and the B2_BUCKET_NAME environment variable is not set." >&2
@@ -114,56 +113,41 @@ if [[ "${BACKUP_MODE}" == "b2" ]]; then
fi fi
KEYCHAIN_ENTRY_NAME="restic_repo_password" KEYCHAIN_ENTRY_NAME="restic_repo_password"
local_user="$(id -un 2>/dev/null || whoami)" if security find-generic-password -a "$(whoami)" -s "${KEYCHAIN_ENTRY_NAME}" >/dev/null 2>&1 ; then
if security find-generic-password -a "${local_user}" -s "${KEYCHAIN_ENTRY_NAME}" >/dev/null 2>&1 ; then export RESTIC_PASSWORD_COMMAND="security find-generic-password -a \"$(whoami)\" -s \"${KEYCHAIN_ENTRY_NAME}\" -w"
printf -v RESTIC_PASSWORD_COMMAND 'security find-generic-password -a %q -s %q -w' "${local_user}" "${KEYCHAIN_ENTRY_NAME}"
export RESTIC_PASSWORD_COMMAND
# Source file? # Source file?
elif [[ -f "${HOME}/.resticpass" ]] ; then elif [[ -f "${HOME}/.resticpass" ]] ; then
export RESTIC_PASSWORD_FILE="${HOME}/.resticpass" export RESTIC_PASSWORD_FILE="${HOME}/.resticpass"
fi fi
# Ensure exclude file exists so restic does not fail when checking exclusions.
if [[ ! -f "${EXCLUDE_FILE}" ]]; then
echo "Exclude file '${EXCLUDE_FILE}' not found. Creating a default macOS exclude file..."
cat << 'EOF' > "${EXCLUDE_FILE}"
# Default restic exclusions for macOS
.Trash
Library/Caches
Library/Logs
.CFUserTextEncoding
EOF
fi
# If the repository does not exist, initialize it. # If the repository does not exist, initialize it.
# The user will be prompted for a password, which will be required for all # The user will be prompted for a password, which will be required for all
# future interactions with the repository. # future interactions with the repository.
if ! restic -r "${REPO}" snapshots >/dev/null 2>&1; then if ! restic -r "${REPO}" snapshots &> /dev/null; then
echo "Restic repository not found or not accessible. Initializing..." echo "Restic repository not found or not accessible. Initializing..."
restic init -r "${REPO}" restic init -r "${REPO}"
fi fi
# --- Run Backup --- # --- Run Backup ---
echo "Starting restic backup..." echo "Starting restic backup..."
echo "Source: ${SOURCE_DIR}" echo "Source: ${SOURCE_DIR}"
echo "Repository: ${REPO}" echo "Repository: ${REPO}"
BACKUP_ARGS=( BACKUP_CMD="restic backup \
"restic" "backup" --verbose \
"--verbose" --repo \"${REPO}\" \
"--repo" "${REPO}" --exclude-file \"${EXCLUDE_FILE}\" \
"--exclude-file" "${EXCLUDE_FILE}" --one-file-system \
"--one-file-system" --tag \"macbook-backup\""
"--tag" "macbook-backup"
)
if [[ -n "${UPLOAD_LIMIT}" ]]; then if [[ -n "${UPLOAD_LIMIT}" ]]; then
BACKUP_ARGS+=("--limit-upload" "${UPLOAD_LIMIT}") BACKUP_CMD="${BACKUP_CMD} --limit-upload ${UPLOAD_LIMIT}"
fi fi
BACKUP_ARGS+=("${SOURCE_DIR}") BACKUP_CMD="${BACKUP_CMD} \"${SOURCE_DIR}\""
"${BACKUP_ARGS[@]}" eval "${BACKUP_CMD}"
echo "Backup complete." echo "Backup complete."

View File

@@ -5,14 +5,8 @@
set -ue set -ue
TOOLS="flameshot scrot" TOOLS="flameshot scrot"
if [ "$(uname)" = "Darwin" ]; then
TOOLS="screencapture ${TOOLS}"
fi
SCREENDIR=${SCREENDIR:-${HOME}/Pictures/Screenshots} SCREENDIR=${SCREENDIR:-${HOME}/Pictures/Screenshots}
SCROT_FORMAT="%F-%T.png" SCROT_FORMAT="%F-%T.png"
# Filename for screencapture
FILE_NAME=$(date "+%Y-%m-%d-%H%M%S.png")
function default_screenshot_command { function default_screenshot_command {
for tool in ${TOOLS} ; do for tool in ${TOOLS} ; do
@@ -47,29 +41,10 @@ function scrot_full_capture {
scrot "${SCREENDIR}/${SCROT_FORMAT}" scrot "${SCREENDIR}/${SCROT_FORMAT}"
} }
function mac_capture {
local mode="${1}"
local target="${SCREENDIR}/${FILE_NAME}"
case "${mode}" in
region)
screencapture -i "${target}"
;;
window)
screencapture -i -w "${target}"
;;
full)
screencapture "${target}"
;;
esac
}
case "${CMD}" in case "${CMD}" in
region|window|full) region|window|full)
mkdir -p "${SCREENDIR}" mkdir -p "${SCREENDIR}"
case "${TOOL}" in case "${TOOL}" in
screencapture)
mac_capture "${CMD}"
;;
flameshot) flameshot)
case "${CMD}" in case "${CMD}" in
region|window) region|window)

View File

@@ -2,20 +2,12 @@
set -ue set -ue
if [ "$(id -u)" -ne 0 ]; then
echo "Error: This script must be run as root." >&2
exit 1
fi
cat >/usr/local/bin/x-resize <<"EOF" cat >/usr/local/bin/x-resize <<"EOF"
#!/bin/sh #!/bin/sh
PATH=/usr/bin:/bin:/usr/local/bin PATH=/usr/bin:/bin:/usr/local/bin
desktopuser=$(/bin/ps -eo user,comm 2>/dev/null | awk '$2 ~ /vdagent/ {print $1; exit}') desktopuser=$(/bin/ps -ef | /bin/grep -oP '^\w+ (?=.*vdagent( |$))') || exit 0
[ -z "$desktopuser" ] && exit 0
desktophome=$(getent passwd "$desktopuser" | cut -d: -f6)
[ -z "$desktophome" ] && exit 0
export DISPLAY=:0 export DISPLAY=:0
export XAUTHORITY="${desktophome}/.Xauthority" export XAUTHORITY=$(eval echo "~$desktopuser")/.Xauthority
/usr/bin/xrandr --output $(/usr/bin/xrandr | awk '/ connected/{print $1; exit; }') --auto /usr/bin/xrandr --output $(/usr/bin/xrandr | awk '/ connected/{print $1; exit; }') --auto
EOF EOF
chmod 755 /usr/local/bin/x-resize chmod 755 /usr/local/bin/x-resize

View File

@@ -72,51 +72,15 @@ shift # Consume the subcommand
# Separate arguments from the file to be signed # Separate arguments from the file to be signed
declare -a remaining_args declare -a remaining_args
file_to_sign="" file_to_sign=""
f_provided=false
n_provided=false
I_provided=false
s_provided=false
while [[ "$#" -gt 0 ]]; do while [[ "$#" -gt 0 ]]; do
case "$1" in # If we see a non-flag argument, assume it's the file to sign.
-f) # This works because the file to sign is the only positional argument.
[[ -z "${2:-}" ]] && error "Option -f requires an argument." if [[ "$1" != -* ]] && [[ -z "$file_to_sign" ]]; then
remaining_args+=("-f" "$2")
f_provided=true
shift 2
;;
-n)
[[ -z "${2:-}" ]] && error "Option -n requires an argument."
remaining_args+=("-n" "$2")
n_provided=true
shift 2
;;
-I)
[[ -z "${2:-}" ]] && error "Option -I requires an argument."
remaining_args+=("-I" "$2")
I_provided=true
shift 2
;;
-s)
[[ -z "${2:-}" ]] && error "Option -s requires an argument."
remaining_args+=("-s" "$2")
s_provided=true
shift 2
;;
-h|--help)
usage
;;
-*)
error "Unknown option: $1"
;;
*)
if [[ -n "$file_to_sign" ]]; then
error "Unexpected positional argument '$1' (already specified '$file_to_sign')."
fi
file_to_sign="$1" file_to_sign="$1"
else
remaining_args+=("$1")
fi
shift shift
;;
esac
done done
# --- Build command based on subcommand --- # --- Build command based on subcommand ---
@@ -126,6 +90,18 @@ CMD_ARGS=("ssh-keygen" "-Y" "$SUBCOMMAND")
# Append all the flag-based arguments (-f, -n, -I, -s) # Append all the flag-based arguments (-f, -n, -I, -s)
CMD_ARGS+=("${remaining_args[@]}") CMD_ARGS+=("${remaining_args[@]}")
# Scan for provided flags to handle defaults correctly
f_provided=false
n_provided=false
I_provided=false
s_provided=false
for arg in "${remaining_args[@]}"; do
[[ "$arg" == "-f" ]] && f_provided=true
[[ "$arg" == "-n" ]] && n_provided=true
[[ "$arg" == "-I" ]] && I_provided=true
[[ "$arg" == "-s" ]] && s_provided=true
done
if [[ "$SUBCOMMAND" == "sign" ]]; then if [[ "$SUBCOMMAND" == "sign" ]]; then
if [[ -z "$file_to_sign" ]]; then if [[ -z "$file_to_sign" ]]; then
error "Path to file to be signed is required for 'sign' command." error "Path to file to be signed is required for 'sign' command."

View File

@@ -1,365 +0,0 @@
#!/usr/bin/env bash
# update-authorized-keys - Manage ~/.ssh/authorized_keys from multiple sources
#
# BEHAVIOR:
# 1. Collects SSH public keys from one or more source directories (default: ~/.ssh/authorized_keys.d).
# 2. Skips empty files and files symlinked to /dev/null (masking).
# 3. Deterministically concatenates keys into a "managed block" wrapped in markers:
# # BEGIN UPDATE-AUTHORIZED-KEYS
# # END UPDATE-AUTHORIZED-KEYS
# 4. Deduplicates managed keys: if the same key (including options) is found in multiple files,
# it is included once with a comment listing all source filenames.
# 5. Preserves "manual" keys found in the target file outside the markers.
# 6. Removes manual keys that exactly match a managed key (options + key data).
# 7. Validates every proposed key individually using 'ssh-keygen -l -f'.
# 8. Optionally validates the whole file with 'authorized-keys-test' if available.
# 9. Displays a unified diff and prompts for confirmation before atomic replacement.
# 10. Supports a --dry-run mode and a --self-test mode for verifying logic.
set -o nounset
set -o errexit
set -o pipefail
CLEANUP_FILES=()
cleanup() {
rm -rf "${CLEANUP_FILES[@]}"
}
trap cleanup EXIT
# Configuration
DEFAULT_DIR="${HOME}/.ssh/authorized_keys.d"
DEFAULT_TARGET="${HOME}/.ssh/authorized_keys"
BEGIN_MARKER="# BEGIN UPDATE-AUTHORIZED-KEYS"
END_MARKER="# END UPDATE-AUTHORIZED-KEYS"
# State
SOURCE_DIRS=()
TARGET_FILE="${DEFAULT_TARGET}"
DRY_RUN=0
usage() {
cat <<EOF
Usage: $(basename "$0") [options]
Options:
--dir DIR Primary directory for managed keys (default: ${DEFAULT_DIR})
--extra-dir DIR Additional directory to scan for keys (can be repeated)
--target FILE Target authorized_keys file (default: ${DEFAULT_TARGET})
--dry-run Show changes and validate without modifying the target
--self-test Run internal suite of tests to verify script logic
--help Show this help message
EOF
}
run_self_test() {
echo "Running self-test..."
local test_root=$(mktemp -d)
CLEANUP_FILES+=("${test_root}")
local d1="${test_root}/d1"
local d2="${test_root}/d2"
local target="${test_root}/target"
mkdir -p "${d1}" "${d2}"
local key1="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8XoR7N7X5XoR7N7X5XoR7N7X5XoR7N7X5XoR7N7X5X key1"
local key2="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL9YpS8O8Y6YpS8O8Y6YpS8O8Y6YpS8O8Y6YpS8O8Y6Y key2"
local key_man="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM0ZqT9P9Z7ZqT9P9Z7ZqT9P9Z7ZqT9P9Z7ZqT9P9Z7Z manual"
local long_opt="environment=\"VAR=VERY_LONG_VALUE_THAT_EXCEEDS_TWENTY_CHARS\""
echo "${key1}" > "${d1}/k1"
echo "${key1}" > "${d2}/k1_dup"
echo "${key2}" > "${d2}/k2"
echo "${long_opt} ${key1}" > "${d1}/k1_long"
echo "${long_opt} ${key2}" > "${d1}/k2_long"
ln -s /dev/null "${d1}/masked"
cat <<EOF > "${target}"
${key_man}
# This is a manual annotation for key1
${key1}
EOF
echo "Executing script in test mode..."
# Pipe "y" to handle the TTY check if we are not in a TTY during test
echo "y" | "$0" --dir "${d1}" --extra-dir "${d2}" --target "${target}" > /dev/null
local content=$(cat "${target}")
echo -n "Check markers... "
if [[ "${content}" == *"${BEGIN_MARKER}"* && "${content}" == *"${END_MARKER}"* ]]; then echo "OK"; else echo "FAIL"; exit 1; fi
echo -n "Check managed deduplication... "
if grep -q "Source: k1, k1_dup" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo -n "Check long option deduplication (should NOT deduplicate different keys)... "
if grep -q "k1_long" "${target}" && grep -q "k2_long" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo -n "Check manual key preservation... "
if grep -q "manual" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo -n "Check manual key filtering... "
local manual_count=$(grep -c "${key1}" "${target}")
# key1 appears twice in managed block (once plain, once with long opt)
# and it was in manual block. The manual one should be removed.
# So we expect 2 occurrences in the final file (both in managed block).
if [[ ${manual_count} -eq 2 ]]; then echo "OK"; else echo "FAIL (Found ${manual_count} occurrences, expected 2)"; exit 1; fi
echo -n "Check masking... "
if ! grep -q "masked" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo -n "Check user comment preservation... "
if grep -q "This is a manual annotation for key1" "${target}"; then echo "OK"; else echo "FAIL"; exit 1; fi
echo "Self-test passed successfully!"
exit 0
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--dir)
[[ -z "${2:-}" ]] && { echo "Error: --dir requires an argument" >&2; exit 1; }
SOURCE_DIRS+=("$2"); shift 2 ;;
--extra-dir)
[[ -z "${2:-}" ]] && { echo "Error: --extra-dir requires an argument" >&2; exit 1; }
SOURCE_DIRS+=("$2"); shift 2 ;;
--target)
[[ -z "${2:-}" ]] && { echo "Error: --target requires an argument" >&2; exit 1; }
TARGET_FILE="$2"; shift 2 ;;
--dry-run) DRY_RUN=1; shift ;;
--self-test) run_self_test ;;
--help) usage; exit 0 ;;
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
esac
done
if [[ ${#SOURCE_DIRS[@]} -eq 0 ]]; then
SOURCE_DIRS+=("${DEFAULT_DIR}")
fi
mkdir -p "$(dirname "${TARGET_FILE}")"
TMP_FILE=$(mktemp)
CLEANUP_FILES+=("${TMP_FILE}")
# Build a map of key-signature -> user comments from the existing target file.
# Comments above keys are preserved into the managed block (# Source: lines are excluded).
# Multiple comment lines are joined with SUBSEP (\034) for safe transport through AWK.
USER_COMMENTS_FILE=$(mktemp)
CLEANUP_FILES+=("${USER_COMMENTS_FILE}")
if [[ -f "${TARGET_FILE}" ]]; then
awk -v begin="${BEGIN_MARKER}" -v end="${END_MARKER}" '
BEGIN { pending="" }
$0 == begin { pending=""; next }
$0 == end { pending=""; next }
/^# Source:/ { next }
/^[[:space:]]*#/ {
pending = (pending == "" ? $0 : pending SUBSEP $0)
next
}
/^[[:space:]]*$/ { pending=""; next }
{
n = split($0, parts, " ")
sig = ""
for (i=1; i<=n; i++) {
sig = (sig == "" ? parts[i] : sig " " parts[i])
if (parts[i] ~ /^(ssh-|ecdsa-|sk-)/ && i < n) {
sig = sig " " parts[i+1]
break
}
}
if (sig != "" && pending != "") {
print sig "\t" pending
}
pending = ""
}
' "${TARGET_FILE}" > "${USER_COMMENTS_FILE}"
fi
collect_keys() {
local dirs=("${@}")
for dir in "${dirs[@]}"; do
if [[ ! -d "${dir}" ]]; then continue; fi
# Use a glob to avoid parsing ls
for file in "${dir}"/*; do
[[ ! -e "${file}" ]] && continue
[[ ! -f "${file}" || ! -s "${file}" ]] && continue
if [[ -L "${file}" && "$(readlink "${file}")" == "/dev/null" ]]; then continue; fi
while read -r line; do
[[ -z "${line}" || "${line}" =~ ^[[:space:]]*# ]] && continue
# Use a specific delimiter that is unlikely to be in the key or filename
# If using tabs, ensure we only split on the first one in AWK
printf "%s\t%s\n" "$(basename "${file}")" "${line}"
done < "${file}"
done
done
}
# Use a HEREDOC for the complex AWK script to avoid shell interpolation issues
MANAGED_BLOCK=$(collect_keys "${SOURCE_DIRS[@]}" | awk -F'\t' -v user_comments_file="${USER_COMMENTS_FILE}" '
BEGIN {
while ((getline line < user_comments_file) > 0) {
tab = index(line, "\t")
if (tab > 0) {
sig = substr(line, 1, tab - 1)
user_comments[sig] = substr(line, tab + 1)
}
}
close(user_comments_file)
}
{
# Splitting on the first tab manually to be robust
tab_idx = index($0, "\t")
source = substr($0, 1, tab_idx - 1)
full_line = substr($0, tab_idx + 1)
# Signature detection: all options + key type + key data
# (Excludes the comment at the end)
n = split(full_line, parts, " ")
sig = ""
for (i=1; i<=n; i++) {
sig = (sig == "" ? parts[i] : sig " " parts[i])
# A key line is [options] <type> <base64> [comment]
# We stop after the base64 part. Key types start with known prefixes.
if (parts[i] ~ /^(ssh-|ecdsa-|sk-)/ && i < n) {
sig = sig " " parts[i+1]
break
}
}
# Fallback if no key type found (should not happen with valid keys)
if (sig == "") sig = full_line
if (!(sig in keys)) {
keys[sig] = full_line
order[++count] = sig
}
sources[sig] = (sources[sig] ? sources[sig] ", " : "") source
}
END {
for (i=1; i<=count; i++) {
sig = order[i]
print "# Source: " sources[sig]
if (sig in user_comments) {
n = split(user_comments[sig], comment_lines, SUBSEP)
for (j=1; j<=n; j++) {
print comment_lines[j]
}
}
print keys[sig]
}
}')
MANUAL_KEYS=""
if [[ -f "${TARGET_FILE}" ]]; then
MANUAL_KEYS=$(awk -v begin="${BEGIN_MARKER}" -v end="${END_MARKER}" '
BEGIN { inside=0 }
$0 == begin { inside=1; next }
$0 == end { inside=0; next }
!inside { print $0 }
' "${TARGET_FILE}")
fi
MANAGED_SIGS_TMP=$(mktemp)
CLEANUP_FILES+=("${MANAGED_SIGS_TMP}")
echo "${MANAGED_BLOCK}" | awk '/^[^#]/ {
n = split($0, parts, " ")
sig = ""
for (i=1; i<=n; i++) {
sig = (sig == "" ? parts[i] : sig " " parts[i])
if (parts[i] ~ /^(ssh-|ecdsa-|sk-)/ && i < n) {
sig = sig " " parts[i+1]
break
}
}
if (sig != "") print sig
}' > "${MANAGED_SIGS_TMP}"
FINAL_MANUAL_KEYS=$(echo "${MANUAL_KEYS}" | awk -v sigs_file="${MANAGED_SIGS_TMP}" '
BEGIN {
while ((getline line < sigs_file) > 0) {
managed[line] = 1
}
close(sigs_file)
}
{
if ($0 ~ /^[[:space:]]*$/ || $0 ~ /^[[:space:]]*#/) {
print $0
next
}
n = split($0, parts, " ")
sig = ""
for (i=1; i<=n; i++) {
sig = (sig == "" ? parts[i] : sig " " parts[i])
if (parts[i] ~ /^(ssh-|ecdsa-|sk-)/ && i < n) {
sig = sig " " parts[i+1]
break
}
}
if (!(sig in managed)) {
print $0
}
}')
rm -f "${MANAGED_SIGS_TMP}"
{
if [[ -n "${MANAGED_BLOCK}" ]]; then
echo "${BEGIN_MARKER}"
echo "${MANAGED_BLOCK}"
echo "${END_MARKER}"
fi
echo "${FINAL_MANUAL_KEYS}"
} > "${TMP_FILE}"
echo "Validating proposed changes..."
VALID=1
while read -r line; do
[[ -z "${line}" || "${line}" =~ ^[[:space:]]*# ]] && continue
if ! echo "${line}" | ssh-keygen -l -f - >/dev/null 2>&1; then
echo "ERROR: Invalid SSH key detected: ${line}" >&2
VALID=0
fi
done < "${TMP_FILE}"
if command -v authorized-keys-test >/dev/null 2>&1; then
if ! authorized-keys-test "${TMP_FILE}"; then
echo "ERROR: Proposed file failed authorized-keys-test." >&2
VALID=0
fi
fi
if [[ ${VALID} -eq 0 ]]; then
echo "Validation failed. Aborting." >&2
exit 1
fi
if [[ -f "${TARGET_FILE}" ]]; then
diff -u "${TARGET_FILE}" "${TMP_FILE}" || true
else
echo "Target file does not exist. Proposed content:"
cat "${TMP_FILE}"
fi
if [[ ${DRY_RUN} -eq 1 ]]; then
echo "Dry run complete. No changes made."
exit 0
fi
if [[ -t 0 ]]; then
echo -n "Apply these changes to ${TARGET_FILE}? [y/N] "
read -r response
elif [[ ! -t 0 ]]; then
# Read from pipe or file if provided
if ! read -r response; then
echo "Non-interactive shell detected and no input provided. Aborting."
exit 1
fi
fi
if [[ "${response}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
chmod 0600 "${TMP_FILE}"
mv "${TMP_FILE}" "${TARGET_FILE}"
echo "Changes applied successfully."
else
echo "Aborted."
exit 1
fi

View File

@@ -1,49 +1,7 @@
#!/bin/sh #!/bin/sh
set -eu set -e
SKEL_DIR=$(dirname -- "$(readlink -f -- "$HOME/.profile")")
resolve_symlink() { cd -- "$SKEL_DIR"
_target="$1" cd -- "$(git rev-parse --show-toplevel)"
if command -v readlink >/dev/null 2>&1 && readlink -f -- "$_target" >/dev/null 2>&1; then
readlink -f -- "$_target"
elif command -v python3 >/dev/null 2>&1; then
python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$_target"
else
while [ -L "$_target" ]; do
_dir=$(cd -P "$(dirname -- "$_target")" >/dev/null 2>&1 && pwd)
_target=$(readlink "$_target")
case "$_target" in
/*) ;;
*) _target="$_dir/$_target" ;;
esac
done
echo "$_target"
fi
}
if [ -e "$HOME/.profile" ]; then
TARGET=$(resolve_symlink "$HOME/.profile")
SKEL_DIR=$(dirname -- "$TARGET")
else
SKEL_DIR=""
fi
REPO_ROOT=""
if [ -n "$SKEL_DIR" ] && cd -- "$SKEL_DIR" 2>/dev/null; then
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
fi
if [ -z "$REPO_ROOT" ] || [ ! -f "$REPO_ROOT/install.sh" ]; then
SCRIPT_DIR=$(dirname -- "$(resolve_symlink "$0")")
if cd -- "$SCRIPT_DIR" 2>/dev/null; then
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
fi
if [ -z "$REPO_ROOT" ] || [ ! -f "$REPO_ROOT/install.sh" ]; then
echo "Error: Could not determine skel repository root." >&2
exit 1
fi
fi
cd -- "$REPO_ROOT"
git pull git pull
./install.sh "$@" ./install.sh

View File

@@ -1,65 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "Usage: $(basename "$0") [--dry-run] user@host" >&2
exit 1
}
DRY_RUN=0
REMOTE=
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run)
DRY_RUN=1
shift
;;
-h|--help)
usage
;;
--)
shift
break
;;
-*)
usage
;;
*)
if [[ -n "${REMOTE}" ]]; then
usage
fi
REMOTE="$1"
shift
;;
esac
done
if [[ $# -gt 0 || -z "${REMOTE}" ]]; then
usage
fi
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
if ! git -C "$SCRIPT_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Error: $SCRIPT_DIR is not inside a git repository." >&2
exit 1
fi
if [[ "$DRY_RUN" -eq 1 ]]; then
archive_list="$(git -C "$SCRIPT_DIR" archive --format=tar HEAD | tar -tf - | sed 's#^\./##' | sed '/^$/d;/^\.$/d' | sort)"
remote_list="$(ssh "$REMOTE" 'if [ -d "$HOME/.skel" ]; then cd "$HOME/.skel" && find . | sed "s#^\./##" | sed "/^$/d;/^\.$/d" | sort; fi' || true)"
printf 'Would deploy HEAD from %s to %s:%s\n' "$SCRIPT_DIR" "$REMOTE" '$HOME/.skel'
printf 'Would replace remote ~/.skel with %s tracked paths\n' "$(printf '%s' "$archive_list" | awk 'NF { n++ } END { print n + 0 }')"
if [[ -n "$remote_list" ]]; then
printf 'Would remove %s existing remote paths not present in HEAD\n' "$(comm -13 <(printf '%s\n' "$archive_list") <(printf '%s\n' "$remote_list") | awk 'NF { n++ } END { print n + 0 }')"
else
printf 'Remote ~/.skel does not exist or is empty\n'
fi
exit 0
fi
git -C "$SCRIPT_DIR" archive --format=tar HEAD | \
ssh "$REMOTE" 'rm -rf "$HOME/.skel" && mkdir -p "$HOME/.skel" && tar -xf - -C "$HOME/.skel"'

View File

@@ -1,6 +1,9 @@
# General aliases, should only be sourced in interactive shells # General aliases, should only be sourced in interactive shells
# Try to keep in sync with ~/.config/fish/conf.d/aliases.fish # Try to keep in sync with ~/.config/fish/conf.d/aliases.fish
# Cryptsetup alias
alias luksFormat='cryptsetup luksFormat --type=luks2 --pbkdf-memory=2560000 --pbkdf=argon2id -i 15000 -s 512 -h sha256 -c aes-xts-plain64'
# Timestamp in a machine-sortable form # Timestamp in a machine-sortable form
alias tstamp="date '+%Y%m%d-%H%M%S'" alias tstamp="date '+%Y%m%d-%H%M%S'"
@@ -10,6 +13,12 @@ alias mdcode="sed 's/^/ /'"
# Intel format plz # Intel format plz
alias objdump="command objdump -M intel" alias objdump="command objdump -M intel"
# Drop caches for swap issues
alias drop_caches="echo 3 | sudo /usr/bin/tee /proc/sys/vm/drop_caches"
# dump acpi temperature
alias gettemp='printf "%02.2f\n" "$(cat /sys/class/thermal/thermal_zone0/temp)e-3"'
# get git working directory # get git working directory
alias gitroot="git rev-parse --show-toplevel" alias gitroot="git rev-parse --show-toplevel"
@@ -22,40 +31,20 @@ alias ipy="ipython3 --no-banner"
# Skip the header on bc # Skip the header on bc
alias bc="command bc -q" alias bc="command bc -q"
# Clear the GPG agent
alias clear-gpg-agent="echo RELOADAGENT | gpg-connect-agent"
# Earthly ssh
alias earthly='earthly --ssh-auth-sock ""'
# ESP-IDF
alias activate_idf="source ~/.espressif/tools/activate_idf_v*.sh"
if [ "$(uname)" = "Linux" ]; then
# Cryptsetup alias
alias luksFormat='cryptsetup luksFormat --type=luks2 --pbkdf-memory=2560000 --pbkdf=argon2id -i 15000 -s 512 -h sha256 -c aes-xts-plain64'
# Drop caches for swap issues
alias drop_caches="echo 3 | sudo /usr/bin/tee /proc/sys/vm/drop_caches"
# dump acpi temperature
alias gettemp='printf "%02.2f\n" "$(cat /sys/class/thermal/thermal_zone0/temp)e-3"'
# Get a decently readable df # Get a decently readable df
alias dfh="df -h -x tmpfs -x devtmpfs -x squashfs -x fuse -x efivarfs" alias dfh="df -h -x tmpfs -x devtmpfs -x squashfs -x fuse -x efivarfs"
# Clear the GPG agent
alias clear-gpg-agent="echo RELOADAGENT | gpg-connect-agent"
# Battery details # Battery details
alias bat-details='upower -i $(upower -e | grep battery)' alias bat-details='upower -i $(upower -e | grep battery)'
# Nvidia refresh rate # Nvidia refresh rate
alias nvidia-refresh-rate='nvidia-settings --display=:0 -q RefreshRate -t' alias nvidia-refresh-rate='nvidia-settings --display=:0 -q RefreshRate -t'
# to clipboard # Earthly ssh
alias toclip='xclip -selection clipboard' alias earthly='earthly --ssh-auth-sock ""'
elif [ "$(uname)" = "Darwin" ]; then
# Get a decently readable df
alias dfh="df -h"
# to clipboard # to clipboard
alias toclip='pbcopy' alias toclip='xclip -selection clipboard'
fi

View File

@@ -1,4 +0,0 @@
# Credentials
.ssh
Passwords.kdbx
Passwords.kdbx.age

View File

@@ -1,63 +0,0 @@
#!/bin/sh
# shellcheck disable=SC1090
# common functions for use in shell scripts
find_first() {
while [ "$#" -gt 0 ]; do
if test -e "${1}" ; then
echo "${1}"
return 0
fi
shift
done
return 1
}
have_command() {
command -v "$1" >/dev/null 2>&1
}
# Helper function: Returns 0 if the directory is in PATH, 1 otherwise
path_contains() {
case ":${PATH}:" in
*:"$1":*) return 0 ;;
*) return 1 ;;
esac
}
# Prepend a directory to PATH if it's not already there
path_prepend() {
if [ -d "$1" ] && ! path_contains "$1"; then
PATH="$1:${PATH}"
fi
}
# Append a directory to PATH if it's not already there
path_append() {
if [ -d "$1" ] && ! path_contains "$1"; then
PATH="${PATH}:$1"
fi
}
source_first_existing() {
_sfe_script="$(find_first "$@")"
_sfe_status=$?
if [ "$_sfe_status" -eq 0 ]; then
. "$_sfe_script"
# Clean up our temporary variables before returning success
unset -v _sfe_script _sfe_status
return 0
fi
# Clean up our temporary variables before returning failure
unset -v _sfe_script _sfe_status
return 1
}
source_if_existing() {
if [ -f "$1" ]; then
. "$1"
fi
}

View File

@@ -1,3 +1,6 @@
# Cryptsetup alias
alias luksFormat 'cryptsetup luksFormat --type=luks2 --pbkdf-memory=2560000 --pbkdf=argon2id -i 15000 -s 512 -h sha256 -c aes-xts-plain64'
# Timestamp in a machine-sortable form # Timestamp in a machine-sortable form
alias tstamp "date '+%Y%m%d-%H%M%S'" alias tstamp "date '+%Y%m%d-%H%M%S'"
@@ -7,6 +10,12 @@ alias mdcode "sed 's/^/ /'"
# Intel format plz # Intel format plz
alias objdump "command objdump -M intel" alias objdump "command objdump -M intel"
# Drop caches for swap issues
alias drop_caches "echo 3 | sudo /usr/bin/tee /proc/sys/vm/drop_caches"
# dump acpi temperature
alias gettemp 'printf "%02.2f\n" (cat /sys/class/thermal/thermal_zone0/temp)e-3'
# get git working directory # get git working directory
alias gitroot "git rev-parse --show-toplevel" alias gitroot "git rev-parse --show-toplevel"
@@ -19,40 +28,23 @@ alias ipy "ipython3 --no-banner"
# Skip the header on bc # Skip the header on bc
alias bc "command bc -q" alias bc "command bc -q"
# Clear the GPG agent
alias clear-gpg-agent "echo RELOADAGENT | gpg-connect-agent"
# Earthly ssh
alias earthly 'earthly --ssh-auth-sock ""'
if test (uname) = "Linux"
# Cryptsetup alias
alias luksFormat 'cryptsetup luksFormat --type=luks2 --pbkdf-memory=2560000 --pbkdf=argon2id -i 15000 -s 512 -h sha256 -c aes-xts-plain64'
# Drop caches for swap issues
alias drop_caches "echo 3 | sudo /usr/bin/tee /proc/sys/vm/drop_caches"
# dump acpi temperature
alias gettemp 'printf "%02.2f\n" (cat /sys/class/thermal/thermal_zone0/temp)e-3'
# Get a decently readable df # Get a decently readable df
alias dfh "df -h -x tmpfs -x devtmpfs -x squashfs -x fuse -x efivarfs" alias dfh "df -h -x tmpfs -x devtmpfs -x squashfs -x fuse -x efivarfs"
# Clear the GPG agent
alias clear-gpg-agent "echo RELOADAGENT | gpg-connect-agent"
# Battery details # Battery details
alias bat-details 'upower -i (upower -e | grep battery)' alias bat-details 'upower -i (upower -e | grep battery)'
# Nvidia refresh rate # Nvidia refresh rate
alias nvidia-refresh-rate 'nvidia-settings --display=:0 -q RefreshRate -t' alias nvidia-refresh-rate 'nvidia-settings --display=:0 -q RefreshRate -t'
# to clipboard # Earthly ssh
alias toclip 'xclip -selection clipboard' alias earthly 'earthly --ssh-auth-sock ""'
else if test (uname) = "Darwin"
# Get a decently readable df
alias dfh "df -h"
# to clipboard # to clipboard
alias toclip 'pbcopy' alias toclip 'xclip -selection clipboard'
end
# On some systems, bat is batcat # On some systems, bat is batcat
if not command -v bat >/dev/null 2>&1 if not command -v bat >/dev/null 2>&1

View File

@@ -34,6 +34,4 @@ end
fish_add_path --move --path {$HOME}/bin fish_add_path --move --path {$HOME}/bin
if test (uname) = "Darwin" if test (uname) = "Darwin"
fish_add_path --move --path {$HOME}/bin/macos fish_add_path --move --path {$HOME}/bin/macos
else if test (uname) = "Linux"
fish_add_path --move --path {$HOME}/bin/linux
end end

View File

@@ -9,8 +9,9 @@ uv_venv_auto = true
[tools] [tools]
age = "latest" age = "latest"
age-plugin-yubikey = "latest"
usage = "latest" usage = "latest"
uv = "0.11.8" uv = "latest"
[hooks] [hooks]
postinstall = "mise sync python --uv" postinstall = "mise sync python --uv"

View File

@@ -39,3 +39,16 @@ disabled = true
[kubernetes] [kubernetes]
disabled = false disabled = false
detect_folders = ["k8s"] detect_folders = ["k8s"]
[custom.gemini_context]
description = "Displays the current Gemini CLI context"
when = "test -n \"$GEMINI_CLI_HOME\""
command = """
context_dir=\"${XDG_CONFIG_HOME:-$HOME/.config}/gemini\"
if [[ \"$GEMINI_CLI_HOME\" == $context_dir/* ]]; then
basename \"$GEMINI_CLI_HOME\"
fi
"""
style = "bold blue"
format = "♊[$output](blue) "
shell = ["/bin/sh", "-c"]

View File

@@ -19,17 +19,14 @@
[difftool] [difftool]
prompt = false prompt = false
[difftool "difftastic"]
cmd = difft "$LOCAL" "$REMOTE"
[alias] [alias]
st = status st = status
last = log -1 HEAD last = log -1 HEAD
# Thanks to # Thanks to
# http://durdn.com/blog/2012/11/22/must-have-git-aliases-advanced-examples/ # http://durdn.com/blog/2012/11/22/must-have-git-aliases-advanced-examples/
logs = log --pretty=format:"%C(yellow)%h%Cred%d %Creset%s%Cblue [%cn]" --decorate logs = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate
lg = log -p lg = log -p
ll = log --pretty=format:"%C(yellow)%h%Cred%d %Creset%s%Cblue [%cn]" --decorate --numstat ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
files = ls-files files = ls-files
ls = ls-files ls = ls-files
lol = log --graph --pretty=format:'%C(yellow)%h%Creset %an: %s - %Creset %C(yellow)%d%Creset %Cblue(%cr)%Creset' --abbrev-commit --date=relative lol = log --graph --pretty=format:'%C(yellow)%h%Creset %an: %s - %Creset %C(yellow)%d%Creset %Cblue(%cr)%Creset' --abbrev-commit --date=relative
@@ -95,18 +92,8 @@
process = git-lfs filter-process process = git-lfs filter-process
[include] [include]
path = ~/.gitconfig.d/aliases
path = ~/.gitconfig.d/override path = ~/.gitconfig.d/override
path = ~/.gitconfig.d/local path = ~/.gitconfig.d/local
[includeIf "gitdir/i:~/personal/"] [includeIf "gitdir:~/personal/"]
path = ~/.gitconfig.d/personal path = ~/.gitconfig.d/personal
[rerere]
enabled = true
[lfs]
concurrenttransfers = 3
[lfs "customtransfer.xet"]
path = git-xet
args = transfer
concurrent = true

View File

@@ -38,4 +38,3 @@ mise.local.toml
.copilot/ .copilot/
.cursor/ .cursor/
.gemini/ .gemini/
.jetskicli/

View File

@@ -4,17 +4,16 @@
# Should only use POSIX constructs. # Should only use POSIX constructs.
# Always load ENV # Always load ENV
test -f "${HOME}/.shenv" && . "${HOME}/.shenv" test -f "$HOME/.shenv" && . "$HOME/.shenv"
# Setup GREP_COLORS # Setup GREP_COLORS
export GREP_COLOR='01;31' export GREP_COLOR='01;31'
export GREP_COLORS='mt=01;31:mc=01;31:ms=01;31' export GREP_COLORS='mt=01;31:mc=01;31:ms=01;31'
# Setup LS_COLORS # Setup LS_COLORS
if command -v dircolors >/dev/null 2>&1 && test -f "${HOME}/.dircolors" ; then if whence dircolors >/dev/null 2>&1 ; then
eval "$(dircolors -b "${HOME}/.dircolors" 2>/dev/null)" test -f "${HOME}/.dircolors" && \
elif command -v gdircolors >/dev/null 2>&1 && test -f "${HOME}/.dircolors" ; then eval "$(dircolors "${HOME}/.dircolors")"
eval "$(gdircolors -b "${HOME}/.dircolors" 2>/dev/null)"
else else
# Static solarized LS_COLORS # Static solarized LS_COLORS
LS_COLORS='no=00:fi=00:di=34:ow=34;40:ln=35:pi=30;44:so=35;44:do=35;44:bd=33;44:cd=37;44:or=05;37;41:mi=05;37;41:ex=01;31:*.cmd=01;31:*.exe=01;31:*.com=01;31:*.bat=01;31:*.reg=01;31:*.app=01;31:*.txt=32:*.org=32:*.md=32:*.mkd=32:*.h=32:*.hpp=32:*.c=32:*.C=32:*.cc=32:*.cpp=32:*.cxx=32:*.objc=32:*.cl=32:*.sh=32:*.bash=32:*.csh=32:*.zsh=32:*.el=32:*.vim=32:*.java=32:*.pl=32:*.pm=32:*.py=32:*.rb=32:*.hs=32:*.php=32:*.htm=32:*.html=32:*.shtml=32:*.erb=32:*.haml=32:*.xml=32:*.rdf=32:*.css=32:*.sass=32:*.scss=32:*.less=32:*.js=32:*.coffee=32:*.man=32:*.0=32:*.1=32:*.2=32:*.3=32:*.4=32:*.5=32:*.6=32:*.7=32:*.8=32:*.9=32:*.l=32:*.n=32:*.p=32:*.pod=32:*.tex=32:*.go=32:*.sql=32:*.csv=32:*.sv=32:*.svh=32:*.v=32:*.vh=32:*.vhd=32:*.bmp=33:*.cgm=33:*.dl=33:*.dvi=33:*.emf=33:*.eps=33:*.gif=33:*.jpeg=33:*.jpg=33:*.JPG=33:*.mng=33:*.pbm=33:*.pcx=33:*.pdf=33:*.pgm=33:*.png=33:*.PNG=33:*.ppm=33:*.pps=33:*.ppsx=33:*.ps=33:*.svg=33:*.svgz=33:*.tga=33:*.tif=33:*.tiff=33:*.xbm=33:*.xcf=33:*.xpm=33:*.xwd=33:*.xwd=33:*.yuv=33:*.aac=33:*.au=33:*.flac=33:*.m4a=33:*.mid=33:*.midi=33:*.mka=33:*.mp3=33:*.mpa=33:*.mpeg=33:*.mpg=33:*.ogg=33:*.opus=33:*.ra=33:*.wav=33:*.anx=33:*.asf=33:*.avi=33:*.axv=33:*.flc=33:*.fli=33:*.flv=33:*.gl=33:*.m2v=33:*.m4v=33:*.mkv=33:*.mov=33:*.MOV=33:*.mp4=33:*.mp4v=33:*.mpeg=33:*.mpg=33:*.nuv=33:*.ogm=33:*.ogv=33:*.ogx=33:*.qt=33:*.rm=33:*.rmvb=33:*.swf=33:*.vob=33:*.webm=33:*.wmv=33:*.doc=31:*.docx=31:*.rtf=31:*.odt=31:*.dot=31:*.dotx=31:*.ott=31:*.xls=31:*.xlsx=31:*.ods=31:*.ots=31:*.ppt=31:*.pptx=31:*.odp=31:*.otp=31:*.fla=31:*.psd=31:*.7z=1;35:*.apk=1;35:*.arj=1;35:*.bin=1;35:*.bz=1;35:*.bz2=1;35:*.cab=1;35:*.deb=1;35:*.dmg=1;35:*.gem=1;35:*.gz=1;35:*.iso=1;35:*.jar=1;35:*.msi=1;35:*.rar=1;35:*.rpm=1;35:*.tar=1;35:*.tbz=1;35:*.tbz2=1;35:*.tgz=1;35:*.tx=1;35:*.war=1;35:*.xpi=1;35:*.xz=1;35:*.z=1;35:*.Z=1;35:*.zip=1;35:*.ANSI-30-black=30:*.ANSI-01;30-brblack=01;30:*.ANSI-31-red=31:*.ANSI-01;31-brred=01;31:*.ANSI-32-green=32:*.ANSI-01;32-brgreen=01;32:*.ANSI-33-yellow=33:*.ANSI-01;33-bryellow=01;33:*.ANSI-34-blue=34:*.ANSI-01;34-brblue=01;34:*.ANSI-35-magenta=35:*.ANSI-01;35-brmagenta=01;35:*.ANSI-36-cyan=36:*.ANSI-01;36-brcyan=01;36:*.ANSI-37-white=37:*.ANSI-01;37-brwhite=01;37:*.log=01;32:*~=01;32:*#=01;32:*.bak=01;33:*.BAK=01;33:*.old=01;33:*.OLD=01;33:*.org_archive=01;33:*.off=01;33:*.OFF=01;33:*.dist=01;33:*.DIST=01;33:*.orig=01;33:*.ORIG=01;33:*.swp=01;33:*.swo=01;33:*,v=01;33:*.gpg=34:*.gpg=34:*.pgp=34:*.asc=34:*.3des=34:*.aes=34:*.enc=34:*.sqlite=34:'; LS_COLORS='no=00:fi=00:di=34:ow=34;40:ln=35:pi=30;44:so=35;44:do=35;44:bd=33;44:cd=37;44:or=05;37;41:mi=05;37;41:ex=01;31:*.cmd=01;31:*.exe=01;31:*.com=01;31:*.bat=01;31:*.reg=01;31:*.app=01;31:*.txt=32:*.org=32:*.md=32:*.mkd=32:*.h=32:*.hpp=32:*.c=32:*.C=32:*.cc=32:*.cpp=32:*.cxx=32:*.objc=32:*.cl=32:*.sh=32:*.bash=32:*.csh=32:*.zsh=32:*.el=32:*.vim=32:*.java=32:*.pl=32:*.pm=32:*.py=32:*.rb=32:*.hs=32:*.php=32:*.htm=32:*.html=32:*.shtml=32:*.erb=32:*.haml=32:*.xml=32:*.rdf=32:*.css=32:*.sass=32:*.scss=32:*.less=32:*.js=32:*.coffee=32:*.man=32:*.0=32:*.1=32:*.2=32:*.3=32:*.4=32:*.5=32:*.6=32:*.7=32:*.8=32:*.9=32:*.l=32:*.n=32:*.p=32:*.pod=32:*.tex=32:*.go=32:*.sql=32:*.csv=32:*.sv=32:*.svh=32:*.v=32:*.vh=32:*.vhd=32:*.bmp=33:*.cgm=33:*.dl=33:*.dvi=33:*.emf=33:*.eps=33:*.gif=33:*.jpeg=33:*.jpg=33:*.JPG=33:*.mng=33:*.pbm=33:*.pcx=33:*.pdf=33:*.pgm=33:*.png=33:*.PNG=33:*.ppm=33:*.pps=33:*.ppsx=33:*.ps=33:*.svg=33:*.svgz=33:*.tga=33:*.tif=33:*.tiff=33:*.xbm=33:*.xcf=33:*.xpm=33:*.xwd=33:*.xwd=33:*.yuv=33:*.aac=33:*.au=33:*.flac=33:*.m4a=33:*.mid=33:*.midi=33:*.mka=33:*.mp3=33:*.mpa=33:*.mpeg=33:*.mpg=33:*.ogg=33:*.opus=33:*.ra=33:*.wav=33:*.anx=33:*.asf=33:*.avi=33:*.axv=33:*.flc=33:*.fli=33:*.flv=33:*.gl=33:*.m2v=33:*.m4v=33:*.mkv=33:*.mov=33:*.MOV=33:*.mp4=33:*.mp4v=33:*.mpeg=33:*.mpg=33:*.nuv=33:*.ogm=33:*.ogv=33:*.ogx=33:*.qt=33:*.rm=33:*.rmvb=33:*.swf=33:*.vob=33:*.webm=33:*.wmv=33:*.doc=31:*.docx=31:*.rtf=31:*.odt=31:*.dot=31:*.dotx=31:*.ott=31:*.xls=31:*.xlsx=31:*.ods=31:*.ots=31:*.ppt=31:*.pptx=31:*.odp=31:*.otp=31:*.fla=31:*.psd=31:*.7z=1;35:*.apk=1;35:*.arj=1;35:*.bin=1;35:*.bz=1;35:*.bz2=1;35:*.cab=1;35:*.deb=1;35:*.dmg=1;35:*.gem=1;35:*.gz=1;35:*.iso=1;35:*.jar=1;35:*.msi=1;35:*.rar=1;35:*.rpm=1;35:*.tar=1;35:*.tbz=1;35:*.tbz2=1;35:*.tgz=1;35:*.tx=1;35:*.war=1;35:*.xpi=1;35:*.xz=1;35:*.z=1;35:*.Z=1;35:*.zip=1;35:*.ANSI-30-black=30:*.ANSI-01;30-brblack=01;30:*.ANSI-31-red=31:*.ANSI-01;31-brred=01;31:*.ANSI-32-green=32:*.ANSI-01;32-brgreen=01;32:*.ANSI-33-yellow=33:*.ANSI-01;33-bryellow=01;33:*.ANSI-34-blue=34:*.ANSI-01;34-brblue=01;34:*.ANSI-35-magenta=35:*.ANSI-01;35-brmagenta=01;35:*.ANSI-36-cyan=36:*.ANSI-01;36-brcyan=01;36:*.ANSI-37-white=37:*.ANSI-01;37-brwhite=01;37:*.log=01;32:*~=01;32:*#=01;32:*.bak=01;33:*.BAK=01;33:*.old=01;33:*.OLD=01;33:*.org_archive=01;33:*.off=01;33:*.OFF=01;33:*.dist=01;33:*.DIST=01;33:*.orig=01;33:*.ORIG=01;33:*.swp=01;33:*.swo=01;33:*,v=01;33:*.gpg=34:*.gpg=34:*.pgp=34:*.asc=34:*.3des=34:*.aes=34:*.enc=34:*.sqlite=34:';
@@ -28,16 +27,16 @@ if [ "$(uname)" = "Darwin" ] ; then
fi fi
# Setup for libvirt # Setup for libvirt
if [ -z "${LIBVIRT_DEFAULT_URI:-}" ] ; then if [ -z "${LIBVIRT_DEFAULT_URI}" ] ; then
export LIBVIRT_DEFAULT_URI="qemu:///system" if [ "$(id -u)" = "0" ] || (id -g -n | grep -q "\blibvirt\b") ; then
LIBVIRT_DEFAULT_URI="qemu:///system"
export LIBVIRT_DEFAULT_URI
fi
fi fi
# Got rust? (gvim, etc.) # Got rust? (gvim, etc.)
if test -d "${HOME}/.cargo/bin" ; then if test -d "${HOME}/.cargo/bin" ; then
case ":${PATH}:" in PATH="${PATH}:${HOME}/.cargo/bin"
*:"${HOME}/.cargo/bin":*) ;;
*) PATH="${PATH}:${HOME}/.cargo/bin" ;;
esac
fi fi
test -f "${HOME}/.profile.local" && . "${HOME}/.profile.local" test -f "${HOME}/.profile.local" && . "${HOME}/.profile.local"

View File

@@ -45,6 +45,3 @@
hibernationfile hibernationfile
sleepimage sleepimage
swapfile swapfile
# Android and other big tools
/Users/*/.android

View File

@@ -15,7 +15,6 @@ export DEBEMAIL="david@systemoverlord.com"
export DEBFULLNAME="David Tomaschik" export DEBFULLNAME="David Tomaschik"
export LESS="-MR" export LESS="-MR"
export QUOTING_STYLE="literal" # Coreutils quotes export QUOTING_STYLE="literal" # Coreutils quotes
export HOMEBREW_NO_ENV_HINTS=1
# Fix gnome-terminal # Fix gnome-terminal
if [ "$TERM" = "xterm" ] && [ "$COLORTERM" = "gnome-terminal" ] ; then if [ "$TERM" = "xterm" ] && [ "$COLORTERM" = "gnome-terminal" ] ; then
@@ -29,9 +28,6 @@ export WORKON_HOME="$HOME/.virtualenvs"
# GPG full key id # GPG full key id
export GPG_ID=7FD58D9A196DCEEEAD671F94F4D7A7915DEA789B export GPG_ID=7FD58D9A196DCEEEAD671F94F4D7A7915DEA789B
# Capture uname early
_UNAME="$(uname)"
# things we need in all interactive shells # things we need in all interactive shells
case "$-" in case "$-" in
*i*) *i*)
@@ -89,6 +85,7 @@ case "$-" in
;; ;;
esac esac
# Opt out of .net telemetry # Opt out of .net telemetry
export DOTNET_CLI_TELEMETRY_OPTOUT=1 export DOTNET_CLI_TELEMETRY_OPTOUT=1
@@ -99,145 +96,78 @@ export LVM_SUPPRESS_FD_WARNINGS=1
export EARTHLY_SSH_AUTH_SOCK="" export EARTHLY_SSH_AUTH_SOCK=""
# Handle SSH_AUTH_SOCK for tmux consistency # Handle SSH_AUTH_SOCK for tmux consistency
case "$-" in
*i*)
_SSH_AUTH_LINK="${HOME}/.ssh/ssh_auth_sock" _SSH_AUTH_LINK="${HOME}/.ssh/ssh_auth_sock"
# Helper to check if a path is our link or points to it # Helper to check if a path is our link or points to it
_is_link_path() { _is_link_path() {
[ -z "$1" ] && return 1 [ -z "$1" ] && return 1
_target="${_SSH_AUTH_LINK:-${HOME}/.ssh/ssh_auth_sock}" [ "$1" = "${_SSH_AUTH_LINK}" ] && return 0
[ "$1" = "${_target}" ] && { unset -v _target; return 0; }
if [ -L "$1" ] && command -v readlink >/dev/null 2>&1; then if [ -L "$1" ] && command -v readlink >/dev/null 2>&1; then
_T=$(readlink "$1") _T=$(readlink "$1")
# Handle relative symlinks # Handle relative symlinks
case "${_T}" in /*) ;; *) _T="$(dirname "$1")/${_T}" ;; esac case "${_T}" in /*) ;; *) _T="$(dirname "$1")/${_T}" ;; esac
[ "${_T}" = "${_target}" ] && { unset -v _target _T; return 0; } [ "${_T}" = "${_SSH_AUTH_LINK}" ] && return 0
unset -v _T
fi fi
unset -v _target
return 1 return 1
} }
# Helper to check if an SSH socket is valid and useful
_is_valid_ssh_sock() {
[ -z "$1" ] && return 1
[ -S "$1" ] || return 1
if command -v nc >/dev/null 2>&1; then
# Use nc to quickly check if the socket is listening.
# We use -N to shutdown the socket after EOF on stdin (for OpenBSD netcat compatibility).
if echo '' | nc -w 1 -N -U "$1" >/dev/null 2>&1; then
return 0
fi
fi
if command -v ssh-add >/dev/null 2>&1; then
SSH_AUTH_SOCK="$1" ssh-add -l >/dev/null 2>&1
case "$?" in
0|1) return 0 ;;
*) return 1 ;;
esac
fi
if command -v nc >/dev/null 2>&1; then
return 1
fi
return 0
}
# Function to get the path to the socket for the local ssh-agent
get_local_ssh_agent_sock() {
_found=""
if [ "$(uname)" = "Darwin" ]; then
_found=$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null)
elif command -v systemctl >/dev/null 2>&1; then
# Query systemd socket units directly to avoid environment overrides.
for _u in ssh-agent.socket openssh-agent.socket gcr-ssh-agent.socket gpg-agent-ssh.socket; do
_p=$(systemctl --user show "${_u}" -p Listen 2>/dev/null | cut -d= -f2- | cut -d' ' -f1)
if ! _is_link_path "${_p}" && _is_valid_ssh_sock "${_p}"; then
_found="${_p}"
break
fi
done
# Fallback to systemd environment
if [ -z "${_found}" ] || _is_link_path "${_found}" || ! _is_valid_ssh_sock "${_found}"; then
_found=$(systemctl --user show-environment 2>/dev/null | grep "^SSH_AUTH_SOCK=" | cut -d= -f2-)
fi
fi
if [ -n "${_found}" ] && ! _is_link_path "${_found}" && _is_valid_ssh_sock "${_found}"; then
echo "${_found}"
unset -v _found _u _p
return 0
fi
# Search common fallback paths
_u=$(id -u)
for _p in "/run/user/${_u}/keyring/ssh" "/run/user/${_u}/ssh-agent.socket" "/run/user/${_u}/openssh_agent" "/run/user/${_u}/gnupg/S.gpg-agent.ssh"; do
if ! _is_link_path "${_p}" && _is_valid_ssh_sock "${_p}"; then
echo "${_p}"
unset -v _found _u _p
return 0
fi
done
# Search /run/user/UID and /tmp for agent.* sockets
_search=""
for _d in "/run/user/${_u}" /tmp; do [ -d "${_d}" ] && _search="${_search} ${_d}"; done
if [ -n "${_search}" ]; then
for _p in $(find ${_search} -maxdepth 2 -type s -name 'agent.*' 2>/dev/null); do
if ! _is_link_path "${_p}" && _is_valid_ssh_sock "${_p}"; then
echo "${_p}"
unset -v _found _u _p _search _d
return 0
fi
done
fi
unset -v _found _u _p _search _d
return 1
}
# Function to reset SSH_AUTH_SOCK to the local ssh-agent
reset_ssh_socket() {
_rss_sock=$(get_local_ssh_agent_sock)
if [ -n "${_rss_sock}" ]; then
_rss_link="${HOME}/.ssh/ssh_auth_sock"
mkdir -p "$(dirname "${_rss_link}")"
ln -sf "${_rss_sock}" "${_rss_link}"
export SSH_AUTH_SOCK="${_rss_link}"
if command -v systemctl >/dev/null 2>&1; then
systemctl --user set-environment SSH_AUTH_SOCK="${_rss_link}" 2>/dev/null
fi
echo "Reset SSH_AUTH_SOCK to ${_rss_link} -> ${_rss_sock}"
unset -v _rss_sock _rss_link
return 0
else
echo "reset_ssh_socket: no valid local ssh-agent socket found." >&2
unset -v _rss_sock
return 1
fi
}
_CANDIDATE="" _CANDIDATE=""
# 1. If current environment has a valid socket that is NOT our link, it's a prime candidate # 1. If current environment has a valid socket that is NOT our link, it's a prime candidate
# (e.g. fresh SSH login: sshd sets SSH_AUTH_SOCK to the raw forwarded socket before ssh/rc # (e.g. fresh SSH login: sshd sets SSH_AUTH_SOCK to the raw forwarded socket before ssh/rc
# rewrites it to the stable symlink; the shell inherits the original raw path). # rewrites it to the stable symlink; the shell inherits the original raw path).
if ! _is_link_path "${SSH_AUTH_SOCK:-}" && _is_valid_ssh_sock "${SSH_AUTH_SOCK:-}"; then if [ -S "${SSH_AUTH_SOCK:-}" ] && ! _is_link_path "${SSH_AUTH_SOCK}"; then
_CANDIDATE="${SSH_AUTH_SOCK}" _CANDIDATE="${SSH_AUTH_SOCK}"
fi fi
# 2. Only look for a system agent if the stable link is already broken. If the link is # 2. Only look for a system agent if the stable link is already broken. If the link is
# valid (e.g. a tmux pane where SSH_AUTH_SOCK points to our symlink which ssh/rc just # valid (e.g. a tmux pane where SSH_AUTH_SOCK points to our symlink which ssh/rc just
# updated to the forwarded socket), leave it alone — don't clobber it with a local agent. # updated to the forwarded socket), leave it alone — don't clobber it with a local agent.
if [ -z "${_CANDIDATE}" ] && ! _is_valid_ssh_sock "${_SSH_AUTH_LINK}"; then if [ -z "${_CANDIDATE}" ] && [ ! -S "${_SSH_AUTH_LINK}" ]; then
_CANDIDATE=$(get_local_ssh_agent_sock) _FOUND=""
if [ "$(uname)" = "Darwin" ]; then
_FOUND=$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null)
elif command -v systemctl >/dev/null 2>&1; then
# Query systemd socket units directly to avoid environment overrides.
for _u in ssh-agent.socket openssh-agent.socket gcr-ssh-agent.socket gpg-agent-ssh.socket; do
_P=$(systemctl --user show "${_u}" -p Listen 2>/dev/null | cut -d= -f2- | cut -d' ' -f1)
if [ -S "${_P}" ]; then
_FOUND="${_P}"
break
fi
done
# Fallback to systemd environment
if [ -z "${_FOUND}" ] || _is_link_path "${_FOUND}"; then
_FOUND=$(systemctl --user show-environment 2>/dev/null | grep "^SSH_AUTH_SOCK=" | cut -d= -f2-)
fi
fi fi
# 3. Sync the stable link if we found a valid "real" socket. if [ -S "${_FOUND}" ] && ! _is_link_path "${_FOUND}"; then
if [ -n "${_CANDIDATE}" ] && ! _is_link_path "${_CANDIDATE}" && _is_valid_ssh_sock "${_CANDIDATE}"; then _CANDIDATE="${_FOUND}"
fi
fi
# 3. Last resort: search common paths if we still don't have a candidate and the link is broken.
if [ ! -S "${_CANDIDATE}" ] && [ ! -S "${_SSH_AUTH_LINK}" ]; then
_U=$(id -u)
for _p in "/run/user/${_U}/keyring/ssh" "/run/user/${_U}/ssh-agent.socket" "/run/user/${_U}/openssh_agent" "/run/user/${_U}/gnupg/S.gpg-agent.ssh"; do
if [ -S "${_p}" ] && ! _is_link_path "${_p}"; then
_CANDIDATE="${_p}"
break
fi
done
if [ -z "${_CANDIDATE}" ]; then
# Build search path list based on what actually exists
_SEARCH=""
for _d in "/run/user/${_U}" /tmp; do [ -d "${_d}" ] && _SEARCH="${_SEARCH} ${_d}"; done
if [ -n "${_SEARCH}" ]; then
_CANDIDATE=$(find ${_SEARCH} -maxdepth 2 -type s -name 'agent.*' 2>/dev/null | grep -F -v "${_SSH_AUTH_LINK}" | head -n 1)
fi
fi
fi
# 4. Sync the stable link if we found a valid "real" socket.
if [ -S "${_CANDIDATE}" ] && ! _is_link_path "${_CANDIDATE}"; then
mkdir -p "$(dirname "${_SSH_AUTH_LINK}")" mkdir -p "$(dirname "${_SSH_AUTH_LINK}")"
ln -sf "${_CANDIDATE}" "${_SSH_AUTH_LINK}" ln -sf "${_CANDIDATE}" "${_SSH_AUTH_LINK}"
export SSH_AUTH_SOCK="${_SSH_AUTH_LINK}" export SSH_AUTH_SOCK="${_SSH_AUTH_LINK}"
@@ -245,18 +175,17 @@ case "$-" in
if command -v systemctl >/dev/null 2>&1; then if command -v systemctl >/dev/null 2>&1; then
systemctl --user set-environment SSH_AUTH_SOCK="${_SSH_AUTH_LINK}" 2>/dev/null systemctl --user set-environment SSH_AUTH_SOCK="${_SSH_AUTH_LINK}" 2>/dev/null
fi fi
elif _is_valid_ssh_sock "${_SSH_AUTH_LINK}"; then elif [ -S "${_SSH_AUTH_LINK}" ]; then
# If we found nothing better but the link is valid, use it. # If we found nothing better but the link is valid, use it.
export SSH_AUTH_SOCK="${_SSH_AUTH_LINK}" export SSH_AUTH_SOCK="${_SSH_AUTH_LINK}"
fi fi
unset _SSH_AUTH_LINK _CANDIDATE unset _SSH_AUTH_LINK _CANDIDATE _FOUND _T _P _U _u _SEARCH _d
;; unset -f _is_link_path
esac
# Setup XDG-like dirs on MacOS # Setup XDG-like dirs on MacOS
# Based on https://leebyron.com/til/mac-xdg/ # Based on https://leebyron.com/til/mac-xdg/
if [ "${_UNAME}" = "Darwin" ] ; then if [ "$(uname)" = "Darwin" ] ; then
export XDG_BIN_HOME="${XDG_BIN_HOME:-$HOME/.local/bin}" export XDG_BIN_HOME="${XDG_BIN_HOME:-$HOME/.local/bin}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/Library/Caches}" export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/Library/Caches}"
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
@@ -265,12 +194,8 @@ if [ "${_UNAME}" = "Darwin" ] ; then
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$TMPDIR/runtime-$(id -u)}" export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$TMPDIR/runtime-$(id -u)}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export PATH="${HOME}/bin/macos:${PATH}" export PATH="${HOME}/bin/macos:${PATH}"
elif [ "${_UNAME}" = "Linux" ] ; then
export PATH="${HOME}/bin/linux:${PATH}"
fi fi
unset _UNAME
if test -e "$HOME/.localenv"; then if test -e "$HOME/.localenv"; then
# shellcheck source=/dev/null # shellcheck source=/dev/null
. "$HOME/.localenv" . "$HOME/.localenv"

View File

@@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDYQOAB5bJ9DjMXyY67GEI99kK1LG8XF+cWJ4md52rPnOeJd0da7l26bn9NtXCma6DP5gZQArfxHsPh7I4SbYJRYxTCCCE/Jsd8mLB22DcoeY+MqPA2g71j3KrYsvuJC++9GHK2Xc7ZRmhAugEmC/NAdtORBVhtBSAUgyCmUczKHoCAqHmq8j54En8kRYjbvlHPpDsNoRuhcH5uDGBIVkbV7UtBl2oUlRNVw7grs6XS7cPU2zCQSxcrRRuAfV4hmGG2eKaPpieNg0MAAbR0G5ssWW3IuYwd1ys5wA0YQuWUhxadUuYc46/cqyyoVIFlfjxCVTX+2w3900SDPOF/YrOwctAb23+78WN6GPnAmmS3zcmXTGsJiw/mmyBlqYI/JdSgrgI+COlcP0rlF/uklzEywfD91m1lno1u2IApdAumZWHR8aFnpHQXfI6rWc1o/V+RBpz5Xe6D2h9CPT3AE303BV09HGmidb0t6bCKoabTDwvE+KojIcbKBji6g8V6KTM=

View File

@@ -1 +0,0 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOP0EQthckpi83EoFXtbPnn4Ytd7FYW6Nb3W9ZahqOKhNAqv1owot957ihKHtGKFnYr0Jwgp0TNOdpz6nV9wwCo= david@zazu

View File

@@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINFlZdKMzY8S/znw16R3X9jO+BaJ30NloH9XWtftjYh6 david@baymax.local

View File

@@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBeDzE5KLJh2a9p0u702H9+rvaB1HoLLBU1I2Lx6NUbC david@scar

View File

@@ -1 +0,0 @@
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBF8YzO0pEZ9DKHyqgPZpwlv6s4FBYDunIV23R4VUfiC3dw3P1vX9+tDO2+K65v+0vL2rAuBr5ZAHmDxiY8PzDwoAAAAEc3NoOg== david@zazu-sk

View File

@@ -45,7 +45,7 @@ set -g window-status-current-style fg=colour235,bg=colour33,bold
set -g status-interval 60 set -g status-interval 60
set -g status-left-length 30 set -g status-left-length 30
set -g status-left '/#h: #S/ ' set -g status-left '/#h: #S/ '
set -g status-right '#{?pane_title,/#{pane_title}/ ,}#(uptime | rev | cut -d":" -f1 | rev | sed s/,//g)#[default] #[fg=colour166]%H:%M#[default]' set -g status-right '#{?pane_title,/#{pane_title}/ ,}#(cut -d " " -f 1-3 /proc/loadavg)#[default] #[fg=colour166]%H:%M#[default]'
# Advanced mouse mode from http://tangledhelix.com/blog/2012/07/16/tmux-and-mouse-mode/ # Advanced mouse mode from http://tangledhelix.com/blog/2012/07/16/tmux-and-mouse-mode/
# Toggle mouse on # Toggle mouse on
@@ -65,9 +65,8 @@ bind M \
display 'Mouse: OFF' display 'Mouse: OFF'
# tmux X clipboard integration # tmux X clipboard integration
if-shell 'test "$(uname)" = "Darwin"' \ bind C-c run "tmux show-buffer | xsel -i -b"
'bind C-c run "tmux show-buffer | pbcopy"; bind C-v run "tmux set-buffer -- \"$(pbpaste)\"; tmux paste-buffer"' \ bind C-v run "tmux set-buffer -- \"$(xsel -o -b)\"; tmux paste-buffer"
'bind C-c run "tmux show-buffer | xsel -i -b"; bind C-v run "tmux set-buffer -- \"$(xsel -o -b)\"; tmux paste-buffer"'
# List of plugins # List of plugins
set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tpm'

View File

@@ -1,11 +1,8 @@
# For interactive shells # For interactive shells
[[ -n "$ZSH_PROFILE" ]] && { [[ -n "$ZSH_PROFILE" ]] && {
zmodload zsh/datetime zmodload zsh/datetime
zmodload zsh/zprof
export PS4='+[%D{%f} / %D{%s.%N}] %N:%i> '
exec 3>&2 2>/tmp/zsh_startup.log
set -x
zshrc_start_time=$EPOCHREALTIME zshrc_start_time=$EPOCHREALTIME
zmodload zsh/zprof
} }
HISTFILE=~/.zhistory HISTFILE=~/.zhistory
HISTSIZE=10000 HISTSIZE=10000
@@ -62,8 +59,6 @@ DIRSTACKSIZE=16
export OS="$(uname 2>/dev/null || echo "Unknown")" export OS="$(uname 2>/dev/null || echo "Unknown")"
source ~/.commonrc.sh
# Set terminal title # Set terminal title
case $TERM in case $TERM in
# Only set the title for terminals that are likely to support it # Only set the title for terminals that are likely to support it
@@ -132,12 +127,7 @@ case $TERM in
else else
# this will also work in tmux but is not what we want # this will also work in tmux but is not what we want
# Set the terminal title to include the command being run # Set the terminal title to include the command being run
# Skip adding (cmd) in iTerm2 — shell integration already injects the job name
if [[ -z "$ITERM_SESSION_ID" ]]; then
print -Pn "\e]0;%n@%m: %~ ($cmd)\a" print -Pn "\e]0;%n@%m: %~ ($cmd)\a"
else
print -Pn "\e]0;%n@%m: %~\a"
fi
fi fi
} }
# Add the hooks to zsh # Add the hooks to zsh
@@ -173,9 +163,28 @@ bindkey '^r' history-incremental-search-backward
# delete really deletes # delete really deletes
bindkey "^[[3~" delete-char bindkey "^[[3~" delete-char
source_if_existing() {
[[ -f "${1}" ]] && source "${1}"
}
path_prepend "${HOME}/.npm-packages/bin" source_first_existing() {
path_prepend "${HOME}/.local/bin" while (($#)); do
if test -e "${1}" ; then
source "${1}"
return
fi
shift
done
return 1
}
have_command() {
command -v "${1}" &>/dev/null
}
if test -d ${HOME}/.local/bin ; then
export PATH="${HOME}/.local/bin:${PATH}"
fi
# Source extras and aliases if interactive # Source extras and aliases if interactive
if [[ $- == *i* ]] ; then if [[ $- == *i* ]] ; then
@@ -222,7 +231,7 @@ if [[ $- == *i* ]] ; then
if [[ ! -f "$DUMPFILE" || ( -n "$newest_comp" && "$newest_comp" -nt "$DUMPFILE" ) ]]; then if [[ ! -f "$DUMPFILE" || ( -n "$newest_comp" && "$newest_comp" -nt "$DUMPFILE" ) ]]; then
compinit -i -d "$DUMPFILE" compinit -i -d "$DUMPFILE"
# Asynchronously compile the dump file with an atomic rename # Asynchronously compile the dump file with an atomic rename
{ zcompile "$DUMPFILE.zwc.$$.tmp" "$DUMPFILE" && mv -f "$DUMPFILE.zwc.$$.tmp" "$DUMPFILE.zwc" } &! { zcompile "$DUMPFILE.zwc.tmp" "$DUMPFILE" && mv -f "$DUMPFILE.zwc.tmp" "$DUMPFILE.zwc" } &!
else else
compinit -C -i -d "$DUMPFILE" compinit -C -i -d "$DUMPFILE"
fi fi
@@ -261,7 +270,8 @@ if [[ $- == *i* ]] ; then
if command -v direnv >/dev/null 2>&1 ; then if command -v direnv >/dev/null 2>&1 ; then
eval "$(direnv hook zsh)" eval "$(direnv hook zsh)"
fi fi
source_if_existing "${HOME}/.iterm2_shell_integration.zsh" test -e "${HOME}/.iterm2_shell_integration.zsh" && \
source "${HOME}/.iterm2_shell_integration.zsh" || true
# mise, if installed # mise, if installed
command -v mise >/dev/null 2>&1 && eval "$(mise activate zsh)" command -v mise >/dev/null 2>&1 && eval "$(mise activate zsh)"
@@ -276,11 +286,9 @@ if [ -x /usr/bin/ack-grep ] ; then
fi fi
# I want these first always # I want these first always
path_prepend "${HOME}/bin" PATH="${HOME}/bin:${PATH}"
if [[ "$(uname)" == "Darwin" ]]; then if [[ "$(uname)" == "Darwin" ]]; then
path_prepend "${HOME}/bin/macos" PATH="${HOME}/bin/macos:${PATH}"
elif [[ "$(uname)" == "Linux" ]]; then
path_prepend "${HOME}/bin/linux"
fi fi
# Load any local settings # Load any local settings
@@ -306,8 +314,6 @@ typeset -U PATH
if [[ -n "$ZSH_PROFILE" ]]; then if [[ -n "$ZSH_PROFILE" ]]; then
zshrc_end_time=$EPOCHREALTIME zshrc_end_time=$EPOCHREALTIME
set +x
exec 2>&3 3>&-
# Calculation in ms using zsh floating point math # Calculation in ms using zsh floating point math
elapsed_ms=$(( (zshrc_end_time - zshrc_start_time) * 1000 )) elapsed_ms=$(( (zshrc_end_time - zshrc_start_time) * 1000 ))
printf "zshrc done: %.0fms\n" "$elapsed_ms" printf "zshrc done: %.0fms\n" "$elapsed_ms"

View File

@@ -18,15 +18,8 @@ alert() {
icon="error" icon="error"
fi fi
if [ "$(uname)" = "Darwin" ]; then
# macOS notification
local title="Finished: '$*'"
local msg="Exit code: $ret"
osascript -e "display notification \"$msg\" with title \"$title\""
else
# Send the notification with the executed command # Send the notification with the executed command
notify-send --urgency=low -i "$icon" "Finished: '$@'" notify-send --urgency=low -i "$icon" "Finished: '$@'"
fi
# Return the original exit code # Return the original exit code
return $ret return $ret

View File

@@ -1,12 +1,7 @@
if [ "$(uname)" = "Darwin" ]; then
ANDROID_HOME=$HOME/Library/Android/sdk ANDROID_HOME=$HOME/Library/Android/sdk
else
ANDROID_HOME=$HOME/Android/Sdk
fi
if test -d "${ANDROID_HOME}" ; then if test -d $ANDROID_HOME ; then
export ANDROID_HOME PATH=$PATH:$ANDROID_HOME/emulator:$ANDROID_HOME/platform-tools
PATH="${PATH}:${ANDROID_HOME}/emulator:${ANDROID_HOME}/platform-tools"
else else
unset ANDROID_HOME unset ANDROID_HOME
fi fi

View File

@@ -6,11 +6,7 @@ if have_command nasm && have_command objdump ; then
local TMPF=`mktemp` local TMPF=`mktemp`
local bytes local bytes
local byte local byte
local format="elf" $NASM -f elf -o $TMPF $1
if [[ "$OSTYPE" == darwin* ]]; then
format="macho64"
fi
$NASM -f $format -o $TMPF $1
$OBJDUMP -M intel -d $TMPF | grep '^ ' | cut -f2 | while read -A bytes ; do $OBJDUMP -M intel -d $TMPF | grep '^ ' | cut -f2 | while read -A bytes ; do
for byte in $bytes ; do for byte in $bytes ; do
echo -n "\\\\x$byte" echo -n "\\\\x$byte"

View File

@@ -14,8 +14,4 @@
have_command docker && \ have_command docker && \
missing_comp _docker && \ missing_comp _docker && \
docker completion zsh > $COMPDIR/_docker || true docker completion zsh > $COMPDIR/_docker || true
have_command resticprofile && \
missing_comp _resticprofile && \
resticprofile generate --zsh-completion > $COMPDIR/_resticprofile || true
} &>/dev/null &! } &>/dev/null &!

View File

@@ -1,19 +1,26 @@
function dumpenv { function dumpenv {
if [ "$(uname)" = "Linux" ]; then
tr '\0' '\n' < /proc/${1}/environ tr '\0' '\n' < /proc/${1}/environ
elif [ "$(uname)" = "Darwin" ]; then
# macOS doesn't have /proc, use ps instead.
# Note: this may truncate if environment is very large.
ps -p ${1} -wwwe -o command= | tr ' ' '\n' | grep '='
fi
} }
_STARSHIP_PATH="$(find_first "$(command -v starship)" /sbin/starship "${HOME}/tools/starship/starship" "${HOME}/.local/bin/starship" /usr/local/bin/starship)" if test -x "/sbin/starship" ; then
if test -n "$_STARSHIP_PATH" ; then _STARSHIP_PATH="/sbin/starship"
function starship_prompt { function starship_prompt {
eval "$($_STARSHIP_PATH init zsh)" eval "$(/sbin/starship init zsh)"
}
elif test -x "${HOME}/tools/starship/starship" ; then
_STARSHIP_PATH="${HOME}/tools/starship/starship"
function starship_prompt {
eval "$($HOME/tools/starship/starship init zsh)"
} }
fi fi
if test -f ${HOME}/.zprompt ; then
if test "$(cat ${HOME}/.zprompt)" = "starship" ; then
if test -n "${_STARSHIP_PATH:-}" ; then
eval "$(${_STARSHIP_PATH} init zsh)"
fi
fi
fi
unset _STARSHIP_PATH
function hashall { function hashall {
tee >(md5sum) | tee >(sha1sum) | sha256sum tee >(md5sum) | tee >(sha1sum) | sha256sum
@@ -72,27 +79,3 @@ function generate_secure_key {
local BYTES=$((BITS/8)) local BYTES=$((BITS/8))
head -c "${BYTES}" /dev/urandom | ${(s: :)ENCODE} head -c "${BYTES}" /dev/urandom | ${(s: :)ENCODE}
} }
function reset-ssh-socket {
reset_ssh_socket "$@"
}
function with-local-ssh-agent {
local sock
sock=$(get_local_ssh_agent_sock)
if [[ -z "${sock}" ]] ; then
echo "with-local-ssh-agent: no valid local ssh-agent socket found." >&2
return 1
fi
if [ "$#" -eq 0 ] ; then
(
export SSH_AUTH_SOCK="${sock}"
"${SHELL:-zsh}"
)
else
(
export SSH_AUTH_SOCK="${sock}"
eval "$@"
)
fi
}

View File

@@ -1,20 +1,8 @@
# Find src-hilite-lesspipe.sh test -f /usr/share/source-highlight/src-hilite-lesspipe.sh && \
_SRCHILITE=""
for _p in /usr/share/source-highlight/src-hilite-lesspipe.sh /opt/homebrew/bin/src-hilite-lesspipe.sh /usr/local/bin/src-hilite-lesspipe.sh ; do
if [ -f "$_p" ] ; then
_SRCHILITE="$_p"
break
fi
done
if [ -n "$_SRCHILITE" ] ; then
function srcless { function srcless {
if [ $# -ne 1 ] ; then if [ $# -ne 1 ] ; then
echo "Usage: srcless <file>" > /dev/stderr echo "$0 <what>" > /dev/stderr
return 1 return 1
fi fi
"$_SRCHILITE" "$1" | less -R /usr/share/source-highlight/src-hilite-lesspipe.sh $1 | less -R
} }
fi
unset _SRCHILITE _p

View File

@@ -3,17 +3,6 @@
# Skelify -- move a file to my .skel and setup symlinks # Skelify -- move a file to my .skel and setup symlinks
function skelify { function skelify {
local -A opts
zparseopts -D -A opts -overlay:
local overlay_name="${opts[--overlay]}"
local base_skel_dir="${HOME}/.skel/dotfiles"
local extra_args=()
if [[ -n "${overlay_name}" ]]; then
base_skel_dir="${HOME}/.skel/dotfile_overlays/${overlay_name}"
extra_args=(--overlay "${overlay_name}")
fi
local target local target
local whichdir local whichdir
local relhome local relhome
@@ -21,19 +10,16 @@ function skelify {
local fulltarget local fulltarget
for target in $~@; do for target in $~@; do
if test -d ${target} ; then if test -d ${target} ; then
skelify "${extra_args[@]}" ${target}/* || return 1 skelify ${target}/* || return 1
elif test -f ${target} ; then elif test -f ${target} ; then
if ! whichdir=$(cd $(dirname $target) && pwd); then if ! whichdir=$(cd $(dirname $target) && pwd); then
echo Could not find directory for $target >/dev/stderr echo Could not find directory for $target >/dev/stderr
return 1 return 1
fi fi
fname=$(basename ${target}) fname=$(basename ${target})
fulltarget="${whichdir}/${fname}"
if [[ ${whichdir} == ${HOME} ]] ; then
relhome=""
elif [[ ${whichdir} == ${HOME}/* ]] ; then
relhome=${whichdir#${HOME}/} relhome=${whichdir#${HOME}/}
else fulltarget="${whichdir}/${fname}"
if [[ ${relhome} == ${whichdir} ]] ; then
echo ${whichdir} is not in home >/dev/stderr echo ${whichdir} is not in home >/dev/stderr
return 1 return 1
fi fi
@@ -46,7 +32,7 @@ function skelify {
return 1 return 1
fi fi
echo ${target} echo ${target}
local skeldir="${base_skel_dir}/${relhome}" local skeldir="${HOME}/.skel/dotfiles/${relhome}"
mkdir -p "${skeldir}" mkdir -p "${skeldir}"
mv ${target} "${skeldir}/${fname}" mv ${target} "${skeldir}/${fname}"
ln -s "${skeldir}/${fname}" "${fulltarget}" ln -s "${skeldir}/${fname}" "${fulltarget}"

View File

@@ -1,56 +0,0 @@
# utility function to "open" a file
o() {
if [[ "$OSTYPE" == "darwin"* ]]; then
open "$@"
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
xdg-open "$@"
else
echo "Unknown OS"
fi
}
# Copy from stdin to the system clipboard
syscopy() {
if command -v pbcopy >/dev/null 2>&1; then
# macOS
pbcopy "$@"
elif command -v wl-copy >/dev/null 2>&1; then
# Linux Wayland
wl-copy "$@"
elif command -v xclip >/dev/null 2>&1; then
# Linux X11
xclip -selection clipboard "$@"
elif command -v xsel >/dev/null 2>&1; then
# Linux X11 (alternative)
xsel --clipboard --input "$@"
elif command -v clip.exe >/dev/null 2>&1; then
# Windows WSL
clip.exe "$@"
else
echo "Error: No clipboard utility found. Please install pbcopy, wl-copy, xclip, or xsel." >&2
return 1
fi
}
# Paste from the system clipboard to stdout
syspaste() {
if command -v pbpaste >/dev/null 2>&1; then
# macOS
pbpaste "$@"
elif command -v wl-paste >/dev/null 2>&1; then
# Linux Wayland
wl-paste "$@"
elif command -v xclip >/dev/null 2>&1; then
# Linux X11
xclip -selection clipboard -o "$@"
elif command -v xsel >/dev/null 2>&1; then
# Linux X11 (alternative)
xsel --clipboard --output "$@"
elif command -v powershell.exe >/dev/null 2>&1; then
# Windows WSL
powershell.exe -noprofile -command Get-Clipboard "$@"
else
echo "Error: No clipboard utility found. Please install pbpaste, wl-paste, xclip, or xsel." >&2
return 1
fi
}

View File

@@ -7,65 +7,14 @@ set -o errexit
set -o shwordsplit 2>/dev/null || true # Make zsh behave like bash set -o shwordsplit 2>/dev/null || true # Make zsh behave like bash
HOME=${HOME:-$(cd ~ && pwd)} HOME=${HOME:-$(cd ~ && pwd)}
LOCAL_BIN="${HOME}/.local/bin"
STARSHIP_INSTALL_HASH="52c64f14a558034ebeb1907ea9364e802b32474576fd3e68265f73bc33cc8fbb"
# 1. Get the raw script path (handles Bash vs Zsh)
TARGET="${BASH_SOURCE[0]}"
# 2. Loop to resolve symlinks completely
while [ -L "$TARGET" ]; do
DIR=$(cd -P "$(dirname -- "$TARGET")" &>/dev/null && pwd)
TARGET=$(readlink "$TARGET")
# If $TARGET is a relative symlink, resolve it relative to the symlink's directory
[[ $TARGET != /* ]] && TARGET="$DIR/$TARGET"
done
# 3. Get the final absolute directory
SCRIPT_DIR="$(cd -P "$(dirname -- "$TARGET")" &>/dev/null && pwd)"
have_command() { have_command() {
command -v "${1}" >/dev/null 2>&1 command -v "${1}" >/dev/null 2>&1
} }
raw_sha256sum() {
local file="${1}"
if [[ -z "${file}" ]]; then
echo "Error: No file specified" >&2
return 1
fi
if [[ ! -f "${file}" ]]; then
echo "Error: File not found: ${file}" >&2
return 1
fi
if have_command sha256sum ; then
sha256sum "${file}" | awk '{print $1}'
elif have_command shasum ; then
shasum -a 256 "${file}" | awk '{print $1}'
else
echo "Error: Neither sha256sum nor shasum is available" >&2
return 1
fi
}
sudo_group() {
if [[ "$(id -u)" -eq 0 ]] ; then
return 0
fi
have_command sudo && ( id -Gn | grep -q '\bsudo\b' )
}
maybe_sudo() {
if [[ "$(id -u)" -eq 0 ]] ; then
"$@"
return
fi
if ! have_command sudo ; then
return 1
fi
sudo "$@"
}
link_directory_contents() { link_directory_contents() {
local SRCDIR="${1}" local SRCDIR="${1}"
@@ -86,6 +35,48 @@ link_directory_contents() {
done done
} }
ssh_key_already_installed() {
# Return 1 if the key isn't already installed, 0 if it is
local AK="${HOME}/.ssh/authorized_keys"
if [[ ! -f "$AK" ]] ; then
return 1
fi
# Extract the key data (field 2) from the key file, ignoring comments
local key_data
key_data=$(awk '/^ssh-/ {print $2}' "$1")
if [[ -z "${key_data}" ]]; then
# Not a valid key file
return 1
fi
# Use grep with fixed-string matching to see if the key is present.
# The exit code of grep is 0 on match, 1 on no match, which is perfect.
grep -F -q -- "${key_data}" "${AK}"
}
install_ssh_keys() {
# Install SSH keys
verbose 'Installing SSH keys...'
local AK="${HOME}/.ssh/authorized_keys"
local key
local keydir
if [[ "${TRUST_ALL_KEYS}" = 1 ]] ; then
keydir="${BASEDIR}/keys/ssh"
else
keydir="${BASEDIR}/keys/ssh/trusted"
fi
for key in "${keydir}"/* ; do
if [[ ! -f "${key}" ]] ; then
continue
fi
if ssh_key_already_installed "${key}" ; then
verbose "Key $(basename "${key}") already installed..."
continue
fi
echo "# $(basename "${key}") added from skel on $(date +%Y-%m-%d)" >> "${AK}"
cat "${key}" >> "${AK}"
done
}
install_gpg_keys() { install_gpg_keys() {
have_command gpg || \ have_command gpg || \
return 0 return 0
@@ -99,7 +90,7 @@ install_known_hosts() {
verbose 'Installing known hosts...' >&2 verbose 'Installing known hosts...' >&2
local skel_hosts="${BASEDIR}/keys/known_hosts" local skel_hosts="${BASEDIR}/keys/known_hosts"
local user_hosts="${HOME}/.ssh/known_hosts" local user_hosts="${HOME}/.ssh/known_hosts"
local merge_script="${BASEDIR}/skeltools/merge_known_hosts" local merge_script="${BASEDIR}/skeltools/merge_authorized_keys"
if [[ ! -f "${skel_hosts}" ]]; then if [[ ! -f "${skel_hosts}" ]]; then
return 0 return 0
@@ -130,10 +121,7 @@ install_known_hosts() {
} }
install_keys() { install_keys() {
if [[ -x "${BASEDIR}/bin/update-authorized-keys" ]]; then install_ssh_keys
verbose 'Installing SSH keys via update-authorized-keys...'
printf 'y\n' | "${BASEDIR}/bin/update-authorized-keys"
fi
install_gpg_keys install_gpg_keys
install_known_hosts install_known_hosts
} }
@@ -151,12 +139,13 @@ read_saved_prefs() {
save_prefs() { save_prefs() {
[[ "$SAVE" = 1 ]] || return 0 [[ "$SAVE" = 1 ]] || return 0
local pref_file="${BASEDIR}/.installed-prefs" local pref_file=${BASEDIR}/.installed-prefs
{ {
printf 'BASEDIR=%q\n' "${BASEDIR}" echo "BASEDIR=\"${BASEDIR}\""
printf 'MINIMAL=%q\n' "${MINIMAL}" echo "MINIMAL=\"${MINIMAL}\""
printf 'INSTALL_KEYS=%q\n' "${INSTALL_KEYS}" echo "INSTALL_KEYS=\"${INSTALL_KEYS}\""
printf 'VERBOSE=%q\n' "${VERBOSE}" echo "TRUST_ALL_KEYS=\"${TRUST_ALL_KEYS}\""
echo "VERBOSE=\"${VERBOSE}\""
} >| "$pref_file" } >| "$pref_file"
} }
@@ -187,55 +176,6 @@ install_dotfiles() {
fi fi
} }
install_starship() {
if have_command starship ; then return 0 ; fi
if have_command brew ; then
verbose "Attempting to install Starship via Homebrew..."
if brew install starship ; then
return 0
fi
echo "brew install starship failed, trying other methods..." >&2
fi
if have_command apt-get && sudo_group ; then
if maybe_sudo apt-get install -qy starship ; then
return 0
fi
echo "apt-get install starship failed, installing locally" >&2
fi
local tmpd
tmpd="$(mktemp -d "${TMPDIR:-/tmp}/starship.XXXXXX")" || return 1
local install_path="${tmpd}/install.sh"
if have_command curl ; then
curl -sSL --show-error -o "${install_path}" https://starship.rs/install.sh
elif have_command wget ; then
wget -q -O "${install_path}" --https-only https://starship.rs/install.sh
else
echo "No curl or wget available!!" >&2
rm -rf "${tmpd}"
return 1
fi
local dl_hash
dl_hash="$(raw_sha256sum "${install_path}")"
if [[ "$dl_hash" != "${STARSHIP_INSTALL_HASH}" ]] ; then
echo "Hash check failed!!" >&2
echo "Expected: ${STARSHIP_INSTALL_HASH}, got ${dl_hash} on ${install_path}" >&2
rm -rf "${tmpd}"
return 1
fi
if sudo_group ; then
if maybe_sudo sh "${install_path}" ; then
rm -rf "${tmpd}"
return 0
fi
echo "root installation failed, falling back to user-local" >&2
fi
sh "${install_path}" -b "${LOCAL_BIN}"
rm -rf "${tmpd}"
}
install_main() { install_main() {
if [[ -d "${BASEDIR}/.git" ]] && have_command git ; then if [[ -d "${BASEDIR}/.git" ]] && have_command git ; then
if [[ -z "$(git -C "${BASEDIR}" status --porcelain)" ]]; then if [[ -z "$(git -C "${BASEDIR}" status --porcelain)" ]]; then
@@ -245,8 +185,6 @@ install_main() {
fi fi
fi fi
[[ "$MINIMAL" = 1 ]] || { [[ "$MINIMAL" = 1 ]] || {
mkdir -p "${LOCAL_BIN}"
install_starship
# Install vim-plug if not already present # Install vim-plug if not already present
local VIM_PLUG_URL="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim" local VIM_PLUG_URL="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"
@@ -305,9 +243,10 @@ read_saved_prefs
# Defaults if not passed in or saved. # Defaults if not passed in or saved.
# TODO: use flags instead of environment variables. # TODO: use flags instead of environment variables.
: ${BASEDIR:=${SCRIPT_DIR}} : ${BASEDIR:=$HOME/.skel}
: ${MINIMAL:=0} : ${MINIMAL:=0}
: ${INSTALL_KEYS:=1} : ${INSTALL_KEYS:=1}
: ${TRUST_ALL_KEYS:=0}
: ${VERBOSE:=0} : ${VERBOSE:=0}
: ${SAVE:=1} : ${SAVE:=1}

View File

@@ -1,51 +1,3 @@
|1|ZWm0E5aueYzKuoY8OrGAI2ZUdWI=|L8KgVjGyomaw47OGrhpPnipXDKU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKX08QrgyP7du28Re9NlKxLm6aJFUD4F2vWBCuiqo7KNrIPbgjVP9yOwy2gXueC6fbuVQj/C4BdnkgHw9hFXbC0= |1|ZWm0E5aueYzKuoY8OrGAI2ZUdWI=|L8KgVjGyomaw47OGrhpPnipXDKU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKX08QrgyP7du28Re9NlKxLm6aJFUD4F2vWBCuiqo7KNrIPbgjVP9yOwy2gXueC6fbuVQj/C4BdnkgHw9hFXbC0=
|1|MjwrIkZqV0wbZ7pWue9nsFREyhk=|lGN2O8BcMHleUkD4yBtYRXSm1Yw= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwbTUJWJ3mytxrYPKrzRDIuBRd+/X/3T/QT2gudQfDN/mxkAMTg+uLoObXnUOtfhXD+lXP/s/GKXoPmsV/ausSz2YxBrQQXH7SwCpUq5GRXcl5s43JAJ1MbQq2EA5pa1CEBzUgd/Osu/WaVsKwfABV7QeKhblMfM0a5XcsfawqVbMJ0q/egYiSsWRVTU2iNMXILChJT6WUVoUiDENRnW98iy1qQgY0ge6hr7Gh6m23Fg6yfYDBQrqszbTfFYlqGe54bGlnxZvGp+Ybas02D29whAHwdNCSmDWXW0EvSpyt9WZUm0WOQt3t9RXpKeKLrWH4V/5BFYrONY1GsKuE783tw== |1|MjwrIkZqV0wbZ7pWue9nsFREyhk=|lGN2O8BcMHleUkD4yBtYRXSm1Yw= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwbTUJWJ3mytxrYPKrzRDIuBRd+/X/3T/QT2gudQfDN/mxkAMTg+uLoObXnUOtfhXD+lXP/s/GKXoPmsV/ausSz2YxBrQQXH7SwCpUq5GRXcl5s43JAJ1MbQq2EA5pa1CEBzUgd/Osu/WaVsKwfABV7QeKhblMfM0a5XcsfawqVbMJ0q/egYiSsWRVTU2iNMXILChJT6WUVoUiDENRnW98iy1qQgY0ge6hr7Gh6m23Fg6yfYDBQrqszbTfFYlqGe54bGlnxZvGp+Ybas02D29whAHwdNCSmDWXW0EvSpyt9WZUm0WOQt3t9RXpKeKLrWH4V/5BFYrONY1GsKuE783tw==
|1|UsEB5ylyIdmc4gs4TsYqE570DWY=|HAKqUTgFyTzodg8h6veV5jIa9GY= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC75TncmMQKEnnyw1S/uHcvs88d2M1NTMSUZyqdvFbx/uRB2rlrJiQHK8vyvN+fgRH5x8vde+vz/lAFgySV9RoS676cMuBIC8usF8REX2ghSXiSoGw35gd2ztGiDdU7FLUQYW+8FkR1soRjKZgyHqP/NCr4jBXjqDawDE33MA5LdmYy7fl1RN3oK4sY+LIoUWVv5x1aJdV86m0zbciavpU5szL++rnwcx+nWjDFFP4ntH1XyPGftyYpIAZwX+2Vl0+uMgv6sHazOx1E6vOIMx1UapCeLyWXzJ49P8K4iBZcNPH6h9aYllF4PIJ97Auh+fpFKBPfmHLq4iKCz4kKByy7 |1|UsEB5ylyIdmc4gs4TsYqE570DWY=|HAKqUTgFyTzodg8h6veV5jIa9GY= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC75TncmMQKEnnyw1S/uHcvs88d2M1NTMSUZyqdvFbx/uRB2rlrJiQHK8vyvN+fgRH5x8vde+vz/lAFgySV9RoS676cMuBIC8usF8REX2ghSXiSoGw35gd2ztGiDdU7FLUQYW+8FkR1soRjKZgyHqP/NCr4jBXjqDawDE33MA5LdmYy7fl1RN3oK4sY+LIoUWVv5x1aJdV86m0zbciavpU5szL++rnwcx+nWjDFFP4ntH1XyPGftyYpIAZwX+2Vl0+uMgv6sHazOx1E6vOIMx1UapCeLyWXzJ49P8K4iBZcNPH6h9aYllF4PIJ97Auh+fpFKBPfmHLq4iKCz4kKByy7
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
ts-jumpbox.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwbpYiRqlgLKbaUlt1k4ms14+vTW8LKequepWdqDUUx
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
ts-jumpbox.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2itf2fAUO5OB7BNAL9Js8pmxIwzLnOxRMexf5KGswUQRvaZwtw1CitJiyEcYWBt7zksd/Pupmp42ikPVoH7myQlWRbeEmJEIlMvkFF0pjAWj9kGKVLyFDbqXSkewKtXwbJHSo0l+mEOyq8NLlOwAA977BzNTn4z3KQEfYBQQEqISa8NuLpVOFvtQfvBlW+Xeh6+rIm54gdJVDWRimvZ5/FUMaRHPBdMFcXZW1GpraAHjHMeJXTIJs10qFy+5RwGTL5UlvssI+IPAIAW7o0goWmCnrlTjhvJ3Mnwq2lQhAuH/aDqVTptXwMni8tkvPFEC4LeoXG9pmb04Fd6bxY4RnvWuTmcvqOGAxJmZcqOYp1qWhyIF4TTB5l4h3J27sUtluEkTbIGtxTcPjFYLLC1lyIweoQSjWTmi5Z4wz1qfxIYZY1UXnyAjILvLAA5XAIpTgVfDx9KMAFdRrqaKN1MMFvfkTy7CZOfIkWhBwuOxMmtknsiJi8INZc+2CWUuI3Q8=
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
ts-jumpbox.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFs4yUU1aYjy5kq0vr8PFEJUA5s90lYzFTXwHuL9JwtL/wi7tC3I1ifyQnzfZIT8ORMHNGdz/DjNyKkE/rfDhEc=
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# ts-jumpbox.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
omega.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQD7TIDPujGWOMkltfBUKoXOIX9W6KBbqT4qfANNivyjvYeS2joncfoCHTws3vTofHjfyzUSFpnjJSjbwoqTK38CsqSMx06KgpOiiz03+OVbtoBKiwY7smYXh2/vB53+EV4fnM1u/6AqAn0FYT/lUjaY6kBWDppW7PbFKRtO+wShMNfbaY1BTDyEEZRU3PCxR4UDXFO7fQLBiQb/XOyxsSXdRtP6BPrpqxUSq/hNchRo4AP08wtEY5iW9po1RMOFAMKPDND34CyWGbtfnpUCAk9jwKrKDRibRZgIe/xWNcXY9P9zuCSMByB3npo2lG2Em/usiO2awY1pcfrHrlfxJFnD+rzQ9LELwvSB8kPd5xlxZjqmNIvACGEYzR2zdbeOXy+G7biQ7cgELIFRF9aDKOe68sSss3SdS2suAXpqtNBE6l8T9u2jUD0po5EsDcNXPHCS8YLq4wyTpkeDAchX4xm8srycvPD9h4UAE9k+QqjkkbUQw/xpx0SL4pq8Xi6VuO0=
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
omega.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL9cVRkixwE7KL112abP+GosO9+MiVUZQqUdRh4ps5O733cJ8tvkqLVkJhEejIFX6BLlmh/l+j/mD4Z8dL/YqmU=
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
omega.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMoxyWy+cXdpxh/KOhbvzB8Tq7NgWTHofOOpeVzuESe0
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
# omega.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u2
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
xi.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCosFo3gGbGQ7PvHzVZ50umQNEILsqkHWnDi2FqHBCV/pQKUlZVuBO2HT0MiV3QkascJ58P4Jj1Ft/ILKvrU5/dDsW8xVs3vJlmHPrmovD93VwuarzlokmzxWPFOEPZIPcQcQcMCt6k4p/6Pb6hbmPGML2N7XGQHGVDFcflusx07wj56lP9xUtdOLcIo9u3rgw2puXqxUNRtx12Dfo9rjGiFFCXCrvFV5BG4utHKSyAOckJQ/oTzy++idM7jaPbnQ0qjH4GMHm2HN8bmWJdHjc6BeBEW4iQrUxNeisM/hKiICZ3kUmeEynx6IlgEXm0UT+AhxZL7BQo9X45pj5AvaU5
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
xi.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN49oL4rzjwfz5F7cUuVhqe9vRzDAE16O5NQvslhpOx3VA7g8qjyK4SmhhRll+N7vS7OvUqswjEIOXFdK2DUGq8=
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
xi.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIg6N+lwA6feLnLDlm6Ssp45YjnaeCCQSBzeidmAb7FY
# xi.systemoverlord.com:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
chi.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7jSON+Pum/scQMwiBH0jI2fKfQ4q6YKBf/Q/uU7RiEzr3g5lRLA3RtFfWYlxSVqRdlQgeTvIRqG6VMQjtxm/UiLaNT82dVSgoSwJnODVWsKzWQNY1nkhGgd/Ue/XQrBi6UFB7QU7iiIHn8FmJDh05jLv4ymp3DuUM6W066cHqVMSslVhsioAJeZJdpFFK0WXbWs8PT83LT1LERP8CMWuaVlF4UxWwaxROA4WwWaUtiMm0e7T9AgCkHmmEWJemrJqkKUBU0BaqyIvF2bP4tNrZXM8EzT+2Dg25BWS6DzP/d7m8umrpQrYP7cbhK0jzNXw/niEjQ7f8ZiuguRGwWBKX0XjMPY36uiBE/bkGiyF2t27nSPyoA/I2CYtArAabVmiNTeK6qpgf1Xo+aBFuotS3+4Ql+9kfzO9ZL05xIBC2PzvL1pqWmTHI4GICLS2EdMks8LW5ZxvjMS0OdrVf1KaMgmr8TbJT+NIqs1SF3H5kmWUtMvQd4YJgU+o88/sO9LM=
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
chi.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIo6eEuZ1F1GGnkJqkyUTj4oGZlcADbmdahSiwif6pWcx6uGdSemPjQmhFknPbzpzH8HIUtrg/NSBGAjwVINz5Q=
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
chi.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINVUVuOLnuVRiUptQxn+HlUtgv4i5+DMK4uyN4voCB1R
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# chi.systemoverlord.com:22 SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
tau.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMUffrd05Q6iyHj1vbvBzD+xWqR6c/YivTieWVim+b2wHEEYyh7eHXzldXZdLP3QOQHXWc68QwfSav5jsrVhsxk=
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
tau.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/vDSvxXQa20+5OjgQpzxMQZR3m80fsIzHNqfjjAGlVTfPuccMnfCXNgQc8mY8qQTMxbBU4ZlSjntjyIBhWoj5flrTpVjHJgAkntu1dhtDYOp8sd+9CsR/40SX/1l8d6fRzuPSZaVO+RpF9Ym/MrxYH8YprBswl4pzT3/DVCgq3DDNocLzmyjMCgQJXxYpKhlnRSxhLvPHeAi4p0/gHmYhtQe4r0DZ/QaU6a/4bU2shGQyKBUUJbRTrNYwAEukZk+U5AkoQ7N43THB1PtdC0PwmaD2yXHiKzR/6SfLWRBE6TqyQKB0R8+lWWIU5s0Nu512UUS78bchkTtU0mgTpQWP
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
tau.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9+GZcp2imEoxDKY3rxdwGARZ6o/vmPCqrRF9ghxhLa
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
# tau.systemoverlord.com:22 SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
zeta.systemoverlord.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBOPOADAIuJ/khxquXi1/wHyJUp1LqmfLVuHnGoqYouZc7AKcwWDOd30p5bSbrgGMXQC6oflMUsL1VL8hyqZPhs=
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
zeta.systemoverlord.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWTvGafS9utruAmLpDdohEiEWSWVq3H6Mj1Z/hwnjVn67UncYDwLJjZem22r6qnW9h8hF9qpIG+XtU9Yk4iEvUk2H9S3gb7UOxwJ29lx2ckFp8V8Ml9t9gwrNpCVL+oiLm+iCmYMctksWbNXuiGRX22/qfeiM2zwyV3tEWbs/ePtVs5RX0EhbqPR5NHazy0NspE+lLsKeoGT5KsjyehStY69ER4iPKJzeiUxYfXj9wafniNiPZPV9jCDH4DIhkUWoOc1DF0cItVGLRnAWFoAEaWoIfC4ou33cuIfk810kf9uwSTgjVtGiGOC9Pemfc3RsFiUtlg4wpyAerBIvJlvrMAdPRhd1Pteg6QzWYbz0/3dGtyURjRg3uZQIiMre3zHHSKDQbdBL5C+9dM+d/PMdN+86GgwfymPHLoUsRpoY/1yxxqq8Zjc7D40amParpXHOkPzMLJy1F8d10QB52ZDx/7ivuPK55WaWiL3jcBLdim/I2te8EWwR0IgKGlkRYL88=
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
zeta.systemoverlord.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLOty9tztaPoyNUY50daxN3l8rM5+Eg1vMfqefgHWLT
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4
# zeta.systemoverlord.com:22 SSH-2.0-OpenSSH_10.3p1 Debian-4