THE GODOT ADDON MANAGER
Godot addons.
All in place.
One manifest for the addons your project needs. Exact GitHub Release tags. A single command to put everything where it belongs.
OPEN SOURCE / NO ACCOUNT TO INSTALL
gdam install ↓ res://addons/ ✓ A SMALL TOOL. A TIDIER PROJECT.
Start with
your first addon.
Install the CLI, create a manifest in your Godot project, then add an addon from the registry.
Installation guide ↗curl -fsSL https://gdam.dev/install | sh $ gdam init created gdam.json $ gdam add @aviorstudio/gd-router installed @aviorstudio/gd-router@v0.0.2 $ gdam install same manifest → same addon tags
01 / PIN
Release tags stay explicit.
The manifest records exact, case-sensitive tags. Without a tag, gdam selects the newest stable Release.
02 / LINK
Room for local work.
Edit an addon next door. Its local path belongs in gdam.link.json, separate from the manifest
you commit.
03 / PUBLISH
Your releases stay yours.
The registry points to GitHub Release assets. Publishing uses an owner-scoped secret key.
Two files, one job each
What ends up in your repo.
The session above wrote both of these. gdam.json is the one you commit: it records exact tags
for gd-observe and gd-router, and lists
gd-gesture with no tag because that addon is linked locally.
Where that link actually points lives in gdam.link.json — an absolute path on one machine,
which is exactly the kind of thing that must never reach anyone else's checkout. Keeping the two apart is
the whole reason there are two.
{
"addons": {
"@aviorstudio/gd-gesture": {},
"@aviorstudio/gd-observe": {
"tag": "gd-v0.0.3"
},
"@aviorstudio/gd-router": {
"tag": "v0.0.2"
}
}
} {
"addons": {
"@aviorstudio/gd-gesture": {
"enabled": true,
"path": "/home/you/code/roguelike/gd-gesture"
}
}
} Commands, GitHub Actions and download integrity
The whole command surface.
Nine commands, and three environment variables behind them:
GDAM_API_URL to point the CLI at another registry,
GDAM_SECRET_KEY to publish from CI, and an optional
GITHUB_TOKEN when release downloads start hitting GitHub's rate limit.
Without a tag, gdam resolves the newest stable (non-prerelease) Release. Exact tags may select prereleases
and are case-sensitive: Release-1 and
release-1 are different.
- uses: aviorstudio/gdam-actions/install@v0.1.0 with: version: v0.0.8 - uses: aviorstudio/gdam-actions/publish@v0.1.0 with: tag: ${{ steps.release.outputs.tag }} asset: ${{ steps.release.outputs.asset }} secret-key: ${{ secrets.GDAM_SECRET_KEY }}
Exact release tags make the snippet readable and reproducible under the project's no-move policy, but Git
tags can be moved or deleted. A Full 40-character commit SHA is the strongest GitHub Actions pin; use
15042aa1ff1e28f5e97828384b78a25c63d0199e when immutability is required.
What v0.0.8 enforces. Registry requests time out after 30 seconds and responses are
limited to 4 MiB. Asset downloads use the immutable asset-ID endpoint, time out after two minutes, follow
at most five redirects, remove authorization on a cross-origin redirect, and stop at 128 MiB. gdam checks
the registered release, commit, asset identity and mandatory SHA-256 digest before extraction, and detects
a truncated declared download. Extraction rejects absolute paths, .. traversal, backslashes
and symlinks, with at most 10,000 entries and 512 MiB total uncompressed content. The resulting package
root must contain plugin.cfg.
| Command | Does |
|---|---|
gdam init | Write gdam.json in this Godot project |
gdam add @user/addon[@tag] | Resolve it, install it, record its exact Release tag |
gdam install | Install every exact tag the manifest records |
gdam remove @user/addon | Take it out, and out of the manifest |
gdam link @user/addon [path] | Point it at a checkout on your disk |
gdam unlink @user/addon | Put the tagged release back |
gdam unlink --all | Undo every link at once |
gdam publish @user/addon TAG [ASSET_NAME] | Publish an exact Release tag and optional asset |
gdam --version | What is installed |
PUT THE PIECES TOGETHER