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

@intlpullhq/cli

v0.2.0

Published

The official CLI for IntlPull - intelligent i18n for modern apps. Manage translations, sync with cloud, and automate localization workflows.

Readme


Table of Contents

| Section | Description | |---------|-------------| | Features | Key capabilities of the CLI | | Installation | How to install the CLI | | Quick Start | Get started in 4 commands | | Authentication | Login, API keys, and auth methods | | Commands Reference | All available commands | | ↳ Initialize | Set up IntlPull in your project | | ↳ Upload | Upload translation keys | | ↳ Download | Download translations | | ↳ Sync | One-time sync for CI/CD | | ↳ Listen / Watch | Real-time sync during dev | | ↳ Import / Export | Bulk import/export translations | | ↳ OTA Releases | Over-the-air updates | | ↳ Migration | Migrate from other platforms | | ↳ Project Management & Tools | Additional CLI features (keys, tm, etc.) | | CI/CD Integration | GitHub Actions, GitLab CI, Docker | | Configuration | Project config and output patterns | | ↳ Output Patterns | Namespace file structures | | ↳ iOS String Tables | Multiple .strings files (Localizable, Settings, etc.) | | ↳ Android Multi-XML | Multiple XML files (strings.xml, strings_settings.xml) | | ↳ Advanced Config | sources/targets mappings for complex setups | | Tips & Best Practices | Recommended usage patterns | | Support | Get help |


Features

  • Parallel Downloads - Fetch translations by namespace concurrently for blazing fast syncs
  • Real-time Sync - Watch for changes and auto-update local files
  • Auto-detect Project - Automatically finds .intlpull.json in parent directories
  • Multiple Output Formats - JSON, YAML, TypeScript, Android XML, iOS Strings
  • CI/CD Ready - Full non-interactive mode support for automation pipelines (no TTY required)
  • OTA Releases - Publish over-the-air updates for mobile/web SDKs
  • Enterprise Workflows - Approval workflows for translation review
  • Migration Tools - Migrate from Lokalise, Crowdin, Phrase, or local files

Installation

# Use with npx (recommended)
npx @intlpullhq/cli <command>

# Or install globally
npm install -g @intlpullhq/cli
intlpull <command>

Quick Start

# 1. Authenticate
npx @intlpullhq/cli login

# 2. Initialize project
npx @intlpullhq/cli init

# 3. Push your translation keys
npx @intlpullhq/cli upload

# 4. Download translations
npx @intlpullhq/cli download

Authentication

# Interactive login (prompts for token)
npx @intlpullhq/cli login

# With API token (warns about shell history)
npx @intlpullhq/cli login --token <your-api-key>

# Or use environment variable (recommended for CI/CD)
export INTLPULL_API_KEY=your-api-key

# Check current auth status
npx @intlpullhq/cli whoami

# Logout
npx @intlpullhq/cli logout

Auth priority: Environment variable (INTLPULL_API_KEY) > Config file (~/.intlpull/auth.json)

Commands Reference

Global Options

| Option | Description | |--------|-------------| | --env-file <path> | Path to custom env file (e.g., .env.production) | | -V, --version | Output version number | | -h, --help | Display help |


Initialize Project

Set up IntlPull in your project with auto-detection.

# Interactive setup
npx @intlpullhq/cli init

# With options
npx @intlpullhq/cli init --framework next --library next-intl --output ./messages

# Non-interactive (auto-detect everything)
npx @intlpullhq/cli init -y

# Link to existing project
npx @intlpullhq/cli init --project <project-id>

Options: | Option | Description | |--------|-------------| | --framework <framework> | Framework: next, react, vue, svelte, astro | | --library <library> | i18n library: next-intl, react-i18next, vue-i18n | | --output <dir> | Output directory for translation files | | --project <id> | Project ID to link | | -y, --yes | Auto-detect and initialize without prompts |


Upload

Upload translation keys to IntlPull. Automatically detects project, files, and git branch.

# Auto-detect and upload
npx @intlpullhq/cli upload

# Upload specific file
npx @intlpullhq/cli upload --file messages/admin.json

# Upload only source language
npx @intlpullhq/cli upload --source-only

# Preview without uploading
npx @intlpullhq/cli upload --dry-run

Options: | Option | Description | |--------|-------------| | --project <id> | Project ID (auto-detected with project-scoped API key) | | --file <path> | Specific file to upload (e.g., messages/admin.json) | | --branch <name> | Branch name (auto-detected from git, pushes to IntlPull branch) | | --platform <platform> | Platform to tag keys with (ios, android, web) | | --all-languages | Upload translations for ALL languages (default: true) (default: true) | | --source-only | Upload only source language keys (default: false) | | --dry-run | Preview without uploading (default: false) | | -v, --verbose | Show detailed detection info (default: false) | | -q, --quiet | Suppress output except errors (CI mode) | | --translation-key-prefix <prefix> | Prepend prefix to all keys (e.g., "checkout" makes "submit" → "checkout.submit") | | --apply-tm | Apply Translation Memory matches after pushing (default: false) | | --tm-threshold <n> | Minimum TM match score (default: 85) (default: "85") | | --tm-dry-run | Preview TM matches without applying (default: false) | | -h, --help | display help for command |


Download

Download translations from IntlPull. Uses parallel fetching by default.

# Auto-detect and download
npx @intlpullhq/cli download

# Specify format and output
npx @intlpullhq/cli download --format json --output ./messages

# Download specific languages
npx @intlpullhq/cli download --languages en,es,fr

# Download specific namespaces
npx @intlpullhq/cli download --namespace common,auth

# Download only approved translations (for production builds)
npx @intlpullhq/cli download --status approved

# Download translations pending review
npx @intlpullhq/cli download --status in_review

# Download only keys tagged with specific tags
npx @intlpullhq/cli download --tags ui,forms

# Combine workflow status and tags filters
npx @intlpullhq/cli download --status approved --tags marketing

# Quiet mode for CI
npx @intlpullhq/cli download --quiet

Options: | Option | Description | |--------|-------------| | --project <id> | Project ID (auto-detected with project-scoped API key) | | --format <format> | Output format (json|yaml|ts|ios|xcstrings|stringsdict|android|arb) | | --output <dir> | Output directory (auto-detected from framework) | | --languages <langs> | Languages to download (comma-separated, defaults to all) | | --namespace <namespaces> | Namespaces to download (comma-separated, defaults to all) | | --branch <branch> | Translation branch to download from | | --platform <platform> | Platform variant (default|ios|android|web) | | --status <status> | Filter by workflow status (draft|in_review|approved|rejected|published) | | --tags <tags> | Filter by tags (comma-separated). Only keys with matching tags are included | | --no-parallel | Disable parallel fetching (use single request) | | -i, --interactive | Run in interactive mode with prompts | | -q, --quiet | Suppress output except errors | | --clean-orphans [mode] | Remove orphaned files (files not in remote). Use "dry-run" to preview | | -f, --force | Skip confirmation prompts for destructive operations | | --translation-key-prefix <prefix> | Strip this prefix from keys (e.g., "checkout" makes "checkout.submit" → "submit") | | --filter-by-prefix <prefix> | Only download keys starting with this prefix | | --default-namespace <ns> | Namespace that maps to platform default file (Localizable.strings/strings.xml) | | --namespace-prefix <prefix> | Prefix for non-default namespace files (Android: "strings_") | | --table <mapping> | iOS String Table mapping (e.g., "common:Localizable,settings:Settings") | | --xml-file <mapping> | Android XML filename mapping (e.g., "common:strings,settings:strings_settings") | | --target <nameOrId> | Export to a specific GitHub target (alias for `export targets --target`) | | --all-targets | Export to all configured GitHub targets (alias for `export targets --all-targets`) | | -h, --help | display help for command |


Sync

One-time sync (equivalent to listen --once). Perfect for CI/CD.

# Quick sync
npx @intlpullhq/cli sync

# With options
npx @intlpullhq/cli sync --output ./locales --format json --languages en,es

# Quiet mode for CI
npx @intlpullhq/cli sync --quiet

Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | --output <dir> | Output directory | | --format <format> | Output format | | --languages <langs> | Languages to sync (comma-separated) | | --platform <platform> | Platform variant | | --quiet | Minimal output | | --no-parallel | Disable parallel fetching (use single request) | | -h, --help | display help for command |


Listen / Watch

Watch for translation updates and auto-sync to local files. Great for development.

# Start watching
npx @intlpullhq/cli listen

# Or use alias
npx @intlpullhq/cli watch

# With custom settings
npx @intlpullhq/cli listen \
  --output ./messages \
  --format json \
  --interval 5 \
  --timeout 300

# Sync once and exit
npx @intlpullhq/cli listen --once

Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | --output <dir> | Output directory (auto-detected from .intlpull.json) | | --format <format> | Output format | | --languages <langs> | Languages to sync (comma-separated) | | --branch <branch> | Translation branch | | --platform <platform> | Platform variant | | --interval <seconds> | Polling interval in seconds (default: "5") | | --timeout <seconds> | Auto-stop after N seconds (default: 300 = 5 min) | | --once | Sync once and exit (no watching) | | --quiet | Minimal output | | --no-parallel | Disable parallel fetching (use single request) | | -h, --help | display help for command |


Status

Show project status and translation progress.

npx @intlpullhq/cli status

Check & Fix

Check for and fix missing translations.

# Check for missing translations
npx @intlpullhq/cli check --source en --target es,fr,de

# Output report to file
npx @intlpullhq/cli check --output report.json

# Check and auto-fix
npx @intlpullhq/cli check --fix

# Auto-fix with preview
npx @intlpullhq/cli fix --source en --dry-run

# Fix specific languages
npx @intlpullhq/cli fix --target es,fr

Check Options: | Option | Description | |--------|-------------| | --source <lang> | Source language (default: en) | | --target <langs> | Target languages (comma-separated) | | --output <file> | Output report file | | --fix | Auto-fix missing translations | | --fail-on-missing | Exit with code 2 if translations are missing | | --output-format <format> | Output format: text or json (default: "text") |

Fix Options: | Option | Description | |--------|-------------| | --source <lang> | Source language (default: en) | | --target <langs> | Target languages (comma-separated) | | --dry-run | Preview without fixing |


Diff

Show what would change on upload/download.

npx @intlpullhq/cli diff --source en --target es

Options: | Option | Description | |--------|-------------| | --source <lang> | Source language | | --target <lang> | Target language to compare |


Drift

Reconcile three sources of truth — source code (keys referenced via t('…'), <FormattedMessage>, $t('…'), etc.), local translation files, and the TMS — and report (or clean up) keys that have drifted apart. Unlike diff (files ↔ TMS only), drift also scans your source code.

# Report only (read-only)
npx @intlpullhq/cli drift

# Machine-readable + CI gate (fail if code references keys that don't exist in the TMS)
npx @intlpullhq/cli drift --json --fail-on code-missing-tms

# Clean up truly-dead keys (asks you to type the count to confirm)
npx @intlpullhq/cli drift --prune-tms           # delete TMS keys absent from BOTH code and files
npx @intlpullhq/cli drift --prune-local         # delete local keys absent from BOTH TMS and code
npx @intlpullhq/cli drift --prune-tms=unused    # delete TMS keys not referenced in code
npx @intlpullhq/cli drift --prune-tms --dry-run # preview only

Buckets: | Bucket (--fail-on id) | Meaning | Action | |-------------------------|---------|--------| | code-missing-tms | Referenced in code, missing from TMS | Define/push the key (often a typo) | | tms-unused | In TMS, not referenced in code | Possibly dead → --prune-tms | | files-ahead | In local files, not in TMS | intlpull upload | | tms-ahead | In TMS, not in local files | intlpull download |

Options: | Option | Description | |--------|-------------| | --source <lang> | Source language (default: config or en) | | --scan-paths <globs> | Comma-separated globs to scan for key usage | | --exclude <globs> | Comma-separated globs to exclude from scanning | | --key-prefix <prefix> | Prefix to resolve namespace-relative code keys | | --ignore <regexes> | Comma-separated regexes of keys to ignore (e.g. dynamic keys) | | --strict-match | Exact namespace.key matching only (no fuzzy bare-key match) | | --project <id> | Project ID (auto-detected with a project-scoped API key) | | --branch <name> | Branch (default: git branch or main) | | --json | Machine-readable JSON output (report only) | | --fail-on <buckets> | Exit 2 if listed buckets are non-empty (comma list or any) | | --prune-tms [mode] | Delete drifted TMS keys: dead (default) or unused | | --prune-local [mode] | Delete drifted local keys: dead (default) or unused | | --dry-run | Preview deletions without applying | | --yes | Skip the interactive typed confirmation (required in CI) |

Cleanup is destructive. drift is read-only by default. A --prune-* flag shows the deletion list and asks you to type the exact count to confirm; in CI/non-TTY it refuses unless --yes is passed. dead mode (the default) only deletes keys absent from both other sources, so it never removes un-pushed-but-used keys.

Note: code scanning is regex-based and cannot resolve dynamic keys (t(`x.${id}`)) or useTranslations('ns') scoping. Use --key-prefix, --ignore <regex>, or --strict-match to tune results.


Import

Import existing translation files into IntlPull.

# Import from directory
npx @intlpullhq/cli import --path ./messages --format json

