Skip to content

Instantly share code, notes, and snippets.

@MedRedha
Last active November 27, 2025 04:21
Show Gist options
  • Select an option

  • Save MedRedha/eb8b8d4b1c4d7492e09d04360adc5812 to your computer and use it in GitHub Desktop.

Select an option

Save MedRedha/eb8b8d4b1c4d7492e09d04360adc5812 to your computer and use it in GitHub Desktop.
Pulse - Checking the vital signs of your developer toolchain
#!/bin/bash
# ____ ___
# /\ _`\ /\_ \
# \ \ \L\ \ __ __\//\ \ ____ __
# \ \ ,__//\ \/\ \ \ \ \ /',__\ /'__`\
# \ \ \/ \ \ \_\ \ \_\ \_ /\__, `\/\ __/
# \ \_\ \ \____/ /\____\/\____/\ \____\
# \/_/ \/___/ \/____/ \/___/ \/____/
#
# Checking the vital signs of your developer toolchain.
#
# by Med Redha Khelifi (@MedRedha)
# Enhanced for flexibility, robustness, and aesthetics.
set -o pipefail
VERSION="1.2.2"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
NOTIFICATION_SOUND="Glass"
NOTIFICATION_ICON="$SCRIPT_DIR/icon.png"
GREEN='\033[0;92m'
RED='\033[0;31m'
YELLOW='\033[1;93m'
ORANGE='\033[38;5;202m'
CYAN='\033[0;96m'
GRAY='\033[0;90m'
BLUE='\033[0;34m'
MAGENTA="\033[1;94m"
NC='\033[0m'
ERASE_LINE='\033[K'
updates_available=0
tools_ok=0
current_check=0
total_checks=0
start_time=0
first_check=true
outdated_npm_packages=()
BASH_MAJOR_VERSION="${BASH_VERSION%%.*}"
if [ "$BASH_MAJOR_VERSION" -ge 4 ]; then
declare -A GH_API_CACHE
declare -A NPM_CACHE
declare -A check_results
USE_CACHE=true
else
USE_CACHE=false
fi
source_nvm() {
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" --no-use
}
source_nvm
fetch_gh_release() {
local repo="$1"
local result=""
if [ "$USE_CACHE" = true ]; then
local cache_key="${repo//\//_}"
if [ -z "${GH_API_CACHE[$cache_key]}" ]; then
result=$(curl -s "https://api.github.com/repos/$repo/releases/latest" 2>/dev/null | jq -r '.tag_name // empty' 2>/dev/null)
GH_API_CACHE[$cache_key]="$result"
else
result="${GH_API_CACHE[$cache_key]}"
fi
else
result=$(curl -s "https://api.github.com/repos/$repo/releases/latest" 2>/dev/null | jq -r '.tag_name // empty' 2>/dev/null)
fi
echo "$result"
}
fetch_npm_version() {
local package="$1"
local result=""
if [ "$USE_CACHE" = true ]; then
if [ -z "${NPM_CACHE[$package]}" ]; then
result=$(npm view "$package" version 2>/dev/null)
NPM_CACHE[$package]="$result"
else
result="${NPM_CACHE[$package]}"
fi
else
result=$(npm view "$package" version 2>/dev/null)
fi
echo "$result"
}
is_latest_newer() {
local current_ver=${1#v} latest_ver=${2#v}
current_ver=${current_ver#\~}; current_ver=${current_ver#\^}
[ -z "$current_ver" ] && current_ver="0"
[ -z "$latest_ver" ] && latest_ver="0"
if [ "$current_ver" == "$latest_ver" ]; then return 1; fi
if [ "$(printf '%s\n' "$current_ver" "$latest_ver" | sort -V | tail -n1)" == "$latest_ver" ]; then
return 0
else
return 1
fi
}
draw_progress_bar() {
local tool_name="$1"
local percentage=$((current_check * 100 / total_checks))
local filled=$((current_check * 40 / total_checks))
local empty=$((40 - filled))
local elapsed=$(($(date +%s) - start_time))
local eta=0
if [ "$current_check" -gt 0 ]; then
local avg_time=$((elapsed / current_check))
local remaining=$((total_checks - current_check))
eta=$((avg_time * remaining))
fi
local bar=""
for ((i=0; i<filled; i++)); do bar+="█"; done
for ((i=0; i<empty; i++)); do bar+="░"; done
printf "\r${ERASE_LINE}${CYAN}${bar}${NC} ${YELLOW}${percentage}%%${NC} | ${GRAY}ETA: ${eta}s${NC} | ${ORANGE}${current_check}/${total_checks}${NC} | Checking ${tool_name}..."
}
process_check_parallel() {
local icon="$1" tool_name="$2" current_ver="$3" latest_ver="$4" update_cmd="$5"
local display_ver="$current_ver"
[ -z "$current_ver" ] && display_ver="not installed"
[ -z "$latest_ver" ] && latest_ver="unknown"
local result=""
if [ "$latest_ver" = "unknown" ]; then
result="${YELLOW}⚠ ${icon} ${tool_name} ${NC}version check unavailable ${CYAN}(${display_ver})${NC}|ok"
elif is_latest_newer "$current_ver" "$latest_ver"; then
result="${RED}⚠ ${icon} ${tool_name} ${NC}needs an update!\n ├─ Installed: ${YELLOW}${display_ver}${NC}\n ├─ Latest: ${GREEN}${latest_ver}${NC}\n └─ Action: ${CYAN}${update_cmd}${NC}|update"
else
result="${GREEN}✓ ${icon} ${tool_name} ${NC}is up-to-date ${CYAN}(${display_ver})${NC}|ok"
fi
if [ "$USE_CACHE" = true ]; then
check_results["$tool_name"]="$result"
fi
echo "$result"
}
process_check() {
local icon="$1" tool_name="$2" current_ver="$3" latest_ver="$4" update_cmd="$5"
local display_ver="$current_ver"
local is_not_installed=false
[ -z "$current_ver" ] && display_ver="not installed" && is_not_installed=true
[ -z "$latest_ver" ] && latest_ver="unknown"
printf "\r${ERASE_LINE}"
echo -e "---------------------------------"
if [ "$latest_ver" = "unknown" ]; then
echo -e "${YELLOW}⚠ ${icon} ${tool_name} ${NC}version check unavailable ${CYAN}(${display_ver})${NC}"
((tools_ok++))
elif is_latest_newer "$current_ver" "$latest_ver"; then
((updates_available++))
if [ "$is_not_installed" = true ]; then
echo -e "${RED}✗ ${icon} ${tool_name} is not installed!${NC}"
echo -e " ├─ Latest: ${GREEN}${latest_ver}${NC}"
echo -e " └─ Install: ${CYAN}${update_cmd}${NC}"
else
echo -e "${RED}⚠ ${icon} ${tool_name} needs an update!${NC}"
echo -e " ├─ Installed: ${YELLOW}${display_ver}${NC}"
echo -e " ├─ Latest: ${GREEN}${latest_ver}${NC}"
echo -e " └─ Action: ${CYAN}${update_cmd}${NC}"
fi
else
((tools_ok++))
echo -e "${GREEN}✓ ${icon} ${tool_name} ${NC}is up-to-date ${CYAN}(${display_ver})${NC}"
fi
}
display_tool_version() {
local icon="$1" tool_name="$2" current_ver="$3"
[ -z "$current_ver" ] || [[ "$current_ver" == *"No such file or directory"* ]] && current_ver="not found"
printf "\r${ERASE_LINE}"
echo -e "---------------------------------"
echo -e "${GREEN}✓ ${icon} ${tool_name}${NC}: ${CYAN}${current_ver}${NC}"
}
check_node_lts() {
local icon="📟"
local tool_name="Node (LTS)"
local current_ver
current_ver=$(node -v 2>/dev/null)
local latest_lts_ver
latest_lts_ver=$(nvm version-remote --lts 2>/dev/null)
local display_ver="$current_ver"
[ -z "$current_ver" ] && display_ver="not installed"
printf "\r${ERASE_LINE}"
echo -e "---------------------------------"
if [ "$current_ver" == "$latest_lts_ver" ]; then
((tools_ok++))
echo -e "${GREEN}✓ ${icon} ${tool_name} ${NC}is correctly set ${CYAN}(${current_ver})${NC}"
else
((updates_available++))
echo -e "${RED}⚠ ${icon} ${tool_name} ${NC}is not the active version."
echo -e " ├─ Active: ${YELLOW}${display_ver}${NC}"
echo -e " ├─ Latest LTS: ${GREEN}${latest_lts_ver}${NC}"
echo -e " └─ Action: ${CYAN}nvm install --lts && nvm use --lts && nvm alias default 'lts/*'"${NC}
fi
}
check_nvm() {
local current_ver=$(nvm --version 2>/dev/null)
local nvm_latest=""
if command -v nvm &>/dev/null; then
nvm_latest=$(fetch_gh_release "nvm-sh/nvm")
if [ -z "$nvm_latest" ]; then
nvm_latest=$(curl -s https://api.github.com/repos/nvm-sh/nvm/tags 2>/dev/null | jq -r '.[0].name' 2>/dev/null)
fi
local install_cmd="curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/\${latest_version}/install.sh | bash"
else
local install_cmd="curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash"
fi
process_check "🎒" "NVM" "$current_ver" "$nvm_latest" "$install_cmd"
}
check_yarn() {
local current_ver=$(yarn -v 2>/dev/null)
local latest_ver=""
if command -v yarn &>/dev/null; then
latest_ver=$(fetch_gh_release "yarnpkg/berry" | sed 's/^@yarnpkg\/cli\///')
if [ -z "$latest_ver" ]; then
latest_ver=$(curl -s https://api.github.com/repos/yarnpkg/berry/tags 2>/dev/null | jq -r '.[0].name' 2>/dev/null | sed 's/^@yarnpkg\/cli\///')
fi
local install_cmd="corepack enable && corepack prepare yarn@stable --activate"
else
local install_cmd="corepack enable && corepack prepare yarn@stable --activate"
fi
process_check "🧶" "Yarn" "$current_ver" "$latest_ver" "$install_cmd"
}
check_npm() {
local current_ver=$(npm --version 2>/dev/null)
local latest_ver=""
if command -v npm &>/dev/null; then
latest_ver=$(fetch_npm_version "npm")
local install_cmd="npm install -g npm@latest"
else
local install_cmd="curl -L https://www.npmjs.com/install.sh | sh"
fi
process_check "📦" "npm" "$current_ver" "$latest_ver" "$install_cmd"
}
check_prettier() {
process_check "💅" "Prettier" "$(prettier -v 2>/dev/null)" "$(fetch_npm_version "prettier")" "npm install -g prettier"
}
check_firebase_cli() {
process_check "🔥" "Firebase CLI" "$(firebase --version 2>/dev/null)" "$(fetch_npm_version "firebase-tools")" "npm install -g firebase-tools"
}
check_ngrok() {
local current_ver=$(ngrok version 2>/dev/null | awk '{print $NF}')
local latest_ver=$(brew info ngrok 2>/dev/null | grep "^==> ngrok:" | awk '{print $3}' | cut -d',' -f1)
process_check "🌍" "Ngrok" "$current_ver" "$latest_ver" "brew upgrade --cask ngrok"
}
check_askcli() {
process_check "🎙️ " "ASK CLI" "$(ask --version 2>/dev/null)" "$(fetch_npm_version "ask-cli")" "npm install -g ask-cli"
}
check_n8n() {
process_check "🔗" "n8n" "$(n8n --version 2>/dev/null)" "$(fetch_npm_version "n8n")" "npm update -g n8n"
}
check_ruby() {
if command -v rbenv &>/dev/null; then
process_check "💎" "Ruby (rbenv)" "$(rbenv version 2>/dev/null | cut -d' ' -f1)" "$(rbenv install -l 2>/dev/null | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | tail -n 1)" "rbenv install <latest_version> && rbenv global <latest_version>"
else
process_check "💎" "Ruby (System)" "$(ruby -v 2>/dev/null | awk '{print $2}' | cut -d'p' -f1)" "$(brew info --json ruby 2>/dev/null | jq -r '.[0].versions.stable')" "brew upgrade ruby"
fi
}
check_rubygems() {
process_check "💍" "RubyGems" "$(gem -v 2>/dev/null)" "$(curl -s https://rubygems.org/api/v1/gems/rubygems-update.json 2>/dev/null | jq -r .version)" "gem update --system"
}
check_python() {
process_check "🐍" "Python" "$(python3 --version 2>/dev/null | awk '{print $2}')" "$(brew info --json python@3 2>/dev/null | jq -r '.[0].versions.stable')" "brew upgrade python@3"
}
check_pip() {
process_check "🪈" "pip" "$(pip3 --version 2>/dev/null | awk '{print $2}')" "$(curl -s https://pypi.org/pypi/pip/json 2>/dev/null | jq -r .info.version)" "pip3 install --upgrade pip"
}
check_bundler() {
process_check "🛠️ " "Bundler" "$(bundle -v 2>/dev/null | awk '{print $3}')" "$(curl -s https://rubygems.org/api/v1/gems/bundler.json 2>/dev/null | jq -r .version)" "gem install bundler && bundle update --bundler"
}
check_fastlane() {
local version=$(fastlane --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1)
process_check "🚀" "fastlane" "$version" "$(curl -s https://rubygems.org/api/v1/gems/fastlane.json 2>/dev/null | jq -r .version)" "gem install fastlane"
}
check_git() {
process_check "🔀" "Git" "$(git --version 2>/dev/null | awk '{print $3}')" "$(brew info --json git 2>/dev/null | jq -r '.[0].versions.stable')" "brew upgrade git"
}
check_cocoapods() {
process_check "🫘" "Cocoapods" "$(pod --version 2>/dev/null)" "$(curl -s https://rubygems.org/api/v1/gems/cocoapods.json 2>/dev/null | jq -r .version)" "gem install cocoapods"
}
check_typescript() {
process_check "📘" "TypeScript" "$(tsc -v 2>/dev/null | awk '{print $2}')" "$(fetch_npm_version "typescript")" "npm install -g typescript"
}
check_homebrew() {
local current_ver=$(brew --version 2>/dev/null | head -n 1 | awk '{print $2}')
local latest_ver=""
if command -v brew &>/dev/null; then
latest_ver=$(fetch_gh_release "Homebrew/brew")
if [ -z "$latest_ver" ]; then
latest_ver=$(curl -s https://api.github.com/repos/Homebrew/brew/tags 2>/dev/null | jq -r '.[0].name' 2>/dev/null)
fi
local install_cmd="brew update && brew upgrade"
else
local install_cmd="/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
fi
process_check "🍺" "Homebrew" "$current_ver" "$latest_ver" "$install_cmd"
}
check_watchman() {
process_check "👀" "Watchman" "$(watchman -v 2>/dev/null)" "$(brew info --json watchman 2>/dev/null | jq -r '.[0].versions.stable')" "brew upgrade watchman"
}
check_java() {
local java_ver=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'_' -f1)
process_check "☕" "Java" "$java_ver" "$(brew info --json openjdk 2>/dev/null | jq -r '.[0].versions.stable')" "brew upgrade openjdk"
}
check_jq() {
process_check "🔧" "JQ" "$(jq --version 2>/dev/null | cut -d- -f2)" "$(brew info --json jq 2>/dev/null | jq -r '.[0].versions.stable')" "brew upgrade jq"
}
check_omzsh() {
local omz_dir="${ZSH:-$HOME/.oh-my-zsh}"
if [ -d "$omz_dir" ]; then
local local_hash=$(cd "$omz_dir" 2>/dev/null && git rev-parse HEAD 2>/dev/null)
local remote_hash=$(cd "$omz_dir" 2>/dev/null && git ls-remote origin HEAD 2>/dev/null | awk '{print $1}')
local local_short="${local_hash:0:7}"
local remote_short="${remote_hash:0:7}"
printf "\r${ERASE_LINE}"
echo -e "---------------------------------"
if [ -z "$remote_hash" ]; then
((tools_ok++))
echo -e "${YELLOW}⚠ 🎨 Oh My Zsh ${NC}version check unavailable ${CYAN}(${local_short})${NC}"
elif [ "$local_hash" = "$remote_hash" ]; then
((tools_ok++))
echo -e "${GREEN}✓ 🎨 Oh My Zsh ${NC}is up-to-date ${CYAN}(${local_short})${NC}"
else
if (cd "$omz_dir" 2>/dev/null && git fetch origin --quiet 2>/dev/null && git merge-base --is-ancestor HEAD origin/HEAD 2>/dev/null); then
((updates_available++))
echo -e "${RED}⚠ 🎨 Oh My Zsh needs an update!${NC}"
echo -e " ├─ Installed: ${YELLOW}${local_short}${NC}"
echo -e " ├─ Latest: ${GREEN}${remote_short}${NC}"
echo -e " └─ Action: ${CYAN}omz update${NC}"
else
((tools_ok++))
echo -e "${GREEN}✓ 🎨 Oh My Zsh ${NC}is up-to-date ${CYAN}(${local_short})${NC}"
fi
fi
else
printf "\r${ERASE_LINE}"
echo -e "---------------------------------"
((updates_available++))
echo -e "${RED}✗ 🎨 Oh My Zsh is not installed!${NC}"
echo -e " └─ Install: ${CYAN}sh -c \"\$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"${NC}"
fi
}
check_claude_code() {
local current_ver=$(claude --version 2>/dev/null | awk '{print $1}')
local latest_ver=$(curl -s "https://formulae.brew.sh/api/cask/claude-code.json" 2>/dev/null | jq -r '.version' 2>/dev/null)
process_check "👾" "Claude Code" "$current_ver" "$latest_ver" "brew upgrade --cask claude-code"
}
check_gradle() {
local current_ver=$(gradle --version 2>/dev/null | grep "Gradle" | awk '{print $2}')
local latest_ver=$(curl -s https://services.gradle.org/versions/current 2>/dev/null | jq -r '.version')
process_check "🐘" "Gradle" "$current_ver" "$latest_ver" "brew upgrade gradle"
}
display_xcode() {
display_tool_version "🔨" "Xcode" "$(xcrun xctrace version 2>/dev/null | head -n 1)"
}
display_android_sdk() {
local sdk_path="${ANDROID_HOME:-$HOME/Library/Android/sdk}/build-tools"
if [ -d "$sdk_path" ]; then
display_tool_version "🤖" "Android SDK" "$(ls "$sdk_path" 2>/dev/null | tail -n 1)"
fi
}
display_android_ndk() {
local ndk_path="${ANDROID_HOME:-$HOME/Library/Android/sdk}/ndk"
if [ -d "$ndk_path" ]; then
display_tool_version "🔩" "Android NDK" "$(ls "$ndk_path" 2>/dev/null | tail -n 1)"
fi
}
check_npm_global_outdated() {
printf "\r${ERASE_LINE}"
echo -e "---------------------------------"
local outdated_output=$(npm outdated -g --json 2>/dev/null)
if [ -n "$outdated_output" ] && [ "$outdated_output" != "{}" ]; then
local count=$(echo "$outdated_output" | jq 'length' 2>/dev/null)
if [ "$count" -gt 0 ]; then
((updates_available += count))
echo -e "${RED}⚠ $count global npm package(s) outdated${NC}"
echo "$outdated_output" | jq -r 'to_entries[] | " ├─ \(.key): \(.value.current) → \(.value.latest)"' 2>/dev/null
echo -e " └─ Action: ${CYAN}npm update -g${NC}"
else
((tools_ok++))
echo -e "${GREEN}✓ All global npm packages are up-to-date${NC}"
fi
else
((tools_ok++))
echo -e "${GREEN}✓ All global npm packages are up-to-date${NC}"
fi
}
send_notification() {
local title="$1"
local message="$2"
local sound="${3:-default}"
if command -v terminal-notifier &>/dev/null; then
if [ -n "$NOTIFICATION_ICON" ] && [ -f "$NOTIFICATION_ICON" ]; then
if [[ "$NOTIFICATION_ICON" == *.png ]]; then
(terminal-notifier -title "$title" -message "$message" -sound "$sound" -contentImage "$NOTIFICATION_ICON" &) >/dev/null 2>&1
else
local temp_icon="/tmp/pulse_icon.png"
if command -v sips &>/dev/null; then
sips -s format png "$NOTIFICATION_ICON" --out "$temp_icon" &>/dev/null
(terminal-notifier -title "$title" -message "$message" -sound "$sound" -contentImage "$temp_icon" &) >/dev/null 2>&1
else
(terminal-notifier -title "$title" -message "$message" -sound "$sound" -appIcon "$NOTIFICATION_ICON" &) >/dev/null 2>&1
fi
fi
else
(terminal-notifier -title "$title" -message "$message" -sound "$sound" &) >/dev/null 2>&1
fi
return 0
fi
title="${title//\\/\\\\}"
title="${title//\"/\\\"}"
message="${message//\\/\\\\}"
message="${message//\"/\\\"}"
osascript -e "display notification \"$message\" with title \"$title\" sound name \"$sound\"" 2>/dev/null
return $?
}
display_logo() {
echo -e "${ORANGE}$(figlet -c -k -f larry3d "Pulse" 2>/dev/null | sed '/^ *$/d')${NC}"
echo -e "\n${CYAN}$(figlet -c -f term "Checking the vital signs of your developer toolchain." 2>/dev/null | sed '/^ *$/d')${NC}"
echo -e "\n${GRAY}$(figlet -c -f term "by Med Redha Khelifi ${MAGENTA}(v${VERSION})" 2>/dev/null | sed '/^ *$/d')${NC}"
}
check_dependencies() {
local missing_deps=0
for dep in curl jq figlet; do
if ! command -v "$dep" &> /dev/null; then
echo -e "${RED}Error: Required dependency '$dep' is not installed.${NC}"
missing_deps=1
fi
done
[ "$missing_deps" -eq 1 ] && exit 1
}
run_with_progress() {
local tool_name="$1" function_to_call="$2"
((current_check++))
draw_progress_bar "$tool_name"
"$function_to_call"
}
check_rn_package() {
local pkg="$1" icon="$2" name="$3" update_cmd="$4"
local current_ver=$(jq -r ".dependencies[\"$pkg\"] // .devDependencies[\"$pkg\"] // \"\"" package.json 2>/dev/null)
if [ -n "$current_ver" ]; then
local latest_ver=$(fetch_npm_version "$pkg")
process_check "$icon" "$name" "$current_ver" "$latest_ver" "$update_cmd"
else
printf "\r${ERASE_LINE}"
fi
}
print_category_header() {
local category="$1"
local color="$2"
printf "\r${ERASE_LINE}"
echo ""
echo -e "${color}${category}${NC}"
}
count_checks() {
total_checks=23
if [ -f "package.json" ]; then
[ -n "$(jq -r '.dependencies["react-native"] // .devDependencies["react-native"] // ""' package.json 2>/dev/null)" ] && ((total_checks++))
[ -n "$(jq -r '.dependencies["@react-native-community/cli"] // .devDependencies["@react-native-community/cli"] // ""' package.json 2>/dev/null)" ] && ((total_checks++))
fi
total_checks=$((total_checks + 4))
}
main() {
check_dependencies
display_logo
count_checks
start_time=$(date +%s)
print_category_header "• Core Tools:" "${ORANGE}"
run_with_progress "Node (LTS)" "check_node_lts"
run_with_progress "NVM" "check_nvm"
run_with_progress "npm" "check_npm"
run_with_progress "Yarn" "check_yarn"
run_with_progress "Git" "check_git"
run_with_progress "Homebrew" "check_homebrew"
print_category_header "• React Native Stack:" "${ORANGE}"
run_with_progress "Watchman" "check_watchman"
run_with_progress "Cocoapods" "check_cocoapods"
if [ -f "package.json" ]; then
if [ -n "$(jq -r '.dependencies["@react-native-community/cli"] // .devDependencies["@react-native-community/cli"] // ""' package.json 2>/dev/null)" ]; then
run_with_progress "React Native CLI" "check_rn_package '@react-native-community/cli' '⚛️' 'React Native CLI' 'yarn add -D @react-native-community/cli@latest'"
fi
if [ -n "$(jq -r '.dependencies["react-native"] // .devDependencies["react-native"] // ""' package.json 2>/dev/null)" ]; then
run_with_progress "React Native" "check_rn_package 'react-native' '⚛️' 'React Native' 'yarn add react-native@latest'"
fi
fi
run_with_progress "Xcode" "display_xcode"
run_with_progress "Android SDK" "display_android_sdk"
run_with_progress "Android NDK" "display_android_ndk"
run_with_progress "Gradle" "check_gradle"
run_with_progress "Java" "check_java"
print_category_header "• CLI Tools:" "${ORANGE}"
run_with_progress "Firebase CLI" "check_firebase_cli"
run_with_progress "ngrok" "check_ngrok"
run_with_progress "Claude Code" "check_claude_code"
run_with_progress "ASK CLI" "check_askcli"
run_with_progress "JQ" "check_jq"
run_with_progress "Oh My Zsh" "check_omzsh"
print_category_header "• Ruby Stack:" "${ORANGE}"
run_with_progress "Ruby" "check_ruby"
run_with_progress "RubyGems" "check_rubygems"
run_with_progress "Bundler" "check_bundler"
run_with_progress "fastlane" "check_fastlane"
print_category_header "• Python Stack:" "${ORANGE}"
run_with_progress "Python" "check_python"
run_with_progress "pip" "check_pip"
print_category_header "• Code Quality:" "${ORANGE}"
run_with_progress "TypeScript" "check_typescript"
run_with_progress "Prettier" "check_prettier"
print_category_header "• Global npm packages:" "${ORANGE}"
run_with_progress "Global npm packages" "check_npm_global_outdated"
local end_time=$(date +%s)
local elapsed=$((end_time - start_time))
printf "\r${ERASE_LINE}"
echo ""
echo -e "🏁 ${BLUE}Pulse Check Complete!${NC}"
echo ""
echo -e " ${GREEN}✓ ${tools_ok} tools are up-to-date.${NC}"
if [ "$updates_available" -gt 0 ]; then
echo -e " ${RED}⚠ ${updates_available} update(s) available.${NC}"
fi
echo -e " ${CYAN}⏱ ${elapsed}s until completion${NC}"
echo ""
if [ "$updates_available" -gt 0 ]; then
send_notification "Pulse Check Complete" "${updates_available} update(s) available, ${tools_ok} tools up-to-date" "$NOTIFICATION_SOUND"
else
send_notification "Pulse Check Complete" "All ${tools_ok} tools are up-to-date! ✨" "$NOTIFICATION_SOUND"
fi
}
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment