Skip to content
Go back

Open your Github Repos blazing fast!!!

Published:  at  05:30 PM

Opening GitHub repos often means browser hassle. While gh is great, finding and opening still takes steps.

Imagine fuzzy-finding and instantly opening any GitHub repo from your terminal. This Bun script does just that, using gh, fzf, and Bun’s speed.

Let’s see how it works and how to set it up.

Table of contents

Open Table of contents

Prerequisites

Before we start, make sure you have the following tools installed:

  1. Bun: A fast JavaScript runtime. Installation instructions are on the official Bun website.
  2. GitHub CLI (gh): GitHub’s official command-line interface. Follow the installation guide. Make sure you’ve authenticated with gh auth login.
  3. fzf: A general-purpose command-line fuzzy finder. Check the fzf repository for installation steps (available via most package managers like Homebrew, apt, etc.).

1. Building the CLI

First, we need two key pieces: Bun’s built-in shell functionality ($) for running commands, and Node.js’s parseArgs utility for handling command-line options and arguments.

Secondly, we need to parse the command-line options and arguments, and then use them to construct a command to run.

const { values, positionals } = parseArgs({
args: Bun.argv, // Feed arguments passed to the bun script
options: {
// Define the --user or -u option
user: {
short: "u", // Alias -u
type: "string", // Expects a value (the username)
},
// Define the --help or -h option
help: {
short: "h", // Alias -h
type: "boolean", // It's a flag, either present (true) or not (false)
},
},
strict: true, // Disallow any options not defined above
allowPositionals: true, // Allow arguments without a preceding flag (our query)
});

Adding the help by identifying the --help or -h option.

if (values.help) {
console.log(`Usage: repos [user] [query]`);
console.log(`Parameters:
query Search query [optional]`);
console.log(`Options:
-u, --user GitHub username [optional]
-h, --help Show this help message`);
process.exit(0);
}

2. The Implementation

The basic logic is simple we can use gh repo list to list all the repos of a user and then use fzf to select the one we want to open. The output of this selection is then passed to gh repo view to open the repo in the browser.

// --- Extracting User and Query ---
const user = values.user ?? "";
const query = positionals[2] ?? "";
// --- Configuring fzf ---
const FZF_ARGS = ["--ansi", '--pointer "⏵"', '--prompt "❯ "'];
// --- Building the Core Command ---
let command = `gh repo list ${user} -L 100 | fzf ${FZF_ARGS.join(" ")}`;
// --- Adding Optional fzf Query ---
if (query) {
command += ` --query ${query}`;
}
// --- Executing the Command and Selecting the Repo ---
const repo = await $`${{ raw: command }}`
.text()
.then((text) => text?.split("\t")[0]);
// --- Handling No Selection ---
if (!repo) {
console.warn("No repo selected.");
process.exit(1);
}
// --- Opening the Repository ---
await $`gh repo view --web ${repo}`.quiet().nothrow();
console.log(`Opening ${repo}...`);

3. Linking the Script

You can run the script using the following command:

bun run repos.ts --user tanishqmanuja

But for convenience, you can also link it so that you can run it directly from your terminal. To do this, you need to setup a project using bun.

mkdir repos
cd repos
bun init -y

Copy the contents of the repos.ts file into the index.ts file and save it. Then add bin property to package.json

package.json
{
"name": "@cli/repos",
"module": "index.ts",
"type": "module",
"bin": {
"repos": "index.ts"
},
"devDependencies": {
"@types/bun": "^1.2.10"
},
"peerDependencies": {
"typescript": "^5.8.3"
}
}

Then finally, link the script using the following command:

bun link

4. Using the Script

Terminal window
repos # Fuzzy find your repos
repos my-project # Start fzf with "my-project"
repos -u octocat # Find repos for 'octocat'
repos -h # Show help

Final Code

repos.ts
import { parseArgs } from "node:util";
import { $ } from "bun";
const { values, positionals } = parseArgs({
args: Bun.argv,
options: {
user: {
short: "u",
type: "string",
},
help: {
short: "h",
type: "boolean",
},
},
strict: true,
allowPositionals: true,
});
if (values.help) {
console.log(`Usage: repos [user] [query]`);
console.log(`Parameters:
query Search query [optional]`);
console.log(`Options:
-u, --user GitHub username [optional]
-h, --help Show this help`);
process.exit(0);
}
const user = values.user ?? "";
const query = positionals[2] ?? "";
const FZF_ARGS = ["--ansi", '--pointer "⏵"', '--prompt "❯ "'];
let command = `gh repo list ${user} -L 100 | fzf ${FZF_ARGS.join(" ")}`;
if (query) {
command += ` --query ${query}`;
}
const repo = await $`${{ raw: command }}`
.text()
.then((text) => text?.split("\t")[0]);
if (!repo) {
console.warn("No repo selected");
process.exit(1);
}
await $`gh repo view --web ${repo}`.quiet().nothrow();


Next Post
Getting Started with Drizzle ORM, MySQL & Typescript