URL: https://github.com/peterbe/gg2/pull/30

Remember my blog post about gg2? It's a CLI tool, written in TypeScript, compiled with Bun, called gg. You use it to help with various git tasks such as creating a new branch. For example gg start will prompt you for a nice title, and create a branch with appropriate name, and remember that title you entered as the default git commit message later.

Anyway, now you can just type gg s[TAB] and it will finish typing gg start for you. It works for flags too. For example, gg pr -[TAB] will suggest gg pr --watch. And simplest of all, gg [TAB] will list all possible commands.

Installation

To install it you need to put this at the bottom of your ~/.bashrc or ~/.zshrc file:


source <(gg shell-completion)

That command gg shell-completion spits out a block of Bash code. You can see the code by typing gg shell-completion or view the source here.

That bash script effectively calls gg shell-completion --list "$arguments-here" which means that when gg changes (for example, a new sub-command is added), you won't need to re-install the Bash/Zsh hook because it refers back to the executable gg to get the completion options.

What was tricky

The TypeScript code for this project compiles the .ts files down to a single executable binary. But making it read the ./src/completion.sh file from disk was hard. You can't rely on Bun.file(path.join(import.meta.here, './scr/completion.sh')) because that won't work after compilation.

The solution, after some sleuthing was to import it with type text.


// @ts-ignore
import code from "./completion.sh" with { type: "text" }

The ts-ignore is because my tsc seems to think it won't work because the file is not .ts.

The code that powers gg shell-completion (which you pipe to source) looks like this:


// @ts-ignore - a trick to make a non TS file part of memory and build
import code from "./completion.sh" with { type: "text" }

export async function shellCompletion() {
  console.log(code)
}

Comments

Peter Bengtsson

I (almost) forgot! The credit for this Shell hook idea came from this blog post: https://mill-build.org/blog/14-bash-zsh-completion.html

Your email will never ever be published.

Previous:
Combining Django signals with in-memory LRU cache August 9, 2025 Python, Django
Next:
Always run biome migrate after upgrading biome August 16, 2025 Node, JavaScript, Bun
Related by category:
Video to Screenshots app June 21, 2025 Bun, JavaScript
Parse a CSV file with Bun September 13, 2023 Bun
How I end-to-end test my Bun CLI app September 18, 2025 Bun
Switching from Next.js to Vite + wouter July 28, 2023 JavaScript
Related by keyword:
Find the source of an alias in bash September 29, 2025 Linux, Bash, macOS
set -ex - The most useful bash trick of the year August 31, 2014 Linux
<datalist> looks great on mobile devices August 28, 2020 Mobile, Web development
How to throttle AND debounce an autocomplete input in React March 1, 2018 Web development, React, JavaScript