___ _____   ___         _      _
  |_ _|_   _| / __| __ _ _(_)_ __| |_ ___
   | |  | |   \__ \/ _| '_| | '_ \  _(_-<
  |___| |_|   |___/\__|_| |_| .__/\__/__/
                             |_|

IT Convenience Scripts

curl it • pipe it • done

/crcfix
Solves CRC error while downloading from filewave booster servers
curl -fsSL https://scripts.bonnier.news/crcfix | bash
#!/usr/bin/env bash
set -euo pipefail
echo "Running CRC booster fix script..."

# Removes all booster servers, forcing the client to connect directly to the filewave server.
echo "Removing booster servers..."
sudo defaults write /usr/local/etc/fwcld.plist booster1 no.booster.set
sudo defaults write /usr/local/etc/fwcld.plist booster2 no.booster.set
sudo defaults write /usr/local/etc/fwcld.plist booster3 no.booster.set
sudo defaults write /usr/local/etc/fwcld.plist booster4 no.booster.set
sudo defaults write /usr/local/etc/fwcld.plist booster5 no.booster.set
sudo chmod 644 /usr/local/etc/fwcld.plist

echo "Booster servers removed succesfully, restarting filewave client..."
sudo fwcontrol client restart
echo "Waiting for 30 seconds to allow the client to restart..."
sleep 30
sudo touch /etc/resolv.conf # Touching resolv.conf triggers a network change, and puts back the boosters we removed.
echo "Done!"
/hwinfo
Prints chip name, battery health, RAM, serial number and macOS version
curl -fsSL https://scripts.bonnier.news/hwinfo | bash
#!/usr/bin/env bash
set -euo pipefail

echo "Device info:"

chip="$(sysctl -n machdep.cpu.brand_string 2>/dev/null || true)"
if [[ -z "$chip" ]]; then
	chip="Unknown"
fi
echo "$chip"

mem_bytes="$(sysctl -n hw.memsize 2>/dev/null || true)"
if [[ -n "$mem_bytes" ]]; then
	mem="$(awk -v b="$mem_bytes" 'BEGIN { if (b>0) printf "%.0f GB", b/1073741824 }')"
fi
if [[ -z "$mem" ]]; then
	mem="Unknown"
fi
echo "$mem"

echo $(ioreg -rd1 -c IOPlatformExpertDevice | grep '"IOPlatformSerialNumber" = "') | awk -F\" '{print $4}'

os_name="$(sw_vers -productName 2>/dev/null || true)"
os_version="$(sw_vers -productVersion 2>/dev/null || true)"
if [[ -n "$os_name" && -n "$os_version" ]]; then
	echo "$os_name $os_version"
else
	echo "Unknown"
fi

battery_health="$(ioreg -l 2>/dev/null | grep -E '"DesignCapacity" =|"AppleRawMaxCapacity"' | grep -o '[0-9]*' | tr '\n' ',' | awk -F',' '{print (int(($2/$1)*1000 + 0.5)/10 "% battery health")}')"
if [[ -z "$battery_health" ]]; then
	battery_health="Unknown battery health"
fi
echo "$battery_health"
/oobe-visualizer
Generates an interactive HTML diagram of the local Windows OOBE setup flow
irm https://scripts.bonnier.news/oobe-visualizer | iex
Write-Host "Installing required PSWriteHTML module..." -ForegroundColor Cyan
Install-Module -Name PSWriteHTML -Force -AcceptLicense -Scope CurrentUser -ErrorAction SilentlyContinue

Write-Host "Generating OOBE flow diagram..." -ForegroundColor Cyan

# Note: Changed $PSScriptRoot to $env:TEMP so it works when executed from memory
New-HTML -TitleText 'OOBE' -Online -FilePath "$env:TEMP\OOBE.html" {
    New-HTMLPanel {
        New-HTMLDiagram -Height '2000px' -Width '3000px' {
            New-DiagramOptionsInteraction -Hover $true
            New-DiagramOptionsPhysics -Enabled $true
            New-DiagramOptionsLayout -RandomSeed 0
            New-DiagramOptionsLinks -ArrowsToEnabled $true -Color BlueViolet -ArrowsToType arrow -ArrowsFromEnabled $false
            New-DiagramOptionsNodes -BorderWidth 1 -FontColor Black -Size 16 -FontMulti true
            
            $file = "C:\Windows\SystemApps\Microsoft.Windows.CloudExperienceHost_cw5n1h2txyewy\data\prod\navigation.json"
            if (-not (Test-Path $file)) {
                Write-Warning "Could not find the OOBE navigation.json file on this system."
                return
            }

            $nav = Get-Content $file | ConvertFrom-Json -Depth 999 -AsHashtable
            $nav.FRXINCLUSIVE.Keys | Where-Object { $nav.FRXINCLUSIVE.$_.count -gt 1} | ForEach-Object {
                Write-Host "Mapping Node: $_"
                New-DiagramNode -Label "$_" -IconSolid desktop -Title "$_"
                if ($null -ne $nav.FRXINCLUSIVE.$_.successID) {
                    New-DiagramLink -From "$_" -To "$($nav.FRXINCLUSIVE.$_.successID)"
                }
            }
        }
    }
} -ShowHTML
/sccm-cycles
Sync SCCM Client Configuration Cycles
irm https://scripts.bonnier.news/sccm-cycles | iex
# Source - https://stackoverflow.com/a/70869951
# Posted by Suncat2000, Retrieved 2026-04-01, License - CC BY-SA 4.0
# Modified for in-memory execution, GPUpdate, and UI improvements

# 1. Smart Self-Elevation (Handles both local .ps1 files and in-memory execution)
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

if (-Not $isAdmin) {
    Write-Warning "Administrator privileges required. Attempting to elevate..."
    
    if ($PSCommandPath) {
        # Executed from a local file (Debugging)
        Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList "-NoProfile -File `"$PSCommandPath`""
    } else {
        # Executed in-memory via 'irm | iex'
        $ElevatedCommand = "-NoProfile -Command `"irm http://192.168.250.1:7676/sccm-cycles | iex`""
        Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $ElevatedCommand
    }
    Exit
}

# 2. Define the SCCM Cycles with descriptions
$sccmCycles = @(
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000001}"; Name = "Hardware Inventory Cycle" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000002}"; Name = "Software Inventory & Collect Files" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000003}"; Name = "Discovery Data Collection (Heartbeat)" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000010}"; Name = "Software Metering Usage Report Cycle" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000021}"; Name = "Request Machine Assignments" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000022}"; Name = "Evaluate Machine Policies" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000031}"; Name = "Software Metering Generate Usage Report" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000040}"; Name = "Machine Policy Agent Cleanup" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000042}"; Name = "Policy Agent Validate Machine Policy" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000105}"; Name = "Get IDMIF Files" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000108}"; Name = "Software Updates Evaluation Cycle" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000111}"; Name = "Windows PE Peer Cache Cleanup" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000113}"; Name = "Software Updates Scan Cycle" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000114}"; Name = "Windows Installer Source List Update" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000115}"; Name = "State Message Manager Delivery" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000121}"; Name = "Application Manager Machine Policy Action" }
    [pscustomobject]@{ ID = "{00000000-0000-0000-0000-000000000131}"; Name = "Power Management Client Activity" }
)

