{"id":20992578,"url":"https://github.com/gary-ash/scripts","last_synced_at":"2026-04-21T22:32:24.726Z","repository":{"id":336348233,"uuid":"1146879802","full_name":"Gary-Ash/Scripts","owner":"Gary-Ash","description":"The utility scripts that keep me and my Mac going","archived":false,"fork":false,"pushed_at":"2026-04-20T00:03:44.000Z","size":3924,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T02:26:23.903Z","etag":null,"topics":["scripts-collection"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Gary-Ash.png","metadata":{"files":{"readme":"Readme.markdown","changelog":null,"contributing":".github/CONTRIBUTING.markdown","funding":".github/FUNDING.yml","license":"LICENSE.markdown","code_of_conduct":".github/CODE_OF_CONDUCT.markdown","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["Gary-Ash"]}},"created_at":"2026-01-31T20:38:45.000Z","updated_at":"2026-04-20T00:03:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Gary-Ash/Scripts","commit_stats":null,"previous_names":["gary-ash/scripts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Gary-Ash/Scripts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gary-Ash%2FScripts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gary-Ash%2FScripts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gary-Ash%2FScripts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gary-Ash%2FScripts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gary-Ash","download_url":"https://codeload.github.com/Gary-Ash/Scripts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gary-Ash%2FScripts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32112963,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["scripts-collection"],"created_at":"2024-11-19T07:11:41.401Z","updated_at":"2026-04-21T22:32:24.721Z","avatar_url":"https://github.com/Gary-Ash.png","language":"Shell","funding_links":["https://github.com/sponsors/Gary-Ash"],"categories":[],"sub_categories":[],"readme":"### Gary's Utility Scripts\n\nA collection of utility scripts and shell libraries for macOS development, system maintenance, and workflow automation.\n\n## Table of Contents\n\n- [Scripts](#scripts)\n- [Shell Library Functions](#shell-library-functions)\n- [Zsh Shell Completions](#zsh-shell-completions)\n- [Xcode Project Templates](#xcode-project-templates)\n- [Pictures](#pictures)\n\n---\n\n## Scripts\n\n| Script | Language | Description |\n|--------|----------|-------------|\n| [blog-post.sh](#blog-postsh) | Bash | Create Jekyll blog posts |\n| [bootstrap.sh](#bootstrapsh) | Bash | Bootstrap a new Mac setup |\n| [check-path.pl](#check-pathpl) | Perl | Validate PATH directories |\n| [find-permission-based-API-usage.sh](#find-permission-based-api-usagesh) | Bash | Find iOS permission-requiring APIs |\n| [finder-setup.sh](#finder-setupsh) | Bash | Configure Finder preferences and window layout |\n| [fix-xcode-templates.pl](#fix-xcode-templatespl) | Perl | Fix Xcode file header templates |\n| [format-project.sh](#format-projectsh) | Bash | Format source code in projects |\n| [generate-gitkeep.sh](#generate-gitkeepsh) | Bash | Add .gitkeep files to empty directories |\n| [git-applescript-filter.sh](#git-applescript-filtersh) | Bash | Git clean/smudge filter for AppleScript |\n| [git-log.sh](#git-logsh) | Bash | Pretty git log with signature highlighting |\n| [git-plist-filter.sh](#git-plist-filtersh) | Bash | Git clean/smudge filter for plist files |\n| [git-rebase-mine-to.sh](#git-rebase-mine-tosh) | Bash | Git merge and rebase utility |\n| [load-simulator.pl](#load-simulatorpl) | Perl | Restore iOS simulator state |\n| [meeting-direct-link.py](#meeting-direct-linkpy) | Python | Convert meeting URLs to app links |\n| [new-xcode-project.pl](#new-xcode-projectpl) | Perl | Generate Xcode projects from templates |\n| [ocd.sh](#ocdsh) | Bash | System cleanup and maintenance |\n| [refresh-compile-commands.sh](#refresh-compile-commandssh) | Bash | Regenerate LSP compile_commands.json |\n| [reset-dates.pl](#reset-datespl) | Perl | Reset file dates and copyright headers |\n| [safari-cleaner.pl](#safari-cleanerpl) | Perl | Delete Safari data for non-bookmarked sites |\n| [safari-restore-icons.sh](#safari-restore-iconssh) | Bash | Restore custom Safari favicons |\n| [safari-update-icons.sh](#safari-update-iconssh) | Bash | Upload Safari favicon cache to server |\n| [settings.sh](#settingssh) | Bash | Configure macOS system settings |\n| [startup-banner.pl](#startup-bannerpl) | Perl | Display terminal startup banner |\n| [strip-comments.pl](#strip-commentspl) | Perl | Remove comments from C-style source |\n| [sync-mac.sh](#sync-macsh) | Bash | Sync files between Mac systems |\n| [update-dots.sh](#update-dotssh) | Bash | Maintain dotfiles repository |\n| [update-site.sh](#update-sitesh) | Bash | Deploy Jekyll website |\n| [wtf-autolayout.py](#wtf-autolayoutpy) | Python | Debug Auto Layout constraints |\n\n---\n\n## Script Details\n\n### blog-post.sh\n\nCreates a new Jekyll blog post or product page with the appropriate front matter and timestamp. Generates files in the `~/Sites/geedbla.com/` directory structure.\n\n**Usage:** `blog-post.sh \u003cblog|products\u003e \"Title\"`\n\n---\n\n### bootstrap.sh\n\nBootstraps a fresh macOS installation by setting up dotfiles, installing Homebrew packages, configuring shells (bash/zsh), installing Ruby gems and Python packages, and setting up the ZDOTDIR environment.\n\n---\n\n### check-path.pl\n\nScans the current PATH environment variable and reports which directories exist and which are missing. Outputs a clean PATH declaration containing only valid directories.\n\n**Usage:** `check-path.pl`\n\n---\n\n### find-permission-based-API-usage.sh\n\nScans Swift and Objective-C source files for usage of APIs that require runtime permissions or entitlements (e.g., file dates, system uptime, disk capacity, UserDefaults).\n\n**Usage:** `find-permission-based-API-usage.sh \u003cdirectory\u003e`\n\n---\n\n### finder-setup.sh\n\nConfigures Finder preferences including list view with specific columns (name, size, kind, date created, date modified), show all files and extensions, sort folders first, and suppresses .DS_Store on network and USB volumes. Cleans existing .DS_Store files, restarts Finder, and uses AppleScript to set the Downloads folder view, resize windows, and clear recent items.\n\n**Usage:** `finder-setup.sh`\n\n**Note:** Requires Accessibility permissions for System Events automation.\n\n---\n\n### fix-xcode-templates.pl\n\nModifies Xcode's internal file and project templates to remove the `//` comment prefix from `___FILEHEADER___` placeholders, allowing custom file headers to work correctly.\n\n**Note:** Requires sudo privileges.\n\n---\n\n### format-project.sh\n\nRuns multiple code formatters on a project directory including uncrustify (C/Objective-C), swiftformat (Swift), black (Python), shfmt (Bash), and perltidy (Perl).\n\n**Usage:** `format-project.sh [directory]`\n\n---\n\n### generate-gitkeep.sh\n\nTraverses a directory tree and adds a `.gitkeep` file to any directory that does not contain files. Useful for preserving empty directory structures in Git repositories.\n\n**Usage:** `generate-gitkeep.sh [directory]`\n\n---\n\n### git-applescript-filter.sh\n\nA Git clean/smudge filter for compiled AppleScript (`.scpt`) files. In `--clean` mode it decompiles a compiled script to source text for storage in Git; in `--smudge` mode it recompiles source text back to a compiled script on checkout.\n\n**Usage:** Configured via `.gitattributes`:\n```\n*.scpt filter=applescript diff=applescript\n```\n\n---\n\n### git-log.sh\n\nDisplays a decorated, graphed git log with commit signature verification. Good signatures are highlighted in green and bad signatures in red using 24-bit truecolor ANSI escapes via Perl.\n\n**Usage:** `git-log.sh [git-log-options...]`\n\n**Requirements:** Git with SSH or GPG signing enabled, truecolor-capable terminal.\n\n---\n\n### git-plist-filter.sh\n\nA Git clean/smudge filter for binary plist files. In `--clean` mode it converts a binary plist to XML for readable diffs in Git; in `--smudge` mode it converts XML back to binary plist on checkout.\n\n**Usage:** Configured via `.gitattributes`:\n```\n*.plist filter=plist diff=plist\n```\n\n---\n\n### git-rebase-mine-to.sh\n\nMerges the current branch into a target branch (with --no-ff) and then rebases the current branch onto the target branch.\n\n**Usage:** `git-rebase-mine-to.sh \u003cbranch\u003e`\n\n---\n\n### load-simulator.pl\n\nResets all iOS simulators and restores a consistent state by loading media files from a backup folder into each simulator.\n\n---\n\n### meeting-direct-link.py\n\nConverts Microsoft Teams and Zoom web URLs into direct app launch URLs (msteams:// and zoommtg:// protocols).\n\n**Usage:** `meeting-direct-link.py \u003curl\u003e`\n\n---\n\n### new-xcode-project.pl\n\nGenerates a new Xcode project from customizable templates. Supports options for GitHub repository creation, open/closed source licensing, and in-file license headers.\n\n**Usage:** `new-xcode-project.pl \u003ctemplate\u003e \u003cname\u003e \u003clocation\u003e [company] [bundle-id]`\n\n**Options:**\n- `-ng, --no-github` - Don't create GitHub repository\n- `-nx, --no-xcode` - Don't open Xcode after generation\n- `-cs, --closed` - Use closed source license\n- `-lif, --inFileLicense` - Add license text to source files\n\n**Templates:** Project templates are located in `templates/Xcode/`. See [Xcode Project Templates](#xcode-project-templates).\n\n---\n\n### ocd.sh\n\nComprehensive macOS system maintenance script that updates Homebrew, gems, pip, and npm packages; cleans caches, history, and temporary files; resets application preferences; clears browser data; and performs various system optimizations.\n\n**Usage:** `ocd.sh [restart|off]`\n\n---\n\n### refresh-compile-commands.sh\n\nRegenerates `compile_commands.json` files for all Xcode projects in ~/Developer to enable LSP support in editors.\n\n---\n\n### reset-dates.pl\n\nResets file creation/modification dates and updates copyright headers in source files. Handles various file types including Xcode project files and compiled AppleScript.\n\n**Usage:** `reset-dates.pl \"Company Name\" [file|directory ...]`\n\n---\n\n### safari-cleaner.pl\n\nDeletes Safari website data (cookies, local storage, observations, URL cache, WebKit cache, Screen Time web usage, and HTTP Alternative Services) for domains that do not match any bookmarked website. Parses and rewrites Safari's `Cookies.binarycookies` file directly.\n\n**Usage:** `safari-cleaner.pl [--dry-run|-n] [--verbose|-v]`\n\n**Options:**\n- `-n, --dry-run` — Report what would be removed without making changes\n- `-v, --verbose` — Print each deleted entry\n\n**Note:** Safari must be quit before running.\n\n---\n\n### safari-restore-icons.sh\n\nDownloads and installs custom Safari favicon files from a remote server to replace the default Apple icons.\n\n---\n\n### safari-update-icons.sh\n\nArchives Safari favicon cache directories and uploads the archive to a remote server via scp. Retrieves the server password from the macOS Keychain.\n\n**Usage:** `safari-update-icons.sh`\n\n---\n\n### settings.sh\n\nConfigures various macOS system defaults including Finder settings, keyboard behavior, Safari options, and Xcode preferences. Also enables developer tools security.\n\n---\n\n### startup-banner.pl\n\nDisplays a colorful terminal startup banner with system information including OS version, hardware specs, Homebrew status, IP addresses, disk usage, and battery status. Supports both light and dark themes.\n\n**Usage:** `startup-banner.pl [--light|--dark]`\n\n---\n\n### strip-comments.pl\n\nRemoves all C-style comments (both `//` and `/* */`) from source files in a directory tree. Handles nested comments and preserves strings.\n\n**Usage:** `strip-comments.pl [directory]`\n\n---\n\n### sync-mac.sh\n\nSynchronizes directories, files, and package manager installations between multiple Mac systems over SSH. Syncs:\n\n- **Directories** — `~/.claude`, `~/.config`, `~/Developer`, `~/Documents`, `/opt/bin`, `/opt/geedbla`, BBEdit support files\n- **Files** — `~/.claude.json`\n- **Mail** — Mail archive (`~/Library/Mail`) and Mail preferences\n- **Package managers** — Homebrew formulae and casks, pip packages, Ruby gems, npm packages (installs missing, removes extras)\n- **Custom apps** — Bespoke applications (CleanStart.app, XcodeGeDblA.app) installed to `/Applications` via sudo. Sudo password prompts are suppressed and sync failures produce descriptive error messages without aborting the remaining sync operations.\n\n---\n\n### update-dots.sh\n\nMaintains a dotfiles Git repository by collecting configuration files, preferences, and application settings from the system and pushing updates to GitHub.\n\n**Usage:** `update-dots.sh [--package]`\n\n---\n\n### update-site.sh\n\nBuilds a Jekyll website and deploys it to a remote server via rsync.\n\n---\n\n### wtf-autolayout.py\n\nParses Auto Layout constraint warnings from Xcode and opens wtfautolayout.com with the constraint log for analysis and debugging help.\n\n**Usage:** `wtf-autolayout.py \u003cconstraint-log\u003e`\n\n---\n\n## Shell Library Functions\n\nReusable shell functions located in `lib/shell/lib/` that can be sourced into scripts.\n\n### get_sudo_password.sh\n\nProvides secure sudo password retrieval for scripts that require elevated privileges.\n\n**Function:** `get_sudo_password`\n\n**Description:** Retrieves the user's sudo password through a secure multi-step process:\n1. First checks if sudo is already authenticated (non-interactive validation)\n2. Attempts to retrieve the password from the macOS Keychain (`security find-generic-password`)\n3. Falls back to interactive password prompt if keychain lookup fails\n\n**Returns:** The sudo password on stdout (for use with `sudo --stdin`)\n\n**Usage:**\n```bash\nsource \"/opt/geedbla/lib/shell/lib/get_sudo_password.sh\"\n\nSUDO_PASSWORD=\"$(get_sudo_password)\"\necho \"$SUDO_PASSWORD\" | sudo --validate --stdin\n```\n\n---\n\n### get_notary_password.sh\n\nProvides secure retrieval of Apple notarization service credentials.\n\n**Function:** `get_notary_password`\n\n**Description:** Retrieves the Apple notarization service password for code signing workflows:\n1. Attempts to retrieve the password from the macOS Keychain (`security find-generic-password`)\n2. Falls back to interactive password prompt if keychain lookup fails\n\n**Returns:** The notarization password on stdout\n\n**Usage:**\n```bash\nsource \"/opt/geedbla/lib/shell/lib/get_notary_password.sh\"\n\nNOTARY_PASSWORD=\"$(get_notary_password)\"\nxcrun notarytool submit app.zip --apple-id \"$APPLE_ID\" --password \"$NOTARY_PASSWORD\"\n```\n\n---\n\n## Zsh Shell Completions\n\nTab completion definitions located in `zsh-completions/` that can be added to a `$fpath` directory for zsh.\n\n| File | Command | Description |\n|------|---------|-------------|\n| `_jekyll` | `jekyll` | Tab completion for Jekyll subcommands and options |\n| `_new-xcode-project` | `new-xcode-project.pl` | Tab completion for project templates (dynamically read from `templates/Xcode/`) and all command-line flags |\n| `_ocd` | `ocd.sh` | Tab completion for `ocd.sh` providing the `restart` and `off` subcommands |\n| `_tv` | `tv` | Tab completion for the television (tv) TUI fuzzy finder |\n\n---\n\n## Xcode Project Templates\n\nReusable Xcode project templates located in `templates/Xcode/`, used by `new-xcode-project.pl` to generate new projects.\n\n### Project Templates\n\n| Template | Description |\n|----------|-------------|\n| `2DGame` | Multiplatform SpriteKit-based game (iOS, macOS, tvOS) |\n| `AppKitProject` | AppKit-based macOS application with unit and UI tests |\n| `CppCLITool` | C++ command-line tool with Objective-C++ unit tests |\n| `MultiPlatform` | SwiftUI multiplatform app (iOS + macOS) with unit and UI tests |\n| `SwiftCLITool` | Swift command-line tool with a separate core library and unit tests |\n| `UIKitProject` | UIKit-based iOS application with unit and UI tests |\n\nEach template directory contains a complete `.xcodeproj` and source tree that `new-xcode-project.pl` copies and customizes with the project name, company, bundle identifier, and license.\n\n### Shared Files (`_Files/`)\n\nFiles in `templates/Xcode/_Files/` are applied to every generated project regardless of template:\n\n| File / Directory | Description |\n|------------------|-------------|\n| `Assets.xcassets.zip` | Pre-built asset catalog (app icon slots, accent color, etc.) |\n| `BuildEnv/` | Build phase scripts: `ci.sh`, `increment-build-number.sh`, `stamp-beta-version.sh`, `restore-stamped-icon.sh`, `swiftlint-project.sh`, `export-github-secrets.sh` |\n| `IDETemplateMacros.plist` | Xcode file header template macros |\n| `IDETemplateMacros-Open.plist` | Header macros variant for open-source projects |\n| `IDETemplateMacros-Closed.plist` | Header macros variant for closed-source projects |\n| `LICENSE-Open.markdown` | Open-source license text |\n| `LICENSE-Closed.markdown` | Closed-source license text |\n| `ci.sh` | Local CI runner script |\n| `organizations.txt` | Known organization names for copyright substitution |\n\n---\n\n## Pictures\n\nResource images located in `pictures/` used by scripts.\n\n| File | Description |\n|------|-------------|\n| `apple-logo.png` | Apple logo image |\n| `SimpleGrey.heic` | Desktop wallpaper image |\n\n---\n\n## Author\n\nGary Ash \u003cgary.ash@icloud.com\u003e\n\n## License\n\nCopyright 2026 By Gary Ash. All rights reserved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgary-ash%2Fscripts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgary-ash%2Fscripts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgary-ash%2Fscripts/lists"}