# Import with glob pattern
npx @intlpullhq/cli import --path ./locales --pattern "*.json"

# Preview import
npx @intlpullhq/cli import --path ./messages --dry-run

# Import to specific namespace
npx @intlpullhq/cli import --path ./messages --namespace admin

Options: | Option | Description | |--------|-------------| | --path <path> | Path to file or directory | | --pattern <pattern> | Glob pattern (e.g., *.json) | | --format <format> | File format: json, yaml, ts, ios, android (default: json) | | --project <id> | Project ID | | --language <code> | Target language (auto-detect if omitted) | | --namespace <name> | Target namespace (default: common) | | --branch <name> | Branch to import to | | --platform <platform> | Platform to tag keys: ios, android, web | | --dry-run | Preview without importing | | --update-existing | Update existing translations (default: true) | | --skip-existing | Skip if key already exists | | --detect-icu-plurals | Detect ICU plural syntax (default: true) |


Export

Export translations as a ZIP archive or directly to GitHub targets.

Export to File

# Export all as JSON
npx @intlpullhq/cli export file --format json --output ./translations.zip

# Export specific languages
npx @intlpullhq/cli export file --languages en,es,fr

# Export for mobile platforms
npx @intlpullhq/cli export file --format android --output ./android-strings.zip
npx @intlpullhq/cli export file --format ios --output ./ios-strings.zip

Options: | Option | Description | |--------|-------------| | --format <format> | Format: json, yaml, ts, android, ios, xliff, po, arb, stringsdict, xcstrings, csv | | --languages <langs> | Languages to export (comma-separated) | | --output <file> | Output file path | | --version <version> | Version to export | | --branch <branch> | Translation branch | | --platform <platform> | Platform variant (auto-sets --format) | | --project <id> | Project ID |

Export to GitHub Targets

# Export to a specific target
npx @intlpullhq/cli export targets --target web-frontend

# Export to all configured targets
npx @intlpullhq/cli export targets --all-targets

# Preview without pushing
npx @intlpullhq/cli export targets --all-targets --dry-run

Options: | Option | Description | |--------|-------------| | --target <nameOrId> | Specific target to export to | | --all-targets | Export to all configured targets | | --platform <platform> | Export to all targets for a platform (ios/android/web/flutter) | | --project <id> | Project ID | | --languages <langs> | Languages to export (comma-separated) | | --include-drafts | Include draft translations | | --dry-run | Preview without pushing to GitHub | | --json | Output results as JSON for CI/CD | | --concurrency <n> | Max parallel exports (default: 3) | | --commit-message <msg> | Custom commit message | | --pr-title <title> | Custom PR title | | -q, --quiet | Suppress output except errors |


OTA Releases

Publish and manage over-the-air releases for mobile/web SDKs.

# Publish new release
npx @intlpullhq/cli publish 1.2.0

# Auto-version
npx @intlpullhq/cli publish

# Preview without publishing
npx @intlpullhq/cli publish --dry-run

# List releases
npx @intlpullhq/cli releases list

# Delete a release
npx @intlpullhq/cli releases delete <releaseId>

Publish Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | --branch <branch> | Translation branch (auto-detected from git) | | --dry-run | Preview without publishing | | -q, --quiet | Only output version on success |

Releases Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | --limit <n> | Number of releases to show (default: 10) | | -q, --quiet | Machine-readable output |


Projects

Manage IntlPull projects.

# List all projects
npx @intlpullhq/cli projects list

# Create new project
npx @intlpullhq/cli projects create "My App" --languages en,es,fr

# Link directory to project
npx @intlpullhq/cli projects link <project-id>

Create Options: | Option | Description | |--------|-------------| | --source-language <lang> | Source language (default: en) | | --languages <langs> | Supported languages (comma-separated) |


Migration

Migrate from other platforms or local files.

Migrate Local Files

# Migrate from current directory
npx @intlpullhq/cli migrate files

# Migrate from specific path
npx @intlpullhq/cli migrate files ./locales

# With options
npx @intlpullhq/cli migrate files ./messages \
  --project "My App" \
  --source en \
  --pattern "*.json" \
  --dry-run

Options: | Option | Description | |--------|-------------| | --project <name> | Project name (prompts if not provided) | | --source <lang> | Source/base language (default: en) | | --namespace <name> | Namespace for keys (default: common) | | --pattern <glob> | File pattern (default: *.json) | | --concurrency <n> | Max parallel uploads (default: 5) | | --dry-run | Preview without importing | | -y, --yes | Skip confirmation prompts |

Migrate from Competitors

