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:
Bun vs. Go for a basic web server benchmark October 24, 2025 Bun
Hosting your static web site with Firebase Hosting November 3, 2025 Bun
Benchmarking oxlint vs biome December 12, 2025 Bun
Testing out vite 8 on SPA: Vite 8 is 5x faster December 6, 2025 Bun
Related by keyword:
Autocomplete using PostgreSQL instead of Elasticsearch December 18, 2025 Python, PostgreSQL, Elasticsearch
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