npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@byterm/agc-cli

v0.8.1

Published

Command-line interface for the AppGallery Connect API

Readme

agc — AppGallery Connect CLI

A command-line interface for the AppGallery Connect (AGC) API, built on @byterm/agc-sdk. Authenticates with a Service Account and prints either human-readable tables or clean, single-document JSON for scripts and agents.

Install

From the workspace root:

pnpm install
pnpm build                 # builds @byterm/agc-sdk then @byterm/agc-cli

Run it via node:

node packages/cli/dist/index.js --help

Or expose the agc binary on your PATH:

pnpm --filter @byterm/agc-cli exec npm link     # now `agc` works anywhere
# or during development, without building:
pnpm --filter @byterm/agc-cli dev -- app info 123     # runs via ts-node

Authentication

Most commands use Service Account auth. Create a developer-level Service Account in AGC (Users and permissions → API key → Connect API → Service Account), download its *.private.json credential file, and make it findable.

Credentials are resolved in this order (first hit wins):

  1. --credentials <path>
  2. $AGC_CREDENTIALS
  3. ./agc-credentials.json (current directory)
  4. ~/.agc/credentials.json

The CLI signs a short-lived PS256 JWT from the credential file and sends it as Authorization: Bearer …. Nothing is sent anywhere except the AGC API host.

pms and comments commands and report crash / report freeze are the exception: those endpoints reject Service Account JWTs (401 client token auth failed) and require API Client auth (OAuth2 client_credentials token exchange). Create an API Client in AGC (Users and permissions → API key → Connect API → API Client). Two hard-won requirements:

  • It must be team-levelproject = N/A. A project-scoped client gets 403 on every PMS call.
  • Its role must be administrator (administrator / account holder / APP administrator / operations per endpoint constraints).

API Client credentials are resolved in this order (first hit wins):

  1. --api-client <path>
  2. $AGC_API_CLIENT
  3. ./api-client.json (current directory)
  4. ~/.agc/api-client.json

pms, comments and the report crash / report freeze commands load only the API Client credentials (plus Service Account ones when also present); every other command needs only the Service Account file.

Keep the credential file secret. The repo .gitignore excludes *.private.json, agc-credentials.json, api-client.json, and .agc/.

Verify your setup:

agc auth whoami       # prints the sub-account the credentials authenticate as

Global options

These apply to every command and may appear before the subcommand:

| Flag | Description | Default | | --- | --- | --- | | -c, --credentials <path> | Path to the Service Account *.private.json file | (see resolution order) | | --api-client <path> | Path to the API Client credentials JSON (required by pms commands) | (see resolution order) | | -s, --site <site> | Region: CN | DE | SG | RU, or an explicit base URL | CN | | --json | Emit JSON instead of formatted tables | off | | --envelope | Wrap JSON output as { ok, data } / { ok, error } (implies --json) | off | | --no-mask | Do not redact sensitive values (see Masking) | masking on | | -v, --verbose | Log each HTTP request to stderr | off | | --timeout <seconds> | Per-request timeout | 60 | | -V, --version | Print the CLI version | | | -h, --help | Show help for the program or a command | |

The --site domain must match the project's configured data-processing location:

| Site | Domain | | --- | --- | | CN | connect-api.cloud.huawei.com | | DE | connect-api-dre.cloud.huawei.com | | SG | connect-api-dra.cloud.huawei.com | | RU | connect-api-drru.cloud.huawei.com |

Output modes

Human mode (default) renders tables and short status lines, e.g.:

$ agc app appid com.example.app
┌─────────┬─────────────────────┐
│ appName │ appId               │
├─────────┼─────────────────────┤
│ Term    │ 1234567890 │
└─────────┴─────────────────────┘

JSON mode (--json) prints the AGC API response as exactly one JSON document — nothing else on stdout. This is the mode to use from scripts and agents:

$ agc app appid com.example.app --json
{
  "ret": { "code": 0, "msg": "success" },
  "appids": [ { "key": "Term", "value": "1234567890" } ]
}

Human mode may show a focused subset of columns for readability; --json carries every field of the response. Both modes redact sensitive values by default — see Masking below. Add --no-mask for the full, unredacted payload.

Envelope mode (--envelope, implies --json) wraps every document in a stable { ok, … } shape so an agent can branch on one field regardless of which command ran — success payloads differ per command, but ok never does:

$ agc app appid com.example.app --envelope
{ "ok": true, "data": { "ret": { "code": 0, … }, "appids": [ … ] } }

$ agc app info bad-id --envelope        # on failure
{ "ok": false, "error": { "error": "AgcApiError", "code": 204144641, "message": "…" } }

Without --envelope, --json keeps the raw contract (the API response as the top-level document); the exit code remains the definitive success/failure signal either way.

Masking sensitive data

To avoid leaking secrets and PII into terminals, logs, screenshots or an agent's context, the CLI redacts sensitive values by default in both human and JSON output. Pass --no-mask to disable it when you genuinely need the raw values.

What gets redacted:

| Category | Examples of fields / values | Result | | --- | --- | --- | | Secrets | token, access_token, client_secret, private_key, signature, apiKey; any JWT-shaped string | fully hidden → •••••• | | Signed URLs | signature-bearing query params (HW-CC-Sign, …Signature, …token, …key) | that param's value hidden, rest of the URL kept | | PII | email, phone/mobile, qqNum, idNumber, developerName*, appReviewName, entityName, account | partially hidden, keeping a short hint → te••••et, 11••••51 |

Non-sensitive identifiers you need for scripting are never masked — e.g. appId, versionId, packageId, projectId, ret.code, status/state fields, timestamps.

agc app info 1234567890 --json                 # developer name/email redacted
agc app info 1234567890 --json --no-mask        # raw values

The auth token command is exempt (its purpose is to emit a usable token), so it always prints the real JWT regardless of masking.

Exit codes

The exit code is the definitive success/failure signal — a shell-level agent can branch on it without parsing stdout:

| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Generic error (unexpected failure, or a non-auth HTTP status) | | 2 | Usage error — unknown command, or a bad/missing argument or option | | 3 | Authentication error — missing/invalid credentials, or HTTP 401/403 | | 4 | Network / transport error — the request never got an HTTP response (DNS, connection, timeout) | | 5 | AGC business error — a 2xx response with a non-zero ret.code |

On error:

  • Human mode prints ✗ <label>: <message> to stderr.
  • JSON mode prints one structured error document to stdout (wrapped in { ok: false, error } under --envelope):
{ "error": "AgcApiError", "code": 204144641, "message": "…", "response": { } }

Error error is AgcApiError (non-zero ret.code, includes code), AgcHttpError (network / non-2xx, includes status), an Agc*Error name such as AgcCredentialsError, or Error. Error response/body payloads are masked like any other output unless --no-mask is set.

The --data convention

Endpoints with a non-trivial request body take -d, --data, which accepts:

  • inline JSON-d '{"versionId":"123"}'
  • @file-d @body.json (reads JSON from a file)
  • --d - (reads JSON from stdin)

The value must be a JSON object. It is sent as the request body (or, for some read endpoints, as the query parameters — noted per command).


Command reference

Workflows

High-level commands that chain the individual API calls for the two common tasks. Both prepare by default and only submit with --submit — submitting sends the build to Huawei review. For the full step-by-step reference (step→API mapping, output shape, SDK equivalents, troubleshooting) see WORKFLOWS.md.

Each workflow runs two ways: from a typed config file (recommended) or from imperative flags.

# Config-driven: define once in .agc/release.ts, then:
agc release run                 # loads .agc/release.{ts,mjs,js,json}
agc release run --submit        # override the config
agc test run --submit

# Imperative (one-offs / CI):
agc release create <appId> <file> [flags]
agc test create <appId> <file> [flags]
// .agc/release.ts — typed config (autocomplete via defineRelease)
import { defineRelease } from '@byterm/agc-cli';
export default defineRelease({
  packageName: 'com.example.app',
  file: './build/entry.app',
  languages: {
    'zh-CN': { newFeatures: '修复若干问题' },
    'en-US': { newFeatures: 'Bug fixes', appDesc: '…' }, // appName/briefInfo also supported
  },
  review: { remark: 'Test guide for the review team…' }, // + testUserName/testUserPassword
  materials: {
    screenshots: { 'zh-CN': { 4: ['./store/1.png', './store/2.png'] } },
    introVideos: { 'zh-CN': { 4: [{ video: './store/v1.mp4', poster: './store/v1.png' }] } },
  },
  submit: false,
});

agc release run accepts --config <path>, --submit / --skip-submit, --release-time, and the compile-wait flags (--no-wait, --poll-interval, --wait-timeout, --initial-delay); agc test run accepts --config, --submit / --skip-submit. See WORKFLOWS.md → Config files for the full schema.

release validate / test validate — local config check

Validates a .agc/release.* / .agc/test.* config file locally — no AGC calls, no credentials needed. Catches schema mistakes (unknown keys, wrong types, malformed materials, mixed screenshot/video orientations, bad releaseTime format, missing appId/packageName, …) before a run hits the API.

agc release validate [--config <path>] [--strict]
agc test validate [--config <path>] [--strict]
  • Errors fail the command (exit 1): unknown keys, wrong types, bad material shapes, orientation conflicts, invalid releaseTime, etc.
  • Warnings don't fail it by default: files that don't exist on disk (resolved relative to the current working directory, like run does), unknown deviceType keys, submit: true without update notes, or appId + packageName both set. --strict promotes warnings to errors.
  • Keys starting with _ (e.g. _comment) are exempt from unknown-key checks.

Human mode prints one line per issue ( errors, ! warnings); --json prints { ok, errors: [{path, message}], warnings: [{path, message}] }.

release create <appId> <file> — production release

Runs: upload the package → bind it to the app → (config) update language/review/material infowait for AGC to compile/parse it → (with --submit) submit for review.

| Option | Description | | --- | --- | | --submit | Submit for review (otherwise stop after compile) | | --notes <text> / --notes-file <path> | Set update notes (newFeatures) before submit | | --notes-lang <lang> | Language for the notes (default: the app's default language) | | --release-time <t> | Scheduled release time (UTC yyyy-MM-ddTHH:mm:ssZZ) | | --name <fileName> | Override the uploaded file name | | --cn-mainland <0\|1> | chineseMainlandFlag | | --no-wait | Skip the compile wait | | --initial-delay <s> | Wait before the first compile poll (AGC advises ~120) | | --poll-interval <s> | Seconds between polls (default 15) | | --wait-timeout <s> | Max seconds to wait (default 600) | | -d, --data <json> | Extra fields merged into the submit body |

# Prepare only (upload + bind + wait for compile) — safe, no review submission:
agc release create 1234567890 ./app.app --initial-delay 120

# Full release, scheduled:
agc release create 1234567890 ./app.app --submit \
  --release-time 2026-08-01T00:00:00+0800

Progress streams to stderr; the final summary (objectId, packageId, compileState, submitted) prints to stdout — one JSON object under --json. On a compile failure or timeout the command exits non-zero.

test create <appId> <file> — test version

Runs: create a test version → upload the package → attach it → (with --submit) submit the test version.

| Option | Description | | --- | --- | | --submit | Submit the test version (otherwise stop after attaching) | | --release-type <n> | Release type (default 6 = HarmonyOS test) | | --test-type <n> | Test type (e.g. 3) | | --desc <text> | Version description | | --distribute-mode <n> | Package distribution mode (default 1) | | --name <fileName> / --cn-mainland <0\|1> | Upload overrides |

agc test create 1234567890 ./app.app --desc "beta build"
agc test create 1234567890 ./app.app --desc "beta build" --submit

Inviting testers is a separate step — see test below.

Permissions: the Testing API requires the Service Account's role to grant testing access. If calls return 205524993 "client token auth failed", the account has API access but not for that API group — grant the role in AGC.

auth

Authentication helpers. No network calls except as noted.

| Command | Description | | --- | --- | | auth whoami | Print the sub-account the current credentials authenticate as | | auth token | Generate and print a Service Account JWT bearer token (human mode prints just the token; --json adds the sub-account) |

agc auth whoami
agc auth token                     # e.g. for use with curl
export TOKEN=$(agc auth token)

app (Publishing)

Manage app info, versions, packages and the release lifecycle.

| Command | Args / Options | Description | | --- | --- | --- | | app info <appId> | -l, --lang <lang>, --release-type <n>, --version-id <id> | Query app information (basic info + languages) | | app appid <packageName> | --types <types> | Resolve package name(s) → appId (comma-separated, max 50) | | app versions | -a, --app-id <id>, -p, --package-name <name>, -s, --state <state> | List versions across all types (appId and/or packageName) | | app package-info <appId> <packageId> | | Query package information | | app compile-status <appId> <pkgIds> | | Poll compile status for package id(s) (comma-separated) | | app submit <appId> | --release-time <t>, -d, --data <json>, -y, --yes | Submit the app for review / publishing | | app cancel-review <appId> <versionId> | -y, --yes | Withdraw a version from review | | app off-shelf <appId> | -r, --reason <r>, --release-type <n>, -y, --yes | Take a published app off the shelf | | app update-info <appId> | -d, --data <json> (required) | Update basic app info | | app update-package <appId> | -d, --data <json> (required) | Bind an uploaded package file to the app version | | app update-language <appId> | -l, --lang, --notes, --notes-file, --name, --desc, --brief, -d, --data | Update localized info / update notes (newFeatures) for one language | | app update-files <appId> | -d, --data <json> (required) | Bind uploaded images/videos (icon, screenshots, …) to the listing |

# Read-only
agc app info 1234567890 --lang zh-CN
agc app appid com.example.app,com.example.other
agc app versions --app-id 1234567890 --state 1
agc app compile-status 1234567890 10004151

# Release lifecycle
agc app submit 1234567890 --release-time 2026-01-01T00:00:00+0800
agc app cancel-review 1234567890 155236000
agc app off-shelf 1234567890 --reason "temporary maintenance"

# Updates (body from --data)
agc app update-info 1234567890 -d '{"defaultLang":"zh-CN"}'
agc app update-package 1234567890 -d '{"fileName":"app.app","objectId":"CN/…/x.app"}'

release-type values: 1 = full network, 6 = HarmonyOS test (requires --version-id).

upload

Upload a file to the AGC file server and print its objectId (which you then pass to app update-package). The bytes are streamed to a pre-signed URL AGC returns; the SDK computes the SHA-256 and sends the correct length.

agc upload <appId> <filePath> [--name <fileName>] [--cn-mainland <0|1>]

agc upload 1234567890 ./app.app
# ✓ File uploaded.
# objectId  CN/2026…/xxxx.app

--cn-mainland sets chineseMainlandFlag (required when the developer is registered outside mainland China).

Provisioning

Devices, signing certificates, provisioning profiles, and app-id creation.

| Command | Args / Options | Description | | --- | --- | --- | | key gen | -a, --alias, -o, --out <p12>, --csr-out, --cn/--ou/--o/--c, --validity <days>, --password, --force | Generate an EC key pair (.p12) + CSR locally via keytool (no AGC call) | | device list | -n, --name, --from <n>, --max <n>, --order <n> | List registered test devices | | device add | -d, --data <json> (required) | Batch add devices | | cert list | --type debug\|release, --ids a,b,c, -d, --data <json> | Query certificates | | cert apply | --name, --type debug\|release, --csr <file>, --out <file>, --force, -d, --data <json> | Apply for a signing certificate; --out downloads the .cer | | cert delete | --ids a,b,c (required), -y, --yes | Delete signing certificates (asks for confirmation) | | profile list | --app-id <id> (required), --id <provisionId>, --from <n>, --max <n>, -d, --data <json> | List provisioning profiles | | profile apply | --name, --type debug\|release, --app-id, --cert-id, --device-ids a,b, --acl a,b, --out <file>, --force, -d, --data <json> | Apply for a provisioning profile; --out downloads the .p7b | | profile delete | --id <provisionId> (required), -y, --yes | Delete a provisioning profile (asks for confirmation) | | profile devices | --id <provisionId>, --device-ids a,b (both required) | Update the test devices bound to a profile | | create-appid | --project-id, --name, --package-name, --parent-type, --installation-free | Create an APP ID under a project |

agc device list --name test --max 50 --order 1
agc create-appid --project-id 10059 --name "My App" \
  --package-name com.example.app --parent-type 13 --installation-free 0

device list sort --order: 1 = create-time desc, 2 = name asc. create-appid: --parent-type 2=game / 13=app; --installation-free 0=HarmonyOS app / 1=atomic service.

For cert apply / profile apply / cert list / profile list, the typed flags and -d, --data are mutually exclusive — --data is the raw escape hatch (its value is sent to the API unchanged).

Signing materials, end to end

The full local-key → certificate → profile flow, ready for a HarmonyOS build-profile.json5:

# 1. Generate the EC key pair (.p12) and CSR locally (keytool; password via
#    --password, $AGC_KEY_PASSWORD, or a hidden prompt):
agc key gen --alias myapp --out myapp.p12 --cn "My App"

# 2. Apply for a certificate and download it:
agc cert apply --name myapp --type release --csr myapp.csr --out myapp.cer

# 3. Apply for a provisioning profile (cert id from `agc cert list`) and
#    download it. A `debug` profile also needs `--device-ids` (ids from
#    `agc device list`) — the API rejects a debug profile with no devices:
agc profile apply --name myapp --type release --app-id 1234567890 \
  --cert-id 123456 --out myapp.p7b

Then reference the three files in build-profile.json5 signingConfigs (certpath.cer, storeFile.p12, profile.p7b).

key gen runs entirely locally — it needs no credentials, only a JDK's keytool (DevEco Studio and the HarmonyOS command-line tools ship one).

test (Testing)

Test versions, groups and invitation codes. All take <appId>. For the end-to-end version flow use the test create workflow above; the commands here are the individual steps.

| Command | Args / Options | Description | | --- | --- | --- | | test create <appId> <file> | (workflow — see above) | Create version + upload + attach [+ submit] | | test new-version <appId> | -d, --data <json> (required) | Create a test version (returns versionId) | | test add-package <appId> <file> | --distribute-mode <n>, --name, --cn-mainland | Upload a package and attach it to the draft version | | test submit <appId> <versionId> | -y, --yes | Submit a test version for review | | test stop <appId> | -d, --data <json> (required), -y, --yes | Stop a test version | | test update <appId> | --version-id, --pkg-id, --desc, --countries, -d, --data | Update a (non-live) test version | | test delete-version <appId> | --version-id, -d, --data, -y, --yes | Delete a test version | | test detect-report <appId> | --version-id (required) | Query the listing self-check report | | test open-test <appId> | --version-id, --start <ms>, --end <ms>, --install-limit <n>, --group-ids a,b, -d, --data | Update an open test's window / quota / group bindings | | test promote <appId> | --version-id, --type full\|phased, --release-time <ms>, --phased-start/--phased-end/--phased-percent/--phased-desc, -d, --data, -y, --yes | Promote the active test version to a full/phased release | | test groups <appId> | -d, --data <json> | List test groups | | test create-group <appId> | -d, --data <json> (required) | Create a test group | | test delete-group <appId> | --group <groupId>, -d, --data, -y, --yes | Delete a test group | | test members <appId> | --group, --account, --nick-name, --add-way, --order-add, --order-install, --page, --page-size, -d, --data | List test group members | | test add-members <appId> | --group, --account, --nick-name, -d, --data | Add a member to a test group (one per call) | | test remove-members <appId> | --group, --tester-ids a,b, -d, --data, -y, --yes | Remove members from a test group | | test notify <appId> | --group, --tester-ids a,b, -d, --data | Send test invitation notifications | | test invite <appId> | -d, --data <json> (required) | Generate an invitation code | | test invite-code <appId> | --group <groupId> (required) | Query a group's invitation code(s) | | test stop-code <appId> | --code-id <id>, -d, --data, -y, --yes | Stop an invitation code |

Typed flags and -d, --data are mutually exclusive — --data is the raw escape hatch (its value is sent to the API unchanged). Times are epoch milliseconds unless noted.

# Manual, step by step:
vid=$(agc test new-version 1234567890 -d '{"releaseType":6,"testType":3,"testDesc":"beta"}' --json | jq -r .versionId)
agc test add-package 1234567890 ./app.app --distribute-mode 1
agc test submit 1234567890 "$vid" --yes

# …or all at once with the workflow:
agc test create 1234567890 ./app.app --desc beta --submit

report (Reports)

Quality metrics and analytics export files.

| Command | Args / Options | Description | | --- | --- | --- | | report crash <appId> | --package-name <name>, --start <t>, --end <t>, -d, --data | Crash metrics (API Client auth) | | report freeze <appId> | (same as crash) | AppFreeze (ANR) metrics (API Client auth) | | report analytics | -d, --data <json> (required) | Analytics report metric data | | report export <kind> | -d, --data <json> (required) | Export file URL; <kind> = user | download | install-failed | distribute | voc |

--start / --end accept epoch milliseconds or an ISO date (e.g. 2026-01-01 or 2026-01-01T00:00:00Z), which the CLI converts to epoch ms. Add filters via --data, e.g. {"filters":{"appVersions":["26.0.4"]}}.

The crash / freeze metric endpoints accept API Client auth only (Service Account JWTs are rejected with 401) and require both the appId argument and the --package-name header — see Authentication. They return aggregate metrics per crash type (JS_ERROR / CPP_CRASH / OOM / PROCESS_KILL) with per-fingerprint summaries (count, affected devices, first/last time, version range); stack traces are not exposed by the API. The analytics / export endpoints use Service Account auth like the rest of the CLI.

agc report crash 1234567890 --package-name com.example.app \
  --start 2026-01-01 --end 2026-01-08 --json
agc report crash 1234567890 --package-name com.example.app \
  --start 2026-01-01 --end 2026-01-08 \
  -d '{"filters":{"appVersions":["26.0.4"],"osVersions":["5.0.0"]}}'
agc report export download -d '{"appId":"1234567890","startDate":"20260101","endDate":"20260108"}'

comments (Store reviews & ratings)

Query store reviews and rating stats, and reply to reviews. All endpoints require API Client auth (Service Account JWTs are rejected with 205524993 client token auth failed) — see Authentication. The caller role must be the account holder or a team member granted 管理评论 / 查看评论.

| Command | Args / Options | Description | | --- | --- | --- | | comments list <appId> | --countries (default CN), --start, --end, --keyword, --ratings, --versions, --reply-states, --langs, --sort, --page, --limit, -d, --data | List store reviews | | comments ratings <appId> | --countries, --start, --end, --page, --limit | Rating stats per country + rating-only entries | | comments detail <reviewId> | --app-id (required) | Single review detail, incl. reply thread | | comments reply <reviewId> | --app-id, --country, --lang, --content, --to-reply-id, -d, --data, -y, --yes | Publish a public reply (confirm-guarded) |

--start / --end accept epoch milliseconds or an ISO date and default to the last ~180 days; the API caps any query window at 180 days (error 50010034 beyond that). --reply-states: 0 unanswered, 1 answered, 6 user follow-up, 3 follow-up answered.

agc comments list 1234567890 --limit 20
agc comments list 1234567890 --ratings 1,2 --reply-states 0   # bad reviews, unanswered
agc comments ratings 1234567890 --countries CN
agc comments reply 3211... --app-id 1234567890 --country CN --lang zh \
  --content "感谢反馈,已修复,敬请期待下个版本!"

domain (Domain Management)

Business-domain configuration for atomic services (元服务).

| Command | Options | Description | | --- | --- | --- | | domain get | -d, --data <json> (required) | Query domain configuration (params via --data) | | domain set | -d, --data <json> (required) | Create/update domain configuration | | domain pre-check | -d, --data <json> (required) | Pre-check a business-domain configuration | | domain limits | -d, --data <json> (required) | Query modification count / config limits |

agc domain get -d '{"appId":"1234567890"}'
agc domain set -d @domain-config.json

pms (Product Management)

IAP digital-product management for HarmonyOS apps: subscription groups, products (consumables, auto-renewing subscriptions, …) and promotions (free trials, introductory prices, …). Every command takes the appId (sent as a header). PMS requires API Client credentials — Service Account JWTs are rejected with 401; see Authentication for the resolution order and the team-level (project = N/A) + administrator-role requirements. All write commands ask for confirmation (pass -y to skip) and auto-generate the requestId (override with --request-id). Complex payloads go through --data (inline JSON, @file.json, or - for stdin).

| Command | Options | Description | | --- | --- | --- | | pms group create <appId> | --name <name> · --status <s> · -d · -y | Create a subscription group | | pms group update <appId> <groupId> | --name <name> · -d · -y | Update a subscription group | | pms group list <appId> | --page · --size · --order-by <json> | List subscription groups | | pms group level <appId> <groupId> | -d (required) · -y | Update subscription group levels | | pms product create <appId> | -d (required) · -y | Create one product (ProductInfo) | | pms product batch-create <appId> | -d '{"products":[…]}' (required) · -y | Batch-create products | | pms product get <appId> | --product-no / --product-id · --country | Query one product's details | | pms product list <appId> | --country (required) · filters · paging | Query products by conditions | | pms product update <appId> | -d (required) · -y | Update one product | | pms product batch-update <appId> | -d '{"products":[…]}' (required) · -y | Batch-update products | | pms product activate <appId> <nos...> | -y | Batch-activate (inactive → online) | | pms product deactivate <appId> <nos...> | -y | Batch-deactivate (online → off sale) | | pms product check <appId> | — | Does the app have any active product? | | pms product review <appId> <ids...> | -y | Submit products for review (≤20 system IDs) | | pms promotion create <appId> | -d (required) · -y | Create a promotion | | pms promotion update <appId> | -d (required, needs promotionId) · -y | Update a promotion | | pms promotion get <appId> <promotionId> | — | Query one promotion's details | | pms promotion list <appId> | filters · paging | Query promotions by conditions | | pms promotion activate <appId> <ids...> | -y | Batch-bring promotions online (≤100) | | pms promotion deactivate <appId> <ids...> | --immediate-end · -y | Batch-take promotions offline (≤100) | | pms app-types <appId> | --purchase-type <types> (required) | Which product types the app already has |

# Create a subscription group, then a monthly auto-renewing subscription in it
agc pms group create 1234567890 --name vip --yes
agc pms product create 1234567890 -d @monthly.json --yes
# Free-trial promotion for a subscription product
agc pms promotion create 1234567890 -d @trial.json --yes
# List everything on sale, machine-readable
agc pms product list 1234567890 --country CN --status active --json

A minimal monthly.json (subscription products need subGroupId, subPeriod and subPeriodUnit, and productNo/purchaseType are immutable after creation):

{
  "productNo": "vip_monthly",
  "productName": "VIP 月卡",
  "purchaseType": "auto_subscription",
  "subGroupId": "<groupId from group create>",
  "subPeriod": 1,
  "subPeriodUnit": "M",
  "currency": "CNY",
  "country": "CN",
  "defaultLocale": "zh_CN",
  "defaultPrice": "1800",
  "productDesc": "VIP 月度订阅",
  "salesCountry": ["CN"]
}

New products must be submitted for review before they take effect: agc pms product review <appId> <productId> (the system-generated id from pms product get, not your productNo).


Scripting & agents

--json guarantees a single parseable document per invocation, and the exit code reflects success. A robust pattern:

# Resolve a package name to a bare appId
appId=$(agc app appid com.example.app --json | jq -r '.appids[0].value')

# Fetch app info, failing the script on any error
if ! info=$(agc app info "$appId" --json); then
  echo "lookup failed" >&2; exit 1
fi
echo "$info" | jq -r '.appInfo.versionNumber'

Notes for agents:

  • Always pass --json; parse stdout as one JSON object.
  • Check the process exit code (0 = ok). On failure, stdout holds { "error", "message", … } and (for API errors) a numeric code.
  • Even on success, inspect ret.code when present — the CLI already treats a non-zero ret.code as an error, but downstream data lives alongside ret.
  • Use --verbose to trace the exact HTTP requests on stderr (does not pollute the JSON on stdout).
  • Destructive commands (app submit, app cancel-review, app off-shelf, test submit, test stop, cert delete, profile delete) ask for confirmation on a TTY; in --json or other non-interactive use they refuse unless you pass -y, --yes.
  • Output is masked by default. Identifiers used for scripting (appId, versionId, packageId, projectId, states, timestamps) are not masked, so most pipelines work unchanged. Add --no-mask only when you specifically need a redacted value (a developer email, a signed download URL, etc.).

See also

  • @byterm/agc-sdk — the programmatic client the CLI is built on.
  • Workspace README — overview and build instructions.