work

module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2026 License: MIT

README

work

A CLI tool that organizes repositories by organization and name in ~/code/{domain}/{org}/{repo}. Jump to code faster; spend less time wondering where you cloned that thing three months ago.

No database, no daemon, no cloud sync that stops working when your wifi hiccups.

Should You Use This?

Good fit:

  • You work across multiple GitHub orgs and/or a GitHub Enterprise instance
  • You've typed find ~ -name '.git' -type d more than once this month
  • You want cd but for repos, with fuzzy matching and the memory of a goldfish (frecency)
  • You're comfortable with CLI tools and don't need a GUI to feel safe

Not a good fit:

  • You have one repo. Congratulations on your focus
  • You already have a system that works (don't fix what isn't broken, I'm not your mom)
  • You want something battle-tested by thousands of users (this is a hobby project, there are dozens of us)

Prerequisites

  • Go 1.26+ (build from source)
  • GitHub CLI (gh) (authentication -- implementing OAuth device flow just to avoid typing gh auth login seemed like the wrong kind of yak shaving)
  • Git (presumably you have this if you're here)

Install

From GitHub Releases

Download the binary for your platform from the releases page:

Platform Binary
macOS (Apple Silicon) work-darwin-arm64
macOS (Intel) work-darwin-amd64
Linux (x86_64) work-linux-amd64
Linux (ARM) work-linux-arm64
# Example: macOS Apple Silicon
curl -Lo work https://github.com/anoldguy/work/releases/latest/download/work-darwin-arm64
chmod +x work
sudo mv work /usr/local/bin/work
Via go install

Requires Go 1.26+:

go install github.com/anoldguy/work/cmd/work@latest
From Source
git clone https://github.com/anoldguy/work.git
cd work
make build
# binary lands at bin/work
Shell Integration

Without shell integration, work cd just prints a path and stares at you. You'd have to manually cd to it, which defeats approximately 90% of the purpose. Add to your shell config:

# bash (~/.bashrc)
eval "$(work activate bash)"

# zsh (~/.zshrc)
eval "$(work activate zsh)"

# fish (~/.config/fish/config.fish)
work activate fish | source

Restart your shell or source the file. Run type work to verify; it should show a function, not just a path.

Tab Completion
work completions bash --install
work completions zsh --install
work completions fish --install

Tab completion turns work cd my<TAB> into something useful. Without it you're just typing full repo names like an animal.

Quick Start

Three steps: authenticate, enable shell integration, navigate to repositories. That's it.

# First-time setup -- walks you through config and auth
work setup

# Jump to a repo (fuzzy match, auto-clones if needed)
work cd myrepo

# Open a repo in your editor
work edit myrepo

# Open a repo on GitHub in the browser
work browse myrepo

Repository lists are cached locally and refresh automatically when stale. Hitting the GitHub API on every typo would be excessive, and typos happen more than anyone wants to admit. You never need to think about the cache -- it updates itself in the background the first time a command notices it's stale. If you're impatient, work update forces a refresh, but you probably won't need it.

Search & Frecency

Search ranks repositories by match quality and usage patterns. The repo you fat-finger every morning beats the exact match you haven't touched since Q2. This is called frecency scoring (frequency + recency) and it works better than pretending all matches are equally important.

Every time you interact with a repo (cd, browse, clone, edit, on, open, pull), it records the access. Recent activity counts more than old activity: last week gets full weight, last month gets half, last quarter gets 20%, and anything older than 90 days barely registers. The repo you mistype as widgts constantly still beats widgets-archive which you spelled perfectly but cloned once in 2023.

All matching is case-insensitive. Type FOO or foo or FoO; same result. Life's too short for shift keys.

For more specificity, qualify with org (acme/foo) or full slug (github.com/acme/foo). Each slash narrows the search. Multiple matches show an interactive picker unless you're in a script, where ambiguity errors instead of picking randomly and hoping.

Commands

Command What it does
work cd <query> Fuzzy-match a repo and cd into it (clones first if needed)
work on <query> Same as cd but opens a new terminal tab, for the tab hoarders
work edit <query> Open a repo in $EDITOR (respects $WORK_EDITOR if you're picky)
work open <query> Open a repo directory in your file manager (for the GUI-curious)
work browse <query> Open a repo's GitHub page in the browser
work clone <query> Clone a repo into the local hierarchy
work list List all cached repos (supports --filter)
work pull <query> Fetch + fast-forward a single repo
work sync Fetch + fast-forward every cloned repo. Go get coffee
work update Manually refresh the repo cache (usually unnecessary)
work config Show current configuration
work config --edit Open config in $EDITOR
work config default Set the default domain
work favorite Pick favorite orgs (only cache repos from orgs you care about)
work setup Interactive first-time setup
work auth login Authenticate with gh
work auth status Check auth status for all domains
work completions Generate shell completions
work activate <shell> Output the shell integration script

Configuration

Configuration is optional. Defaults work for most people: ~/code for repositories, ~/.local/state/work for cache. XDG conventions are followed; somebody should.

Config lives at ~/.config/work/config.toml. The tool creates it on first run if needed. Edit it by hand if you prefer; it's just TOML.

work_dir = "~/code"
cache_path = "~/.local/state/work"

[filters]
exclude_orgs = ["that-org-from-2019-you-forgot-to-leave"]
include_orgs = ["my-team"]

[domains."github.com"]
is_default = true
favorite_orgs = ["my-team", "my-company"]

[domains."github.enterprise.com"]
favorite_orgs = ["team-a", "team-b"]

Default Domains

One domain can be marked as default to shorten filesystem paths. The default domain's repositories live at ~/code/org/repo. Other domains keep the full path: ~/code/domain/org/repo.

The first domain you configure gets marked as default automatically. Change the default anytime:

work config default                   # Interactive picker
work config default github.com        # Set specific domain

Changing the default doesn't move existing repositories. You'll need to re-clone or manually relocate them to match the new paths.

Favorite Organizations

Cache updates sync all organizations you belong to. If you just got added to 47 orgs at your new enterprise job and only care about 3 of them, this gets tedious.

Configure favorite organizations to sync only those:

work favorite                        # Interactive picker for default domain
work favorite github.enterprise.com  # Pick favorites for specific domain

Once configured, only favorite orgs (plus personal repositories) get synced. Use work update --all to sync everything, ignoring favorites. Clear favorites by deselecting everything in the picker; you're back to syncing all organizations.

Authentication

The tool uses GitHub CLI. No tokens are stored directly. GitHub CLI already solved this problem; reimplementing it felt like trust issues with extra steps.

# Standard GitHub
gh auth login

# GitHub Enterprise
gh auth login --host github.enterprise.com

Run gh auth login once; everything else works. Check work auth status if things seem broken.

How It Works

work maintains a local JSON cache of repo metadata fetched from the GitHub API via gh. When you run work cd foo, it:

  1. Fuzzy-matches "foo" against all cached repos
  2. Ranks results by frecency (repos you use often float to the top)
  3. If there's one clear winner, cds you there
  4. If it's ambiguous and you're in an interactive terminal, shows a picker
  5. If the repo isn't cloned locally, clones it first

The cache auto-updates when stale (older than 24 hours). This happens transparently during normal use -- you don't need to manually refresh anything. The tool just quietly fetches new data in the background while a spinner pretends to keep you company.

The local directory structure mirrors GitHub's hierarchy:

~/code/
  acme/              # default domain omits the prefix
    api/
    web/
  github.enterprise.com/
    corp-team/
      internal-tool/

Troubleshooting

"No matching repository found" Stale cache. Run work update to force a refresh. This happens when you join new organizations or when your coworker creates another microservice at 4pm on Friday.

Shell integration not working The activation line didn't load. Run type work to verify; it should show a function, not a path. Check your shell config file has the activation line. Source it. Yes, I forget this step too.

Authentication failures Check work auth status first. Usually the fix is gh auth login. Sometimes it's realizing you're on the VPN but pointing at the wrong GitHub instance.

Cloning fails This tool shells out to git clone. If git can't clone it manually, neither can the tool. Your SSH keys, HTTPS credentials, or repository access might be the problem.

License

MIT

Directories

Path Synopsis
cmd
work command
internal
cmd
Package cmd implements all CLI commands for the work tool.
Package cmd implements all CLI commands for the work tool.
git
ui
Package ui provides terminal UI components for the work CLI.
Package ui provides terminal UI components for the work CLI.
Package shell provides embedded shell integration scripts.
Package shell provides embedded shell integration scripts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL