CLI and SDKs
Status. The CLI and both clients exist in the repository (
tools/cli,packages/sdk-js,src/ResilientLang.Client). None is published to npm or NuGet, and there is no default API address because the domain is undecided: you always pass--api-urlorRL_API_URL.
The rl command line#
Zero dependencies, Node 18.17 or newer. From the repository: node tools/cli/bin/rl.mjs help.
printf %s "$RL_SECRET_KEY" | rl login --api-url https://api.example --key-stdin
rl sites create --name Shop --source en --targets fr,de
rl push strings.json --site <id> # --dry-run works offline
rl translate --wait && rl publish --wait
rl export --format xliff --out backup.xlf
| Command | What it does |
|---|---|
login, logout, whoami | Store, remove and show the credentials (key from stdin or RL_API_KEY) |
doctor | Read-only check of the key, API URL, site, scopes, allowance and the signature of the published manifest: --offline (no network), --json. Exit 0 unless a check fails (3 auth, 5 plan, 6 unavailable, otherwise 1) |
sites | list, get, create, update |
push FILE | Send source strings: a JSON array, {"items":[...]} or one string per line; - reads stdin; --dry-run |
pull | Bundle mode (default): download and verify the published bundle |
pull --translations | API mode: write <lang>.json with {key: text} from the API |
translate | Machine-translate missing strings: --lang, --force, --wait |
scan | Crawl pages: --url (repeatable) and --sitemap, --wait |
publish | Build and publish: --always, --wait |
jobs | get ID, wait ID [--timeout seconds] |
export | Download everything you own: --format json|xliff|xliff2|po|pot|csv|tmx, --lang, --out |
import FILE | Upload translations: the export file, a [{key, lang, text, status?}] array, or xliff, xliff2, po, csv, tmx, android, messages-json or keyvalue-json (auto-detected). Flags: --format, --lang, --reference FILE, --status machine|reviewed|manual, --dry-run |
quota | Plan allowance and where you stand this period (GET /v1/usage/quota) |
usage | Strings, characters and engine cost: --from, --to |
glossary | get, put FILE.json |
keys | list, create --name N --scopes a,b, rotate ID [--grace s], revoke ID |
Global options: --site ID (else RL_SITE, else .resilientlang.json), --api-url URL, --json, --help. Environment: RL_API_KEY, RL_API_URL, RL_SITE, RL_CONFIG_DIR, RL_BASE, RL_PUBLIC_KEY, RL_SITE_KEY. Exit codes: 0 ok, 1 error, 2 usage, 3 not authenticated or not allowed (401 or 403), 4 a job you waited for failed or timed out, 5 a plan, allowance or licence limit (402), 6 service unavailable or rate limited (429, 502, 503, 504 or a network error): try again later.
rl pull in bundle mode#
Bundle mode needs no API key and never sends one. It fetches the static files from the delivery origins and verifies them with the loader's rules: a mandatory Ed25519 signature over the canonical manifest, the kid, the SHA-256 of each file, and rollback protection. The result is a folder (./bundle by default) holding manifest.json and <version>/<lang>.<hash8>.json, which is a complete offline copy you can host yourself.
rl pull --base https://cdn.example/ --public-key <ed25519-base64url> --site-key rl_site_live_... --lang fr,de --out bundle
There is no default origin; pass --base (or RL_BASE).
Key handling#
The key is read from stdin or RL_API_KEY (passing --key prints a warning). Credentials are stored in a file readable only by you under $RL_CONFIG_DIR, $XDG_CONFIG_HOME/resilientlang or ~/.config/resilientlang. All output is redacted of rl_sec_ values. A .resilientlang.json project file is refused if it contains a key, so it is safe to commit.
JavaScript SDK#
@resilientlang/sdk, zero dependencies, Node 18.17 or newer.
import { ResilientLangClient } from '@resilientlang/sdk';
const rl = new ResilientLangClient({ baseUrl: process.env.RL_API_URL, apiKey: process.env.RL_API_KEY });
const site = await rl.sites.create({ name: 'Shop', sourceLanguage: 'en', targetLanguages: ['fr'] });
await rl.strings.submitAll(site.id, [{ text: 'Add to cart' }]);
const { jobs } = await rl.translate(site.id);
await rl.jobs.wait(jobs[0].id);
await rl.publish(site.id);
The key is sent only to baseUrl (https, or http on localhost), redirects are never followed, requests time out, 429 is retried honouring Retry-After, and other retries happen only where repeating is safe. @resilientlang/sdk/testing provides an in-memory mock server for offline tests. The SDK's own tests fail when openapi.json gains an operation without a client method.
Python, PHP and Go#
Clients for these three languages exist too (WP-54, not yet merged or published): see Python, PHP and Go SDKs.
.NET client#
ResilientLang.Client: services.AddResilientLangClient(configuration) binds the ResilientLang:Client section (BaseUrl, ApiKey from user secrets or environment, Timeout, MaxRetries), validates at start and disables redirects.
Both clients cover the control-plane operations in the API reference. They do not yet cover webhooks, audit, billing, licensing or team routes, which are not in the OpenAPI file.