polycast-cli
v0.7.3
Published
Command-line client for Polycast — OTA localization for iOS
Maintainers
Readme
polycast-cli
The polycast CLI is the command-line client for Polycast — OTA
localization for iOS. It manages projects, languages, and publishing from
your terminal and CI. Your app's day-to-day string syncing is handled
automatically by the Xcode build plugin; the CLI is for setup, control,
and CI.
Requires Node 18+.
npx polycast-cli init # or: npm install -g polycast-cli → `polycast` # or: npm install -g polycastQuickstart (60 seconds)
npx polycast login # paste your org admin token
npx polycast-cli init # or: npm install -g polycast-cli → `polycast` # creates the project, writes polycast.json
npx polycast langs add ja pt-BR es # AI drafting starts immediately
npx polycast publish --wait # drafts → live bundlesAdd the two integration touches init printed, build once so the plugin
pushes your strings, and your app is live in four languages.
Authentication — two credentials, on purpose
| Credential | Prefix | Used by | Where it lives |
|---|---|---|---|
| Org admin token | pcadm_ | login, init, langs, publish, status | OS keychain (macOS) / ~/.config/polycast/token 0600 |
| Project key | pc_live_ / pc_test_ | push, pull, build plugin | polycast.json in your repo; safe for CI |
The project key can only submit source strings and read published
translations (which your app ships publicly anyway). The admin token can
enable languages, edit, and publish — it never goes in files or CI.
POLYCAST_ADMIN_TOKEN / POLYCAST_PROJECT_KEY env vars override for
headless use.
polycast.json
{
"endpoint": "https://api.polycast.dev",
"edgeEndpoint": "https://polycast-edge.mecurylab.workers.dev",
"projectKey": "pc_live_8f2k...",
"catalogPath": "App/Localizable.xcstrings"
}endpoint is the write path (ingest/admin — also what the build plugin
uses); edgeEndpoint is the public read path (pull, doctor). init
writes both and gitignores .polycast/ (local push state, shared
byte-for-byte with the Swift build plugin — digests are identical, so the
CLI and plugin never re-push each other's work).
Commands
login/logout— keychain-stored admin tokeninit— detect catalog + Xcode project, create project + key, write config. Idempotent: re-running verifies instead of recreating. Flags:--name,--catalog,--endpoint,--yeslangs— coverage table ·langs add ja ko th/langs add all(App Store locale set) /langs remove th. Adding shows the draft count and confirms (auto-yes with--yesorCI=true).push— manual string push (what the plugin does on every build)pull— merge published translations into the catalog so binary fallbacks stay fresh.--locales ja,pt-BRto limit;--checkexits 1 if the catalog is stale (CI guard). Never touches the source language; preserves Xcode's JSON formatting.publish [locales...]— promote drafts to live bundles.--waitpolls until drafting finishes first. Needs-review strings stay unpublished and are called out.status— the project at a glance; exit 1 if jobs are dead-lettered (CI health gate).--jsonfor scripts.doctor— every local + remote check with a one-line fix each: catalog parses · polycast.json valid · build plugin attached · .polycast gitignored · project key authenticates · admin token valid · edge reachable · ETag/304 round-trip.gen— type-safe Swift constants from the catalog (--output Sources/Generated/PolycastKeys.swift); use withPText(L.paywall.title).
All commands: --json where output is data, no prompts when CI=true
or --yes. Exit codes: 0 success · 1 actionable failure · 2 usage error.
CI recipes
# bake fresh fallbacks into every release, before xcodebuild archive
- run: npx polycast pull
env:
POLYCAST_PROJECT_KEY: ${{ secrets.POLYCAST_PROJECT_KEY }}
# or fail the build if fallbacks are stale
- run: npx polycast pull --checkOnly the project key ever goes in CI secrets; if polycast.json is
committed, no secret is needed at all.
Troubleshooting
- No strings after building →
polycast doctor; usual cause is the plugin missing from the target or a sandboxed network push (workaround:polycast push). - Translations not showing in the app → drafts aren't live until
polycast publish; devices refresh on foreground. - A translation looks wrong → edit via the admin API/dashboard grid (becomes human-locked), publish. Live in minutes.
- 401 → admin commands need
polycast login; push/pull need a validpolycast.json. Doctor says which.
