Created
January 5, 2026 20:58
-
-
Save RoseSecurity/9a32919c7d9758a4fc61a99beceaaa50 to your computer and use it in GitHub Desktop.
utils is a curated gist of my favorite local dev environment utilities.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Generate commit messages using conventional commits with gum | |
| # Requires gum for interactivity | |
| # Install gum: brew install gum | |
| # Show git diff with fallback for better visibility | |
| git --no-pager diff --cached | gum format -t code || git --no-pager diff --cached | |
| trap "echo -e '\nCanceled.'; exit 1" INT | |
| if ! command -v gum &>/dev/null; then | |
| echo "Error: Gum is not installed. Install it with 'brew install gum'." | |
| exit 1 | |
| fi | |
| # Handle quick commit with -m flag | |
| if [ "$1" == "-m" ]; then | |
| shift | |
| QUICK_MSG=$* | |
| if [ -z "$QUICK_MSG" ]; then | |
| echo "Error: Commit message cannot be empty for -m." | |
| exit 1 | |
| fi | |
| git commit -m "$QUICK_MSG" | |
| echo "Quick commit created successfully." | |
| exit 0 | |
| fi | |
| # Interactive commit generation | |
| JIRA_TICKET=$(gum input --placeholder "JIRA ticket number (e.g., DEV-4000)") | |
| if [ -z "$JIRA_TICKET" ]; then | |
| echo "Error: JIRA ticket number cannot be empty." | |
| exit 1 | |
| fi | |
| SUMMARY=$(gum input --placeholder "Summary of this change") | |
| if [ -z "$SUMMARY" ]; then | |
| echo "Error: Summary cannot be empty." | |
| exit 1 | |
| fi | |
| DESCRIPTION=$(gum write --placeholder "Details of this change (optional)") | |
| COMMIT_MSG="$JIRA_TICKET: $SUMMARY" | |
| [ -n "$DESCRIPTION" ] && COMMIT_MSG="$COMMIT_MSG"$'\n\n'"$DESCRIPTION" | |
| if gum confirm "Commit changes?"; then | |
| git commit -m "$COMMIT_MSG" | |
| echo "Commit created successfully." | |
| else | |
| echo "Commit canceled." | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Create Git branches from Jira tickets | |
| # Ensure gum is installed | |
| if ! command -v gum &> /dev/null; then | |
| echo "gum could not be found, please install it first." | |
| exit 1 | |
| fi | |
| if ! command -v jira &> /dev/null; then | |
| echo "jira could not be found, please install it first." | |
| exit 1 | |
| fi | |
| # Accept argv[1] as the Jira ticket ID or prompt the user for input | |
| TICKET_ID=$1 | |
| if [ -z "$TICKET_ID" ]; then | |
| TICKET_ID=$(gum input --placeholder "Enter Jira Ticket ID" | xargs -L1 echo) | |
| if [ -z "$TICKET_ID" ]; then | |
| echo "No Jira Ticket ID provided. Exiting." | |
| exit 1 | |
| fi | |
| fi | |
| # Fetch Jira ticket details | |
| ISSUE_DETAILS=$(gum spin --spinner dot --title "Fetching Jira Ticket Details..." \ | |
| -- bash -c "jira issue view '$TICKET_ID' --plain") | |
| if [ -z "$ISSUE_DETAILS" ]; then | |
| echo "No matching Jira ticket found for ID: $TICKET_ID" | |
| exit 1 | |
| fi | |
| TITLE=$( | |
| echo "$ISSUE_DETAILS" \ | |
| | grep -E '^[[:space:]]*#[[:space:]]' \ | |
| | head -n 1 \ | |
| | sed 's/^[[:space:]]*#[[:space:]]*//' | |
| ) | |
| # Create a lowercase slug from the title | |
| TITLE_SLUG=$( | |
| echo "$TITLE" \ | |
| | tr '[:upper:]' '[:lower:]' \ | |
| | xargs \ | |
| | tr ' ' '-' \ | |
| | tr -cd '[:alnum:]-' | |
| ) | |
| # Convert TICKET_ID to uppercase (so DEV, ABC, etc. are capitalized) | |
| TICKET_ID_UPPER=$(echo "$TICKET_ID" | tr '[:lower:]' '[:upper:]') | |
| # Create final branch name like "DEV-6416-some-description" | |
| BRANCH_NAME="${TICKET_ID_UPPER}-${TITLE_SLUG}" | |
| echo "Creating branch: $BRANCH_NAME" | |
| git checkout -b "$BRANCH_NAME" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # A utility for searching code and repos on GitHub | |
| main() { | |
| local query="$*" | |
| if [[ -z "$query" ]]; then | |
| echo "Usage: $0 <query>" | |
| exit 1 | |
| fi | |
| if [[ "$query" =~ ^repo:([^[:space:]]+) ]]; then | |
| local repo="${BASH_REMATCH[1]}" | |
| gh search repos "$repo" --web | |
| else | |
| gh search code "$query" --web | |
| fi | |
| } | |
| main "$@" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Fetch instance list: InstanceId, Hostname | |
| instances=$(aws ssm describe-instance-information \ | |
| --query "InstanceInformationList[*].[InstanceId,ComputerName]" \ | |
| --output text) | |
| if [[ -z "$instances" ]]; then | |
| echo "No SSM-managed instances found." | |
| exit 1 | |
| fi | |
| mapfile -t ids < <(echo "$instances" | awk '{print $1}') | |
| name_data=$(aws ec2 describe-instances \ | |
| --instance-ids "${ids[@]}" \ | |
| --query "Reservations[].Instances[].{InstanceId:InstanceId, Name:(Tags[?Key=='Name']|[0].Value)}" \ | |
| --output text) | |
| # Build name lookup table | |
| declare -A name_map | |
| while read -r id name; do | |
| name_map["$id"]="${name:-N/A}" | |
| done <<< "$name_data" | |
| # Append Name to instance list with aligned columns | |
| enriched=$(while read -r line; do | |
| id=$(awk '{print $1}' <<< "$line") | |
| hostname=$(awk '{print $2}' <<< "$line") | |
| platform=$(awk '{print $3}' <<< "$line") | |
| name="${name_map[$id]:-N/A}" | |
| printf "%-30s %-20s %-30s %-10s\n" "$name" "$id" "$hostname" "$platform" | |
| done <<< "$instances") | |
| selected=$(echo "$enriched" | fzf --header="Select an instance to connect via SSM" --height=50%) | |
| instance_id=$(awk '{print $4}' <<< "$selected") | |
| if [[ -n "$instance_id" ]]; then | |
| echo "Starting SSM session to $instance_id..." | |
| aws ssm start-session --target "$instance_id" | |
| else | |
| echo "No instance selected." | |
| exit 1 | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Generate Jira tickets programmatically with AI-enhanced descriptions | |
| # Requires gum, jira-cli, and claude CLI for interactivity | |
| # Install gum: brew install gum | |
| # Install claude CLI: https://docs.anthropic.com/en/docs/claude-code | |
| if ! command -v gum &>/dev/null; then | |
| echo "Error: Gum is not installed. Install it with 'brew install gum'." | |
| exit 1 | |
| fi | |
| if ! command -v claude &>/dev/null; then | |
| echo "Error: Claude CLI is not installed. Visit https://docs.anthropic.com/en/docs/claude-code" | |
| exit 1 | |
| fi | |
| # Default to Task if not selected | |
| TYPE="Task" | |
| # Get priority | |
| PRIORITY=$(gum choose --limit=1 --header="Select Priority" "Lowest" "Low" "Medium" "High" "Highest") | |
| # Get title | |
| TITLE=$(gum input --placeholder "Enter Ticket Title") | |
| if [ -z "$TITLE" ]; then | |
| echo "Error: Ticket Title cannot be empty." | |
| exit 1 | |
| fi | |
| # Get change category | |
| CHANGE_TYPE=$(gum choose --limit=1 --header="Select Change Category" \ | |
| "Feature" "Bugfix" "Documentation" "Refactoring" "Performance" "Security" "Testing" "Infrastructure") | |
| # Get historical context | |
| echo "" | |
| echo "Provide any relevant historical context (prior discussions, related tickets, background):" | |
| HISTORICAL_CONTEXT=$(gum write --placeholder "Optional: Add context about why this work is needed, previous attempts, related issues, etc.") | |
| # Get technical details | |
| echo "" | |
| echo "Provide technical details or initial implementation thoughts:" | |
| TECHNICAL_DETAILS=$(gum write --placeholder "Optional: Add technical considerations, affected components, dependencies, etc.") | |
| # Get acceptance criteria | |
| echo "" | |
| echo "Define acceptance criteria (what does 'done' look like?):" | |
| ACCEPTANCE_CRITERIA=$(gum write --placeholder "Optional: List the specific conditions that must be met") | |
| # Get labels | |
| LABELS=$(gum input --placeholder "Enter labels for this ticket (comma-separated, optional)") | |
| # Get story points | |
| STORY_POINTS=$(gum input --placeholder "Enter story points for this ticket (press Enter for 1)") | |
| if [ -z "$STORY_POINTS" ]; then | |
| STORY_POINTS=1 | |
| fi | |
| # Build the prompt for Claude | |
| PROMPT="Generate a concise, well-structured Jira ticket description based on the following information: | |
| Title: ${TITLE} | |
| Type: ${TYPE} | |
| Change Category: ${CHANGE_TYPE} | |
| Priority: ${PRIORITY} | |
| Historical Context: | |
| ${HISTORICAL_CONTEXT:-None provided} | |
| Technical Details: | |
| ${TECHNICAL_DETAILS:-None provided} | |
| Acceptance Criteria: | |
| ${ACCEPTANCE_CRITERIA:-None provided} | |
| Please create a professional Jira ticket description that includes: | |
| 1. A brief overview/summary section | |
| 2. Background/context (if provided) | |
| 3. Technical approach or details (if provided) | |
| 4. Clear acceptance criteria formatted as checkable items | |
| 5. Any relevant notes or considerations | |
| Keep the description concise but comprehensive. Use markdown formatting appropriate for Jira. Do not add sections that have no information provided. Only provide the ticket information back." | |
| echo "" | |
| echo "Generating enhanced ticket description with Claude..." | |
| echo "" | |
| # Generate description using Claude | |
| GENERATED_DESCRIPTION=$(claude -p "$PROMPT") | |
| if [ $? -ne 0 ] || [ -z "$GENERATED_DESCRIPTION" ]; then | |
| echo "Warning: Failed to generate AI description. Using manual input instead." | |
| GENERATED_DESCRIPTION="${TECHNICAL_DETAILS}\n\n${ACCEPTANCE_CRITERIA}" | |
| fi | |
| # Display the generated ticket | |
| echo "═══════════════════════════════════════════════════════════════" | |
| echo "Generated Ticket Preview" | |
| echo "═══════════════════════════════════════════════════════════════" | |
| echo "Type: ${TYPE}" | |
| echo "Title: ${TITLE}" | |
| echo "Priority: ${PRIORITY}" | |
| echo "Change Category: ${CHANGE_TYPE}" | |
| echo "Story Points: ${STORY_POINTS}" | |
| echo "Labels: ${LABELS:-None}" | |
| echo "" | |
| echo "Description:" | |
| echo "───────────────────────────────────────────────────────────────" | |
| echo "$GENERATED_DESCRIPTION" | |
| echo "═══════════════════════════════════════════════════════════════" | |
| echo "" | |
| # Confirm and create the ticket | |
| if gum confirm "Do you want to create this ticket?"; then | |
| # Prepare labels with change type | |
| if [ -z "$LABELS" ]; then | |
| FINAL_LABELS="$CHANGE_TYPE" | |
| else | |
| FINAL_LABELS="$LABELS,$CHANGE_TYPE" | |
| fi | |
| jira issue create \ | |
| -t "$TYPE" \ | |
| -s "$TITLE" \ | |
| -y "$PRIORITY" \ | |
| -b "$GENERATED_DESCRIPTION" \ | |
| -l "$FINAL_LABELS" \ | |
| --custom story-points="$STORY_POINTS" \ | |
| -a "$(jira me)" \ | |
| --no-input | |
| if [ $? -eq 0 ]; then | |
| echo "✓ Ticket created successfully!" | |
| else | |
| echo "✗ Error: Failed to create the ticket." | |
| exit 1 | |
| fi | |
| else | |
| echo "Ticket creation cancelled." | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| WORKLOG_DIR="$HOME/Desktop/worklog" | |
| mkdir -p "$WORKLOG_DIR" | |
| FILE="$WORKLOG_DIR/$(date +%F).md" | |
| touch "$FILE" | |
| # Fetch issues first and store in temp file | |
| ISSUES_FILE=$(mktemp) | |
| jira issue list \ | |
| --jql 'assignee = currentUser() AND status CHANGED AFTER -1d AND status IN ("In Progress", "In Review", "Done")' \ | |
| --columns 'key,summary' \ | |
| --plain > "$ISSUES_FILE" | |
| if [ ! -s "$ISSUES_FILE" ]; then | |
| echo "No Jira work items discovered" | |
| rm -f "$ISSUES_FILE" | |
| exit 1 | |
| fi | |
| PRs=$(gh search prs --author=@me --merged --merged-at=$(date "+%Y-%m-%d") --json title --jq '.[].title') | |
| # Ensure ## Pull Requests section exists | |
| if [[ -n "$PRs" ]] && ! grep -q '^## Merged Pull Requests' "$FILE"; then | |
| echo -e "\n## Merged Pull Requests\n" >> "$FILE" | |
| echo "$PRs" >> "$FILE" | |
| fi | |
| # Ensure ## Tickets section exists | |
| if ! grep -q '^## Tickets' "$FILE"; then | |
| echo -e "\n## Tickets\n\n" >> "$FILE" | |
| fi | |
| # Use awk to insert the issues under ## Tickets | |
| TMPFILE=$(mktemp) | |
| awk -v issf="$ISSUES_FILE" ' | |
| BEGIN { | |
| inserted = 0 | |
| while ((getline line < issf) > 0) { | |
| issues[++n] = line | |
| } | |
| close(issf) | |
| } | |
| { | |
| if (!inserted && /^## Tickets/) { | |
| for (i = 1; i <= n; i++) print issues[i] | |
| print "" | |
| inserted = 1 | |
| } | |
| } | |
| ' "$FILE" > "$TMPFILE" | |
| mv "$TMPFILE" "$FILE" | |
| rm -f "$ISSUES_FILE" | |
| echo "Today's work items have been added to your worklog" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # A utility for getting up and running with a clean Library cache, updating brew packages, and pruning Docker resources | |
| # Check dependencies | |
| for cmd in gum brew docker; do | |
| if ! command -v "$cmd" &>/dev/null; then | |
| echo "$(tput setaf 1)Error: $cmd is not installed$(tput sgr0)" >&2 | |
| exit 1 | |
| fi | |
| done | |
| # Clean Library Caches | |
| gum spin --spinner dot --title "Cleaning Library Caches..." -- rm -rf ~/Library/Caches/*/ | |
| # Update Homebrew (separate commands for proper error handling) | |
| gum spin --spinner dot --title "Updating Homebrew..." -- brew update | |
| gum spin --spinner dot --title "Upgrading Homebrew Packages..." -- brew upgrade | |
| gum spin --spinner dot --title "Cleaning Homebrew Cache..." -- brew cleanup --prune=all | |
| # Prune Docker (only if daemon is running) | |
| if docker info &>/dev/null; then | |
| gum spin --spinner dot --title "Pruning Docker Resources..." -- docker system prune --all --force | |
| else | |
| echo "$(tput setaf 3)Skipping Docker prune (daemon not running)$(tput sgr0)" | |
| fi | |
| echo "$(tput setaf 2)Done!$(tput sgr0)" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment