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 releases 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, kept only when that release still has a version entry after the max_versions cap. Matching is by release, not by version string, so several releases that resolve to the same version (e.g. a date-bearing tag like release-v1.2.3-2026-08-21 vs ...-2026-08-14) each get their own news entry only while their version entry survives the cap. [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.5.tar.gz (30.4 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.5-py3-none-any.whl (19.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: altgen-0.2.5.tar.gz
  • Upload date:
  • Size: 30.4 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.5.tar.gz
Algorithm Hash digest
SHA256 ede33fedd0359ea3508b677a50120496e62a92b46f12531b9ca99532282491c7
MD5 7efe5fd240ba37036ae706a5e6544533
BLAKE2b-256 ad0e8741c8e4672307b1b924599d6bc2d0011996438923d0ff1a7a8ce1cc643b

See more details on using hashes here.

Provenance

The following attestation bundles were made for altgen-0.2.5.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.5-py3-none-any.whl.

File metadata

  • Download URL: altgen-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 19.7 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.5-py3-none-any.whl
Algorithm Hash digest
SHA256 8f3aa0745b5fc7a56e1381b70f169d245d5f2f4313c076db397974c7921833c7
MD5 ca2606d1103de86903b5dbd8dd24b527
BLAKE2b-256 423a11881b06b4bba2e96ee397569a0ac99c0d156a19be4eef39d1fe6e5dca63

See more details on using hashes here.

Provenance

The following attestation bundles were made for altgen-0.2.5-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

This release

0.2.5 This release

2 files

0.2.4

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