# Migrate from Lokalise
npx @intlpullhq/cli migrate from lokalise --api-key <key>

# Migrate from Crowdin
npx @intlpullhq/cli migrate from crowdin --api-key <key> --project-id <id>

# Migrate from Phrase
npx @intlpullhq/cli migrate from phrase --api-key <key>

# Preview migration
npx @intlpullhq/cli migrate from lokalise --api-key <key> --dry-run

Options: | Option | Description | |--------|-------------| | --api-key <key> | API key for source platform (required in CI/CD) | | --project-id <id> | Specific project to migrate | | --to <id> | Target IntlPull project ID | | --dry-run | Preview without importing |

Note: In non-interactive environments (CI/CD), the --api-key flag is required.

Workflows (Enterprise)

Manage approval workflows for translation review.

# Check workflow status
npx @intlpullhq/cli workflow status

# List pending approvals
npx @intlpullhq/cli workflow pending

# Approve a translation
npx @intlpullhq/cli workflow approve <translationId>
npx @intlpullhq/cli workflow approve <translationId> -m "Looks good!"

# Reject a translation (reason required)
npx @intlpullhq/cli workflow reject <translationId> -m "Needs revision"

Options: | Command | Options | |---------|---------| | status | --project <id> | | pending | --project <id> | | approve | --project <id>, -m, --comment <message> | | reject | --project <id>, -m, --reason <message> (required) |


Email Templates

Manage React Email template translations.

# Upload HTML email templates to IntlPull
npx @intlpullhq/cli emails upload --dir ./emails

# Download translations for email templates
npx @intlpullhq/cli emails download --output ./emails/translations --format json

# List templates
npx @intlpullhq/cli emails list

# Check status
npx @intlpullhq/cli emails status

Upload Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | -d, --dir <path> | Emails directory (default: ./emails) | | --dry-run | Preview without uploading |

Download Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | -o, --output <dir> | Output directory | | --languages <langs> | Languages to download (comma-separated) | | --format <format> | Output format: json, ts (default: json) |


Documents

Manage document translations (PDF, DOCX, etc.).

# List documents
npx @intlpullhq/cli documents list

# Upload document for translation
npx @intlpullhq/cli documents upload --file ./manual.pdf --target es,fr,de

# Download translated document
npx @intlpullhq/cli documents download --id <docId> --lang es --output ./manual-es.pdf

Upload Options: | Option | Description | |--------|-------------| | --file <path> | Path to file (required) | | --project <id> | Project ID | | --source <lang> | Source language | | --target <langs> | Target languages (comma-separated) |

Download Options: | Option | Description | |--------|-------------| | --id <docId> | Document ID (required) | | --lang <lang> | Target language (required) | | --project <id> | Project ID | | --output <path> | Output file path |


Zendesk Integration

Sync Help Center articles with Zendesk.

# Check integration status
npx @intlpullhq/cli zendesk status

# Connect to Zendesk
npx @intlpullhq/cli zendesk connect \
  --subdomain mycompany \
  --email [email protected] \
  --token <api-token>

# Pull articles from Zendesk
npx @intlpullhq/cli zendesk sync --direction pull

# Push translations to Zendesk
npx @intlpullhq/cli zendesk sync --direction push --locale es

# Disconnect
npx @intlpullhq/cli zendesk disconnect

Connect Options: | Option | Description | |--------|-------------| | --subdomain <subdomain> | Zendesk subdomain (required) | | --email <email> | Admin email address (required) | | --token <token> | Zendesk API token (required) |

Sync Options: | Option | Description | |--------|-------------| | --direction <direction> | Sync direction: pull, push (default: pull) | | --locale <locale> | Target locale (required for push) | | --dry-run | Preview without syncing |



Project Management & Tools

IntlPull CLI includes several commands for managing various aspects of your i18n workflow:

keys

Manage translation keys.

# List keys
npx @intlpullhq/cli keys list --search "welcome" --format table

# List keys filtered by workflow status
npx @intlpullhq/cli keys list --status approved

# List keys filtered by tags
npx @intlpullhq/cli keys list --tags "ui,forms"

# Combine status and tags filters
npx @intlpullhq/cli keys list --status in_review --tags "v2"

# Create a key
npx @intlpullhq/cli keys create "auth.login.title" --value "Log In" --namespace auth

# Update a key
npx @intlpullhq/cli keys update "auth.login.title" --tags "v2,auth"

# Delete a key
npx @intlpullhq/cli keys delete "auth.login.title"

