hop
Part of HexoKit — see all projects there.
A small Go CLI that turns one config file (hop.yaml) into a personal directory of all your git repos — navigate, clone, run commands, and batch-update them from any directory.
Install
curl -fsSL https://shll.ai/install | sh -s -- hop # install hop (+ shll) via Homebrew
shll shell-setup # wire the shell shim into your rc file
hop add -r ~/code # walk your code dir, build hop.yaml from git remotesThe first line installs hop (plus the shll meta-CLI) via Homebrew, handling tap trust automatically; the next two wire the shell shim into your rc file and build hop.yaml from your existing clones — that's the whole setup. Now open a new terminal — or exec zsh (bash: exec bash): shll shell-setup edits your rc file, so the shim (the hop function, h alias, and tab completion) only exists in shells started after it. Then confirm it all works:
hop ls # every repo from hop.yaml — the bootstrap worked
h web # substring-match and cd into a repo (any partial name) — the shim worksTo install the entire shll toolkit instead:
curl -fsSL https://shll.ai/install | shWhy hop?
- One config, every machine — hop.yaml lives at ~/.config/hop/hop.yaml and lists every repo you care about (with groups). Keep it in your dotfiles and symlink that path to it, and your repo directory follows you between laptops.
- Substring navigation — h web<TAB or hop web matches webapp and cds your shell straight there. No more cd ~/code/sahil87/webapp.
- Run anything inside a repo, from anywhere — hop dotfiles cursor . opens your dotfiles in Cursor without changing your cwd. Works for any tool, PATH binary, or shell alias: hop webapp git status, hop infra-tf terraform plan, hop loom npm test.
- Batch git ops over groups — hop --all pull pulls every cloned repo. hop work sync rebases-and-pushes every repo in the work group. Group-level fan-out built in.
- Bootstrap from disk, not yaml-by-hand — hop add -r ~/code walks your existing clones, reads git remote, and populates hop.yaml for you. Comment-preserving merges, idempotent re-runs.
- Plays nicely with wt — hop <name open delegates to wt's app menu, so you get the same "open in editor / terminal / file manager / cd here" experience for every repo in the registry. The hop <name/<wt-name suffix lands you straight inside a worktree (h webapp/feat-x cds you there, hop webapp/feat-x git status runs git in it), and hop ls --trees shows worktree state across every repo at a glance.
The mental model
One grammar: hop <selection <action. The selection comes first — always. Then an action: a builtin verb (cd, open, where), a git batch verb (pull, push, sync), or any command, PATH binary, or shell alias.
Colored half = what you type · grey half = what the h alias or tab completion fills in.
General form — hop <selection <action:
h web<TAB> cursor . # → hop webapp cursor .
h dot<TAB> ls -la # → hop dotfiles ls -la
h web<TAB> git status # → hop webapp git status
h web<TAB> pull # → hop webapp pull (git batch verb)The action is whatever follows the selection — a builtin verb, a git verb, a PATH binary, or even a shell alias you've defined (hop webapp p). The shim runs it with cwd set to the repo, then returns you to where you started.
Plural form — the selection can be a group or --all, fanning the git batch verbs across many repos: