Skip to main content

AltGen icon

AltGen

Python versions PyPI version MIT license

Generate AltStore apps.json source files from GitHub Releases IPA assets.

Static app metadata (name, bundle identifier, icon and screenshot URLs, descriptions…) comes from a TOML config; everything dynamic (version, build version, release date, download URL, file size, release notes) is read live from the GitHub Releases API.

GitHub Releases API ──┐
                      ├──► altgen ──► apps.json
app config TOML ──────┘

Install

pip install altgen
altgen --version

Requires Python ≥ 3.10.

Usage

One TOML config = one app = one apps.json:

altgen -c piliplus.toml          # writes apps.json next to the config
altgen -c piliplus.toml -o out/piliplus.json   # override output path

Or skip the config file entirely for a quick single-app source (any CLI flag overrides its TOML counterpart):

altgen --repo owner/App --app-name App --bundle-id com.owner.app -o apps.json

Hosting many sources is just many configs — loop over them or use a CI matrix, one altgen -c <config> per app.

Merge sources

Combine several apps.json files into one source (e.g. host many apps under a single source while keeping one config per app):

altgen merge a.json b.json -o merged.json
altgen merge -c merge.toml a.json b.json    # root values + output from TOML
altgen merge --name MySource --tint-color "#00AEEF" a.json b.json
  • apps are taken from the inputs and sorted by name (case-insensitive); news entries from all inputs (root news plus each app's news) are combined and sorted newest-first.
  • Root values (name, subtitle, description, icon_url, website, tint_color) come from the CLI flags or the config's [source] table — same rules as build mode, and --name (or [source] name) is required.
  • Merge configs only support [source] and [output] tables; build-mode tables ([github], [app], …) are rejected.
  • A duplicate bundleIdentifier or duplicate news identifier across inputs is an error (exit 2).

See examples/merge.toml for a full merge config.

GitHub token

Unauthenticated requests are limited to 60/hour; a token raises that to 5,000/hour. Precedence: --token > GITHUB_TOKEN env var > [github] token.

TOML schema

Only [github] repo, [app] name, and [app] bundle_identifier are required. Keys are snake_case in TOML and become the AltStore camelCase JSON keys (bundle_identifierbundleIdentifier, icon_urliconURL, min_os_versionminOSVersion, …). Unknown keys are rejected with an error.

See examples/piliplus.toml for a full example.

[github]
repo = "owner/App"               # REQUIRED: GitHub repo with releases
token = ""                       # optional (see above)

[source]                         # the source this apps.json describes
name = "App"                     # defaults to the repo name
subtitle = ""
description = ""
icon_url = ""                    # omitted from JSON when unset
website = ""
tint_color = "#00AEEF"           # must be #RRGGBB

[app]                            # the app inside the source
name = "App"                     # REQUIRED
bundle_identifier = "com.x.y"    # REQUIRED
developer_name = ""              # defaults to the repo owner (CLI mode)
subtitle = ""
description = ""                 # fallback when a release body is empty
icon_url = ""                    # falls back to [source].icon_url
screenshots = ["https://…"]
tint_color = ""                  # falls back to [source].tint_color
min_os_version = "14.0"          # omitted from versions when unset

[versions]
strip_v_prefix = true            # tag "v1.2.3" → version "1.2.3"
include_prereleases = false      # drafts are always skipped
asset_pattern = "\\.ipa$"        # regex, case-insensitive search on asset name
build_version_pattern = "\\+(\\d+)\\.ipa$"  # group 1 = buildVersion; no match → key omitted
# version_pattern = "…"         # optional: extract version with this regex instead of the tag
                                 # (for projects whose tags lack a version); no match → tag-derived version
# version_source = "release"     # where version_pattern runs: "release" (default, release name) or "filename" (IPA asset name)
max_versions = 1                 # default: newest version only; 0 = all versions

[news]
enabled = true
title_template = "{name} {version} - {date}"  # default; placeholders: {name} {version} {tag} {date} (e.g. 07 Aug 2026)
caption_template = ""                     # optional; default: "{name} {version} is available."
image_url = ""                            # optional; omitted from JSON when unset
                                          # news appID = [app] bundle_identifier
max_entries = 0                           # 0 = unlimited; caps after sorting; news already limited to versions kept by max_versions

[output]
path = "apps.json"               # resolved against THIS file's directory

Behavior notes

  • Versions are sorted newest-first by (date, version); one version entry per matching release asset. A release with several IPAs produces several entries — sharing one version by default, or one version each when version_source = "filename".
  • The version is the release tag by default (strip_v_prefix strips a leading v). For projects whose tags carry no version (e.g. youproextra-ipa2), set version_pattern to extract it from the release name or IPA filename instead; on no match the version falls back to the tag-derived value.
  • By default only the newest version is emitted (max_versions = 1); set max_versions = 0 (or --max-versions 0) to include all versions.
  • News follows the same convention: one news entry per release, dropped when max_versions caps away all of that release's versions. [news] max_entries can further cap the list.
  • News entries follow the AltStore spec: appID first (the app's bundle_identifier), a full ISO date timestamp, identifier derived from the release tag (release-<tag>), and an optional imageURL; title_template / caption_template support {name}, {version}, {tag}, {date} placeholders.
  • A release with no matching asset contributes nothing — not even a news entry. One news entry is emitted per release that has assets.
  • Empty output (no releases, only drafts, …) is a valid source: altgen warns on stderr and exits 0.

CLI

altgen [-c PATH] [--repo OWNER/REPO] [--token TOKEN]
       [--name] [--subtitle] [--description] [--icon-url] [--website] [--tint-color]
       [--app-name] [--bundle-id] [--developer-name] [--app-subtitle]
       [--app-description] [--app-icon-url] [--app-tint-color] [--min-os-version]
       [--screenshots URL …] [--include-prereleases] [--max-versions N]
       [-o PATH] [-q] [-v] [--version]

altgen merge APPS_JSON… [-c PATH] [--name] [--subtitle] [--description]
       [--icon-url] [--website] [--tint-color] [-o PATH] [-q]
  • Without -c, --repo, --app-name, and --bundle-id are required (build mode).
  • --max-versions N caps the output after sorting (newest first); it defaults to 1 (latest version only) and 0 means all versions.
  • CLI flags override TOML values; -o resolves against the current directory while [output] path resolves against the config file's directory (so a config next to its sources works from any CWD).
  • altgen merge combines apps.json files; see Merge sources.
  • -v logs skipped releases (draft / prerelease / no matching assets) to stderr; -q silences the success message.
  • Exit codes: 0 success, 1 GitHub, IO, or write error, 2 usage or configuration error.

Development

pip install -e ".[dev]"
pytest            # fully offline — fixtures captured from the GitHub API

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

altgen-0.2.4.tar.gz (29.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

altgen-0.2.4-py3-none-any.whl (19.4 kB view details)

Uploaded Python 3

File details

Details for the file altgen-0.2.4.tar.gz.

File metadata

  • Download URL: altgen-0.2.4.tar.gz
  • Upload date:
  • Size: 29.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for altgen-0.2.4.tar.gz
Algorithm Hash digest
SHA256 26871835ed20c66ad6df6baec10ef566c563b57e5b0346c24354b21440036105
MD5 8bf887fd5945cb87c8cc2a2096e550d5
BLAKE2b-256 1c08cdf3d2d428629bd3622dc859a6abbf0e92cdfbf3b0d6a2fe42908f9c4d1a

See more details on using hashes here.

Provenance

The following attestation bundles were made for altgen-0.2.4.tar.gz:

Publisher: publish-pypi.yml on bebound/AltGen

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file altgen-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: altgen-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 19.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for altgen-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 4dba0db42e3be7f2d90e8fad76ef633c3c3f2617a5f0df1d4120e357913a239b
MD5 b014cdfad9ea474f8d0d696cb34e90a9
BLAKE2b-256 afbd469fa1f89f4118db0c0fa2eb4cd8c041a99da95d17274061e426315cc893

See more details on using hashes here.

Provenance

The following attestation bundles were made for altgen-0.2.4-py3-none-any.whl:

Publisher: publish-pypi.yml on bebound/AltGen

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.5

2 files

This release

0.2.4 This release

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page