# Bulk delete keys
npx @intlpullhq/cli keys bulk-delete --query "deprecated_*" --dry-run

Options: | Subcommand | Options | |------------|---------| | list | --project <id>, --namespace <ns>, --search <query>, --tags <tags>, --status <status>, --limit <n>, --format <format> | | create | --project <id>, --value <text>, --namespace <ns>, --context <text>, --tags <tags> | | update | --project <id>, --context <text>, --tags <tags> | | delete | --project <id>, --force | | bulk-delete | --project <id>, --query <search>, --dry-run, --force |

tm

Manage Translation Memory (TM).

# Apply TM matches to project translations
npx @intlpullhq/cli tm apply --language es --threshold 85

# Search TM
npx @intlpullhq/cli tm search "Hello World" --source en --target es

# Add entry to TM
npx @intlpullhq/cli tm add "Hello World" "Hola Mundo" --source-lang en --target-lang es

# Show stats
npx @intlpullhq/cli tm stats

Options: | Subcommand | Options | |------------|---------| | apply | --project <id>, --language <code>, --namespace <ns>, --threshold <n>, --dry-run | | search | --source <lang>, --target <lang>, --min-quality <n> | | add | --source-lang <lang>, --target-lang <lang>, --quality <n>, --context <text> |

snapshots

Capture and restore project state snapshots.

# Create a snapshot
npx @intlpullhq/cli snapshots create --name "v1.0.0-release" --description "Before major refactor"

# List snapshots
npx @intlpullhq/cli snapshots list

# Restore from a snapshot
npx @intlpullhq/cli snapshots restore <snapshotId>

Options: | Subcommand | Options | |------------|---------| | create | --project <id>, --name <name>, --description <desc> | | list | --project <id> | | restore | --project <id>, --force | | delete | --project <id>, --force |

webhooks

Manage project webhooks.

# List webhooks
npx @intlpullhq/cli webhooks list

# Create a webhook
npx @intlpullhq/cli webhooks create --url "https://api.example.com/webhook" --events "translation.created,key.updated"

# Test a webhook
npx @intlpullhq/cli webhooks test <webhookId>

Options: | Subcommand | Options | |------------|---------| | list | --project <id>, --format <format> | | create | --project <id>, --url <url>, --events <events>, --secret <secret>, --enabled | | test | --project <id> | | delete | --project <id>, --force |

contributors

Manage team contributors.

# List contributors
npx @intlpullhq/cli contributors list

# Invite a new team member
npx @intlpullhq/cli contributors add --email "[email protected]" --role "admin"

# Update role
npx @intlpullhq/cli contributors update <userId> --role "viewer"

Options: | Subcommand | Options | |------------|---------| | list | --project <id>, --format <format> | | add | --project <id>, --email <email>, --role <role>, --languages <langs>, --message <msg> | | update | --project <id>, --role <role>, --languages <langs> | | remove | --project <id>, --force |

cleanup

Detect and delete orphaned translation keys that are no longer used in your codebase.

# Preview orphans (dry run)
npx @intlpullhq/cli cleanup --scan-codebase --dry-run

# Delete orphans older than 30 days
npx @intlpullhq/cli cleanup --days 30

Options: | Option | Description | |--------|-------------| | --project <id> | Project ID | | --scan-codebase | Scan local files for key usage patterns | | --dry-run | Preview orphans without deleting | | --days <n> | Only consider keys not updated in N days | | -f, --force | Skip confirmation prompt |

CI/CD Integration

All CLI commands support non-interactive mode and work without a TTY. The CLI automatically detects when running in a non-interactive environment (CI/CD pipelines, Docker, scripts) and adjusts its behavior accordingly.

Non-Interactive Mode

Commands automatically work in non-interactive environments:

| Command | Non-Interactive Behavior | |---------|-------------------------| | upload | Auto-confirms plan limit warnings | | download | Works with --quiet flag | | init | Auto-detects framework (use -y for explicit) | | sync | Full support | | check / fix | Full support | | diff | Full support | | import / export | Full support | | migrate files | Use --yes flag to skip prompts | | migrate from | Requires --api-key flag |

Docker

FROM node:20-alpine

WORKDIR /app
COPY . .

RUN npx @intlpullhq/cli sync --quiet
RUN npm run build

GitHub Actions

name: Sync Translations
on: [push]
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Sync translations
        env:
          INTLPULL_API_KEY: ${{ secrets.INTLPULL_API_KEY }}
        run: npx @intlpullhq/cli sync --quiet

GitLab CI

