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 . # or: pip install git+https://github.com/…
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.
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 = 0 # 0 = unlimited; caps after sorting (newest first)
[news]
enabled = true
title_template = "{name} {version}"
max_entries = 0 # 0 = unlimited; caps after sorting
[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). - 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]
- Without
-c,--repo,--app-name, and--bundle-idare required. - 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). -vlogs skipped releases (draft / prerelease / no matching assets) to stderr;-qsilences the success message.- Exit codes:
0success,1GitHub or write error,2usage or config 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.1.0.tar.gz.
File metadata
- Download URL: altgen-0.1.0.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe0e0fb04684c8bd11dbe36670308c8921d2c4e63372a1b5d36d9208e0d8c561
|
|
| MD5 |
6661fa56c917f92623cdc5a6fde189a2
|
|
| BLAKE2b-256 |
089d0e9e39e847940644d6a33ecd1577d07848a12f0b310f266518762d7421fc
|
File details
Details for the file altgen-0.1.0-py3-none-any.whl.
File metadata
- Download URL: altgen-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
415158dfc23a994705738a28fbd2464e7384df739506fc36375a8d1866fbb6db
|
|
| MD5 |
8eef0daf39266fd31182c79a986e9c96
|
|
| BLAKE2b-256 |
25fcf45592bda1a7b28fa0766423f8e19e2f3d3f1051c1a868b1bf0162b439af
|