Community app registry consumed by RokidBrew (phone app) and the RokidBrew web store. Apps added here show up in both automatically — no redeploy needed.
# 1. Create the app definition
# Edit apps/<app-id>.json (see format below).
# 2. Build the manifest locally to validate
node scripts/build-registry.mjs
# 3. Commit and push
git add apps/<app-id>.json dist/apps.v1.json
git commit -m "Add <app-name>"
git push
# 4. Go to GitHub Actions — run "Extract missing icons" (force: false)
# This downloads the APK, extracts the launcher icon, and auto-commits.
# 5. Go to GitHub Actions — run "Update artifact metadata" (force: false)
# This downloads the APK, computes sha256 / size / package metadata, and auto-commits.After these steps, the app is live. RokidBrew pulls from:
https://raw.githubusercontent.com/Anezium/RokidBrew-Registry/main/dist/apps.v1.json
Rokid Nexus plugins use a separate source directory and generated feed. Every
change to a real plugins-nexus/<plugin-id>.json descriptor must include the
corresponding rebuilt feed in the same pull request:
node scripts/build-registry.mjs
git add plugins-nexus/<plugin-id>.json dist/nexus-plugins.v1.json
git commit -m "Update <plugin-name>"
git pushThe Nexus Store reads:
https://raw.githubusercontent.com/Anezium/RokidBrew-Registry/main/dist/nexus-plugins.v1.json
See plugins-nexus/README.md for the complete
descriptor, APK verification, and release-update workflow.
{
"id": "example-app",
"name": "Example App",
"category": "Utility",
"type": "glasses",
"version": "1.0.0",
"summary": "Short one-line summary.",
"description": "Longer detail shown in RokidBrew.",
"author": "Example Author",
"sourceUrl": "https://github.com/owner/repo",
"phoneRequired": false,
"artifacts": [
{
"target": "glasses",
"url": "https://github.com/owner/repo/releases/download/v1.0.0/example.apk"
}
]
}| Field | Notes |
|---|---|
id |
Unique slug. Use kebab-case (e.g. my-app). |
name |
Display name shown in RokidBrew. |
category |
AI, Navigation, Media, Games, Utility, Browser, Launcher, Translation, Learning, Shopping, Camera, Fitness, Experiment, Mobility, Music, Reader, Developer, Accessibility |
type |
glasses, phone, or combo (both phone and glasses APKs). |
version |
Human-readable version string. |
summary |
One-line description. |
description |
Longer description. Defaults to summary if omitted. |
phoneRequired |
true if the glasses-side APK needs a phone companion. |
artifacts |
Array of APK download objects (see below). |
| Field | Required | Notes |
|---|---|---|
target |
Yes | glasses or phone. |
url |
Yes | Direct APK download URL. |
sha256 |
No | Populated by the "Update artifact metadata" Action. |
sizeBytes |
No | Populated by the "Update artifact metadata" Action. |
packageName |
No | Populated by the "Update artifact metadata" Action. |
versionCode |
No | Populated by the "Update artifact metadata" Action. |
versionName |
No | Populated by the "Update artifact metadata" Action. |
| Field | Notes |
|---|---|
author |
Inferred from the GitHub repository owner if omitted. |
sourceUrl |
Inferred from the artifact download URL if omitted. |
iconAsset |
Filename in assets/icons/. Auto-populated by the icon extraction Action. |
iconUrl |
Remote URL for the icon. Auto-generated from the registry repo. |
screenshotAssets |
Array of filenames in assets/screenshots/. Add manually. |
screenshotUrls |
Remote URLs for screenshots. Auto-generated from the registry repo. |
listing.descriptionMarkdown |
Store-detail body shown in RokidBrew. Supports readable Markdown-style paragraphs, headings, and bullets. |
releases |
Store-detail changelog entries shown in RokidBrew. |
For "type": "combo", provide both a phone and glasses artifact:
"artifacts": [
{ "target": "glasses", "url": "..." },
{ "target": "phone", "url": "..." }
]All write workflows create or update pull requests against main. They do not
push registry changes directly to main.
| Trigger | Purpose |
|---|---|
Push to main |
Validates the manifest builds correctly. |
| Pull request | CI check. |
| Manual dispatch | Rebuild on demand. |
scripts/build-registry.mjs uses the main branch for generated raw asset URLs by default.
Override with ROKIDBREW_PUBLIC_BASE_URL or ROKIDBREW_PUBLIC_BRANCH only when
you intentionally need a non-production manifest.
Both generated feeds are committed artifacts. The build job reconstructs them
deterministically and fails when either dist/apps.v1.json or
dist/nexus-plugins.v1.json differs from the committed result. This prevents a
source descriptor from being merged without the Store-visible feed update.
Runs once per day and can also be triggered manually. It checks upstream APK sources, refreshes APK metadata, extracts missing icons, rebuilds the registry, and opens or updates a review PR. The maintenance PR includes both generated feeds, so it also repairs a Nexus feed that was left out of an earlier change.
The workflow is resilient by design: individual APK metadata or icon failures are reported in logs, but do not block unrelated app updates from being proposed.
Manual trigger for adding a new app from a GitHub URL.
Supported inputs:
- Normal GitHub repo, release, or release tag URL.
- EUNG SOFT
info.jsonURL, or a GitHub tree URL likedownload/RokidGlasses/<App>.
The workflow creates apps/<id>.json, adds future update rules, copies GitHub
release bodies into releases[], optionally uses OpenRouter only for the store
description fields, refreshes APK metadata, extracts the launcher icon, and opens
a PR. Screenshot import is best-effort only and checks a few likely folders:
screenshots, docs/screenshots, docs/images, assets/screenshots, images.
Manual trigger only. For every app in apps/*.json that is missing assets/icons/<app-id>.png:
- Downloads the first APK artifact (preferring glasses).
- Reads the launcher icon with
aapt dump badging. - Extracts a direct raster icon when available.
- Falls back to
apktool+rsvg-convertfor adaptive / vector launcher icons. - Opens or updates a PR with the generated icons and rebuilt manifest.
| Input | Value |
|---|---|
force: false |
Skip apps that already have an icon (normal use). |
force: true |
Regenerate all icons even if they already exist. |
Manual trigger only. Downloads every APK referenced in the registry and populates:
sha256— SHA-256 checksum of the APK.sizeBytes— File size in bytes.packageName— Android package name (from AndroidManifest).versionCode— Integer version code.versionName— Human-readable version name.
Opens or updates a PR with the updated apps/*.json and rebuilt manifest.
| Input | Value |
|---|---|
force: false |
Only fill in missing metadata (normal use). |
force: true |
Recompute all metadata even if already present (use after APK URL changes). |
Manual trigger for checking upstream APK sources without running the full daily maintenance pipeline. It opens a pull request when it finds newer artifacts.
Supported sources:
- Normal GitHub Releases: inferred automatically from existing
github.com/<owner>/<repo>/releases/download/...URLs. - Release buckets: use an app-level
updateblock to pin a release tag and match APK assets by regex. This is used foreung3392/eungsoft, where many apps live under the singleRokidGlassesApprelease. - Raw GitHub APK URLs: exact-file monitoring only. If the file at the current URL changes, the workflow refreshes checksum/package metadata, but it does not guess new filenames.
Example release-bucket rule:
"update": {
"source": "githubReleaseAssets",
"repo": "eung3392/eungsoft",
"release": "RokidGlassesApp",
"assets": [
{
"target": "glasses",
"match": "^EKReader_v(?<version>\\d+(?:\\.\\d+)*)\\.apk$"
}
]
}update rules are registry-maintenance metadata only. They are stripped from dist/apps.v1.json.
Screenshots are best-effort during the "Add app from GitHub URL" workflow. The workflow intentionally checks only a few likely folders and never blocks a PR if screenshots cannot be found. To add or fix screenshots manually:
- Place image files in
assets/screenshots/. - Reference them in the app JSON:
"screenshotAssets": ["my-app-1.jpg", "my-app-2.png"]
- Rebuild and push:
node scripts/build-registry.mjs git add assets/screenshots/ apps/*.json dist/apps.v1.json git commit -m "Add screenshots for <app-name>" git push
---
## Importing EUNG SOFT info.json
EUNG SOFT apps expose localized metadata in `download/RokidGlasses/<App>/info.json`.
The all-in-one "Add app from GitHub URL" workflow supports those URLs directly.
For local or manual refreshes, `import-eung-info.mjs` is a thin wrapper around
the same EUNG import module:
```bash
node scripts/import-eung-info.mjs \
https://github.com/eung3392/eungsoft/blob/main/download/RokidGlasses/EKMeta/info.json \
--category Utility
node scripts/build-registry.mjs
The importer maps:
| EUNG field | Registry field |
|---|---|
title.en |
name |
version |
version |
releaseDate |
publishedAt and latest release date |
shortDescription.en |
summary |
description.en |
description and listing.descriptionMarkdown |
control.en |
Appended to listing.descriptionMarkdown as usage/control notes |
updated[].en |
releases[].notes |
download[0] |
Current APK artifact URL |
images[] |
Downloaded to assets/screenshots/ and referenced as screenshotAssets |
For apps that use the same APK on phone and glasses, run with --type combo.
For one-off cleanup, use --id, --category, --phone-required, or --no-screenshots.
For apps that only have a README, use OpenRouter to generate a reviewable
store description from the README. GitHub Releases are copied mechanically into
releases[]; the AI does not rewrite changelogs.
OPENROUTER_API_KEY=... \
node scripts/generate-ai-listing.mjs rokid-scribe \
--repo Anezium/Rokid-Scribe \
--release-limit 5 \
--report .tmp/ai-listing-report.md
node scripts/build-registry.mjsThe AI part only writes:
summarydescriptionlisting.descriptionMarkdown
The script also copies GitHub release bodies into releases[] without asking the
model to summarize or rewrite them, and stores private maintenance metadata in
listingSource.
It does not update APK URLs, checksums, package names, icons, screenshots, or install targets. Those stay managed by the normal registry scripts and Actions.
To import only GitHub release changelogs without AI:
node scripts/import-github-releases.mjs rokid-scribe --limit 5
node scripts/build-registry.mjsSet the repository secret OPENROUTER_API_KEY, then run Generate AI listing
from the Actions tab. Run it from dev while testing. The workflow creates or
updates a PR branch named automation/ai-listing-<app-id> against the branch
where the workflow was started.
Useful inputs:
| Input | Notes |
|---|---|
app |
Required app id from apps/<id>.json. |
repo |
Optional owner/repo override if it cannot be inferred. |
readme_path |
Optional README path inside the repo. |
readme_ref |
Optional branch, tag, or SHA. |
model |
OpenRouter model, defaults to openai/gpt-6-luna. |
release_limit |
Number of GitHub Releases to copy into releases[]. |
dry_run |
Runs generation without creating a PR. |
1. Run "Add app from GitHub URL" for new apps
2. Review the generated PR
3. Run "Extract missing icons" → gets the icon
4. Run "Update artifact metadata" → gets sha256, package info
5. Daily registry maintenance opens PRs for new releases, metadata, and icons
6. (Optional) Add or adjust screenshots manually
Licensed under the Apache License, Version 2.0. See NOTICE for attribution.
Contributions are accepted under the same license (Apache-2.0, section 5) — no CLA required.