A Decky Loader plugin for managing every plugin on your Deck, including the ones that never went through the official store.
Point it at a GitHub repo, and it finds the latest release zip, installs it through Decky's own installer, remembers the version, and tells you when a newer release shows up.
- Lists every installed plugin, store-sourced or not, read straight from
~/homebrew/plugins. - Finds the repo for plugins you already have. One press matches your installed plugins against
the official store's plugin database — which records the upstream repo behind every plugin it
carries — and links them. Plugins the store never carried fall back to the repo named in their own
plugin.jsonandpackage.json; those are marked detected, since a plugin's own files can point at the repo it was forked from. Nothing outside GitHub is guessed at. - Adds plugins from GitHub without typing a URL. You get
https://github.com/followed by an owner field, a/, and a repo field. Paste a full URL into either field and it splits itself across both. - Finds the release zip for you. It lists releases that ship a
.zipasset, newest first, and reads the plugin's real name and version out of the zip before installing, so the plugin lands under the name Decky expects rather than a guess from the file name. - Pins a plugin to a branch. Pick a branch when adding or re-pointing a plugin and only releases
tagged from it are offered — then and on every later update check. Follow
mainon one plugin and abetabranch on another. Leave it on Any branch to consider every release, which is what plugins tracked before this existed keep doing. Because a preview branch usually ships pre-releases, Include pre-releases sits next to the branch picker and reports how many releases it is hiding. - Tracks versions and offers updates. Each tracked plugin records the release tag and branch it came from. One button re-checks them all against GitHub.
- Adopts plugins you already have. Link an existing plugin to a repo and mark the release you are already on, without reinstalling anything.
- Optional GitHub token to lift the 60-requests-per-hour anonymous rate limit and reach private repos.
Bazaar does not unpack anything itself. It downloads the release zip, inspects it, and hands the
file to decky-loader's utilities/install_plugin. That means installs go through exactly the same
path as the official store: the standard confirmation prompt, unzip, remote binary download,
permission fixup, and hot reload. Uninstalls go through utilities/uninstall_plugin the same way.
A zip is only accepted if it looks like a real plugin package: exactly one top-level folder
containing a plugin.json. Repository source archives and multi-plugin zips are rejected with an
explanation rather than being installed into a broken state.
Open the Quick Access menu, pick Decky Bazaar, and:
| Action | Where |
|---|---|
| Install something new | Add plugin from GitHub |
| Link what you already have to its repo | Find repos for … unlinked plugins |
| Re-check every tracked plugin | Check … for updates |
| Update, relink, change branch, or uninstall one plugin | Tap its row in Installed |
| Token and pre-release options | Settings |
Rows sort so anything with an update waiting is at the top.
Tracked sources go in ~/homebrew/settings/decky-bazaar/bazaar.json. The GitHub token is stored in
that same file, which is chmod'd to 600. Downloads are staged in the plugin's runtime directory
and cleared on unload.
Requires Node 16.14+ and pnpm 9+.
pnpm i
pnpm run build # bundles src/ into dist/index.js
pnpm run typecheck # tsc --noEmit
pnpm run package # stages the plugin folder and zips it into out/pnpm run package produces the same out/Decky-Bazaar-v<version>.zip that CI attaches to a
release, so it is what to install from when testing a build by hand.
To deploy straight to a Deck over SSH instead, use the
Decky CLI — .vscode/setup.sh fetches it, and the
build / deploy VSCode tasks drive it. Copy .vscode/defsettings.json to
.vscode/settings.json and point it at your Deck first.
Pushing to main builds, typechecks and packages the plugin. When package.json's version is one
that has not been tagged yet, the workflow also cuts a v<version> release with the zip attached
and the matching ## v<version> section of CHANGELOG.md as its notes. So a release
is one commit: bump the version, write the changelog section, push.
main.py backend: GitHub API, zip inspection, tracked-source storage
src/lib/api.ts typed callables + the decky-loader websocket bridge
src/lib/repo.ts owner/repo parsing for typed and pasted input
src/lib/install.ts download -> inspect -> hand to loader -> record source
src/components/RepoInput.tsx the split github.com/owner/repo field
src/components/*Modal.tsx add/relink, per-plugin detail, settings
src/index.tsx the Quick Access panel
- Update detection compares release tags. A repo that reuses or rewrites tags will look up to date when it isn't.
- Branch pinning uses the branch GitHub recorded for the tag (
target_commitish). A release tagged straight from a commit rather than a branch carries a bare commit SHA there, so it matches no branch at all and only shows up under Any branch. - If a plugin is updated outside Bazaar, its row is flagged as drifted rather than silently re-pointed.
- Only
.ziprelease assets are considered, since that is what decky-loader can install.
This plugin is free and open source, and it will stay that way. If it saved you a trip through Desktop Mode and a hand-unzipped plugin folder, you can buy me a coffee — it is genuinely appreciated and it keeps the updates coming ☕
Starring the repo, reporting a bug or suggesting a feature helps just as much — and costs nothing.
BSD 3-Clause — see LICENSE. Built on the Decky plugin template.