Write-Host ""
Write-Host "===========================================================" -ForegroundColor Cyan
Write-Host " Initiating System Sync & Configuration Cycles" -ForegroundColor White
Write-Host "===========================================================" -ForegroundColor Cyan
Write-Host ""

# 3. Group Policy Update
Write-Host " > Triggering " -NoNewline
Write-Host "$("Group Policy Update (gpupdate)".PadRight(45))" -ForegroundColor Yellow -NoNewline

try {
    # Pipe output to $null to keep the console clean while it waits
    $null = gpupdate.exe /force /Wait:-1 2>&1
    if ($LASTEXITCODE -eq 0) {
        Write-Host "[ OK ]" -ForegroundColor Green
    } else {
        Write-Host "[WARN]" -ForegroundColor DarkYellow
    }
} catch {
    Write-Host "[FAIL]" -ForegroundColor Red
}

# 4. SCCM Cycles
foreach ($cycle in $sccmCycles) {
    Write-Host " > Triggering " -NoNewline
    Write-Host "$($cycle.Name.PadRight(45))" -ForegroundColor Yellow -NoNewline
    
    try {
        $null = Invoke-WMIMethod -Namespace root\ccm -Class SMS_CLIENT -Name TriggerSchedule -ArgumentList $cycle.ID -ErrorAction Stop
        Write-Host "[ OK ]" -ForegroundColor Green
    } catch {
        Write-Host "[FAIL]" -ForegroundColor Red
    }
}

Write-Host ""
Write-Host "===========================================================" -ForegroundColor Cyan
Write-Host " Sync completed!" -ForegroundColor Green
Write-Host "===========================================================" -ForegroundColor Cyan
Write-Host ""
/usbsn
Prints serial number for all connected and unlocked iOS and Android devices
curl -fsSL https://scripts.bonnier.news/usbsn | bash
#!/bin/bash

# Parses Apple internal model numbers to the public device model
parse_cfgutil_data() {
    local raw_data="$1"
    
    # cfgutil returns 2 items, device type and serial. This parses device type to model 
    # and then macthes together the rows given by cfgutil to build output
    # This also replaces cfgutil error 604 with device in recovery/dfu mode since it is expected
    echo "$raw_data" | awk -F": " '
    BEGIN {
        # Create the lookup dictionary before processing the text
        name["iPhone12,8"] = "iPhone SE (2nd generation)"
        
        name["iPhone13,1"] = "iPhone 12 mini"
        name["iPhone13,2"] = "iPhone 12"
        name["iPhone13,3"] = "iPhone 12 Pro"
        name["iPhone13,4"] = "iPhone 12 Pro Max"
        
        name["iPhone14,2"] = "iPhone 13 Pro"
        name["iPhone14,3"] = "iPhone 13 Pro Max"
        name["iPhone14,4"] = "iPhone 13 mini"
        name["iPhone14,5"] = "iPhone 13"
        
        name["iPhone14,6"] = "iPhone SE (3rd generation)"
        
        name["iPhone14,7"] = "iPhone 14"
        name["iPhone14,8"] = "iPhone 14 Plus"
        name["iPhone15,2"] = "iPhone 14 Pro"
        name["iPhone15,3"] = "iPhone 14 Pro Max"
        
        name["iPhone15,4"] = "iPhone 15"
        name["iPhone15,5"] = "iPhone 15 Plus"
        name["iPhone16,1"] = "iPhone 15 Pro"
        name["iPhone16,2"] = "iPhone 15 Pro Max"
        
        name["iPhone17,1"] = "iPhone 16 Pro"
        name["iPhone17,2"] = "iPhone 16 Pro Max"
        name["iPhone17,3"] = "iPhone 16"
        name["iPhone17,4"] = "iPhone 16 Plus"
        name["iPhone17,5"] = "iPhone 16e"
        
        name["iPhone18,1"] = "iPhone 17 Pro"
        name["iPhone18,2"] = "iPhone 17 Pro Max"
        name["iPhone18,3"] = "iPhone 17"
        name["iPhone18,4"] = "iPhone Air"
        name["iPhone18,5"] = "iPhone 17e"
    }

    /^deviceType:/ { section="type"; row=1; next }
    /^serialNumber:/ { section="serial"; row=1; next }
    /^$/ { next }

    section=="type" { 
        internal_model = $NF
        
        # Check if the internal model exists in our dictionary
        if (internal_model in name) {
            models[row] = name[internal_model]
        } else {
            # Fallback to the raw ID if it is not in the list
            models[row] = internal_model
        }
        
        row++ 
    }

    section=="serial" {
        if ($NF == "The device is not booted into the System. (ConfigurationUtilityKit.error 604)") {
            print "Model: " models[row] " | Serial: In Recovery/DFU Mode"
        }
        else {
            print "Model: " models[row] " | Serial: " $NF
        }
        row++ 
    }
    '
}

# This parses the device model from the extra inforamtion contained in the serial number entry in ioreg
parse_ios_usb_row() {
    local raw_string="$1"
    local cpid=""
    local bdid=""
    local srnm=""
    local model="Unknown Device"

    # Extract CPID
    if [[ $raw_string =~ CPID:([0-9A-Fa-f]+) ]]; then
        cpid="${BASH_REMATCH[1]}"
    fi

    # Extract BDID
    if [[ $raw_string =~ BDID:([0-9A-Fa-f]+) ]]; then
        bdid="${BASH_REMATCH[1]}"
    fi

    # Extract SRNM
    if [[ $raw_string =~ SRNM:\[([A-Za-z0-9]+)\] ]]; then
        srnm="${BASH_REMATCH[1]}"
    fi

    # Mapping CPID & BDID to model
    if [[ -n "$cpid" && -n "$bdid" ]]; then
        case "${cpid}-${bdid}" in
            "8030-10"|"8030-14") model="iPhone SE (2nd Gen)" ;;
            "8030-01"|"8030-02") model="iPhone 11" ;;
            "8030-04") model="iPhone 11 Pro" ;;
            "8030-06") model="iPhone 11 Pro Max" ;;
            "8030-"*)            model="Unknown A13 Device" ;;

            "8101-14"|"8101-16") model="iPhone 12 mini" ;;
            "8101-0C"|"8101-0E") model="iPhone 12" ;;
            "8101-10")           model="iPhone 12 Pro" ;;
            "8101-12")           model="iPhone 12 Pro Max" ;;
            "8101-"*)            model="Unknown A14 Device" ;;

            "8110-10")           model="iPhone SE (3rd Gen)" ;;
            "8110-14"|"8110-15") model="iPhone 13 mini" ;;
            "8110-16"|"8110-17") model="iPhone 13" ;;
            "8110-0A"|"8110-0B") model="iPhone 13 Pro" ;;
            "8110-0C"|"8110-0D") model="iPhone 13 Pro Max" ;;
            "8110-18")           model="iPhone 14" ;;
            "8110-1A")           model="iPhone 14 Plus" ;;
            "8110-"*)            model="Unknown A15 Device" ;;

            "8120-0C")           model="iPhone 14 Pro" ;;
            "8120-0E")           model="iPhone 14 Pro Max" ;;
            "8120-08")           model="iPhone 15" ;;
            "8120-0A")           model="iPhone 15 Plus" ;;
            "8120-"*)            model="Unknown A16 Device" ;;

            "8130-02")           model="iPhone 15 Pro" ;;
            "8130-04")           model="iPhone 15 Pro Max" ;;
            "8130-"*)            model="Unknown A17 Pro Device" ;;

            "8140-08")           model="iPhone 16" ;;
            "8140-0A")           model="iPhone 16 Plus" ;;
            "8140-0C")           model="iPhone 16 Pro" ;;
            "8140-0E")           model="iPhone 16 Pro Max" ;;
            "8140-"*)            model="Unknown A18 Device" ;;
        

            *)                   model="Unknown (${cpid}-${bdid})" ;;
        esac
    fi

    # Handling if no serial number was found
    if [[ -z "$srnm" ]]; then
        srnm="N/A"
    fi

    echo "Model: $model | Serial: $srnm"
}

