Skip to content

Instantly share code, notes, and snippets.

@chrisportela
Created December 5, 2025 15:49
Show Gist options
  • Select an option

  • Save chrisportela/caa81de3c22c3223848706248fa24afc to your computer and use it in GitHub Desktop.

Select an option

Save chrisportela/caa81de3c22c3223848706248fa24afc to your computer and use it in GitHub Desktop.
"NixOS Wrapped 2025"

πŸ₯³ NixOS Wrapped (2025)

I asked Claude to write me a script that generates a fun "NixOS Wrapped" output based on the configuration repos I have.

  • Dotfiles: Public NixOS, Home-Manager, and Nix-Darwin configuration
  • Infra: Private config for personal services

I had Claude make it easier to change where your special repos are. Mine are in ~/src/dotfiles and ~/src/infra, but I've update the script for more common locations like /etc/nixos/.

Note: For counting generations it only works on the local machine it's run, but I've provided a commented out "ssh" version too.

πŸŽ‰ Improvements are welcome!

#!/usr/bin/env bash
# ============================================================================
# NixOS Wrapped 2025 - Configuration
# ============================================================================
# Year to analyze
YEAR="2025"
# Local git repositories to analyze (space-separated paths)
REPOS=(
"/etc/nixos/"
#"$HOME/src/dotfiles"
#"$HOME/src/infra"
)
# Remote machines to query for generations (SSH hosts)
# Leave empty to skip remote queries: REMOTE_HOSTS=()
REMOTE_HOSTS=(
# "user@server1"
# "user@server2"
)
# Thresholds for personality messages
THRESHOLD_FLAKE_LOCK_HIGH=50
THRESHOLD_FLAKE_LOCK_MED=20
THRESHOLD_FIX_HIGH=30
THRESHOLD_FIX_MED=10
THRESHOLD_BUILDER_ERA=60 # % new additions to be "builder era"
THRESHOLD_MAINTAINER=30 # % new additions to be "maintainer mode"
THRESHOLD_LARGE_COMMIT_FILES=10
THRESHOLD_LARGE_COMMITS_HIGH=5
THRESHOLD_SERVICES_HIGH=10
THRESHOLD_SERVICES_MED=5
THRESHOLD_COMMITS_WILD=250
THRESHOLD_COMMITS_HIGH=150
THRESHOLD_COMMITS_MED=50
# Services to detect in commit messages
SERVICES_PATTERN="(nextcloud|jellyfin|grafana|prometheus|forgejo|openwebui|home.?assistant|coder)"
# ============================================================================
# Helper Functions
# ============================================================================
ask_yes_no() {
local prompt="$1"
local default="${2:-n}"
if [[ "$default" == "y" ]]; then
prompt="$prompt [Y/n] "
else
prompt="$prompt [y/N] "
fi
read -r -p "$prompt" response
response="${response,,}" # lowercase
if [[ -z "$response" ]]; then
response="$default"
fi
[[ "$response" == "y" || "$response" == "yes" ]]
}
get_highest_generation() {
# Parse generation list and return highest number
grep -E '^\s*[0-9]+' 2>/dev/null | awk '{print $1}' | sort -n | tail -1
}
# This script is sent to remote hosts to gather their generation info
# shellcheck disable=SC2016 # Single quotes intentional - variables expand on remote host
REMOTE_SCRIPT='
#!/usr/bin/env bash
hostname=$(hostname)
sys_gen=$(nix-env --list-generations --profile /nix/var/nix/profiles/system 2>/dev/null | grep -E "^\s*[0-9]+" | awk "{print \$1}" | sort -n | tail -1)
sys_gen=${sys_gen:-0}
hm_gen=0
if [ -d "$HOME/.local/state/nix/profiles" ]; then
hm_gen=$(nix-env --list-generations --profile "$HOME/.local/state/nix/profiles/home-manager" 2>/dev/null | grep -E "^\s*[0-9]+" | awk "{print \$1}" | sort -n | tail -1)
elif [ -d "$HOME/.nix-profile" ]; then
hm_gen=$(nix-env --list-generations 2>/dev/null | grep -E "^\s*[0-9]+" | awk "{print \$1}" | sort -n | tail -1)
fi
hm_gen=${hm_gen:-0}
echo "HOST:$hostname"
echo "SYS_GEN:$sys_gen"
echo "HM_GEN:$hm_gen"
'
# ============================================================================
# Core Functions
# ============================================================================
get_local_system_generations() {
local_sys_generations=0
echo "To count system generations, this script needs to run:"
echo " sudo nix-env --list-generations --profile /nix/var/nix/profiles/system"
echo ""
if ask_yes_no "Allow sudo for this command?"; then
local_sys_generations=$(sudo nix-env --list-generations --profile /nix/var/nix/profiles/system 2>/dev/null | get_highest_generation)
local_sys_generations=${local_sys_generations:-0}
else
echo "Skipping system generation count."
fi
echo ""
}
get_local_hm_generations() {
local_hm_generations=0
if [ -d "$HOME/.local/state/nix/profiles" ]; then
local_hm_generations=$(nix-env --list-generations --profile "$HOME/.local/state/nix/profiles/home-manager" 2>/dev/null | get_highest_generation)
local_hm_generations=${local_hm_generations:-0}
elif [ -d "$HOME/.nix-profile" ]; then
local_hm_generations=$(nix-env --list-generations 2>/dev/null | get_highest_generation)
local_hm_generations=${local_hm_generations:-0}
fi
}
query_remote_machines() {
declare -g -A remote_sys_gens
declare -g -A remote_hm_gens
total_remote_sys=0
total_remote_hm=0
if [ ${#REMOTE_HOSTS[@]} -gt 0 ]; then
echo "πŸ“‘ Querying ${#REMOTE_HOSTS[@]} remote machine(s)..."
echo ""
for host in "${REMOTE_HOSTS[@]}"; do
echo -n " Connecting to $host... "
if result=$(ssh -o ConnectTimeout=5 -o BatchMode=yes "$host" "$REMOTE_SCRIPT" 2>/dev/null); then
hostname=$(echo "$result" | grep "^HOST:" | cut -d: -f2)
sys_gen=$(echo "$result" | grep "^SYS_GEN:" | cut -d: -f2)
hm_gen=$(echo "$result" | grep "^HM_GEN:" | cut -d: -f2)
remote_sys_gens["$hostname"]=$sys_gen
remote_hm_gens["$hostname"]=$hm_gen
total_remote_sys=$((total_remote_sys + sys_gen))
total_remote_hm=$((total_remote_hm + hm_gen))
echo "βœ“ (sys: $sys_gen, hm: $hm_gen)"
else
echo "βœ— (unreachable)"
fi
done
echo ""
fi
}
print_generation_summary() {
total_sys_generations=$((local_sys_generations + total_remote_sys))
total_hm_generations=$((local_hm_generations + total_remote_hm))
echo "πŸ“¦ System Generations: $total_sys_generations total"
if [ "$local_sys_generations" -gt 0 ]; then
echo " └─ local: $local_sys_generations"
fi
for hostname in "${!remote_sys_gens[@]}"; do
echo " └─ $hostname: ${remote_sys_gens[$hostname]}"
done
if [ "$total_hm_generations" -gt 0 ]; then
echo "🏠 Home-Manager Generations: $total_hm_generations total"
if [ "$local_hm_generations" -gt 0 ]; then
echo " └─ local: $local_hm_generations"
fi
for hostname in "${!remote_hm_gens[@]}"; do
if [ "${remote_hm_gens[$hostname]}" -gt 0 ]; then
echo " └─ $hostname: ${remote_hm_gens[$hostname]}"
fi
done
fi
echo ""
}
analyze_git_repos() {
total_commits=0
flake_lock_commits=0
fix_commits=0
merge_commits=0
added_commits=0
updated_commits=0
large_commits=0
services_deployed=0
for repo in "${REPOS[@]}"; do
if [ ! -d "$repo/.git" ]; then
continue
fi
commits=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | wc -l | tr -d ' ')
total_commits=$((total_commits + commits))
flake_locks=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | grep -ci "flake lock")
flake_lock_commits=$((flake_lock_commits + flake_locks))
fixes=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | grep -ciE "^[a-f0-9]+ (fix|fixed)")
fix_commits=$((fix_commits + fixes))
merges=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | grep -ci "^[a-f0-9]+ merge")
merge_commits=$((merge_commits + merges))
added=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | grep -ci "^[a-f0-9]+ add")
added_commits=$((added_commits + added))
updated=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | grep -ci "^[a-f0-9]+ updat")
updated_commits=$((updated_commits + updated))
large=$(git -C "$repo" log --since="$YEAR-01-01" --pretty=format:"%h" --shortstat 2>/dev/null | \
awk -v threshold="$THRESHOLD_LARGE_COMMIT_FILES" '/^ [0-9]+ file/ {if ($1 >= threshold) count++} END {print count+0}')
large_commits=$((large_commits + large))
services=$(git -C "$repo" log --since="$YEAR-01-01" --oneline 2>/dev/null | \
grep -ciE "(added|enabled|setup|configured).*$SERVICES_PATTERN")
services_deployed=$((services_deployed + services))
done
echo "πŸ’Ύ You Made $total_commits Commits To Your Config Repos."
echo ""
}
print_personality_insights() {
if [ "$flake_lock_commits" -gt "$THRESHOLD_FLAKE_LOCK_HIGH" ]; then
echo "πŸ”„ You Updated flake.lock $flake_lock_commits times."
echo " Dependency management is your cardio."
echo ""
elif [ "$flake_lock_commits" -gt "$THRESHOLD_FLAKE_LOCK_MED" ]; then
echo "πŸ”„ You Updated flake.lock $flake_lock_commits times."
echo " Staying fresh with dependencies!"
echo ""
fi
if [ "$fix_commits" -gt "$THRESHOLD_FIX_HIGH" ]; then
echo "πŸ”§ You Fixed Things $fix_commits Times."
echo " Professional bug whisperer status achieved."
echo ""
elif [ "$fix_commits" -gt "$THRESHOLD_FIX_MED" ]; then
echo "πŸ”§ You Fixed Things $fix_commits Times."
echo " The debugging was real this year."
echo ""
fi
if [ "$added_commits" -gt 0 ] && [ "$updated_commits" -gt 0 ]; then
ratio=$((added_commits * 100 / (added_commits + updated_commits)))
if [ "$ratio" -gt "$THRESHOLD_BUILDER_ERA" ]; then
echo "πŸ†• ${ratio}% of your commits were adding new things."
echo " You're in your builder era."
echo ""
elif [ "$ratio" -lt "$THRESHOLD_MAINTAINER" ]; then
echo "πŸ“ Only ${ratio}% of your commits were new additions."
echo " Maintainer mode activated."
echo ""
fi
fi
if [ "$large_commits" -gt "$THRESHOLD_LARGE_COMMITS_HIGH" ]; then
echo "πŸ—οΈ You Did $large_commits Major Restructures."
echo " Brave enough to touch ${THRESHOLD_LARGE_COMMIT_FILES}+ files at once."
echo ""
elif [ "$large_commits" -gt 0 ]; then
echo "πŸ—οΈ You Did $large_commits Major Restructures."
echo ""
fi
if [ "$services_deployed" -gt "$THRESHOLD_SERVICES_HIGH" ]; then
echo "πŸš€ You Deployed/Configured Services $services_deployed Times."
echo " Your homelab is basically a small datacenter."
echo ""
elif [ "$services_deployed" -gt "$THRESHOLD_SERVICES_MED" ]; then
echo "πŸš€ You Deployed/Configured Services $services_deployed Times."
echo " Self-hosting champion."
echo ""
fi
}
print_punchline() {
echo "━━━━━━━━━━━━━━━━━━━━"
if [ "$total_commits" -gt "$THRESHOLD_COMMITS_WILD" ]; then
echo "❓ Do You Need Help?"
echo ""
echo " (No seriously, $total_commits commits is wild.)"
elif [ "$total_commits" -gt "$THRESHOLD_COMMITS_HIGH" ]; then
echo "πŸ˜… That's... a lot of commits."
echo ""
echo " But hey, at least it's all in version control!"
elif [ "$total_commits" -gt "$THRESHOLD_COMMITS_MED" ]; then
echo "✨ Pretty active NixOS year!"
else
echo "✨ Steady and sensible. We respect it."
fi
}
# ============================================================================
# Main
# ============================================================================
main() {
echo "🎁 Nix Wrapped $YEAR"
echo "===================="
echo ""
get_local_system_generations
get_local_hm_generations
query_remote_machines
print_generation_summary
analyze_git_repos
print_personality_insights
print_punchline
}
# Only execute if script is run directly (not sourced)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment