Skip to content

Plugin Store

Dan Riddell edited this page Sep 30, 2026 · 1 revision

Plugin store

letsgo plugin install [<name>] [--link] [-o dir] [--repo] [--token]
letsgo plugin list [--json] [--available]
letsgo plugin prune

A plugin is pinned by the digest of its executable, so the question "which plugin is this" has exactly one answer. The store is where that answer lives on disk.

Content-addressed

Plugins are installed under their own digest:

$XDG_DATA_HOME/letsgo/plugins/sha256/<digest>/<name>

The plugins directive in config.mod moves the root somewhere else.

Because the path is the digest, two versions of one plugin coexist without colliding. Repository A pinning letsgo-multi v0.2.0 and repository B pinning v0.3.0 both work on one machine, at the same time, with no reinstall when you move between them — which the old arrangement, one binary per name on PATH, could not do.

When letsgo runs a plugin it looks the pinned digest up in the store first, then falls back to PATH. Either way it re-hashes the file before running it. The path is a strong hint, not a guarantee: a store entry whose contents no longer hash to its own path fails the plan, naming the path, and is never executed.

Installing

letsgo plugin install                       # every pin in letsgo.mod
letsgo plugin install letsgo-multi          # the latest release
letsgo plugin install letsgo-multi@v0.2.0   # one exact version

With no name it installs every pin in letsgo.mod, which is the one people actually want after a fresh clone.

The download is checked twice against the release's own manifest — once as an archive, once as the executable inside it — and then it is placed at its digest. That is the difference between this and the curl | tar recipe it replaces, which fetched over TLS and trusted whatever came back.

Flag Description
--link Also put the plugin on PATH, for running it by hand
-o With --link, the directory to link into (default: $GOBIN, or $GOPATH/bin)
--repo Repository to install from, as owner/name
--token Forge token (default: $GITHUB_TOKEN or $GH_TOKEN)

A release does not need --link — letsgo finds pinned plugins in the store without help. It is for the plugins you also want to type the name of.

Listing

$ letsgo plugin list
archive-layout letsgo-multi   v0.2.0    ok  /home/you/.local/share/letsgo/plugins/sha256/4934.../letsgo-multi
ldflags        letsgo-env     v0.2.0    not installed

list reads letsgo.mod and reports, per pin, whether the program is present and whether it is the one the pin means. A drifted digest is the failure this is for: letsgo would refuse it at release time, and finding out first is cheaper. It also shows store entries nothing references.

--available lists the plugins letsgo publishes instead, with their hooks and summaries. --json prints what this repository pins, with schema: 1.

Pruning

letsgo plugin prune

Removes store entries that no pin in the current repository references. A content-addressed store only grows otherwise, since every upgrade adds a path rather than replacing one.

Run it in a repository, not as a machine-wide tidy-up: it knows about the pins it can see, so pruning from one repository removes entries another repository still uses, and that one reinstalls them next time.

Per-plugin configuration

A plugin's own settings live in .letsgo/<short name>.mod, where the short name drops the letsgo- prefix:

repo/
  go.mod
  letsgo.mod          ← the release definition, core directives only
  .letsgo/
    env.mod           ← letsgo-env
    cask.mod          ← letsgo-cask

The plugin receives the absolute path to that directory as config_dir in its hook input, so it reads its own file rather than guessing where the repository root is.

A legacy root-level letsgo-<name>.mod is still read, with a Warn. Both files present at once is a Fail — two configurations for one plugin have no correct precedence, and picking one silently is how a setting stops taking effect without anyone noticing.

Clone this wiki locally