Skip to content

The release manifest

.ngit/release.yaml is a committed file that tells ngit release publish which files to publish, what to say about the application, and where to send everything. With it in place, a release needs nothing but a version. See Releases for the workflow; this page is the field reference.

The filename is singular. Unknown fields are rejected, so a typo fails before anything is uploaded.

Where ngit looks

ngit release publish reads .ngit/release.yaml automatically when it is creating a release and you pass no asset flags. Use --manifest <PATH> to name another file, to combine a manifest with --file or --asset flags, or when editing with --edit.

Relative paths, in the manifest and in --manifest itself, are resolved from the repository root, never from the directory you ran the command in.

A complete example

One asset entry describes one file. List every platform that file supports in its platforms list rather than repeating the entry:

yaml
schema: 1
application: my-tool
pubkey: npub1expectedpublisher...
name: My Tool
summary: A short listing summary
description: |
  A longer application description.
tags: [nostr, cli]
license: MIT
website: https://example.com
repository: nostr://npub1maintainer.../my-tool
icon: assets/icon.png
images:
  - assets/screenshot.png
  - https://cdn.example.com/existing-screenshot.png
channel: main
release_notes: CHANGELOG.md
publication:
  blossom_servers:
    - https://blossom.example.com
    - https://mirror.example.com
  relays:
    - wss://releases.example.com
assets:
  - file: dist/my-tool-{version}-linux-x86_64
    filename: my-tool-{version}-linux-x86_64
    platforms: [linux-x86_64]
  - file: dist/my-tool-{version}-macos-universal
    platforms: [macos-x86_64, macos-aarch64]
  - source: https://downloads.example.com/{version}/my-tool-windows.zip
    platforms: [windows-x86_64]
  - file: dist/checksums.txt
    platform_agnostic: true

Placeholders

{version} expands to the release version. {tag} expands to the Git tag, which ngit knows when it derived the version from a tag or you passed --tag. Both work in file, source, filename, original_url, and release_source. There is no shell, environment variable, glob, or other template expansion.

Top-level fields

FieldMeaning
schemaRequired. Currently 1.
applicationApplication identifier. Optional when the repository has only one application to discover.
identifierZapstore-compatible alias for application. Do not set both.
pubkeyExpected publisher. Publication fails before upload if the active signer is a different key.
name, summary, descriptionApplication listing text.
tags, license, website, repositoryFurther application metadata.
icon, imagesApplication media; see Media.
communitiesCommunity identifiers as 64-character hex strings.
supported_nipsDefault supported_nips for assets that do not set their own.
channelRelease channel. Defaults to main when creating.
notesLiteral release notes.
release_notesPath to a Keep a Changelog file; see Release notes.
commitGit commit the release represents, when it is not the current commit.
release_sourceOne local APK; see Android.
publicationWhere and how to publish; see Publication.
assetsThe files to publish; see Assets.

A manifest must contain either release_source or at least one entry in assets, and not both.

Application metadata uses the same names as zapstore.yaml where the meanings agree. On the first release, the metadata you supply creates the application, with repository metadata filling any gaps. On later releases, a changed value replaces the application's value and an omitted field keeps whatever the application already has.

Media

For icon and each entry in images, an HTTP or HTTPS URL is kept exactly as written and is never downloaded or re-uploaded. Any other value is a repository-relative image file. It must be tracked by Git, sit inside the repository, have an image MIME type, and be at most 20 MiB. Local images are uploaded to your Blossom servers before any event is signed, and the application record uses the first server that confirms the copy.

Release notes

notes and release_notes are mutually exclusive.

release_notes names a Keep a Changelog file. ngit takes the level-two section whose heading matches the release version, allowing an optional leading v in the heading or the version. Both ## [1.2.3] - 2026-08-31 and ## 1.2.3 match. The section's Markdown is kept as written and stops at the next level-two heading. A missing, duplicated, or empty section fails before publication rather than publishing the whole changelog.

--notes and --notes-file on the command line override either manifest field. --notes-file is literal and does no changelog extraction.

Publication

FieldMeaning
blossom_serversOrdered list of Blossom servers. Every file is uploaded to each one; the first server to confirm a copy supplies the asset URL.
relaysAdditional relays for discovery and publication.
zapstore_relayAlso publish to the Zapstore catalog relay.
strict_metadataFail on metadata warnings instead of publishing with them.
allow_partial_platformsLet a release on a channel other than main cover only part of the application's platforms.
add_application_platformsLet a main release add platforms to the application record.

Command-line flags combine with this block predictably. --blossom-server replaces the manifest's server list. --relay values are added to the manifest's relays. Boolean flags and manifest booleans are enabling: if either is true, the policy is on.

The version, the signer, --released-at, --tag, --edit, and the output format are always command-line inputs. A committed manifest cannot supply a key, silently replace a release, or freeze data that changes every release.

Assets

Each entry has exactly one source:

  • file: a repository-relative or absolute local path, uploaded to your Blossom servers; or
  • source: a public HTTP or HTTPS URL that ngit downloads and hashes before signing. Credentials in the URL are rejected because the URL is published.

Two entries may not resolve to the same path, URL, or filename.

FieldMeaning
platformsEvery platform this file supports. Required unless platform_agnostic is set or the file is a local APK.
platform_agnostictrue for files such as checksums that apply to every platform. Cannot be combined with platforms.
filenamePublished filename. No path separators.
mimePublished MIME type.
identifier, versionOverrides for the asset's own identity.
min_platform_version, target_platform_versionPlatform version bounds.
supported_nipsOverrides the top-level default.
variant, commit, min_allowed_versionFurther asset metadata.
original_urlWhere the file was originally published.
androidAndroid package metadata; see Android.

Android

An asset is treated as an APK when its mime is application/vnd.android.package-archive or its file or filename ends in .apk. APKs cannot be platform agnostic.

For a local APK, ngit reads the package name, version data, SDK levels, signing-certificate hashes, and supported ABIs from the file itself. Values you also declare under android are checked against the file, not used to override it. That is why a local APK needs no platforms list.

release_source is the Zapstore-compatible shorthand for exactly one local APK. It must be a repository-relative path ending in .apk, and it replaces the assets list:

yaml
schema: 1
identifier: com.example.myapp
name: Example App
release_notes: CHANGELOG.md
release_source: dist/example-app-{version}.apk
publication:
  blossom_servers:
    - https://blossom.example.com
    - https://mirror.example.com
  zapstore_relay: true

An APK that ngit does not have locally, given with source, needs an android block with version_code and at least one certificate_sha256:

yaml
schema: 1
application: com.example.myapp
assets:
  - source: https://downloads.example.com/{version}/example-app.apk
    mime: application/vnd.android.package-archive
    android:
      version_code: 10203
      min_allowed_version_code: 10100
      certificate_sha256:
        - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
FieldMeaning
version_codeAndroid version code. Must be greater than zero.
min_allowed_version_codeOldest version code allowed to update to this one. Requires version_code and may not exceed it.
certificate_sha256Signing-certificate hashes as 64-character hex strings.

Several applications in one repository

A repository can publish more than one application, which suits a monorepo with, say, a command-line tool and an Android app. Give each application its own manifest with application or identifier set, and choose it at publish time:

bash
ngit release publish 1.2.0 --manifest .ngit/release-cli.yaml --tag cli-v1.2.0
ngit release publish 4.0.0 --manifest .ngit/release-android.yaml --tag android-v4.0.0

Pass the version explicitly in this arrangement. When ngit derives a version from a tag it only strips one leading v, so a prefixed tag such as cli-v1.2.0 would otherwise become the version verbatim. --tag still pins the release to that tag's commit and fills {tag} in the manifest.

Each application has its own owner and publication history; see Keep one publishing identity.

Exact reference

Git collaboration, without the platform.