CMD_NAME="cfgutil"
HARDCODED_PATH="/Applications/Apple Configurator.app/Contents/MacOS/cfgutil"
EXECUTABLE=""

echo $'\nConnected non-recovery mode iOS devices\n-----------------------------------------'

# Check if cfgutil is available
if command -v "$CMD_NAME" >/dev/null 2>&1; then
    EXECUTABLE="$CMD_NAME"

elif [ -f "$HARDCODED_PATH" ] && [ -x "$HARDCODED_PATH" ]; then
    EXECUTABLE="$HARDCODED_PATH"

else
    echo "Unable to scan for non-recovery mode iOS devices!"
    echo "Error: Could not locate cfgutil, make sure Apple Configurator is installed"
fi

# Handle iOS non-recovery devices using cfgutil
if [ -n "$EXECUTABLE" ]; then
    CFG_OUTPUT=$("$EXECUTABLE" -f get deviceType serialNumber 2>&1)
    
    # Handle no discovered devices
    if [[ "$CFG_OUTPUT" == *"cfgutil: error: no devices found"* ]]; then
        echo "No non-recovery mode iOS devices detected! Make sure passcode locked devices are unlocked."
        
    else
        FORMATTED_DEVICES=$(parse_cfgutil_data "$CFG_OUTPUT")
        
        if [ -n "$FORMATTED_DEVICES" ]; then
            echo "$FORMATTED_DEVICES"
        else
            echo "Devices detected, but they are in Recovery/DFU mode."
        fi
    fi
fi

echo $'\nConnected recovery mode iOS devices\n-----------------------------------------'

# Handle iOS recovery mode devices

DEVICES=$(ioreg -p IOUSB -n "Apple Mobile Device (Recovery Mode)" -l -r | grep "USB Serial Number")

if [ -z "$DEVICES" ]; then 
    echo "No connected recovery mode iOS devices"
else 
    while IFS= read -r row; do
    if [[ -z "$row" ]]; then
        continue
    fi
    parse_ios_usb_row "$row"
    done <<< "$DEVICES"
fi

echo $'\nConnected Android devices\n-----------------------------------------'

# Handle Pixel devices
ioreg -p IOUSB | grep -o "Pixel[^@]*" | while read -r device_name; do
    echo "Model: $device_name | Serial:  $(ioreg -p IOUSB -n "$device_name" | grep "kUSBSerialNumberString" | awk -F\" '{print $4}')"
done

# Handle Samsung devices
ioreg -p IOUSB -n "SAMSUNG_Android" -l -r | grep "kUSBSerialNumberString" | awk -F\" '{print "Model: Samsung | Serial: " $4}'

# Handle Samsung Recovery mode
ioreg -p IOUSB | grep -Eo "\bSM-[A-Z][0-9]{3}[A-Z0-9]{1,2}\b" | while read -r device_name; do
    echo "Model: Samsung | Serial: $(ioreg -p IOUSB -n "$device_name" -l -r | grep "kUSBSerialNumberString" | awk -F\" '{print $4}')"
done

echo ""