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

polycast-cli

v0.15.0

Published

Command-line client for Polycast — OTA localization for iOS

Downloads

60

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, capturing everything on screen, and shipping translations live.

Requires Node 18+.

npm install -g polycast-cli      # provides the `polycast` command
# or run without installing:  npx polycast-cli <command>

Quickstart (60 seconds)

polycast login                   # sign in (browser flow, or --token to paste a PAT)
polycast init                    # detect catalog + Xcode project, create the project, write polycast.json
polycast langs add ja es de      # enable languages — AI drafting starts, with live progress
polycast coverage                # capture every on-screen string, then draft it
polycast sync                    # push · publish --wait · pull — translations go live

Add the two integration touches init prints, build once so the plugin pushes your strings, and your app is live in four languages.

The two everyday commands

Almost all daily work is these two, in this order:

polycast coverage — get to full coverage. It plants the Text → PText shadow into any module missing it, discovers your custom display components in rounds (registering them so the scanner sees them), then runs an LLM pass over your source to catch what static parsing structurally can't — computed properties, enum cases, strings composed at runtime. Everything it finds is captured into the catalog and pushed, so the new strings start drafting. It repeats until a round finds nothing new. (converge is an alias — same command.)

polycast coverage                # capture everything, then draft it
polycast coverage --no-cache     # force the LLM to re-read EVERY file (not just changed ones)
polycast coverage --no-llm       # scanner rounds only, skip the LLM pass

The LLM pass caches by file content, so unchanged files cost nothing on the next run. --no-cache bypasses that cache and re-reads every file — and, in coverage, surfaces an extraction failure instead of silently skipping it, so you're never told "fully covered" when the LLM pass didn't actually run.

polycast sync — ship it. Runs push · publish --wait · pull end to end: pushes source strings, waits (with a live per-language dashboard) for drafting to finish, publishes drafts to the live CDN bundles, then pulls the published translations back so your bundled fallbacks stay fresh.

polycast sync                    # push · publish --wait · pull
polycast sync --fix              # also triage + apply runtime misses around the loop

So a normal change is just: polycast coverage && polycast sync.

Authentication — two credentials, on purpose

| Credential | Prefix | Used by | Where it lives | |---|---|---|---| | Admin token / PAT | pcadm_ / pcat_ | login, init, langs, coverage, publish, status, sync | 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 credential 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

init writes just what your project needs:

{
  "projectKey": "pc_live_8f2k...",
  "catalogPath": "App/Localizable.xcstrings"
}

The hosted endpoints are built into the CLI, the build plugin, and the SDK, so they never land in your repo. init also 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).

Self-hosting Polycast? Add an "endpoint" field pointing at your API and the CLI and build plugin use it instead of the default.

Command reference

Everyday

  • coverage (alias converge) — capture every on-screen string in rounds, then draft it. --no-cache re-reads every source file (and fails loud on an extraction error); --no-llm skips the LLM pass.
  • sync — the whole ship loop: push · publish --wait · pull. --fix triages runtime misses around it.
  • status — the project at a glance: coverage %, drafts pending, misses, dead-lettered jobs. Exit 1 on dead letters (CI health gate). --json.

Setup

  • login — sign in and store the admin credential (browser flow, or --token to paste a PAT). logout clears it. whoami shows orgs/roles.
  • init — detect catalog + Xcode project, create the project + key, write polycast.json. Idempotent: re-running verifies instead of recreating. Flags: --name, --catalog, --endpoint, --yes.
  • plugin — attach the build plugin to your targets (Package.swift or pbxproj). shadow — plant the Text → PText shadow into source modules.

Languages

  • langs — the coverage table for every enabled language.
  • langs add ja ko th / langs add all (App Store locale set) — enable languages; AI drafting starts immediately and is shown live per language. --no-wait returns at once (drafting continues in the background); --timeout <minutes> raises the wait ceiling.
  • langs remove th — disable languages (their bundles stop on next publish).

Strings

  • push — push new/changed source strings (what the plugin does on every build). Malformed / junk keys are skipped automatically.
  • pull — merge published translations into the catalog so binary fallbacks stay fresh. --locales ja,es to limit; --check exits 1 if the catalog is stale (CI guard). Never touches the source language.
  • publish [locales...] — promote drafts to live bundles, with a live per-language dashboard. --wait watches drafting finish first; --timeout <minutes> raises the wait ceiling. Needs-review strings stay unpublished and are called out.
  • prune [--apply] — list, then delete, junk catalog keys (empty artifacts, dangling fragments, corrupt printf formats). Dry-run by default.
  • gen --output <path> — type-safe Swift key constants; use with PText(L.paywall.title).

Health

  • doctor — every local + remote check with a one-line fix each: catalog parses · polycast.json valid · plugin attached · .polycast gitignored · project key authenticates · admin token valid · edge reachable · ETag/304.
  • lint — every literal accounted for, or the build fails — the all-text gate. --json.
  • extract [--apply] — the LLM source pass on its own (what coverage runs). --no-cache re-reads every file; --no-depth runs a single pass.
  • suggest [--apply] — find display components missing from scanCalls.
  • misses — runtime miss telemetry: keys devices requested that the bundle couldn't serve. --fix [--apply] triages them; --clear wipes rows.
  • audit [--locale en-XA] — walk screens in the pseudo-locale and report any untranslated text on screen.

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 --check

Only the project key ever goes in CI secrets; if polycast.json is committed, no secret is needed at all.

Troubleshooting

  • New on-screen text isn't getting translated → run polycast coverage (the LLM pass catches computed/composed strings the plugin's lexer can't see), then polycast sync. polycast coverage --no-cache forces a full re-read.
  • No strings after buildingpolycast 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 (or sync); 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 valid polycast.json. Doctor says which.