dotfiles/zsh/.aliases
2026-02-19 22:51:56 -07:00

822 lines
23 KiB
Text

# ~/dotfiles/aliases.sh
# ---- PAI Commands -----
alias cmd='bun ~/.claude/commands/cmd.md'
alias freq='~/.claude/skills/frequency-therapy/tools/freq'
# ---- Fabric -----
yt() {
if [[ "$#" -eq 0 ]] || [[ "$#" -gt 2 ]]; then
echo "Usage: yt [[-t | --timestamps]] youtube-link"
echo "Use the '-t' flag to get the transcript with timestamps."
return 1
fi
transcript_flag="--transcript"
if [[ "$1" = "-t" ]] || [[ "$1" = "--timestamps" ]]; then
transcript_flag="--transcript-with-timestamps"
shift
fi
local video_link="$1"
fabric -y "$video_link" $transcript_flag
}
# Fabric pattern aliases removed - now using lazy loading in ~/.zshenv
# (command_not_found_handler automatically detects fabric patterns)
# ----------------------------
# Sudo Wrapper with PATH Preservation
# ----------------------------
# Preserve PATH when using sudo with user-installed tools
# Usage: S uv pip install something --system (capital S)
alias S='sudo env PATH="$PATH"'
# ----------------------------
# Python Package Managers Quick Reference
# ----------------------------
# pip/pip3/uv → Venv-focused (use for projects)
# pipx → CLI tools (use for global tools like yt-dlp, black, ruff)
# S uv → System install with PATH preserved (only when pipx won't work)
# Pipx management aliases
alias U='pipx upgrade-all' # Update all pipx packages
alias P='pipx list' # List pipx packages
# --- GUI Applications (background + disown) ---
alias nemo='nemo . > /dev/null 2>&1 & disown'
alias hugo-serve='hugo server --bind 0.0.0.0 --baseURL http://localhost:1313 -D > /dev/null 2>&1 & disown'
# --- OpenCode ---
ide() {
local project="${1:-$(pwd)}" # directory to open, pwd if not specified
local editor="${2:-hx}" # default helix
local win_name="ide"
if [[ -n "$TMUX" ]]; then
tmux new-window -n "$win_name" -c "$project"
# Left pane: opencode
tmux select-pane -t 0
tmux send-keys "opencode" C-m
# Split right: right side gets 75%, left remains 25%
tmux split-window -h -p 75 -c "$project" # pane 1 (right)
tmux send-keys "$editor \"$project\"" C-m
# Now on right side, split horizontally for bottom editor (~25%)
tmux select-pane -t 1
# Bottom-right: editor
tmux select-pane -t 2
tmux split-window -v -p 25 -c "$project" # pane 2 (bottom-right)
# Focus back on top-right (main terminal)
tmux select-pane -t 1
else
tmux new-session -s "$win_name" -n main -d -c "$project"
tmux split-window -h -p 75 -c "$project"
tmux select-pane -t 0
tmux send-keys "opencode" C-m
tmux select-pane -t 1
tmux split-window -v -p 25 -c "$project"
tmux select-pane -t 2
tmux send-keys "$editor \"$project\"" C-m
tmux select-pane -t 1
tmux attach -t "$win_name"
fi
}
# TMUX-RECON Aliases
# ----------------------------
# Clipboard (Wayland-first, fallback to X11)
# ----------------------------
if command -v wl-copy &> /dev/null && [[ -n "$WAYLAND_DISPLAY" ]]; then
# Wayland - use wl-clipboard
alias pbcopy='wl-copy'
alias pbpaste='wl-paste'
elif command -v xsel &> /dev/null; then
alias pbcopy='xsel --input --clipboard'
alias pbpaste='xsel --output --clipboard'
elif command -v xclip &> /dev/null; then
alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'
fi
# ----------------------------
# Basic Shortcuts
# ----------------------------
alias a='~/arsenal/run -t'
alias any='~/AnythingLLMDesktop/start'
alias c='clear'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
cpy() {
cat "$1" | pbcopy
}
alias d='docker'
alias dc='docker compose'
# alias h='history'
alias f='fabric'
#f() {
# fd "$1" -exec bat {} +
#}
alias i='sudo apt install'
alias j='journalctl -f'
# Note: jj is now a script in ~/scripts/ (upgraded from alias)
# For quick clipboard pretty-print, still use: pbpaste | jq . | pbcopy
alias jjj='pbpaste | jq .' # Quick view (no copy back)
alias kill='kill $(ps aux | fzf | awk '\''{print $2}'\'')'
# alias k9='kill -9 **'
alias nano='hx'
alias nf='fzf -m --preview="bat --color=always --style=numbers --line-range:300 {}" --bind "enter:become(hx {+})"'
alias oc='opencode'
alias p='parallel'
alias rec='meeting-record' # Override for transcription
alias rec-audio='parecord --device=alsa_output.pci-0000_00_1f.3.analog-stereo.monitor \
--file-format=wav ~/recordings/meeting-$(date +%Y%m%d-%H%M%S).wav'
alias rm='rm -I'
if [[ -n "$ZSH_VERSION" ]]; then
alias s='source ~/.zshrc' # zshrc already sources ~/.aliases and ~/.exports
elif [[ -n "$BASH_VERSION" ]]; then
alias s='source ~/.bashrc' # bashrc already sources ~/.aliases
fi
alias sa='source ~/.aliases'
alias snaabu="sudo /home/$USER/.pdtm/go/bin/naabu"
alias ta='tmux attach -t'
alias trim="awk '{\$1=\$1;print}'"
alias up='sudo apt update && sudo apt upgrade -y'
alias v='fd --type f --hidden --exclude .git | fzf-tmux -p --reverse | xargs hx'
alias vp='fd --type f --hidden --exclude .git | fzf --preview "bat {} --color=always --style=numbers" | xargs hx'
alias vv='hx $(fzf --preview="bat {} --color=always")'
alias gr='glow $(fzf --preview="bat {} --color=always")'
alias xx='exit'
alias eixt='exit'
alias yy='yazi'
# --------------------------------------
# Navigation
# --------------------------------------
# alias ..='cd ..'
# alias ...='cd ../..'
# alias cdf='cd $(fd -t d | fzf)'
# alias cdi='zoxide query -i'
function take {
mkdir -p "$1"
cd "$1" || exit
}
# ----------------------------
# File & Disk Utilities
# ----------------------------
# Unalias potential conflicts
unalias batclip 2>/dev/null
unalias dl 2>/dev/null
batclip() {
bat "$1" | xclip
}
# alias du='dust'
alias dfh='gdu -dn'
dl() {
yt-dlp -f best "$1"
}
if [[ -n "$ZSH_VERSION" ]]; then
alias reload='source ~/.zshrc'
elif [[ -n "$BASH_VERSION" ]]; then
alias reload='source ~/.bashrc'
fi
tailb() {
tail -f "$1" | bat --paging=never -l log
}
# --------------------------------------
# Search / Fuzzy Finder
# --------------------------------------
# alias f='fd -H -I -t f'
# f() { cd "$(find . -type d | fzf)" }
alias fzf="fzf --preview 'bat --color=always {}'"
# alias fzf="fzf --height 40% --layout reverse --border --preview 'bat --color=always {}' --preview-window '~3'"
alias ff='find * -type f | fzf --preview "bat --color=always {}"'
# alias fd='fdfind' # Debian compatibility
# Press F1 to open the file with less without leaving fzf
# Press CTRL-Y to copy the line to clipboard and aborts fzf (requires pbcopy)
alias fo="fzf --bind 'f1:execute(less -f {}),ctrl-y:execute-silent(echo {} | pbcopy)+abort'"
alias psf="ps -ef |
fzf --bind 'ctrl-r:reload(ps -ef)' \
--header 'Press CTRL-R to reload' --header-lines=1 \
--height=50% --layout=reverse"
# List all commands or search through them
if [[ -n "$ZSH_VERSION" ]]; then
alias findcmd='print -l ${(k)commands} | fzf --prompt="Search command: "'
elif [[ -n "$BASH_VERSION" ]]; then
alias findcmd='compgen -c | sort -u | fzf --prompt="Search command: "'
fi
# alias findcmd='compgen -c | sort -u | fzf --prompt="Search command: "'
# alias allcmds='compgen -c | sort -u | fzf'
# ----------------------------
# Taskwarrior
# ----------------------------
alias t='task'
alias tl='task list'
alias twa='task add'
# tm() {
# task modify
# }
# Commented out: conflicts with TabMan alias at line 731
# Use 'task modify' directly or create 'tmod' alias if needed
alias tb='task burndown.daily'
# ----------------------------
# Miscellaneous
# ----------------------------
# Note: note() is now a script in ~/scripts/ (upgraded from function)
# Old notes are still in ~/drafts.txt if you need them
help() {
if builtin help "$1" &>/dev/null; then
builtin help "$1" | bat --plain
else
"$@" --help 2>&1 | bat --plain
fi
}
mdstrip() {
sed -i 's/\\n/\n/g' "$1"
}
# help() {
# "$@" --help 2>&1 | bat --plain --language=txt
# }
# alias shelp='builtin help | bat --plain --language=help'
# alias bathelp='bat --plain --language=help'
# help() {
# "$@" --help 2>&1 | bathelp
# }
# ----------------------------
# Conditional Fallbacks
# ----------------------------
# Debian-specific fix for fd
if ! command -v fd &> /dev/null && command -v fdfind &> /dev/null; then
alias fd='fdfind'
fi
# if command -v bat &> /dev/null; then
# alias cat="bat"
# elif command -v batcat &> /dev/null; then
# alias cat="batcat"
# fi
alias l='eza -lah --icons'
alias sl='eza'
if command -v exa &> /dev/null; then
alias ls='exa'
# alias l='exa -l'
alias lsl='exa --icons'
alias ll='exa -lah --icons'
alias lt='exa -lah --tree --level=3 --icons'
fi
if command -v eza &> /dev/null; then
alias lg='eza -lah --icons --git -a'
# Newest files first (like ls -ltr but reversed to show newest at bottom)
alias ltr='eza --color=always -lrsnew'
alias snew='eza --color=always -lrsnew | head -20' # Newest 20 files
alias lnew='eza --color=always -lsnew | tail -20' # Newest 20 at bottom
fi
# Fallbacks if neither exa nor eza are found
if ! command -v exa &> /dev/null && ! command -v eza &> /dev/null; then
alias ls='ls --color=auto'
alias ll='ls -lah'
alias la='ls -A'
fi
if command -v rg &> /dev/null; then
alias rg='rg --smart-case'
alias rgl='rg --files | fzf --preview "bat --color=always {}"'
fi
if command -v ag &> /dev/null; then
alias ags='ag --smart-case'
alias agf='ag -l | fzf --preview "bat --color=always {}"'
fi
# Smart history with atuin (fallback to fzf if not available)
if command -v atuin &> /dev/null; then
alias h='atuin search --interactive'
else
alias h='history | fzf --preview "echo {}" --preview-window="up:3:wrap"'
fi
# Python as 'py' and pip
alias py='python3'
alias pip='python3 -m pip'
alias serve='python3 -m http.server 80'
# --------------------------------------
# Networking & System Info
# --------------------------------------
alias xh='xh --style auto'
# Note: myip is now a script in ~/scripts/ (upgraded from alias)
alias localip="ip a | grep inet"
if command -v mtr &> /dev/null; then
alias ping='mtr'
else
unalias ping
fi
alias net='bandwhich'
alias sniff='sudo tcpdump -i any -n'
# Note: ports is now a script in ~/scripts/ (upgraded from alias)
alias psnet='sudo netstat -tulnp'
alias fire='sudo ufw status verbose'
alias logs='sudo tail -f /var/log/syslog'
alias chkports='sudo lsof -i -P -n | less'
# unalias zi
# GIT ALIASES -----------------------------------------------------------------
alias gc='git commit'
alias gco='git checkout'
alias ga='git add'
alias gst='git rev-parse --git-dir > /dev/null 2>&1 && git status || eza'
alias grv='git remote -v'
copy-line() {
rg --line-number . | fzf --delimiter ':' --preview 'bat --color=always --highlight-line {2} {1}' | awk -F ':' '{print "+"$2" "$1}'
}
open-at-line() {
hx $(rg --line-number . | fzf --delimiter ':' --preview 'bat --color=always --highlight-line {2} {1}' | awk -F ':' '{print "+"$2" "$1}')
}
# PAI Context Manager
alias cm="~/.claude/commands/context-manager.sh"
alias cms="~/.claude/commands/context-manager.sh search"
alias cmr="~/.claude/commands/context-manager.sh recent"
alias cmn="~/.claude/commands/context-manager.sh new"
alias cmt="~/.claude/commands/context-manager.sh tree"
# Enhanced fzf file operations with better previews
alias fzfg='rg --line-number --color=always . | fzf --ansi --delimiter ":" --preview "bat --color=always --highlight-line {2} {1}" --bind "enter:execute(hx +{2} {1})"'
alias fzfd='fd --type d | fzf --preview "eza --tree --level=2 --color=always {} 2>/dev/null || tree -L 2 -C {}"'
# Better process management
alias psg='ps aux | fzf --header-lines=1 --preview "echo {}" --preview-window=up:1'
# Enhanced git fzf integration
alias gfzf='git log --oneline --color=always | fzf --ansi --preview "git show --color=always {1}" --bind "enter:execute(git show {1} | less -R)"'
# --------------------------------------
# N8N API Helper
# --------------------------------------
# Requires N8N_API_KEY and N8N_BASE_URL in ~/.env
n8n_api() {
source ~/.env
local endpoint="${1:-/workflows}"
shift
curl -s -H "X-N8N-API-KEY: ${N8N_API_KEY}" \
"${N8N_BASE_URL}/api/v1${endpoint}" \
"$@"
}
# --------------------------------------
# Baserow API Helper
# --------------------------------------
# Requires BASEROW_API_KEY and BASEROW_TABLE_ID in ~/.env
# Baserow is on localhost:3000 via SSH tunnel
baserow_api() {
source ~/.env
local endpoint="${1:-database/rows/table/${BASEROW_CONTACTS_TABLE_ID}/}"
if [ $# -gt 0 ]; then
shift
fi
curl -s -H "Authorization: Token ${BASEROW_API_KEY}" \
"http://baserow:3000/api/${endpoint}" \
"$@"
}
alias docker-compose="docker compose"
# ----------------------------
# Manual Redshift Control (Nuclear Option - 2025-10-16)
# ----------------------------
alias night='redshift -O 2600 -P && echo "🌙 Night mode activated (2600K)"'
alias day='redshift -x && echo "☀️ Day mode activated (reset to default)"'
alias evening='redshift -O 3500 -P && echo "🌅 Evening mode activated (3500K)"'
# WhisperTux quick launch aliases
alias wt='systemctl --user start whispertux'
alias wtr='systemctl --user restart whispertux'
alias wt-stop='systemctl --user stop whispertux'
alias wt-status='systemctl --user status whispertux'
alias wt-log='journalctl --user -u whispertux -f'
alias reload='source ~/.zshrc && echo "✅ Shell reloaded - WhisperTux aliases active"'
# ----------------------------
# Evan Hahn Inspired Utilities (Tier 1)
# ----------------------------
# Source: https://evanhahn.com/scripts-i-wrote-that-i-use-all-the-time/
# Copy current directory to clipboard (strips trailing newline)
cpwd() {
pwd | tr -d '\n' | pbcopy
}
# ISO date format for filename prefixes (2025-10-28)
hoy() {
echo -n "$(date '+%Y-%m-%d')"
}
# Text case conversion
alias uppered='tr "[:lower:]" "[:upper:]"'
alias lowered='tr "[:upper:]" "[:lower:]"'
# Print specific line from stdin (usage: cat file | line 10)
line() {
sed -n "${1}p"
}
# Jump to temporary directory
tempe() {
cd "$(mktemp -d)"
}
# True background execution (suppress ALL output)
bb() {
nohup "$@" >/dev/null 2>&1 &
}
# Note: running() is now a script in ~/scripts/ with PID highlighting
# Quick scratch buffer in editor (temp file)
scratch() {
"${EDITOR:-vim}" "$(mktemp)"
}
# Note: tryna and trynafail are now scripts in ~/scripts/
# ----------------------------
# Claude Code Hook Management
# ----------------------------
# Fix Claude Code hooks when they stop firing
# Touches all hook files to force file watcher reload
# Usage: fix-hooks (then wait 60s before sending next message)
alias fix-hooks='cd ~/.claude && touch settings.json hooks/*.ts && echo "✅ Hooks refreshed - wait 60-90 seconds before next message"'
# ----------------------------
# Column Formatting Function Family
# ----------------------------
# col - Column formatter with custom delimiter (supports files and stdin)
# Usage: col <file> [delimiter]
# cat file | col [delimiter]
# Default delimiter is whitespace
# Examples:
# col file.txt # Default whitespace delimiter
# col file.csv ',' # CSV with comma delimiter
# col file.tsv $'\t' # TSV with tab delimiter
# cat file.csv | col ',' # Piped input
col() {
local delim="${2:- }"
if [[ $# -eq 0 ]] || [[ "$1" == "-" ]]; then
# Read from stdin
column -t -s "$delim"
else
# Read from file
local file="$1"
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found" >&2
return 1
fi
column -t -s "$delim" < "$file"
fi
}
# colp - Explicit piped version (alias for clarity)
# Usage: cat file.csv | colp ','
colp() {
local delim="${1:- }"
column -t -s "$delim"
}
colah() { cola "$1" | sed '1s/^/\x1b[1;36m/; 1s/$/\x1b[0m/'; }
# cola - Auto-detect delimiter (CSV/TSV/space)
# Usage: cola <file>
# Automatically detects comma, tab, or space delimiters
cola() {
if [[ $# -eq 0 ]]; then
echo "Usage: cola <file>" >&2
return 1
fi
local file="$1"
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found" >&2
return 1
fi
# Detect delimiter by sampling first line
local first_line=$(head -n1 "$file")
local delim
if [[ "$first_line" =~ $'\t' ]]; then
delim=$'\t'
echo "# Auto-detected: TSV (tab-delimited)" >&2
elif [[ "$first_line" =~ , ]]; then
delim=','
echo "# Auto-detected: CSV (comma-delimited)" >&2
else
delim=' '
echo "# Auto-detected: Space-delimited" >&2
fi
column -t -s "$delim" < "$file"
}
# colh - Column formatter with highlighted header row
# Usage: colh <file> [delimiter]
# First row is displayed in bold cyan
colh() {
if [[ $# -eq 0 ]]; then
echo "Usage: colh <file> [delimiter]" >&2
return 1
fi
local file="$1"
local delim="${2:- }"
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found" >&2
return 1
fi
{
# Header in bold cyan
head -n1 "$file" | column -t -s "$delim" | sed 's/^/\x1b[1;36m/' | sed 's/$/\x1b[0m/'
# Rest of file normal
tail -n+2 "$file" | column -t -s "$delim"
}
}
# coln - Column formatter with numbered rows
# Usage: coln <file> [delimiter]
# Adds line numbers like cat -n
coln() {
if [[ $# -eq 0 ]]; then
echo "Usage: coln <file> [delimiter]" >&2
return 1
fi
local file="$1"
local delim="${2:- }"
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found" >&2
return 1
fi
column -t -s "$delim" < "$file" | nl -w3 -s' '
}
# Bonus: CSV/TSV converters
csv2tsv() {
if [[ $# -eq 0 ]]; then
echo "Usage: csv2tsv <file>" >&2
return 1
fi
sed 's/,/\t/g' "$1"
}
tsv2csv() {
if [[ $# -eq 0 ]]; then
echo "Usage: tsv2csv <file>" >&2
return 1
fi
sed 's/\t/,/g' "$1"
}
# colj - Convert CSV to JSON array (first row = keys)
colj() {
local input
if [[ $# -eq 0 ]] || [[ "$1" == "-" ]]; then
input=$(cat)
else
[[ -f "$1" ]] || { echo "Error: File '$1' not found" >&2; return 1; }
input=$(cat "$1")
fi
# Use Python for reliable CSV parsing (handles quoted fields with commas)
echo "$input" | python3 -c '
import csv, json, sys
reader = csv.DictReader(sys.stdin)
print(json.dumps([row for row in reader], indent=2))
'
}
# ----------------------------
# Reconnaissance & Pentesting Aliases
# ----------------------------
# Note: recon, web-recon, and wes are now scripts in ~/scripts/pentesting/
# Access them directly: recon, web-recon, wes
# Web reconnaissance alias (alternative name)
discover() {
web-recon "$1"
}
# enum4linux-ng docker wrapper
e4l() {
docker run --rm -t enum4linux-ng -A -C "$1"
}
# Naabu + nmap combo (uses pscan if available)
gomap() {
if command -v pscan &>/dev/null; then
pscan "$1" -v
elif command -v naabu &>/dev/null; then
naabu -host "$1" -nmap-cli "nmap $2"
else
echo "Install naabu or use pscan script"
fi
}
# Metasploit multi-handler
msfl() {
if [ ! -f "$HOME/scripts/multi_handler.rc" ]; then
echo -e "\033[0;33m⚠\033[0m multi_handler.rc not found"
echo "Create it at: ~/scripts/multi_handler.rc"
return 1
fi
msfconsole -r "$HOME/scripts/multi_handler.rc"
}
# ================================================================
# System Backup Workflow
# ================================================================
# Full system backup to encrypted volume before major OS changes
#
# Usage:
# 1. Mount encrypted volume:
# sudo veracrypt -t <vault-path> /mnt/veracrypt1
# 2. Run backup:
# run-backup
# 3. Unmount when complete:
# sudo veracrypt -t -d /mnt/veracrypt1
#
# Notes:
# - Uses encrypted storage (VeraCrypt) for data at rest
# - Backup script is in ~/.claude/context/personal/scripts/
# - Logs to /var/log/system-backup.log
# - For low /tmp space, set TMPDIR before mounting:
# mkdir -p /path/to/temp && sudo env TMPDIR=/path/to/temp veracrypt -t ...
# ================================================================
alias run-backup='sudo ~/.claude/context/personal/scripts/full-system-backup.sh /mnt/backup-vault'
# ================================================================
# ProtonVPN Automation - Quick Reference & Documentation
#
# Created: 2025-11-08
#
# Quick reference for VPN server curation and automation system.
# See full docs: ~/.claude/skills/app-troubleshooting/SKILL.md (lines 2130-2369)
#
# Common commands:
# proton-connect-colorado - Connect to random top-quality server
# test-vpn-quality - Test current connection quality
# proton-rank-servers 20 - View top 20 servers by quality
# proton-discover-servers 1 50 - Discover new servers
# ================================================================
alias vpn-help='bat ~/.local/share/doc/protonvpn-automation-quickref.md 2>/dev/null || cat ~/.local/share/doc/protonvpn-automation-quickref.md'
# Kill stale ProtonVPN connections (fixes zombie openvpn after Plasma partial shutdown)
vpn-kill() {
nmcli connection show --active | grep -i proton | while read -r line; do
name=$(echo "$line" | awk '{print $1" "$2}')
nmcli connection down "$name" 2>/dev/null && echo "Disconnected: $name"
done
}
# TabMan - Browser tab manager
alias tabman="bun ~/github/tabman/index.ts"
alias tm="bun ~/github/tabman/index.ts"
# Port reference quick access
alias lp='cat ~/.claude/context/infrastructure/ports-reference.md | less'
# Reddit video downloader for Redlib
alias reddit-dl="bun /home/e/opt/redlib/reddit-dl.ts"
alias inotify-check='echo "Instances: $(find /proc/*/fd -lname "anon_inode:inotify" 2>/dev/null | wc -l) / $(cat /proc/sys/fs/inotify/max_user_instances)"'
# SimpleX Bot - E2EE automation
alias sbot='~/opt/simplex-bot/simplex'
# ----------------------------
# GPG Encryption Helpers
# ----------------------------
# Simple file encryption/decryption using your default GPG key
# Usage: gpg-encrypt notes.md → creates notes.md.gpg
# gpg-decrypt notes.md.gpg → creates notes.md
gpg-encrypt() {
local file="$1"
if [[ -z "$file" ]]; then
echo "Usage: gpg-encrypt <file>" >&2
return 1
fi
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found" >&2
return 1
fi
gpg --output "${file}.gpg" --encrypt --default-recipient-self "$file" \
&& echo "✅ Encrypted: ${file}.gpg"
}
gpg-decrypt() {
local file="$1"
if [[ -z "$file" ]]; then
echo "Usage: gpg-decrypt <file.gpg>" >&2
return 1
fi
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found" >&2
return 1
fi
local output="${file%.gpg}"
if [[ "$output" == "$file" ]]; then
output="${file}.decrypted"
fi
gpg --decrypt "$file" > "$output" \
&& echo "✅ Decrypted: $output"
}
# Standard Notes (AppImage in Downloads)
alias standard-notes='/home/$USER/Downloads/standard-notes-3.201.2-linux-x86_64.AppImage'
alias dailies='~/.claude/context/personal/scripts/daily-reminders.sh'
# ---- Meshtastic -----
mesh-nodes() {
for port in /dev/ttyUSB*; do
[ -e "$port" ] || continue
echo "=== $port ==="
timeout 5 meshtastic --port "$port" --info 2>&1 | grep -iE "Owner|Short Name|Role|Hardware" || echo "No Meshtastic device"
done
}
mesh-send() {
local port="${1:-/dev/ttyUSB0}"
shift
meshtastic --port "$port" --sendtext "$*"
}
mesh-listen() {
local port="${1:-/dev/ttyUSB0}"
meshtastic --port "$port" --listen
}