diff --git a/dots/copilot.sh b/dots/copilot.sh
deleted file mode 100755
index 4149a28..0000000
--- a/dots/copilot.sh
+++ /dev/null
@@ -1,272 +0,0 @@
-#!/bin/sh
-
-# GitHub Copilot client ID
-CLIENT_ID="Iv1.b507a08c87ecfe98"
-
-# Token cache file location
-CACHE_DIR="${HOME}/.config/crush/github-copilot"
-CACHE_FILE="${CACHE_DIR}/bearer_token"
-GITHUB_TOKEN_FILE="${CACHE_DIR}/github_token"
-GITHUB_COPILOT_APPS_FILE="${HOME}/.config/github-copilot/apps.json"
-
-# Function to extract OAuth token from GitHub Copilot apps.json
-extract_oauth_token() {
- local client_id="$1"
- if [ -f "$GITHUB_COPILOT_APPS_FILE" ]; then
- # Extract the oauth_token for our client ID (key format is "github.com:CLIENT_ID")
- local oauth_token=$(grep -o "\"github.com:${client_id}\":{[^}]*\"oauth_token\":\"[^\"]*" "$GITHUB_COPILOT_APPS_FILE" | grep -o '"oauth_token":"[^"]*' | cut -d'"' -f4)
- echo "$oauth_token"
- fi
-}
-
-# Function to extract expiration from token
-extract_expiration() {
- local token="$1"
- echo "$token" | grep -o 'exp=[0-9]*' | cut -d'=' -f2
-}
-
-# Function to check if token is valid
-is_token_valid() {
- local token="$1"
- local exp=$(extract_expiration "$token")
-
- if [ -z "$exp" ]; then
- return 1
- fi
-
- local current_time=$(date +%s)
- # Add 60 second buffer before expiration
- local buffer_time=$((exp - 60))
-
- if [ "$current_time" -lt "$buffer_time" ]; then
- return 0
- else
- return 1
- fi
-}
-
-# Function to exchange GitHub token for bearer token
-exchange_github_token() {
- local github_token="$1"
- local bearer_response=$(curl -s -X GET "https://api.github.com/copilot_internal/v2/token" \
- -H "Authorization: Token ${github_token}" \
- -H "User-Agent: CRUSH/1.0")
-
- local bearer_token=$(echo "$bearer_response" | grep -o '"token":"[^"]*' | cut -d'"' -f4)
- echo "$bearer_token"
-}
-
-# Check for cached bearer token
-if [ -f "$CACHE_FILE" ]; then
- CACHED_TOKEN=$(cat "$CACHE_FILE")
- if is_token_valid "$CACHED_TOKEN"; then
- # Token is still valid, output and exit
- echo "$CACHED_TOKEN"
- exit 0
- fi
-fi
-
-# Bearer token is expired/missing, try to use cached GitHub token
-if [ -f "$GITHUB_TOKEN_FILE" ]; then
- GITHUB_TOKEN=$(cat "$GITHUB_TOKEN_FILE")
- if [ -n "$GITHUB_TOKEN" ]; then
- # Try to exchange GitHub token for new bearer token
- BEARER_TOKEN=$(exchange_github_token "$GITHUB_TOKEN")
- if [ -n "$BEARER_TOKEN" ]; then
- # Successfully got new bearer token, cache it
- echo "$BEARER_TOKEN" > "$CACHE_FILE"
- chmod 600 "$CACHE_FILE"
- echo "$BEARER_TOKEN"
- exit 0
- fi
- fi
-fi
-
-# Try to get OAuth token from GitHub Copilot apps.json
-OAUTH_TOKEN=$(extract_oauth_token "$CLIENT_ID")
-if [ -n "$OAUTH_TOKEN" ]; then
- # Try to exchange OAuth token for new bearer token
- BEARER_TOKEN=$(exchange_github_token "$OAUTH_TOKEN")
- if [ -n "$BEARER_TOKEN" ]; then
- # Successfully got new bearer token, cache it
- mkdir -p "$CACHE_DIR"
- echo "$BEARER_TOKEN" > "$CACHE_FILE"
- chmod 600 "$CACHE_FILE"
- echo "$OAUTH_TOKEN" > "$GITHUB_TOKEN_FILE"
- chmod 600 "$GITHUB_TOKEN_FILE"
- echo "$BEARER_TOKEN"
- exit 0
- fi
-fi
-
-# Step 1: Get device code
-DEVICE_RESPONSE=$(curl -s -X POST "https://github.com/login/device/code" \
- -H "Content-Type: application/x-www-form-urlencoded" \
- -H "User-Agent: CRUSH/1.0" \
- -H "Accept: application/json" \
- -d "client_id=${CLIENT_ID}&scope=user:email read:user copilot")
-
-# Extract values from response
-DEVICE_CODE=$(echo "$DEVICE_RESPONSE" | grep -o '"device_code":"[^"]*' | cut -d'"' -f4)
-USER_CODE=$(echo "$DEVICE_RESPONSE" | grep -o '"user_code":"[^"]*' | cut -d'"' -f4)
-VERIFICATION_URI=$(echo "$DEVICE_RESPONSE" | grep -o '"verification_uri":"[^"]*' | cut -d'"' -f4)
-INTERVAL=$(echo "$DEVICE_RESPONSE" | grep -o '"interval":[0-9]*' | cut -d':' -f2)
-EXPIRES_IN=$(echo "$DEVICE_RESPONSE" | grep -o '"expires_in":[0-9]*' | cut -d':' -f2)
-
-# Ensure minimum interval
-if [ "$INTERVAL" -lt 5 ]; then
- INTERVAL=5
-fi
-
-# Step 2: Create a temporary HTML file with the code
-TEMP_HTML="/tmp/copilot_auth_$$.html"
-cat > "$TEMP_HTML" << EOF
-
-
-
- GitHub Copilot Authentication
-
-
-
-
-
GitHub Copilot Authentication
-
Copy this code:
-
$USER_CODE
-
Copy Code & Continue to GitHub
-
Click the button to copy the code and go to GitHub
-
-
-
-
-EOF
-
-# Open the HTML file (suppress all output to avoid issues in POSIX shell)
-if command -v xdg-open >/dev/null 2>&1; then
- xdg-open "$TEMP_HTML" >/dev/null 2>&1 &
-elif command -v open >/dev/null 2>&1; then
- open "$TEMP_HTML" >/dev/null 2>&1 &
-elif command -v start >/dev/null 2>&1; then
- start "$TEMP_HTML" >/dev/null 2>&1 &
-fi
-
-# Step 3: Poll for token
-POLL_COUNT=0
-MAX_POLLS=60
-GITHUB_TOKEN=""
-
-# Initial delay
-sleep 2
-
-while [ $POLL_COUNT -lt $MAX_POLLS ] && [ -z "$GITHUB_TOKEN" ]; do
- TOKEN_RESPONSE=$(curl -s -X POST "https://github.com/login/oauth/access_token" \
- -H "Content-Type: application/x-www-form-urlencoded" \
- -H "User-Agent: CRUSH/1.0" \
- -H "Accept: application/json" \
- -d "client_id=${CLIENT_ID}&device_code=${DEVICE_CODE}&grant_type=urn:ietf:params:oauth:grant-type:device_code")
-
- # Check for access token
- ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
-
- if [ -n "$ACCESS_TOKEN" ]; then
- GITHUB_TOKEN="$ACCESS_TOKEN"
- break
- fi
-
- # Check for errors
- ERROR=$(echo "$TOKEN_RESPONSE" | grep -o '"error":"[^"]*' | cut -d'"' -f4)
-
- case "$ERROR" in
- "authorization_pending")
- # Still waiting, continue
- ;;
- "slow_down")
- # Rate limiting
- exit 1
- ;;
- "expired_token")
- # Token expired
- exit 1
- ;;
- *)
- if [ -n "$ERROR" ]; then
- exit 1
- fi
- ;;
- esac
-
- POLL_COUNT=$((POLL_COUNT + 1))
- sleep $INTERVAL
-done
-
-if [ -z "$GITHUB_TOKEN" ]; then
- exit 1
-fi
-
-# Step 4: Exchange GitHub token for Copilot bearer token
-BEARER_TOKEN=$(exchange_github_token "$GITHUB_TOKEN")
-
-if [ -z "$BEARER_TOKEN" ]; then
- exit 1
-fi
-
-# Create cache directory if it doesn't exist
-mkdir -p "$CACHE_DIR"
-
-# Cache both tokens
-echo "$BEARER_TOKEN" > "$CACHE_FILE"
-chmod 600 "$CACHE_FILE"
-echo "$GITHUB_TOKEN" > "$GITHUB_TOKEN_FILE"
-chmod 600 "$GITHUB_TOKEN_FILE"
-
-# Output only the bearer token to stdout
-echo "$BEARER_TOKEN"
diff --git a/dots/dump-keybinds-mac.sh b/dots/dump-keybinds-mac.sh
deleted file mode 100755
index 5f28aee..0000000
--- a/dots/dump-keybinds-mac.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-
-defaults export com.apple.symbolichotkeys - > /tmp/symbolichotkeys.plist
-plutil -convert json -o /tmp/symbolichotkeys.json /tmp/symbolichotkeys.plist
-cat /tmp/symbolichotkeys.json | \
-jq -r '
- .AppleSymbolicHotKeys
- | to_entries
- | map(
- " \"" + .key + "\" = {\n" +
- " enabled = " + (
- if (.value.enabled == 1 or .value.enabled == true) then
- "true"
- else
- "false"
- end
- ) + ";\n" +
- (
- if (.value.value? and .value.value.parameters? and .value.value.type?) then
- " value = {\n" +
- " parameters = [ " + (
- .value.value.parameters
- | map(tostring)
- | join(" ")
- ) + " ];\n" +
- " type = \"" + .value.value.type + "\";\n" +
- " };\n"
- else
- ""
- end
- ) +
- " };\n"
- )
- | " AppleSymbolicHotKeys = {\n" + ( join("") ) + " };\n"
-'
-
diff --git a/dots/hyprrec.sh b/dots/hyprrec.sh
index aba2642..bfab7a7 100755
--- a/dots/hyprrec.sh
+++ b/dots/hyprrec.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+##
## Requirements:
## - `slurp`: to select an area
## - `notify-send`: to show notifications (provided by libnotify)
@@ -21,24 +23,24 @@ if [ -n "$DEFAULT_DEVICE" ]; then
MONITOR_DEVICE="${DEFAULT_DEVICE}.monitor"
# Check if the device exists by attempting to get its properties
- wpctl inspect $(wpctl status | grep -A 1 "Built-in Audio Analog Stereo" | grep -o '[0-9]\+\.' | head -1 | tr -d '.') > /dev/null 2>&1
- if [ $? -eq 0 ]; then
+ DEVICE_ID=$(wpctl status | grep -A 1 "Built-in Audio Analog Stereo" | grep -o '[0-9]\+\.' | head -1 | tr -d '.')
+ if [ -n "$DEVICE_ID" ] && wpctl inspect "$DEVICE_ID" > /dev/null 2>&1; then
echo "Found audio device, will use monitor: $MONITOR_DEVICE"
- AUDIO_ARGS="--audio --audio-device \"$MONITOR_DEVICE\""
+ AUDIO_ARGS=(--audio --audio-device "$MONITOR_DEVICE")
else
echo "Couldn't confirm monitor device, falling back to default audio"
- AUDIO_ARGS="--audio"
+ AUDIO_ARGS=(--audio)
fi
else
echo "No default audio device found, falling back to default audio capture"
- AUDIO_ARGS="--audio"
+ AUDIO_ARGS=(--audio)
fi
# Process arguments to determine if full screen or area selection
if [ "$1" = "fullscreen" ]; then
# Full screen recording
notify-send -t 1000 -a "wl-screenrec" "Starting full screen recording"
- ARGS=""
+ ARGS=()
else
# Area selection
notify-send -t 1000 -a "wl-screenrec" "Select area or window to record"
@@ -52,21 +54,23 @@ else
exit 1
fi
notify-send -t 1000 -a "wl-screenrec" "Starting area recording"
- ARGS="-g \"$GEOMETRY\""
+ ARGS=(-g "$GEOMETRY")
fi
-# Start recording with the selected parameters
-touch /tmp/notify_result.txt
-eval "wl-screenrec $ARGS $AUDIO_ARGS -f \"$FILE\"" && \
+# Start recording. Arrays rather than eval: a path or a geometry carrying a
+# space should be one argument, not a new command.
+NOTIFY_RESULT=$(mktemp -t hyprrec.XXXXXX)
+trap 'rm -f "$NOTIFY_RESULT"' EXIT
+wl-screenrec "${ARGS[@]}" "${AUDIO_ARGS[@]}" -f "$FILE" && \
# Create a thumbnail from the recording
ffmpeg -i "$FILE" -ss 00:00:00 -vframes 1 -update 1 -frames:v 1 /tmp/screenrec_thumbnail.png -y && \
# Notify that recording is saved with clickable action
notify-send -a "wl-screenrec" "Recording saved to $FILE" \
-i "/tmp/screenrec_thumbnail.png" \
- -A "default=Open" > /tmp/notify_result.txt
+ -A "default=Open" > "$NOTIFY_RESULT"
# Check if notification was clicked
-if [ -f /tmp/notify_result.txt ] && grep -q "default" /tmp/notify_result.txt; then
+if grep -q "default" "$NOTIFY_RESULT"; then
if command -v xdg-open > /dev/null; then
xdg-open "$FILE"
elif command -v gdbus > /dev/null; then
diff --git a/dots/prettify-ss.sh b/dots/prettify-ss.sh
index ec22785..261afa9 100644
--- a/dots/prettify-ss.sh
+++ b/dots/prettify-ss.sh
@@ -1,4 +1,6 @@
-#!/bin/bash
+#!/usr/bin/env bash
+
+set -euo pipefail
# Define temporary files
TEMP_IMAGE=$(mktemp --suffix=.png)
@@ -7,14 +9,16 @@ MASK_IMAGE=$(mktemp --suffix=.png)
GRADIENT_IMAGE=$(mktemp --suffix=.png)
FINAL_IMAGE=$(mktemp --suffix=.png)
+# Clean up whatever we got to, not just the happy path.
+trap 'rm -f "$TEMP_IMAGE" "$MASK_IMAGE" "$SHADOWED_IMAGE" "$GRADIENT_IMAGE" "$FINAL_IMAGE"' EXIT
+
# Grab the clipboard image
wl-paste --type image/png > "$TEMP_IMAGE"
-# Extract standout colors (3 dominant colors)
+# Extract standout colors, and gradient between the two furthest apart
COLORS=$(magick "$TEMP_IMAGE" -colors 3 -unique-colors txt: | grep -oP '#[0-9A-Fa-f]{6}')
COLOR1=$(echo "$COLORS" | head -n 1)
-COLOR2=$(echo "$COLORS" | tail -n 1 | head -n 1)
-COLOR3=$(echo "$COLORS" | tail -n 1)
+COLOR2=$(echo "$COLORS" | tail -n 1)
# Get original image dimensions
WIDTH=$(magick identify -format "%w" "$TEMP_IMAGE")
@@ -41,7 +45,4 @@ magick "$GRADIENT_IMAGE" "$SHADOWED_IMAGE" -gravity center -composite "$FINAL_IM
# Copy the final image back to the clipboard
wl-copy < "$FINAL_IMAGE"
-# Clean up temporary files
-rm "$TEMP_IMAGE" "$MASK_IMAGE" "$SHADOWED_IMAGE" "$GRADIENT_IMAGE" "$FINAL_IMAGE"
-
diff --git a/dots/update-crush-models.sh b/dots/update-crush-models.sh
deleted file mode 100755
index b6dd1f6..0000000
--- a/dots/update-crush-models.sh
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-# Configuration
-COPILOT_TOKEN=$(bash ~/.config/crush/copilot.sh)
-ANTHROPIC_TOKEN=$(bunx anthropic-api-key)
-
-# Colors for output
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-NC='\033[0m' # No Color
-
-echo -e "${GREEN}Fetching latest models from APIs...${NC}"
-
-# Fetch Copilot models
-echo " → Fetching Copilot models..."
-COPILOT_MODELS=$(curl -s https://api.githubcopilot.com/models \
- -H "Authorization: Bearer $COPILOT_TOKEN" \
- -H "Editor-Version: CRUSH/1.0" \
- -H "Editor-Plugin-Version: CRUSH/1.0" \
- -H "Copilot-Integration-Id: vscode-chat")
-
-# Fetch Anthropic models
-echo " → Fetching Anthropic models..."
-ANTHROPIC_MODELS=$(curl -s https://api.anthropic.com/v1/models \
- -H "Authorization: Bearer $ANTHROPIC_TOKEN" \
- -H "anthropic-version: 2023-06-01" \
- -H "anthropic-beta: oauth-2025-04-20")
-
-# Extract model-picker enabled Copilot models
-echo -e "\n${GREEN}Copilot models (model_picker_enabled):${NC}"
-echo "$COPILOT_MODELS" | jq -r '.data[] | select(.model_picker_enabled == true) | " ✓ \(.id) - \(.name)"'
-
-# Extract all Anthropic models
-echo -e "\n${GREEN}Anthropic models:${NC}"
-echo "$ANTHROPIC_MODELS" | jq -r '.data[] | " ✓ \(.id) - \(.display_name)"'
-
-# Generate Copilot models Nix config
-generate_copilot_models() {
- echo "$COPILOT_MODELS" | jq -r '.data[] | select(.model_picker_enabled == true) |
- (if .capabilities.supports.tool_calls then true else false end) as $can_reason |
- (if .capabilities.supports.vision then true else false end) as $supports_attachments |
- " {\n" +
- " id = \"\(.id)\";\n" +
- " name = \"Copilot: \(.name)\";\n" +
- " cost_per_1m_in = 0;\n" +
- " cost_per_1m_out = 0;\n" +
- " cost_per_1m_in_cached = 0;\n" +
- " cost_per_1m_out_cached = 0;\n" +
- " context_window = \(.capabilities.limits.max_context_window_tokens);\n" +
- " default_max_tokens = \(.capabilities.limits.max_output_tokens);\n" +
- " can_reason = \($can_reason);\n" +
- " has_reasoning_efforts = false;\n" +
- " supports_attachments = \($supports_attachments);\n" +
- " }"'
-}
-
-# Generate Anthropic models Nix config with pricing
-generate_anthropic_models() {
- echo "$ANTHROPIC_MODELS" | jq -r '.data[] |
- # Determine pricing based on model family
- (if (.id | contains("opus-4")) then
- {in: 15.0, out: 75.0, in_cached: 1.5, out_cached: 75.0}
- elif (.id | contains("sonnet-4")) then
- {in: 3.0, out: 15.0, in_cached: 0.225, out_cached: 15.0}
- elif (.id | contains("3-7-sonnet")) then
- {in: 2.5, out: 12.0, in_cached: 0.187, out_cached: 12.0}
- elif (.id | contains("3-5-sonnet")) then
- {in: 3.0, out: 15.0, in_cached: 0.225, out_cached: 15.0}
- elif (.id | contains("3-5-haiku")) then
- {in: 0.8, out: 4.0, in_cached: 0.06, out_cached: 4.0}
- elif (.id | contains("3-haiku")) then
- {in: 0.25, out: 1.25, in_cached: 0.03, out_cached: 1.25}
- elif (.id | contains("3-opus")) then
- {in: 15.0, out: 75.0, in_cached: 1.5, out_cached: 75.0}
- else
- {in: 3.0, out: 15.0, in_cached: 0.225, out_cached: 15.0}
- end) as $pricing |
-
- # Determine context window and max tokens
- (if (.id | test("claude-sonnet-4-5"))
- then {context: 200000, max_tokens: 64000}
- elif (.id | test("claude-sonnet-4-"))
- then {context: 200000, max_tokens: 64000}
- elif (.id | test("claude-3-7-sonnet"))
- then {context: 200000, max_tokens: 64000}
- elif (.id | test("claude-opus-4-1"))
- then {context: 200000, max_tokens: 32000}
- elif (.id | test("claude-opus-4-"))
- then {context: 200000, max_tokens: 32000}
- elif (.id | test("claude-3-5-haiku"))
- then {context: 200000, max_tokens: 8192}
- elif (.id | test("claude-3-haiku"))
- then {context: 200000, max_tokens: 4096}
- else
- {context: 200000, max_tokens: 8192}
- end) as $limits |
-
- # Determine has_reasoning_efforts
- (if (.id | contains("opus-4")) then true else false end) as $has_reasoning |
-
- " {\n" +
- " id = \"\(.id)\";\n" +
- " name = \"\(.display_name)\";\n" +
- " cost_per_1m_in = \($pricing.in);\n" +
- " cost_per_1m_out = \($pricing.out);\n" +
- " cost_per_1m_in_cached = \($pricing.in_cached);\n" +
- " cost_per_1m_out_cached = \($pricing.out_cached);\n" +
- " context_window = \($limits.context);\n" +
- " default_max_tokens = \($limits.max_tokens);\n" +
- " can_reason = true;\n" +
- " has_reasoning_efforts = \($has_reasoning);\n" +
- " supports_attachments = true;\n" +
- " }"'
-}
-
-# Generate formatted model arrays
-COPILOT_MODELS_NIX=$(generate_copilot_models)
-ANTHROPIC_MODELS_NIX=$(generate_anthropic_models)
-
-# Output results
-echo -e "\n${BLUE}═══════════════════════════════════════════════════════════${NC}"
-echo -e "${YELLOW}COPILOT MODELS${NC}"
-echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}"
-echo -e "\nPaste this into your copilot.models array:\n"
-echo " models = ["
-echo "$COPILOT_MODELS_NIX"
-echo " ];"
-
-echo -e "\n${BLUE}═══════════════════════════════════════════════════════════${NC}"
-echo -e "${YELLOW}ANTHROPIC MODELS${NC}"
-echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}"
-echo -e "\nPaste this into your claude-pro.models array:\n"
-echo " models = ["
-echo "$ANTHROPIC_MODELS_NIX"
-echo " ];"
-
-echo -e "\n${BLUE}═══════════════════════════════════════════════════════════${NC}"
-echo -e "\n${GREEN}Summary:${NC}"
-echo " • Copilot models: $(echo "$COPILOT_MODELS" | jq '[.data[] | select(.model_picker_enabled == true)] | length')"
-echo " • Anthropic models: $(echo "$ANTHROPIC_MODELS" | jq '.data | length')"
diff --git a/modules/home/apps/halloy.nix b/modules/home/apps/halloy.nix
index 0a04efc..a35fcb5 100644
--- a/modules/home/apps/halloy.nix
+++ b/modules/home/apps/halloy.nix
@@ -42,7 +42,7 @@
"#meta"
"#fraud-land"
];
- channel-keys = {
+ channel_keys = {
fraud-land = "fraudpheus";
};
};
diff --git a/modules/home/system/shell.nix b/modules/home/system/shell.nix
index 82183e4..030be03 100644
--- a/modules/home/system/shell.nix
+++ b/modules/home/system/shell.nix
@@ -149,12 +149,16 @@ let
host="hackatime.hackclub.com"
fi
+ # A predictable name in a shared directory is somebody else's to write.
+ summary=$(mktemp -t hackatime.XXXXXX)
+ trap 'rm -f "$summary"' EXIT
+
${pkgs.gum}/bin/gum spin --spinner dot --title "Fetching summary from $host for $user_id..." -- \
${pkgs.curl}/bin/curl -s -X 'GET' \
"https://$host/api/summary?user=''${user_id}&interval=month" \
-H 'accept: application/json' \
-H 'Authorization: Bearer 2ce9e698-8a16-46f0-b49a-ac121bcfd608' \
- > /tmp/hackatime-$$.json
+ > "$summary"
${pkgs.gum}/bin/gum style --bold --foreground 212 "Summary for $user_id"
echo
@@ -168,7 +172,7 @@ let
else
0
end
- ' /tmp/hackatime-$$.json)
+ ' "$summary")
if [[ "$total_seconds" -gt 0 ]]; then
hours=$((total_seconds / 3600))
@@ -190,7 +194,7 @@ let
else
" No projects"
end
- ' /tmp/hackatime-$$.json
+ ' "$summary"
echo
@@ -203,9 +207,7 @@ let
else
" No languages"
end
- ' /tmp/hackatime-$$.json
-
- rm -f /tmp/hackatime-$$.json
+ ' "$summary"
'';
now = pkgs.writeShellScriptBin "now" ''
@@ -228,9 +230,13 @@ let
esac
done
- # Load account information from agenix secrets
+ # Load account information from agenix secrets. Exported rather than
+ # spliced into the script below: a password with a quote in it would
+ # otherwise end the string it was sitting in.
if [[ -f "/run/agenix/bluesky" ]]; then
+ set -a
source "/run/agenix/bluesky"
+ set +a
else
${pkgs.gum}/bin/gum style --foreground 196 "Error: Bluesky credentials file not found at /run/agenix/bluesky"
exit 1
@@ -245,6 +251,8 @@ let
fi
fi
+ export message
+
${pkgs.gum}/bin/gum spin --spinner dot --title "Posting to Bluesky..." -- /bin/bash <