Godot Addon Manager

Godot addons, pinned.

One manifest lists what your project uses, and gdam install puts exactly those versions under res://addons/. Releases are GitHub releases, the registry only records which one each version points at, and installing needs no account.

go install github.com/aviorstudio/gdam@latest

MIT · one static binary · Linux, macOS and Windows

roguelike / godot_client
$ gdam init
created ~/code/roguelike/godot_client/gdam.json

$ gdam add @aviorstudio/gd-router
installed @aviorstudio/gd-router@0.0.2 (v0.0.2)

$ gdam add @aviorstudio/gd-observe
installed @aviorstudio/gd-observe@0.0.3 (gd-v0.0.3)

$ gdam link @aviorstudio/gd-gesture ../gd-gesture
linked @aviorstudio/gd-gesture -> ~/code/roguelike/gd-gesture

$ gdam install
installed @aviorstudio/gd-observe@0.0.3
installed @aviorstudio/gd-router@0.0.2
3 addons two pinned, one linked0 accounts reads are public
01

The manifest you ship never learns about your disk

gdam.json holds addon names and versions and nothing else. A local checkout is recorded in a separate gdam.link.json, so you can build against an addon you are editing without the file your teammates install from changing at all.

02

The registry stores a pointer, not your code

Publishing points a semver version at a GitHub release tag and an asset in it. The ZIP has the addon files at its root, plugin.cfg included, and GDAM unpacks it into res://addons/@owner_repo/ whatever the asset was called. Your releases stay yours.

03

Installing needs no account

Reads are public and anonymous, and the CLI carries no credentials — which is why there is nothing to log into before gdam install works in CI. Publishing uses a secret key scoped to one user or org, and it can only cut releases for addons already under that owner.

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 pins gd-observe and gd-router, and lists gd-gesture with no version at all, because a linked addon has no published version to pin.

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.

gdam.json commit this
{
  "addons": {
    "@aviorstudio/gd-gesture": {},
    "@aviorstudio/gd-observe": {
      "version": "0.0.3"
    },
    "@aviorstudio/gd-router": {
      "version": "0.0.2"
    }
  }
}
gdam.link.json yours alone
{
  "addons": {
    "@aviorstudio/gd-gesture": {
      "enabled": true,
      "path": "/home/you/code/roguelike/gd-gesture"
    }
  }
}

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.

Publishing from a release workflow is two steps, because the publish action refuses to guess whether the CLI is there — it says so plainly rather than failing with gdam: command not found.

- uses: aviorstudio/gdam-actions/install@v0

- uses: aviorstudio/gdam-actions/publish@v0
  with:
    version: ${{ steps.release.outputs.version }}
    tag: ${{ steps.release.outputs.tag }}
    secret-key: ${{ secrets.GDAM_SECRET_KEY }}
CommandDoes
gdam init Write gdam.json in this Godot project
gdam add @user/addon[@version] Resolve it, install it, record it
gdam install Install every version the manifest pins
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 published version back
gdam unlink --all Undo every link at once
gdam publish @user/addon VERSION TAG Point a version at a release asset
gdam --version What is installed

One file in.
The same addons out.

GDAM.JSONGITHUB RELEASERES://ADDONS/

macOS and Linux

curl -fsSL https://raw.githubusercontent.com/aviorstudio/gdam/main/scripts/install_cli.sh | sh

With the Go toolchain

go install github.com/aviorstudio/gdam@latest