# CLI reference

Find commands by task and distinguish baseline registration, bundling and deployment.

Complete [your first release](/docs/publish), then use this command reference. Run commands from the app root. Backslash continuations are for Bash / zsh; use a single line in PowerShell.

## Install {#install}

```bash
npm install -g rn-update-cli
```

After installation, invoke commands via `pakta <command>`. Requires Node.js ≥18.17. For login and first setup see [Publishing](/docs/publish#setup).

## Command quick reference {#commands}

| Purpose | Commands |
| --- | --- |
| Account | `login`, `logout`, `me` |
| Apps | `createApp`, `apps`, `selectApp`, `deleteApp` |
| Channels | `channels`, `createChannel`, `updateChannel`, `deleteChannel` |
| Native packages | `uploadApk`, `uploadAab`, `uploadIpa`, `uploadApp`, `packages`, `deletePackage` |
| Parsing | `parseApk`, `parseAab`, `parseIpa`, `parseApp`, `extractApk` |
| OTA | `bundle`, `publish`, `versions`, `update`, `updateVersionInfo`, `deleteVersion` |
| Differencing | `hdiff`, `hdiffFromApk`, `hdiffFromIpa`, `hdiffFromApp`, `registerPdiff` |
| Diagnostics | `symbolicate`, `cache`, `cache clean` |

`pakta list` prints available commands. Use the canonical option names below.

## bundle {#bundle}

Generate a `.ppk` update package (JS bundle and assets only):

```bash
pakta bundle --platform android --output .pakta/output/android.ppk --no-interactive
```

Key options:

- `--platform ios|android|harmony` — target platform.
- `--output` — `.ppk` output path; pin it to avoid timestamped filenames.
- `--entryFile` — entry script (index.js by default; inferred for Expo).
- `--dev true` — build a development bundle.
- `--sourcemap` / generated by default — Hermes projects get the final mapping composed automatically.
- `--hermesBase auto|none|<path>` — Hermes baseline strategy; `auto` reuses historical baselines to shrink patches, `none` disables, or pass an explicit `.hbc/.ppk/.apk/.ipa`.
- `--expo` — bundle for Expo projects.
- `--name` — when present, publishing starts right after bundling.

## publish {#publish}

```bash
pakta publish <ppk-path> \
  --platform android --name fix-001 \
  --channel default --packageVersion 1.0.0 --rollout 10 \
  --sourcemap .pakta/intermedia/android/index.bundlejs.map
```

- Pick one target form: `--targets targets.json` (multi-channel), `--packageId` (resolve a target from a native package ID), or `--channel + --packageVersion` (single target).
- Omitting `--rollout` means 100%; per-line `rollout` in `targets.json` overrides the global value.
- `--dryRun` preflight: resolves targets and percentages without writing anything.
- `--deploymentIds id1,id2`: exact retry of failed deployments.
- `--sourcemap`: archive the sourcemap for later `symbolicate`.

A publish produces two independent objects: the **slim native baseline** registered at upload time and the **`.ppk`** uploaded now; the full store binary is never uploaded as-is. After publishing, the platform creates differential jobs in one transaction for every exact build in the channel × native version group; until jobs finish, `checkUpdate` falls back to the full package.

## Versions and diffs {#versions-diff}

```bash
pakta versions                     # list versions
```

Local `hdiff`/`hdiffFromApk`/`hdiffFromIpa`/`hdiffFromApp` only produce patch files; to attach a patch to an exact native build, register it afterwards via `registerPdiff` (bound precisely by `deploymentId + nativeVersionId`, never mis-delivered to another build of the same version).

## Diagnostics {#diagnostics}

```bash
pakta symbolicate stack.txt --platform android --hash <UPDATE_HASH>
```

`hash` comes from the SDK's `getUpdateMetadata().currentVersion`; `--versionId` works too, and `-` reads the stack from stdin. `cache clean` removes the local Hermes baseline cache.

## Environment variables {#env-vars}

| Variable | Purpose |
| --- | --- |
| `RNU_SERVICE_URL` | Self-hosted service address (`/admin/api/v1` appended automatically) |
| `PAKTA_API_TOKEN` | CI personal access token, see [API Key](/docs/api-token) |
| `NO_INTERACTIVE=true` | Disable all prompts |
| `RNU_LANG` | `zh` (default) or `en` |
| `RNU_DEBUG=1` | Print error stacks |
| `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` | Proxy settings (lowercase accepted) |
| `PAKTA_CACHE_DIR` | Hermes baseline cache directory |
| `PAKTA_HERMES_PROBE_TIMEOUT_MS` and siblings | Hermes probe/verify/compile deadlines (ms) |
| `RNU_AUTO_UPDATE=0` | Disable CLI background self-update |

## Programmatic API {#provider-api}

Build scripts can skip the command line and use the exported provider directly:

```typescript
import { CLIProviderImpl } from 'rn-update-cli';

const provider = new CLIProviderImpl();
const bundle = await provider.bundle({
  platform: 'android',
  output: '.pakta/output/android.ppk',
  sourcemap: true,
});
if (!bundle.success) throw new Error(bundle.error);

const release = await provider.publish({
  filePath: '.pakta/output/android.ppk',
  sourcemap: '.pakta/intermedia/android/index.bundlejs.map',
  platform: 'android',
  name: 'fix-001',
  targets: 'targets.json',
});
if (!release.success) throw new Error(release.error);
```

Results are `CommandResult` objects — check `success` before consuming `data`.

## IDs that look similar {#identifiers}

The `publish --packageId` input is a native package ID used to resolve a target. The returned `packageId` identifies the update package. Do not feed the output ID into that option. Prefer `targets.json` for multiple targets and returned `deploymentIds` for retries.