sync-translations:
  stage: build
  image: node:20-alpine
  script:
    - npx @intlpullhq/cli sync --quiet
  variables:
    INTLPULL_API_KEY: $INTLPULL_API_KEY
  only:
    - main

Vercel / Netlify

Add INTLPULL_API_KEY to your environment variables and update your build command:

npx @intlpullhq/cli sync --quiet && next build

Pre-commit Hook (.husky/pre-commit)

npx @intlpullhq/cli check --source en

Recommended CI/CD Flags

| Flag | Description | |------|-------------| | --quiet or -q | Suppress output except errors | | --dry-run | Preview changes without applying | | --yes or -y | Skip confirmation prompts | | --no-parallel | Disable parallel fetching (if rate limited) |


Configuration

Project Configuration (.intlpull.json)

Created by intlpull init, this file configures your project:

{
  "projectId": "proj_xxxx",
  "framework": "next",
  "library": "next-intl",
  "outputDir": "./messages",
  "output": "messages/[locale]/[namespace].json",
  "sourceLanguage": "en",
  "namespaces": ["common", "admin"]
}

Output Patterns (Namespace Support)

The CLI supports flexible output patterns with placeholders to match any i18n library structure.

Placeholders:

  • [locale] or {locale} - Language code (e.g., en, es, zh-CN)
  • [namespace] or {namespace} - Namespace name (e.g., common, auth)

Namespaces in Native Mobile Formats (ios / android) When exporting namespaces for mobile platforms using --platform ios or --platform android:

  • iOS (.strings): Namespaces are preserved using dot-notation. For example, a key welcome in the auth namespace becomes "auth.welcome" = "Welcome";. This flat representation perfectly maps to Xcode localization dictionaries and matches standards in platforms like Phrase and Lokalise.
  • Android (.xml): Namespaces are prefixed using underscores. For example, a key welcome in the auth namespace becomes <string name="auth_welcome">Welcome</string>, fully compliant with Android Resource XML ID requirements.

Note on --platform vs --format: The --platform flag sets the target variant when querying the backend (e.g., fetching platform-specific override keys) and auto-sets the corresponding local file --format. You only need to provide --format manually if you wish to override the default platform file type (e.g. download web keys as TS using --platform web --format ts).

Common Patterns by Framework:

| Framework/Library | Pattern | Example Output | |------------------|---------|----------------| | next-intl | messages/[locale].json | messages/en.json | | next-i18next | public/locales/[locale]/[namespace].json | public/locales/en/common.json | | react-i18next | public/locales/[locale]/[namespace].json | public/locales/en/auth.json | | i18next | locales/[locale]/[namespace].json | locales/en/common.json | | vue-i18n | src/locales/[locale].json | src/locales/en.json | | Chrome Extension | _locales/[locale]/messages.json | _locales/en/messages.json | | React Native | assets/locales/[locale]/[namespace].json | assets/locales/en/common.json |

Configure via CLI flag:

# Namespaced output (creates separate files per namespace)
npx @intlpullhq/cli download --output "public/locales/[locale]/[namespace].json"

# Flat output (merges all namespaces into one file)
npx @intlpullhq/cli download --output "messages/[locale].json"

# Namespace-first structure
npx @intlpullhq/cli download --output "locales/[namespace]/[locale].json"

Configure in .intlpull.json:

{
  "projectId": "proj_xxxx",
  "output": "public/locales/[locale]/[namespace].json"
}

Important: Ensure your i18n library's configuration matches the output path:

| Library | Config Update Required | |---------|----------------------| | next-intl | Update src/i18n/request.ts to load from the correct path | | i18next / react-i18next | Update backend.loadPath in your i18n config | | Chrome Extension | Must use _locales/[locale]/messages.json (Chrome requirement) |

iOS String Tables

iOS uses .strings files organized by "String Tables" (separate files for different modules). The CLI supports this natively:

Default Behavior:

  • The common namespace maps to Localizable.strings (accessed without tableName: in Swift)
  • Other namespaces become their own String Table files (e.g., settingsSettings.strings)
# Download with iOS String Tables
npx @intlpullhq/cli download --format ios --default-namespace common

# Custom namespace-to-table mapping
npx @intlpullhq/cli download --format ios --table "common:Localizable,settings:UserSettings,auth:Authentication"

# Output structure:
# ios/en.lproj/Localizable.strings    (common namespace)
# ios/en.lproj/UserSettings.strings   (settings namespace)
# ios/en.lproj/Authentication.strings (auth namespace)

Swift Usage:

// From Localizable.strings (default table)
NSLocalizedString("welcome", comment: "")

