I’ve come across multiple neat tools. Given all of my configs are literate programming configs, this sets up those scripts. Otherwise, I’d either not have those tools, or I’d have two processes for getting my dotfiles setup.

snapshot (~/bin/snapshot)#

A simple screenshot tool. Uses screencapture on macOS or imagemagick’s import on Linux.

#!/bin/bash
name=$1
if [[ "$name" != *"png"* ]]; then
    name="$name.png"
fi

if command -v screencapture &>/dev/null; then
    screencapture -i ~/Desktop/$name
else
    import ~/Desktop/$name
fi

Copy-pasta $ (~/bin/$)#

Allow copying things from the internet which have a preceding $.

#!/usr/bin/env bash
exec "$@"

timestamp conversion (~/bin/epoch)#

I need to convert epochs all the time from log diving. Thanks to Aaron Flatten for the script.

#!/bin/bash
# > epoch # Return the current timestamp
# > epoch <number> # Convert the numeric unix timestamp to a readable date string
# > epoch <str> # Converts the readable date string to a timestamp

if [ $# -eq 0 ]; then
  date +%s
elif [[ $1 == *[-T:Z]* ]]; then
  python3 -c "from datetime import datetime; import sys; print(int(datetime.fromisoformat(sys.argv[1].replace('Z','+00:00')).timestamp()))" "$1"
else
  VAL=$1
  if [[ $1 -gt 1000000000000 ]]; then
    VAL=$(( $1 / 1000 ))
  fi
  # macOS date -r, falling back to GNU date -d
  date -r "$VAL" 2>/dev/null || date -d "UTC 1970-01-01 $VAL secs" 2>/dev/null
fi

git-churn (~/bin/git-churn)#

When doing some code analysis suggested by the talk Sandi Metz gave at DeconstructConf 2018, I needed to figure out how to calculate the churn of a particular file. This script helps in that regard.

#!/bin/bash
# Written by Corey Haines
# Scriptified by Gary Bernhardt
#
# Put this anywhere on your $PATH (~/bin is recommended). Then git will see it
# and you'll be able to do `git churn`.
#
# Show churn for whole repo:
#   $ git churn
#
# Show churn for specific directories:
#   $ git churn app lib
#
# Show churn for a time range:
#   $ git churn --since='1 month ago'
#
# (These are all standard arguments to `git log`.)

set -e
git log --all -M -C --name-only --format='format:' "$@" | sort | grep -v '^$' | uniq -c | sort -n | awk 'BEGIN {print "count\tfile"} {print $1 "\t" $2}'

git worktrees (~/bin/gwt)#

gwt keeps throwaway and parallel branches out of the source checkout by placing them under ~/worktrees/<repo>/<branch-slug>. The script does the git worktree creation; the shell function in the zsh config handles changing into the new directory because an executable cannot change its parent shell.

#!/usr/bin/env bash
set -euo pipefail

usage() {
    cat <<'USAGE'
Usage:
  gwt new [--branch BRANCH] [--from REF] NAME
  gwt list
  gwt remove PATH
  gwt prune

Create and manage git worktrees rooted at ${GWT_HOME:-~/worktrees}.

Examples:
  gwt new "dry run pr"
  gwt new --branch tep-1234-dry-run-pr "dry run pr"
  gwt new --from main "spike parser"
USAGE
}

die() {
    printf 'gwt: %s\n' "$*" >&2
    exit 1
}

slugify() {
    local input="$*"
    local slug

    slug=$(
        printf '%s' "$input" |
            tr '[:upper:]' '[:lower:]' |
            sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-+/-/g'
    )

    [[ -n "$slug" ]] || die "name must contain at least one letter or number"
    printf '%s\n' "$slug"
}

repo_name_for() {
    local root="$1"
    local primary

    primary=$(
        git -C "$root" worktree list --porcelain |
            awk 'NR == 1 && $1 == "worktree" { sub(/^worktree /, ""); print; exit }'
    )

    basename "${primary:-$root}"
}

new_worktree() {
    local branch=""
    local start_point="HEAD"

    while [[ $# -gt 0 ]]; do
        case "$1" in
            -b | --branch)
                [[ $# -ge 2 ]] || die "$1 requires a branch name"
                branch="$2"
                shift 2
                ;;
            --from)
                [[ $# -ge 2 ]] || die "$1 requires a ref"
                start_point="$2"
                shift 2
                ;;
            -h | --help)
                usage
                exit 0
                ;;
            --)
                shift
                break
                ;;
            -*)
                die "unknown option for new: $1"
                ;;
            *)
                break
                ;;
        esac
    done

    [[ $# -gt 0 ]] || die "new requires a worktree name"

    local name="$*"
    local slug
    local root
    local repo_name
    local target_root
    local target

    slug="$(slugify "$name")"
    branch="${branch:-$slug}"

    root="$(git rev-parse --show-toplevel 2>/dev/null)" || die "not inside a git repository"
    repo_name="$(repo_name_for "$root")"
    target_root="${GWT_HOME:-$HOME/worktrees}"
    target="$target_root/$repo_name/$slug"

    [[ ! -e "$target" ]] || die "target already exists: $target"

    if git -C "$root" show-ref --verify --quiet "refs/heads/$branch"; then
        die "branch already exists: $branch"
    fi

    mkdir -p "$(dirname "$target")"
    git -C "$root" worktree add -b "$branch" "$target" "$start_point" >&2
    printf '%s\n' "$target"
}

main() {
    local command="${1:-help}"
    [[ $# -eq 0 ]] || shift

    case "$command" in
        new)
            new_worktree "$@"
            ;;
        list | ls)
            git worktree list "$@"
            ;;
        remove | rm)
            git worktree remove "$@"
            ;;
        prune)
            git worktree prune "$@"
            ;;
        help | -h | --help)
            usage
            ;;
        *)
            git worktree "$command" "$@"
            ;;
    esac
}

main "$@"

PR review tools (~/bin/pr-comments, ~/bin/pr-state, ~/bin/pr-doctor, ~/bin/pr-babysit)#

These wrappers expose the shared pr-review-tools agent skill as normal shell commands. The implementation lives in ~/.agents/skills so Claude, Codex, and interactive shell use all share the same GitHub PR comment/check logic.

#!/usr/bin/env bash
set -euo pipefail
exec python3 "$HOME/.agents/skills/pr-review-tools/scripts/pr_tool.py" comments "$@"
#!/usr/bin/env bash
set -euo pipefail
exec python3 "$HOME/.agents/skills/pr-review-tools/scripts/pr_tool.py" state "$@"
#!/usr/bin/env bash
set -euo pipefail
exec python3 "$HOME/.agents/skills/pr-review-tools/scripts/pr_tool.py" doctor "$@"
#!/usr/bin/env bash
set -euo pipefail
exec python3 "$HOME/.agents/skills/pr-review-tools/scripts/pr_tool.py" babysit "$@"

Agent GitHub shim (~/bin/agent-shims/gh)#

Claude and Codex sessions put this directory ahead of Homebrew’s gh binary. The shim keeps regular read/investigation workflows working while stopping risky org and repo policy mutations unless an explicit Jira-ticket break-glass environment variable is present.

#!/usr/bin/env bash
set -euo pipefail

shim_path="${BASH_SOURCE[0]}"
shim_dir="$(cd "$(dirname "$shim_path")" && pwd -P)"

find_real_gh() {
    if [[ -n "${PARLOA_REAL_GH:-}" && -x "${PARLOA_REAL_GH:-}" ]]; then
        printf '%s\n' "$PARLOA_REAL_GH"
        return 0
    fi

    local candidate
    for candidate in /opt/homebrew/bin/gh /usr/local/bin/gh /usr/bin/gh; do
        if [[ -x "$candidate" && "$candidate" != "$shim_path" ]]; then
            printf '%s\n' "$candidate"
            return 0
        fi
    done

    local path_dir
    IFS=:
    for path_dir in $PATH; do
        [[ -n "$path_dir" && "$path_dir" != "$shim_dir" ]] || continue
        candidate="$path_dir/gh"
        if [[ -x "$candidate" && "$candidate" != "$shim_path" ]]; then
            printf '%s\n' "$candidate"
            return 0
        fi
    done
    unset IFS

    return 1
}

real_gh="$(find_real_gh)" || {
    printf 'agent-gh: could not find the real gh binary\n' >&2
    exit 127
}

break_glass_active() {
    [[ "${PARLOA_GH_BREAK_GLASS:-}" =~ ^TEP-[0-9]+$ ]]
}

allow_or_block() {
    local reason="$1"

    if break_glass_active; then
        printf 'agent-gh: break-glass active (%s); allowing %s\n' "$PARLOA_GH_BREAK_GLASS" "$reason" >&2
        return 0
    fi

    cat >&2 <<EOF
agent-gh: blocked $reason

This shell is using the Parloa agent gh shim. If this is intentional, rerun
with a Jira ticket in PARLOA_GH_BREAK_GLASS, for example:

  PARLOA_GH_BREAK_GLASS=TEP-3600 gh ...

Real gh binary: $real_gh
EOF
    exit 1
}

upper() {
    printf '%s' "$1" | tr '[:lower:]' '[:upper:]'
}

normalize_endpoint() {
    local endpoint="$1"

    endpoint="${endpoint#https://api.github.com}"
    endpoint="${endpoint#http://api.github.com}"
    endpoint="${endpoint#api.github.com}"
    endpoint="${endpoint%%\?*}"
    [[ "$endpoint" == /* ]] || endpoint="/$endpoint"

    printf '%s\n' "$endpoint"
}

is_mutating_method() {
    case "$(upper "$1")" in
        POST | PUT | PATCH | DELETE)
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}

is_dangerous_endpoint() {
    local endpoint
    endpoint="$(normalize_endpoint "$1")"

    case "$endpoint" in
        /orgs/parloa/actions | /orgs/parloa/actions/* | \
        /orgs/parloa/rulesets | /orgs/parloa/rulesets/* | \
        /orgs/parloa/members | /orgs/parloa/members/* | \
        /orgs/parloa/teams | /orgs/parloa/teams/* | \
        /orgs/parloa/hooks | /orgs/parloa/hooks/* | \
        /orgs/parloa/actions/secrets | /orgs/parloa/actions/secrets/* | \
        /orgs/parloa/actions/runner-groups | /orgs/parloa/actions/runner-groups/* | \
        /orgs/parloa/codespaces/secrets | /orgs/parloa/codespaces/secrets/* | \
        /orgs/parloa/dependabot/secrets | /orgs/parloa/dependabot/secrets/* | \
        /orgs/parloa/security-managers | /orgs/parloa/security-managers/* | \
        /enterprises/*/actions | /enterprises/*/actions/* | \
        /enterprises/*/rulesets | /enterprises/*/rulesets/* | \
        /enterprises/*/members | /enterprises/*/members/* | \
        /enterprises/*/teams | /enterprises/*/teams/* | \
        /repos/parloa/*/actions/permissions | /repos/parloa/*/actions/permissions/* | \
        /repos/parloa/*/rulesets | /repos/parloa/*/rulesets/* | \
        /repos/parloa/*/branches/*/protection | /repos/parloa/*/branches/*/protection/* | \
        /repos/parloa/*/collaborators | /repos/parloa/*/collaborators/* | \
        /repos/parloa/*/teams | /repos/parloa/*/teams/* | \
        /repos/parloa/*/hooks | /repos/parloa/*/hooks/* | \
        /repos/parloa/*/actions/secrets | /repos/parloa/*/actions/secrets/*)
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}

parse_api_call() {
    local method=""
    local endpoint=""
    local fields_make_post=0
    local query_value=""
    local arg

    while [[ $# -gt 0 ]]; do
        arg="$1"
        case "$arg" in
            -X | --method)
                [[ $# -ge 2 ]] || break
                method="$2"
                shift 2
                ;;
            --method=*)
                method="${arg#--method=}"
                shift
                ;;
            -X*)
                method="${arg#-X}"
                shift
                ;;
            -f | -F | --field | --raw-field)
                fields_make_post=1
                if [[ $# -ge 2 && "$2" == query=* ]]; then
                    query_value="${2#query=}"
                fi
                if [[ $# -ge 2 ]]; then
                    shift 2
                else
                    shift
                fi
                ;;
            --field=* | --raw-field=*)
                fields_make_post=1
                if [[ "$arg" == *=query=* ]]; then
                    query_value="${arg#*=query=}"
                fi
                shift
                ;;
            --input)
                fields_make_post=1
                if [[ $# -ge 2 ]]; then
                    shift 2
                else
                    shift
                fi
                ;;
            --input=*)
                fields_make_post=1
                shift
                ;;
            -H | --header | -p | --preview | -q | --jq | --template | --hostname | --cache)
                if [[ $# -ge 2 ]]; then
                    shift 2
                else
                    shift
                fi
                ;;
            --header=* | --preview=* | --jq=* | --template=* | --hostname=* | --cache=*)
                shift
                ;;
            --paginate | --slurp | --silent | --verbose)
                shift
                ;;
            --)
                shift
                [[ $# -gt 0 && -z "$endpoint" ]] && endpoint="$1"
                break
                ;;
            -*)
                shift
                ;;
            *)
                [[ -z "$endpoint" ]] && endpoint="$arg"
                shift
                ;;
        esac
    done

    if [[ -z "$method" ]]; then
        if [[ "$fields_make_post" -eq 1 ]]; then
            method="POST"
        else
            method="GET"
        fi
    fi

    if [[ "$endpoint" == "graphql" && "$query_value" == *mutation* ]]; then
        allow_or_block "GraphQL mutation through gh api"
    fi

    if [[ -n "$endpoint" ]] && is_mutating_method "$method" && is_dangerous_endpoint "$endpoint"; then
        allow_or_block "$(upper "$method") $(normalize_endpoint "$endpoint")"
    fi
}

arg_has_org_parloa() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --org=parloa | -o=parloa)
                return 0
                ;;
            --org | -o)
                [[ "${2:-}" == "parloa" ]] && return 0
                shift 2
                ;;
            *)
                shift
                ;;
        esac
    done
    return 1
}

parse_high_level_command() {
    case "${1:-} ${2:-}" in
        "secret set" | "secret delete" | "variable set" | "variable delete")
            if arg_has_org_parloa "${@:3}"; then
                allow_or_block "gh $1 $2 --org parloa"
            fi
            ;;
        "ruleset create" | "ruleset edit" | "ruleset delete")
            allow_or_block "gh $1 $2"
            ;;
        "repo delete" | "repo archive")
            if [[ "${3:-}" == parloa/* || "${3:-}" == https://github.com/parloa/* ]]; then
                allow_or_block "gh $1 $2 ${3:-}"
            fi
            ;;
        "repo edit")
            if [[ "${3:-}" == parloa/* || "${3:-}" == https://github.com/parloa/* ]]; then
                allow_or_block "gh $1 $2 ${3:-}"
            fi
            ;;
    esac
}

doctor() {
    printf 'agent gh shim: %s\n' "$shim_path"
    printf 'real gh: %s\n' "$real_gh"
    printf 'PATH gh: %s\n' "$(command -v gh 2>/dev/null || true)"
    printf 'GH_CONFIG_DIR: %s\n' "${GH_CONFIG_DIR:-<default gh config>}"
    printf 'PARLOA_AGENT_GH_SAFE_MODE: %s\n' "${PARLOA_AGENT_GH_SAFE_MODE:-<unset>}"
    if [[ -n "${PARLOA_GH_BREAK_GLASS:-}" ]]; then
        printf 'PARLOA_GH_BREAK_GLASS: %s\n' "$PARLOA_GH_BREAK_GLASS"
    else
        printf 'PARLOA_GH_BREAK_GLASS: <inactive>\n'
    fi
    printf '\n'
    if "$real_gh" auth status --help 2>/dev/null | grep -q -- '--show-token-scopes'; then
        "$real_gh" auth status --show-token-scopes || true
    else
        printf 'Token scopes: unavailable; this gh version only exposes --show-token, which is intentionally not used here.\n\n'
        "$real_gh" auth status || true
    fi
}

case "${1:-}" in
    agent-doctor)
        shift
        doctor "$@"
        exit 0
        ;;
    api)
        parse_api_call "${@:2}"
        ;;
    *)
        parse_high_level_command "$@"
        ;;
esac

exec "$real_gh" "$@"