Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions lib/hook-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,23 @@ get_hook_config() {
# Convert dot-notation to jq path (e.g., "audio.enabled" -> ".audio.enabled")
local jq_path=".${key_path}"

# Single jq call per file: extract value if present, output nothing if null
local value

# Try local config first (personal overrides)
if [[ -f "$HOOK_CONFIG_LOCAL" ]]; then
local local_type
local_type=$(jq -r "$jq_path | type" "$HOOK_CONFIG_LOCAL" 2>/dev/null)
if [[ "$local_type" != "null" ]] && [[ -n "$local_type" ]]; then
jq -r "if ($jq_path | type) == \"null\" then empty else ($jq_path | tostring) end" "$HOOK_CONFIG_LOCAL" 2>/dev/null
value=$(jq -r "if ($jq_path | type) == \"null\" then empty else ($jq_path | tostring) end" "$HOOK_CONFIG_LOCAL" 2>/dev/null)
if [[ -n "$value" ]]; then
echo "$value"
return 0
fi
fi

# Fall back to team config
if [[ -f "$HOOK_CONFIG_TEAM" ]]; then
local team_type
team_type=$(jq -r "$jq_path | type" "$HOOK_CONFIG_TEAM" 2>/dev/null)
if [[ "$team_type" != "null" ]] && [[ -n "$team_type" ]]; then
jq -r "if ($jq_path | type) == \"null\" then empty else ($jq_path | tostring) end" "$HOOK_CONFIG_TEAM" 2>/dev/null
value=$(jq -r "if ($jq_path | type) == \"null\" then empty else ($jq_path | tostring) end" "$HOOK_CONFIG_TEAM" 2>/dev/null)
if [[ -n "$value" ]]; then
echo "$value"
return 0
fi
fi
Expand Down
18 changes: 18 additions & 0 deletions lib/platform.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ get_timestamp() {
date +%Y%m%d%H%M%S
}

# Get file modification time (Unix epoch) - cross-platform
# Usage: get_file_mtime <file>
get_file_mtime() {
stat -f%m "$1" 2>/dev/null || stat -c%Y "$1" 2>/dev/null || echo 0
}

# Get file size in bytes - cross-platform
# Usage: get_file_size <file>
get_file_size() {
stat -f%z "$1" 2>/dev/null || stat -c%s "$1" 2>/dev/null || echo 0
}

# Get file modification time in human-readable format - cross-platform
# Usage: get_file_mtime_human <file>
get_file_mtime_human() {
stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$1" 2>/dev/null || stat -c "%y" "$1" 2>/dev/null | cut -d. -f1
}

# Platform-specific command check
has_command() {
command -v "$1" &>/dev/null
Expand Down
7 changes: 5 additions & 2 deletions scripts/checkpoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -euo pipefail
# Checkpoint system for long-running Claude Code tasks
# Usage: checkpoint.sh <save|list|show|restore|clean> [args]

# Source shared color library (installed to ~/.claude/lib/ by setup.sh)
# Source shared libraries (installed to ~/.claude/lib/ by setup.sh)
LIB_DIR="${HOME}/.claude/lib"
if [[ -f "${LIB_DIR}/colors.sh" ]]; then
source "${LIB_DIR}/colors.sh"
Expand All @@ -17,6 +17,9 @@ else
CYAN='\033[0;36m'
RESET='\033[0m'
fi
if [[ -f "${LIB_DIR}/platform.sh" ]]; then
source "${LIB_DIR}/platform.sh"
fi

# Determine project name from git or directory
get_project_name() {
Expand Down Expand Up @@ -183,7 +186,7 @@ cmd_clean() {
| while IFS= read -r fp; do
# macOS stat: -f '%m', Linux stat: -c '%Y'
local ts
ts=$(stat -f '%m' "$fp" 2>/dev/null || stat -c '%Y' "$fp" 2>/dev/null || echo "0")
ts=$(get_file_mtime "$fp")
echo "$ts $fp"
done | sort -rn | cut -d' ' -f2-)

Expand Down
17 changes: 6 additions & 11 deletions scripts/compile-skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,12 @@ COMPILED_CHECKSUM="${CLAUDE_DIR}/skill-index.checksum"
# Source shared library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${SCRIPT_DIR}/../lib"
if [[ -f "${LIB_DIR}/colors.sh" ]]; then
source "${LIB_DIR}/colors.sh"
log_info() { info "$1"; }
log_warn() { warn "$1"; }
log_error() { error "$1"; }
else
# Fallback if lib not available
log_info() { echo "[INFO] $1"; }
log_warn() { echo "[WARN] $1"; }
log_error() { echo "[ERROR] $1"; }
fi
[[ -f "${LIB_DIR}/colors.sh" ]] && source "${LIB_DIR}/colors.sh"

# Logging helpers — use colors.sh functions if available, plain echo otherwise
log_info() { if type info &>/dev/null; then info "$1"; else echo "[INFO] $1"; fi; }
log_warn() { if type warn &>/dev/null; then warn "$1"; else echo "[WARN] $1"; fi; }
log_error() { if type error &>/dev/null; then error "$1"; else echo "[ERROR] $1"; fi; }

# Source shared skill patterns
if [[ -f "${LIB_DIR}/skill-patterns.sh" ]]; then
Expand Down
11 changes: 9 additions & 2 deletions scripts/handoff.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@

set -euo pipefail

# Source shared platform utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${SCRIPT_DIR}/../lib"
if [[ -f "${LIB_DIR}/platform.sh" ]]; then
source "${LIB_DIR}/platform.sh"
fi

HANDOFF_DIR="${HOME}/.claude/handoffs"

# Ensure handoff directory exists
Expand Down Expand Up @@ -42,7 +49,7 @@ cmd_create() {
local LATEST_HANDOFF="${HANDOFF_DIR}/latest.json"
if [ -f "$LATEST_HANDOFF" ]; then
local now=$(date +%s)
local last_mod=$(stat -f%m "$LATEST_HANDOFF" 2>/dev/null || stat -c%Y "$LATEST_HANDOFF" 2>/dev/null || echo 0)
local last_mod=$(get_file_mtime "$LATEST_HANDOFF")
local age=$((now - last_mod))
if [ "$age" -lt 5 ]; then
echo ""
Expand Down Expand Up @@ -238,7 +245,7 @@ cmd_list() {
for file in "$HANDOFF_DIR"/handoff_*.md; do
if [ -f "$file" ]; then
local id=$(basename "$file" .md | sed 's/handoff_//')
local created=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$file" 2>/dev/null || stat -c "%y" "$file" 2>/dev/null | cut -d. -f1)
local created=$(get_file_mtime_human "$file")

# Extract project name from the file
local project=$(grep -m1 "^\- \*\*Name:\*\*" "$file" 2>/dev/null | sed 's/.*\*\*Name:\*\* //' || echo "unknown")
Expand Down
9 changes: 7 additions & 2 deletions scripts/session-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ CLAUDE_DIR="${HOME}/.claude"
PROJECT_DIR="$(pwd)"
PROJECT_NAME=$(basename "$PROJECT_DIR")

# Source shared platform utilities
if [[ -f "${CLAUDE_DIR}/lib/platform.sh" ]]; then
source "${CLAUDE_DIR}/lib/platform.sh"
fi

# ============================================
# Parallel helper functions
# ============================================
Expand All @@ -22,7 +27,7 @@ rotate_log() {

if [[ -f "$log" ]]; then
local size
size=$(stat -f%z "$log" 2>/dev/null || stat -c%s "$log" 2>/dev/null || echo 0)
size=$(get_file_size "$log")
if [[ "$size" -gt "$max_size" ]]; then
mv "$log" "${log}.old"
fi
Expand Down Expand Up @@ -71,7 +76,7 @@ auto_warm_tldr() {

# Check if we've tried warming recently (within last hour) to avoid repeated attempts
if [[ -f "$tldr_cache" ]]; then
local cache_age=$(($(date +%s) - $(stat -f%m "$tldr_cache" 2>/dev/null || stat -c%Y "$tldr_cache" 2>/dev/null || echo 0)))
local cache_age=$(($(date +%s) - $(get_file_mtime "$tldr_cache")))
if [[ "$cache_age" -lt 3600 ]]; then
return 0
fi
Expand Down
12 changes: 5 additions & 7 deletions scripts/tldr-stats.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ if [ ! -f "$STATS_FILE" ]; then
exit 0
fi

if command -v jq &>/dev/null; then
CALLS=$(jq -r '.calls // 0' "$STATS_FILE" 2>/dev/null)
TOKENS_SAVED=$(jq -r '.tokens_saved // 0' "$STATS_FILE" 2>/dev/null)
else
CALLS=$(grep -o '"calls":[0-9]*' "$STATS_FILE" 2>/dev/null | grep -o '[0-9]*')
TOKENS_SAVED=$(grep -o '"tokens_saved":[0-9]*' "$STATS_FILE" 2>/dev/null | grep -o '[0-9]*')
fi
# Extract a numeric JSON value with jq fallback to grep
json_num() { jq -r ".$1 // 0" "$2" 2>/dev/null || grep -o "\"$1\":[0-9]*" "$2" 2>/dev/null | grep -o '[0-9]*'; }

CALLS=$(json_num calls "$STATS_FILE")
TOKENS_SAVED=$(json_num tokens_saved "$STATS_FILE")

CALLS=${CALLS:-0}
TOKENS_SAVED=${TOKENS_SAVED:-0}
Expand Down
12 changes: 5 additions & 7 deletions scripts/track-tldr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ case "$TOOL_NAME" in
;;
esac

if command -v jq &>/dev/null; then
CURRENT_CALLS=$(jq -r '.calls // 0' "$STATS_FILE" 2>/dev/null)
CURRENT_SAVED=$(jq -r '.tokens_saved // 0' "$STATS_FILE" 2>/dev/null)
else
CURRENT_CALLS=$(grep -o '"calls":[0-9]*' "$STATS_FILE" 2>/dev/null | grep -o '[0-9]*')
CURRENT_SAVED=$(grep -o '"tokens_saved":[0-9]*' "$STATS_FILE" 2>/dev/null | grep -o '[0-9]*')
fi
# Extract a numeric JSON value with jq fallback to grep
json_num() { jq -r ".$1 // 0" "$2" 2>/dev/null || grep -o "\"$1\":[0-9]*" "$2" 2>/dev/null | grep -o '[0-9]*'; }

CURRENT_CALLS=$(json_num calls "$STATS_FILE")
CURRENT_SAVED=$(json_num tokens_saved "$STATS_FILE")

CURRENT_CALLS=${CURRENT_CALLS:-0}
CURRENT_SAVED=${CURRENT_SAVED:-0}
Expand Down