// From Settings.strings (custom table)
NSLocalizedString("theme_dark", tableName: "UserSettings", comment: "")

// SwiftUI
Text("welcome")                           // Localizable.strings
Text("theme_dark", tableName: "UserSettings")  // UserSettings.strings

CLI Options for iOS: | Option | Description | |--------|-------------| | --default-namespace <ns> | Namespace that maps to Localizable.strings (default: common) | | --table <mapping> | Custom namespace→table mapping (e.g., common:Localizable,settings:Settings) |

Android Multi-XML Files

Android commonly splits translations into multiple XML files to reduce merge conflicts and organize code by feature:

Default Behavior:

  • The common namespace maps to strings.xml (the main resource file)
  • Other namespaces use a prefix (default: strings_) → strings_settings.xml, strings_auth.xml
# Download with Android multi-XML
npx @intlpullhq/cli download --format android --default-namespace common

# Custom prefix for non-default namespaces
npx @intlpullhq/cli download --format android --namespace-prefix "app_"
# Output: strings.xml, app_settings.xml, app_auth.xml

# Custom namespace-to-filename mapping
npx @intlpullhq/cli download --format android --xml-file "common:strings,settings:strings_settings,billing:billing_strings"

# Output structure:
# res/values/strings.xml           (default locale, common namespace)
# res/values/strings_settings.xml  (default locale, settings namespace)
# res/values-es/strings.xml        (Spanish, common namespace)
# res/values-es/strings_settings.xml

Key Collision Warning: Android requires globally unique keys across ALL XML files (they compile to a single R.string.* namespace). The CLI automatically detects and warns about key collisions:

Warning: 3 key collision(s) detected across namespaces.
Android requires globally unique keys across all XML files.
Colliding keys:
  - "title" in: common, settings
  - "submit" in: common, auth
  - "cancel" in: settings, auth

Consider prefixing keys with namespace (e.g., "settings_title" instead of "title").

CLI Options for Android: | Option | Description | |--------|-------------| | --default-namespace <ns> | Namespace that maps to strings.xml (default: common) | | --namespace-prefix <prefix> | Prefix for non-default namespace files (default: strings_) | | --xml-file <mapping> | Custom namespace→filename mapping |

Advanced Config (.intlpull.json)

For complex setups, configure namespace mappings in your project config:

{
  "projectId": "proj_xxxx",
  "platform": ["ios", "android"],

  "sources": [
    { "file": "ios/en.lproj/Localizable.strings", "namespace": "common", "format": "ios" },
    { "file": "ios/en.lproj/Settings.strings", "namespace": "settings", "format": "ios" },
    { "file": "android/app/src/main/res/values/strings.xml", "namespace": "common", "format": "android" }
  ],

  "targets": [
    { "file": "ios/[locale].lproj/Localizable.strings", "namespace": "common", "format": "ios" },
    { "file": "ios/[locale].lproj/Settings.strings", "namespace": "settings", "format": "ios" },
    { "file": "android/app/src/main/res/values-[locale]/strings.xml", "namespace": "common", "format": "android" },
    { "file": "android/app/src/main/res/values-[locale]/strings_settings.xml", "namespace": "settings", "format": "android" }
  ],

  "namespaceRename": {
    "common": { "ios": "Localizable", "android": "strings" },
    "settings": { "ios": "Settings", "android": "strings_settings" }
  },

  "platformDefaults": {
    "ios": { "defaultTable": "Localizable", "extension": ".strings" },
    "android": { "defaultFile": "strings", "prefix": "strings_" }
  }
}

Environment Variables

| Variable | Description | |----------|-------------| | INTLPULL_API_KEY | API key for authentication (required) | | INTLPULL_PROJECT_ID | Default project ID | | INTLPULL_DEBUG | Enable debug logging (true/false) |


Tips & Best Practices

| Practice | Recommendation | |----------|----------------| | 🔑 API Keys | Use project-scoped keys for auto-detection (no --project flag needed) | | ⚡ Parallel Mode | Enabled by default — downloads namespaces concurrently | | 🤫 CI/CD Output | Use --quiet for minimal, machine-friendly logs | | 🔍 Preview Changes | Use --dry-run before applying destructive operations | | 🌿 Branch Workflows | CLI auto-detects git branch for branch-based translations | | 📦 Namespace Files | Use output patterns like [locale]/[namespace].json for organized files |


Support

| Resource | Link | |:---------|:-----| | 📚 Documentation | https://intlpull.com/docs | | 📧 Email Support | [email protected] |