npm package: @intlpullhq/cli
Description: The official CLI for IntlPull - intelligent i18n for modern apps. Manage translations, sync with cloud, and automate localization workflows.
Author: Intlpull
Latest version: 0.1.16

<p align="center">
  <a href="https://intlpull.com">
    <img src="https://intlpull.com/logo.png" alt="IntlPull" width="120" />
  </a>
</p>

<h1 align="center">IntlPull CLI</h1>

<p align="center">
  The official CLI for <a href="https://intlpull.com">IntlPull</a> - intelligent i18n for modern apps.<br/>
  Transform code, manage translations, and sync with IntlPull cloud.
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@intlpullhq/cli"><img src="https://img.shields.io/npm/v/@intlpullhq/cli.svg" alt="npm version" /></a>
  <a href="https://www.npmjs.com/package/@intlpullhq/cli"><img src="https://img.shields.io/npm/dm/@intlpullhq/cli.svg" alt="npm downloads" /></a>
  <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="node version" />
</p>

---

## Table of Contents

| Section | Description |
|---------|-------------|
| [Features](#features) | Key capabilities of the CLI |
| [Installation](#installation) | How to install the CLI |
| [Quick Start](#quick-start) | Get started in 4 commands |
| [Authentication](#authentication) | Login, API keys, and auth methods |
| [Commands Reference](#commands-reference) | All available commands |
| ↳ [Initialize](#initialize-project) | Set up IntlPull in your project |
| ↳ [Upload / Push](#upload--push) | Upload translation keys |
| ↳ [Download / Pull](#download--pull) | Download translations |
| ↳ [Sync](#sync) | One-time sync for CI/CD |
| ↳ [Listen / Watch](#listen--watch) | Real-time sync during dev |
| ↳ [Import / Export](#import) | Bulk import/export translations |
| ↳ [OTA Releases](#ota-releases) | Over-the-air updates |
| ↳ [Migration](#migration) | Migrate from other platforms |
| [CI/CD Integration](#cicd-integration) | GitHub Actions, GitLab CI, Docker |
| [Configuration](#configuration) | Project config and output patterns |
| ↳ [Output Patterns](#output-patterns-namespace-support) | Namespace file structures |
| [Tips & Best Practices](#tips--best-practices) | Recommended usage patterns |
| [Support](#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

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

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

## Quick Start

```bash
# 1. Authenticate
npx @intlpullhq/cli login

# 2. Initialize project
npx @intlpullhq/cli init

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

# 4. Pull translations
npx @intlpullhq/cli download
```

## Authentication

```bash
# 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.

```bash
# 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 / Push

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

```bash
# 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

# Also available as 'push'
npx @intlpullhq/cli push
```

**Options:**
| Option | Description |
|--------|-------------|
| `--project <id>` | Project ID (auto-detected with project-scoped API key) |
| `--file <path>` | Specific file to upload |
| `--branch <name>` | Branch name (auto-detected from git) |
| `--platform <platform>` | Platform to tag keys: `ios`, `android`, `web` |
| `--all-languages` | Upload ALL languages (default: true) |
| `--source-only` | Upload only source language keys |
| `--dry-run` | Preview without uploading |
| `-v, --verbose` | Show detailed detection info |

---

### Download / Pull

Download translations from IntlPull. Uses parallel fetching by default.

```bash
# 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

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

# Also available as 'pull'
npx @intlpullhq/cli pull
```

**Options:**
| Option | Description |
|--------|-------------|
| `--project <id>` | Project ID (auto-detected) |
| `--format <format>` | Output format: `json`, `yaml`, `ts` (default: `json`) |
| `--output <dir>` | Output directory (auto-detected from framework) |
| `--languages <langs>` | Languages to download (comma-separated) |
| `--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` |
| `--no-parallel` | Disable parallel fetching |
| `-i, --interactive` | Run in interactive mode |
| `-q, --quiet` | Suppress output except errors |

---

### Sync

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

```bash
# 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: `json`, `yaml`, `ts` |
| `--languages <langs>` | Languages to sync (comma-separated) |
| `--platform <platform>` | Platform variant |
| `--quiet` | Minimal output |
| `--no-parallel` | Disable parallel fetching |

---

### Listen / Watch

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

```bash
# 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 |
| `--format <format>` | Output format: `json`, `yaml`, `ts` |
| `--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) |
| `--once` | Sync once and exit |
| `--quiet` | Minimal output |
| `--no-parallel` | Disable parallel fetching |

---

### Status

Show project status and translation progress.

```bash
npx @intlpullhq/cli status
```

---

### Check & Fix

Check for and fix missing translations.

```bash
# 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 |

**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 push/pull.

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

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

---

### Import

Import existing translation files into IntlPull.

```bash
# 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` (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.

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

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

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

**Options:**
| Option | Description |
|--------|-------------|
| `--format <format>` | Format: `json`, `yaml`, `ts`, `android`, `ios` |
| `--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 |
| `--project <id>` | Project ID |

---

### OTA Releases

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

```bash
# 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.

```bash
# 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

```bash
# 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

```bash
# 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.

```bash
# 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.

```bash
# Push email templates
npx @intlpullhq/cli emails push --dir ./emails

# Pull email translations
npx @intlpullhq/cli emails pull --output ./emails/translations

# List templates
npx @intlpullhq/cli emails list

# Check status
npx @intlpullhq/cli emails status
```

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

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

---

### Documents

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

```bash
# 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.

```bash
# Check integration status
npx @intlpullhq/cli zendesk status

# Connect to Zendesk
npx @intlpullhq/cli zendesk connect \
  --subdomain mycompany \
  --email admin@example.com \
  --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 |

---

## 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` / `push` | Auto-confirms plan limit warnings |
| `download` / `pull` | 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

```dockerfile
FROM node:20-alpine

WORKDIR /app
COPY . .

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

### GitHub Actions

```yaml
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

```yaml
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:

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

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

```bash
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:

```json
{
  "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`)

**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:**
```bash
# Namespaced output (creates separate files per namespace)
npx @intlpullhq/cli pull --output "public/locales/[locale]/[namespace].json"

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

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

**Configure in `.intlpull.json`:**
```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) |

### 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](https://intlpull.com/docs) |
| 📧 Email Support | [support@intlpull.com](mailto:support@intlpull.com) |


---

<p align="center">
  <a href="#features">Features</a> •
  <a href="#installation">Installation</a> •
  <a href="#commands-reference">Commands</a> •
  <a href="#cicd-integration">CI/CD</a> •
  <a href="#configuration">Config</a>
</p>

<p align="center">
  MIT © <a href="https://intlpull.com">IntlPull</a>
</p>