Commands
hoplocate, open, and operate on repos from hop.yaml.
hop — locate, open, and operate on repos from hop.yaml. Grammar: hop <selection> <action> <selection> = a repo name (substring → fzf on ambiguity), a repo/worktree, a group name, or --all (every cloned repo). <action> = a builtin verb (cd, open, where), a batch verb (pull, push, sync), any PATH binary (git pull, code .), or a shell alias/function (p). Omit the action to cd into the selection. Getting started: 1. Run `hop config init` to create a starter hop.yaml. 2. Edit it to list your repos (each entry: name + git URL + parent dir). 3. For interactive use, install the shim: eval "$(hop shell-init zsh)" Cheat sheet: hop fzf picker, print selection hop <name> cd into the repo (shell function — needs `eval "$(hop shell-init zsh)"`) hop <name>/<wt> same, but rooted at <wt> (a worktree of <name> per `wt list --json`) hop <name> cd same — explicit verb form hop <name> where echo abs path of matching repo (or worktree, with /<wt> suffix) hop <name> open open the repo in an app (delegates to wt's menu; "Open here" cds the parent shell) hop <name> git pull run `git pull` with cwd = <name>'s repo dir (any PATH binary works) hop <name> code . open the editor in <name>'s repo dir (tool-form — runs in the parent shell) hop <name> p run the shell alias/function `p` in <name>'s repo dir hop <name> pull run `git pull` in the named repo (batch verb, selection-first) hop <name> push run `git push` in the named repo hop <name> sync auto-commit dirty tree, then `git pull --rebase` + `git push` hop <group> pull run `git pull` in every cloned repo of <group> hop --all pull run `git pull` in every cloned repo hop --all sync run sync in every cloned repo hop clone <name> git clone the repo if it isn't already on disk hop clone <url> ad-hoc clone: clone the URL, register it in hop.yaml, print landed path hop clone --all clone every repo from hop.yaml that isn't already on disk hop clone fzf picker, then clone if missing hop ls list all repos hop ls --trees list all repos with worktree summaries (fans out `wt list --json`) hop add <dir> register on-disk repos into hop.yaml (-r walks a tree, -p previews) hop rm [<name>] remove a repo from hop.yaml (fzf picker if no name) hop shell-init <shell> emit shell integration (zsh or bash). Use: eval "$(hop shell-init zsh)" hop config init bootstrap a starter hop.yaml hop config where print the resolved hop.yaml path hop config print print the resolved hop.yaml contents to stdout hop update self-update the hop binary via Homebrew hop -h | --help show this help hop -v | --version print version Notes: - `hop <name>` and `hop <name> cd` require shell integration (a binary can't change its parent shell's cwd). Without it, use: cd "$(hop <name> where)" - Tool-form (`hop <name> <tool> ...`) and `hop <name> open`'s "Open here" choice run in the parent shell via the shim. Scripts/CI that bypass the shim must use `hop <name> where` for path resolution and run tools themselves. - `pull`, `push`, `sync` accept a repo, a worktree, a group, or `--all` as the selection. `sync` is `pull --rebase` + `push` (linear history, no auto-resolve on conflict), auto-committing a dirty tree first. - A plural selection (`--all` or a group) accepts only `pull`/`push`/`sync` — cd, open, where, and arbitrary tools across many repos are refused. - On ambiguous or no-match queries, fzf opens prefilled with your query. - Config lives at ~/.config/hop/hop.yaml.
hop [flags]hop [command]
| flag | type | description | copy |
|---|---|---|---|
--all | select every cloned repo from hop.yaml (plural selection — use with pull/push/sync) |
No flags match that filter.
show raw -h output
hop — locate, open, and operate on repos from hop.yaml.
Grammar: hop <selection> <action>
<selection> = a repo name (substring → fzf on ambiguity), a repo/worktree, a
group name, or --all (every cloned repo).
<action> = a builtin verb (cd, open, where), a batch verb (pull, push,
sync), any PATH binary (git pull, code .), or a shell
alias/function (p). Omit the action to cd into the selection.
Getting started:
1. Run `hop config init` to create a starter hop.yaml.
2. Edit it to list your repos (each entry: name + git URL + parent dir).
3. For interactive use, install the shim: eval "$(hop shell-init zsh)"
Cheat sheet:
hop fzf picker, print selection
hop <name> cd into the repo (shell function — needs `eval "$(hop shell-init zsh)"`)
hop <name>/<wt> same, but rooted at <wt> (a worktree of <name> per `wt list --json`)
hop <name> cd same — explicit verb form
hop <name> where echo abs path of matching repo (or worktree, with /<wt> suffix)
hop <name> open open the repo in an app (delegates to wt's menu; "Open here" cds the parent shell)
hop <name> git pull run `git pull` with cwd = <name>'s repo dir (any PATH binary works)
hop <name> code . open the editor in <name>'s repo dir (tool-form — runs in the parent shell)
hop <name> p run the shell alias/function `p` in <name>'s repo dir
hop <name> pull run `git pull` in the named repo (batch verb, selection-first)
hop <name> push run `git push` in the named repo
hop <name> sync auto-commit dirty tree, then `git pull --rebase` + `git push`
hop <group> pull run `git pull` in every cloned repo of <group>
hop --all pull run `git pull` in every cloned repo
hop --all sync run sync in every cloned repo
hop clone <name> git clone the repo if it isn't already on disk
hop clone <url> ad-hoc clone: clone the URL, register it in hop.yaml, print landed path
hop clone --all clone every repo from hop.yaml that isn't already on disk
hop clone fzf picker, then clone if missing
hop ls list all repos
hop ls --trees list all repos with worktree summaries (fans out `wt list --json`)
hop add <dir> register on-disk repos into hop.yaml (-r walks a tree, -p previews)
hop rm [<name>] remove a repo from hop.yaml (fzf picker if no name)
hop shell-init <shell> emit shell integration (zsh or bash). Use: eval "$(hop shell-init zsh)"
hop config init bootstrap a starter hop.yaml
hop config where print the resolved hop.yaml path
hop config print print the resolved hop.yaml contents to stdout
hop update self-update the hop binary via Homebrew
hop -h | --help show this help
hop -v | --version print version
Notes:
- `hop <name>` and `hop <name> cd` require shell integration (a binary can't change
its parent shell's cwd). Without it, use: cd "$(hop <name> where)"
- Tool-form (`hop <name> <tool> ...`) and `hop <name> open`'s "Open here" choice run in
the parent shell via the shim. Scripts/CI that bypass the shim must use
`hop <name> where` for path resolution and run tools themselves.
- `pull`, `push`, `sync` accept a repo, a worktree, a group, or `--all` as the
selection. `sync` is `pull --rebase` + `push` (linear history, no auto-resolve on
conflict), auto-committing a dirty tree first.
- A plural selection (`--all` or a group) accepts only `pull`/`push`/`sync` —
cd, open, where, and arbitrary tools across many repos are refused.
- On ambiguous or no-match queries, fzf opens prefilled with your query.
- Config lives at ~/.config/hop/hop.yaml.
Usage:
hop [flags]
hop [command]
Available Commands:
add register on-disk repos into hop.yaml (single dir, or -r to walk a tree)
clone git clone the resolved repo, an ad-hoc URL, or all missing repos with --all
completion Generate the autocompletion script for the specified shell
config config helpers (init, where, print)
help Help about any command
ls list all repos as aligned name/path columns
rm remove a registered repo from hop.yaml
shell-init emit shell integration (zsh or bash)
update self-update the hop binary via Homebrew
Flags:
--all select every cloned repo from hop.yaml (plural selection — use with pull/push/sync)
Use "hop [command] --help" for more information about a command.
hop addregister on-disk repos into hop.yaml (single dir, or -r to walk a tree)
Register on-disk repos into hop.yaml. By default, classifies just <dir> and — when it is a normal git repo with a remote — merges its URL into hop.yaml using the group convention (convention layout → the 'default' group; otherwise an invented group keyed off the parent dir basename). add writes by default. With -r/--recursive, walks <dir> for git repos (DFS, depth-bounded via --depth, symlink-following) and registers every one it finds. With -p/--print, renders the merge plan to stdout instead of writing (a dry-run, valid at both breadths). With -g/--group <name>, forces all discovered repos into the named group, auto-creating it if absent. A non-git directory is a no-op (a clear message, exit 0), not an error.
hop add <dir> [flags]
| flag | type | description | copy |
|---|---|---|---|
--depth | int | maximum DFS depth (only meaningful with -r; root counts as depth 0; must be >= 1) (default 3) | |
-g, --group | string | force all discovered repos into the named group, auto-creating it if absent | |
-p, --print | render the merge plan to stdout instead of writing to hop.yaml (a dry-run) | ||
-r, --recursive | walk <dir> for git repos (DFS) instead of classifying just <dir> |
No flags match that filter.
hop add ~/code/acme/widget register one existing repo into hop.yaml hop add -r ~/code walk ~/code and register every repo found hop add -r -p ~/code preview the recursive plan without writing hop add -g vendor ~/forks/x register into a forced (auto-created) group
show raw -h output
Register on-disk repos into hop.yaml.
By default, classifies just <dir> and — when it is a normal git repo with a
remote — merges its URL into hop.yaml using the group convention (convention
layout → the 'default' group; otherwise an invented group keyed off the parent
dir basename). add writes by default.
With -r/--recursive, walks <dir> for git repos (DFS, depth-bounded via --depth,
symlink-following) and registers every one it finds. With -p/--print, renders
the merge plan to stdout instead of writing (a dry-run, valid at both breadths).
With -g/--group <name>, forces all discovered repos into the named group,
auto-creating it if absent.
A non-git directory is a no-op (a clear message, exit 0), not an error.
Examples:
hop add ~/code/acme/widget register one existing repo into hop.yaml
hop add -r ~/code walk ~/code and register every repo found
hop add -r -p ~/code preview the recursive plan without writing
hop add -g vendor ~/forks/x register into a forced (auto-created) group
Usage:
hop add <dir> [flags]
Flags:
--depth int maximum DFS depth (only meaningful with -r; root counts as depth 0; must be >= 1) (default 3)
-g, --group string force all discovered repos into the named group, auto-creating it if absent
-p, --print render the merge plan to stdout instead of writing to hop.yaml (a dry-run)
-r, --recursive walk <dir> for git repos (DFS) instead of classifying just <dir>
hop clonegit clone the resolved repo, an ad-hoc URL, or all missing repos with --all
hop clone [<name> | <url> | --all] [flags]
| flag | type | description | copy |
|---|---|---|---|
--all | clone every repo from hop.yaml that isn't already on disk | ||
--group | string | target group for ad-hoc URL clone (only used with <url>) (default "default") | |
--name | string | override the URL-derived name for the on-disk path (only used with <url>) | |
--no-add | skip the hop.yaml write-back (only used with <url>) | ||
--no-cd | suppress the printed path so the shell shim does not cd (only used with <url>) |
No flags match that filter.
show raw -h output
Usage:
hop clone [<name> | <url> | --all] [flags]
Flags:
--all clone every repo from hop.yaml that isn't already on disk
--group string target group for ad-hoc URL clone (only used with <url>) (default "default")
--name string override the URL-derived name for the on-disk path (only used with <url>)
--no-add skip the hop.yaml write-back (only used with <url>)
--no-cd suppress the printed path so the shell shim does not cd (only used with <url>)
hop configconfig helpers (init, where, print)
hop confighop config [command]
show raw -h output
Usage: hop config hop config [command] Available Commands: init bootstrap a starter hop.yaml at the resolved write target print print the resolved hop.yaml contents to stdout where print the resolved hop.yaml path (regardless of file existence) Use "hop config [command] --help" for more information about a command.
hop config initbootstrap a starter hop.yaml at the resolved write target
hop config init
show raw -h output
Usage: hop config init
hop config printprint the resolved hop.yaml contents to stdout
hop config print
show raw -h output
Usage: hop config print
hop config whereprint the resolved hop.yaml path (regardless of file existence)
hop config where
show raw -h output
Usage: hop config where
hop lslist all repos as aligned name/path columns
hop ls [flags]
| flag | type | description | copy |
|---|---|---|---|
--treeswt list --json | list worktrees per repo via wt list --json |
No flags match that filter.
show raw -h output
Usage:
hop ls [flags]
Flags:
--trees wt list --json list worktrees per repo via wt list --json
hop rmremove a registered repo from hop.yaml
Remove a registered repo from hop.yaml. With no argument, pipes the registered repos through fzf and removes the selected entry's URL from its group. With a <name>, resolves it via the same match-or-fzf algorithm used by 'hop <name> where' and removes that entry directly — naming a repo prunes it even if its folder is already gone. Removal always targets a whole repo entry; any '/<worktree>' suffix on <name> is ignored (worktrees are not registry entries). Removing a group's last URL leaves the (now-empty) group as a placeholder, so it stays a valid 'hop clone --group' target. With --stale, the picker is pre-filtered to repos whose resolved path no longer exists on disk — the quick way to prune entries for repos you have deleted. --stale is a picker-scoping flag and cannot be combined with a <name>.
hop rm [<name>] [flags]
| flag | type | description | copy |
|---|---|---|---|
--stale | limit the picker to repos whose resolved path no longer exists on disk |
No flags match that filter.
hop rm pick any registered repo to remove hop rm widget remove the repo matching 'widget' directly (no picker) hop rm --stale pick among only the repos missing from disk
show raw -h output
Remove a registered repo from hop.yaml.
With no argument, pipes the registered repos through fzf and removes the
selected entry's URL from its group. With a <name>, resolves it via the same
match-or-fzf algorithm used by 'hop <name> where' and removes that entry
directly — naming a repo prunes it even if its folder is already gone. Removal
always targets a whole repo entry; any '/<worktree>' suffix on <name> is
ignored (worktrees are not registry entries).
Removing a group's last URL leaves the (now-empty) group as a placeholder, so
it stays a valid 'hop clone --group' target.
With --stale, the picker is pre-filtered to repos whose resolved path no longer
exists on disk — the quick way to prune entries for repos you have deleted.
--stale is a picker-scoping flag and cannot be combined with a <name>.
Examples:
hop rm pick any registered repo to remove
hop rm widget remove the repo matching 'widget' directly (no picker)
hop rm --stale pick among only the repos missing from disk
Usage:
hop rm [<name>] [flags]
Flags:
--stale limit the picker to repos whose resolved path no longer exists on disk
hop shell-initemit shell integration (zsh or bash)
hop shell-init <shell>
show raw -h output
Usage: hop shell-init <shell>
hop updateself-update the hop binary via Homebrew
hop update [flags]
| flag | type | description | copy |
|---|---|---|---|
--skip-brew-updatebrew update | skip the internal brew update tap-metadata refresh (the version check and upgrade still run) |
No flags match that filter.
show raw -h output
Usage:
hop update [flags]
Flags:
--skip-brew-update brew update skip the internal brew update tap-metadata refresh (the version check and upgrade still run)