A collection of interactive Bash utilities and custom Git subcommands designed to supercharge your Git workflow.
These utilities rely on the following CLI dependencies:
- Git
- Bash (>= 4.0): Required for features like the
mapfile(orreadarray) command. Note that the default pre-installed Bash on macOS is version 3.2.x, which is too old and does not supportmapfile. - gum (for interactive selection prompts)
- tmux & Python 3 (required for
agy-usageheadless terminal screen capture and parsing)
To install these dependencies (on macOS via Homebrew):
# Install modern Bash (which includes mapfile support)
brew install bash
# Install gum, tmux, and python3
brew install gum tmux python3This package provides interactive commands for Git workflow automation:
Stage changes for a file, commit them as a fixup! commit against a target commit, and automatically execute an interactive rebase with autosquash and autostash.
-
Options:
git fixup [NUMBER]: Search the lastNUMBERcommits from the entire history (by default, shows the last 10 commits related to the selected files).-h, --help: Show help message.
-
How it works:
- Checks if any staged files exist in the repository. If staged files are found, they are automatically selected. Otherwise, prompts you to interactively choose from modified/untracked files.
- Displays a list of commits to choose as the target.
- By default, shows the last 10 commits related to the selected files.
- If a positional
NUMBERargument (e.g.15) is provided, shows the lastNUMBERcommits from the entire history.
- Stages the selected file(s) (if unstaged) and commits them with
fixup! <target commit subject>. - Backs up the pre-rewrite state to a temporary backup branch
fixup-backup/...to keep your history safe. - Rebases and autosquashes automatically using
git rebase -i --autosquash --autostashwithout opening your editor. - Prompts you to delete the temporary backup branch.
-
Examples:
# Fix up staged files (or interactively choose modified files if none staged) git fixup # Search from the last 15 commits in the entire history git fixup 15
Interactively pull files out of a selected commit in your history, rewriting the commit history to exclude them and returning the pulled files to your working tree as modifications.
-
Options:
git out [COMMIT]orgit out [NUMBER]: Specify the target commit directly via positional argument (e.g.,HEAD~1,~1,feat/abc,a1b2c3d) or specify an interactive limit (e.g.,5,20). If omitted, defaults to interactively selecting from the last 50 commits.-h, --help: Show help message.-a, --all, --acc, --accumulation: Find all files changed from the selected commit up toHEAD(accumulate changes across subsequent commits).
-
How it works:
- Identifies files changed in the selected commit (or up to
HEADif-ais used). - Displays an interactive list allowing you to select (or multi-select) files using
gum. - Automatically performs an interactive rebase to check out the parent state of the target commit for those selected files (effectively removing them from the commit).
- Resolves conflicts cleanly, deletes files if they didn't exist in the parent commit, and handles empty commits gracefully.
- Restores the selected files to your working tree as staged modifications.
- Identifies files changed in the selected commit (or up to
-
Examples:
# Interactively select a commit from the last 50 commits (Default) git out # Interactively select a commit from the last 5 commits git out 5 # Pull files out of the commit HEAD~1 using shorthand ~1 git out ~1 # Pull files out of commit HEAD~2 git out HEAD~2 # Pull files out of commit at branch feat/abc git out feat/abc # Pull files out of commit hash a1b2c3d git out a1b2c3d # Pull files out of ~1 and all subsequent commits up to HEAD git out ~1 -a
Interactively select one or multiple commits from history, preview their accumulated file changes, and move them to be placed directly after a chosen target commit using automated rebase.
-
Options:
-
git move [NUMBER]: Specify the number of recent commits to display in the interactive menu (default: 50). -
-h, --help: Show help message.
-
-
How it works:
- Checks for staged, unstaged, or untracked changes, creates a working tree integrity snapshot, and stashes uncommitted work to keep the repository clean during rebase.
- Displays an interactive menu using
gumallowing you to multi-select$n$ commits to move. - Displays a summary of total accumulated file changes across only the selected commits.
- Prompts you to pick a single target commit (from the recent commits minus the selected ones) to insert the moved commits after.
- Executes
git rebase -iautomatically to reorder the commits in history.- If conflicts occur, aborts the rebase immediately and restores your initial working tree and file states cleanly.
- Performs an integrity check on final file states against the pre-rebase snapshot, automatically rolling back and notifying you if any deviation is detected.
-
Examples:
# Interactively select commit(s) from the last 50 commits to move (Default) git move # Interactively select commit(s) from the last 15 commits to move git move 15
Interactively generate and initialize .gitattributes and .gitignore files for your project by fetching official templates from GitHub repositories.
-
Options:
-h, --help: Show help message.
-
How it works:
- Checks if
.gitattributesexists in the current project repository and prompts for confirmation to overwrite if present. - Fetches the complete list of
.gitattributestemplates from gitattributes/gitattributes. - Prompts you to search and select one or multiple languages/environments using
gum. - Downloads and appends the selected templates with clear block headers (
#! ----- <Language> ----- !#) and GitHub source URLs, ending with a professional Custom section. - Repeats the same interactive generation flow for
.gitignoretemplates from github/gitignore.
- Checks if
-
Examples:
# Interactively initialize .gitattributes and .gitignore for your repository git init-config # Display help message git init-config --help
An interactive, responsive Terminal UI (TUI) dashboard for visualizing AI CLI usage and quota metrics in real-time. Currently, this command only supports the Google Antigravity CLI (agy).
-
Options:
- (None at the moment, just run
ai-usage)
- (None at the moment, just run
-
How it works:
- Headless Terminal Emulation: Spawns a background
tmuxsession to run theagyCLI invisibly. - Automated Data Extraction: Continuously monitors the startup screen to parse your account profile and automatically triggers the initial
/usagecommand. - 2-Stage Prompt & Response Lifecycle Tracking:
- Trigger 1 (Prompt Sent): Monitors
~/.gemini/antigravity-cli/history.jsonlfor new token-consuming AI prompts (filtering byconversationIdand ignoring non-token slash commands like/usageor/model) to fetch initial quota metrics when a prompt starts. - Trigger 2 (Response Completed / Timeout): Dynamically tracks
~/.gemini/antigravity-cli/brain/<conversationId>/.system_generated/logs/transcript.jsonluntil the LLM finishes generating (source: MODEL,type: PLANNER_RESPONSE,status: DONE) or hits a 120-second sliding inactivity timeout (reset on any new log activity). Triggers a second/usagequery to capture exact final token consumption.
- Trigger 1 (Prompt Sent): Monitors
- Dynamic Local Time Delta Calculations: Recalculates elapsed time, remaining quota countdowns, and pacing differentials (
% token usedvs% time passed) locally every second using high-precision local clock deltas, providing a smooth real-time TUI update. - Instant Non-Blocking Controls (0ms delay): Uses OS I/O multiplexing (
select.select) to instantly handle user input.- Use
[tab]to switch between Model Groups (e.g.,GEMINI MODELSvsCLAUDE AND GPT MODELS). - Use
[f]to toggle the visibility of the Five-Hour Limit metrics. - Use
[r]or[enter]to trigger a live manual background refresh instantly. - Use
[esc]to cleanly exit the session.
- Use
- Headless Terminal Emulation: Spawns a background
-
Examples:
# Launch the interactive AI Usage dashboard ai-usage -
Example Output:
Antigravity Usage CLI Antigravity CLI 1.1.8 email@gmail.com (Google AI Pro) GEMINI MODELS (13.33%) | CLAUDE AND GPT MODELS (100.00%) Models within this group: Gemini Flash, Gemini Pro Weekly Limit [ββββββββββββββββββββββββββββββββββββββββββββββββββ] 13.80% 14% remaining Β· Refreshes in 57m Weekly Remaining [ββββββββββββββββββββββββββββββββββββββββββββββββββ] 87.50% Passed: 167h (6d 23h) Β· Remaining: 0h 43m You are using tokens 12.90% slower than time elapsed (keep going!) ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ [tab] Switch Group Β· [f] Toggle 5-Hour Limit [r] or [enter] Refresh Β· [esc] Exit
(Note: This is the legacy one-shot print command. It is currently in maintain-only mode and may be removed in the future. Please use ai-usage instead for the full interactive experience.)
An automated script for Google Antigravity CLI (agy) usage metrics, leveraging headless PTY screen capture to parse TUI output with 0 LLM token cost and 0 API risk.
-
Options:
--mock: Run in mock mode with sample data to test visual rendering without invokingtmuxoragy.
-
How it works:
- Headless Terminal Emulation: Spawns a background
tmuxPTY session (agy_usage_<PID>) at a fixed resolution (120x40) running theagyCLI. - Automated Handshake & Query: Continuously polls the terminal buffer via
tmux capture-pane, auto-confirms prompt trust dialogues, and sends the/usageTUI command once the CLI is ready. - Regex Metric Parsing: Captures pane output upon detecting
/usageresponse, extracts remaining Gemini quota percentage and refresh duration, and terminates thetmuxsession cleanly. - Quota Pacing & Time Analysis: Calculates elapsed time vs. consumed quota across the 7-day (168-hour) cycle to determine your consumption pace differential (
% token usedvs% time passed). - Rich Terminal Visuals: Prints ANSI progress bars, status spinners, remaining time metrics, and dynamic color-coded pace warnings before exiting.
- Headless Terminal Emulation: Spawns a background
-
Examples:
# Query real-time agy quota usage and pace once and exit agy-usage # Run in mock mode to preview UI formatting agy-usage --mock
-
Example Output:
[1/4] β Starting headless tmux session... [2/4] β Launching agy CLI and waiting for sign-in... [3/4] β Querying usage via /usage command... [4/4] β Capturing screen and parsing quota metrics... Weekly Limit [ββββββββββββββββββββββββββββββββββββββββββββββββββ] 62.82% Weekly Remaining [ββββββββββββββββββββββββββββββββββββββββββββββββββ] 66.22% Passed: 56h (2d 8h) Β· Remaining: 111h (4d 15h) You are using tokens 3.40% faster than time elapsed (be careful, might run out!)
Clone the repository to your local machine:
git clone https://github.com/culur/bash.git
cd bashMake sure the scripts have executable permissions. Run this command inside the cloned repository root:
chmod +x bin/git-fixup bin/git-out bin/git-move bin/git-init-config bin/agy-usageChoose one of the following options to make the commands available in your environment:
Since the scripts inside the bin/ directory are prefixed with git- (git-fixup, git-out, and git-move), adding the bin/ directory directly to your shell's PATH allows Git to automatically discover them as subcommands.
Add this line to your shell configuration file (e.g., ~/.zshrc or ~/.bash_profile), replacing /path/to/cloned/bash with the actual absolute path to the directory where you cloned the repository:
export PATH="/path/to/cloned/bash/bin:$PATH"(Tip: Or dynamically if you are in the project folder: export PATH="$(pwd)/bin:$PATH")
Then reload your configuration:
source ~/.zshrcIf you prefer not to modify your shell's PATH variable, you can define Git aliases pointing directly to the scripts. Make sure to replace /path/to/cloned/bash with the actual absolute path to the directory where you cloned the repository.
git config --global alias.fixup "!/path/to/cloned/bash/bin/git-fixup"
git config --global alias.out "!/path/to/cloned/bash/bin/git-out"
git config --global alias.move "!/path/to/cloned/bash/bin/git-move"
git config --global alias.init-config "!/path/to/cloned/bash/bin/git-init-config"git config alias.fixup "!/path/to/cloned/bash/bin/git-fixup"
git config alias.out "!/path/to/cloned/bash/bin/git-out"
git config alias.move "!/path/to/cloned/bash/bin/git-move"
git config alias.init-config "!/path/to/cloned/bash/bin/git-init-config"(Note: The ! prefix at the start of the alias command is required. It tells Git to run the script in an external shell using its absolute path.)
This project is licensed under the MIT License.