AltGen
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
appsare taken from the inputs and sorted by name;newsentries from all inputs (rootnewsplus each app'snews) 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
bundleIdentifieror duplicate newsidentifieracross 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_identifier → bundleIdentifier, icon_url →
iconURL, min_os_version → minOSVersion, …). 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
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 the same version). - By default only the newest version is emitted (
max_versions = 1); setmax_versions = 0(or--max-versions 0) to include all versions. - News follows the same convention: one news entry per kept version, so
versions dropped by
max_versionscontribute no news either.[news] max_entriescan further cap the list. - News entries follow the AltStore spec:
appIDfirst (the app'sbundle_identifier), a full ISOdatetimestamp,identifierderived from the release tag (release-<tag>), and an optionalimageURL;title_template/caption_templatesupport{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-idare required (build mode). --max-versions Ncaps the output after sorting (newest first); it defaults to1(latest version only) and0means all versions.- CLI flags override TOML values;
-oresolves against the current directory while[output] pathresolves against the config file's directory (so a config next to its sources works from any CWD). altgen mergecombines apps.json files; see Merge sources.-vlogs skipped releases (draft / prerelease / no matching assets) to stderr;-qsilences the success message.- Exit codes:
0success,1GitHub, IO, or write error,2usage 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file altgen-0.2.2.tar.gz.
File metadata
- Download URL: altgen-0.2.2.tar.gz
- Upload date:
- Size: 27.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69b2c28f9b66b0f66a708c3f63f17333db16fd3b5f53aa63dc4f18cc26851980
|
|
| MD5 |
28a43292dbfc8a0224b43c31ae60d292
|
|
| BLAKE2b-256 |
6f6e8b8fc6c94e0b8003e018784ab8fa1bb1f5770bf88794c3628237bb8116dc
|
Provenance
The following attestation bundles were made for altgen-0.2.2.tar.gz:
Publisher:
publish-pypi.yml on bebound/AltGen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
altgen-0.2.2.tar.gz -
Subject digest:
69b2c28f9b66b0f66a708c3f63f17333db16fd3b5f53aa63dc4f18cc26851980 - Sigstore transparency entry: 2496083663
- Sigstore integration time:
-
Permalink:
bebound/AltGen@f41c4de45884e6f3104fa11229b17359e22c311b -
Branch / Tag:
refs/heads/release - Owner: https://github.com/bebound
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@f41c4de45884e6f3104fa11229b17359e22c311b -
Trigger Event:
push
-
Statement type:
File details
Details for the file altgen-0.2.2-py3-none-any.whl.
File metadata
- Download URL: altgen-0.2.2-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab1cecc53910ab6e5cc7b7cdea23548846c9adb6f564b69ad15293c92c14f1d2
|
|
| MD5 |
9cfb3858146337abb1067a717b1c7110
|
|
| BLAKE2b-256 |
02b337aa5e9c3f1c6dd67416efad71d35c712b114732a9d427a1e13628e7281b
|
Provenance
The following attestation bundles were made for altgen-0.2.2-py3-none-any.whl:
Publisher:
publish-pypi.yml on bebound/AltGen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
altgen-0.2.2-py3-none-any.whl -
Subject digest:
ab1cecc53910ab6e5cc7b7cdea23548846c9adb6f564b69ad15293c92c14f1d2 - Sigstore transparency entry: 2496084193
- Sigstore integration time:
-
Permalink:
bebound/AltGen@f41c4de45884e6f3104fa11229b17359e22c311b -
Branch / Tag:
refs/heads/release - Owner: https://github.com/bebound
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@f41c4de45884e6f3104fa11229b17359e22c311b -
Trigger Event:
push
-
Statement type: