CLI Reference

Use the CLI to upload bundles, release them, inspect bundle and release history, and manage apps.

Project config

Project commands read from capacitor.config.*.

// capacitor.config.ts
import type { CapacitorConfig } from "@capacitor/cli";

const config: CapacitorConfig = {
  appId: "com.example.myapp",
  appName: "My App",
  webDir: "out",
  plugins: {
    OtaKit: {
      appId: "app_xxxxxxxx",
      // Optional named channel:
      // channel: "staging"
      // Optional compatibility lane:
      // runtimeVersion: "2026.04"
    }
  }
};

export default config;

Authentication

For local development, sign in once and the CLI stores a token locally. For CI or non-interactive environments, use an organization secret key instead.

If your account has multiple organizations, login asks you to choose a default by name for commands that are not tied to an app. Change it with otakit organization select. Configured apps still use their owning organization, and organization keys are already bound to one.

# Local development
otakit login

# CI / non-interactive
export OTAKIT_TOKEN=otakit_sk_...
export OTAKIT_APP_ID=app_xxxxxxxx

Release flow

  • Upload only: otakit upload
  • Upload and release to the base channel: otakit upload --release
  • Upload and release to a named channel: otakit upload --release beta
  • Promote an existing bundle later: otakit release <bundleId> --channel production

Resolution order

The CLI resolves values in a deterministic order.

  • App ID: --app-id -> OTAKIT_APP_ID -> capacitor.config.*
  • Server URL: --server -> OTAKIT_SERVER_URL -> plugins.OtaKit.serverUrl -> hosted default
  • Auth token: OTAKIT_TOKEN -> stored login token
  • App-less organization: OTAKIT_ORGANIZATION_ID -> stored login default
  • Upload path: CLI path argument -> OTAKIT_BUILD_DIR -> capacitor.config.* webDir
  • Release channel: --release -> base channel, --release <channel> -> named channel
  • Runtime version: plugins.OtaKit.runtimeVersion -> bundle metadata during upload
  • Upload version: --version -> OTAKIT_VERSION -> auto-generated version

Command reference

otakit upload[path]

Upload a bundle. Optionally release it immediately.

[path]Bundle directory. If omitted, the CLI uses OTAKIT_BUILD_DIR or capacitor.config.* webDir.
--app-id <id>App ID override.
--server <url>Server URL override.
--version <version>Version string. Otherwise OTAKIT_VERSION, then auto-generated.
--strict-versionRequire explicit or env-provided version.
--release [channel]Release after upload. Omit channel to release to the base channel.
--strategy <strategy>Upload strategy: "zip" (single archive, default) or "deltas" (per-file objects; devices download only what changed).
--force-immediateWith --release: devices apply and reload this release on their next check (emergency fixes).
--rollout <percent>With --release: release to this share of devices first (1-100, default 100). See Percentage rollouts.
--replace-rolloutWith --release: cancel the channel's active rollout and release this bundle in its place.
--previewAlso create a preview link and QR code for the uploaded bundle. See Preview links.
--encryptEncrypt the bundle with OTAKIT_ENCRYPTION_KEY before upload (auto-enabled when the env var is set).
--fail-on-incompatibleExit non-zero when the native compatibility check finds changes that need a store build.
--ignore-compatSkip the native compatibility check.
otakit upload --release

otakit release[bundleId]

Release a bundle to the base channel or a named channel. The bundle already carries its runtimeVersion, so release only chooses the rollout channel.

--channel <channel>Target named channel. Omit it to use the base channel.
--force-immediateDevices apply and reload this release on their next check (emergency fixes).
--rollout <percent>Release to this share of devices first (1-100, default 100). The channel needs a previous release.
--replace-rolloutCancel the channel's active rollout and release this bundle in its place.
otakit release --channel production --rollout 10

otakit rollout[releaseId]

Show active rollouts, or raise, lower, complete, or cancel one. Without a release ID it acts on the rollout of the selected channel.

--channel <channel>Channel of the rollout.
--baseThe rollout on the base channel.
--percent <percent>Set the share of devices (1-100; 100 completes the rollout).
--completeRelease to every device.
--cancelRevert the rolling release; every device returns to the previous release.
otakit rollout --channel production --percent 50

otakit preview[bundleId]

Create a private link and QR code that open a bundle in the installed app on one phone, without releasing it. Defaults to the latest upload. The app needs previewLinks: true and a custom URL scheme.

--expires <duration>How long the link works: 1h, 24h, 7d (default) or 30d.
--scheme <scheme>The app's custom URL scheme, such as myapp. Needed once; the app remembers it.
--listList active preview links.
--revoke <previewId>Revoke a preview link.
--jsonPrint JSON output.
otakit preview --scheme myapp

otakit compatibility

Check the local native plugin set against a channel's current release without uploading.

--channel <channel>Channel to compare against. Omit for the base channel.
--package-json <path>package.json used for native dependency detection.
--node-modules <path>node_modules used for native dependency detection.
otakit compatibility --channel production

otakit list

List uploaded bundles.

--limit <n>Max results. Defaults to 20.
otakit list --limit 20

otakit releases

Show release history across all streams or a specific target.

--channel <channel>Show only a named channel.
--baseShow only the base channel.
--limit <n>Max results. Defaults to 10.
otakit releases --base

otakit delete<bundleId>

Delete a bundle.

--forceSkip confirmation prompt.
otakit delete abc123 --force

otakit register

Create a new app and print the plugin snippet to paste into capacitor.config.ts.

--slug <slug>App slug (for example com.example.app).
--server <url>Server URL override.
--token <token>Access token or organization API key.
--secret-key <key>Alias for --token.
otakit register --slug com.example.myapp

otakit login

Sign in with email OTP and store a token locally.

--email <email>Email address. If omitted, prompts interactively.
--server <url>Server URL override.
--token-onlyPrint token to stdout only.
otakit login --email you@example.com

otakit whoami

Show current authenticated user and organization context.

--server <url>Server URL override.
--jsonPrint machine-readable account and organization details.
otakit whoami

otakit organization select

Choose the default organization for commands not tied to an app. Configured apps always use their owning organization.

--server <url>Server URL override.
otakit organization select

otakit logout

Remove stored token for a server.

--server <url>Server URL override.
otakit logout

otakit config resolve

Show effective CLI values and where they came from.

--app-id <id>App ID override.
--server <url>Server URL override.
--output-dir <path>Output directory override.
--channel <channel>Channel override.
--jsonPrint machine-readable JSON output.
otakit config resolve --json

otakit connect

Connect this project to your coding agent. Signs in if needed, then writes the client's MCP configuration after showing exactly what it resolved and what it will write.

--client <client>claude, codex, or vscode. Defaults to detected.
--project-root <path>Project to connect. Defaults to the current directory.
--server <url>OtaKit console URL override.
--dry-runShow the plan and exit without writing.
--yesSkip the confirmation prompt.
npx -y @otakit/cli@latest connect

otakit push send

Send a push notification to your app users. Needs the Push notifications add-on (Settings → Add-ons) and an APNs key and/or Firebase service account for the app. Shows the audience size and asks before sending.

--title <title>Notification title (required).
--body <body>Notification text (required).
--url <url>Path or https link the app opens, sent as data.url.
--data <key=value>Extra data for the app (repeatable).
--platform <platform>ios or android (repeatable; default both).
--channel <channel>Only devices on this OTA channel (repeatable).
--topic <topic>Only devices subscribed to this topic (repeatable).
--user <id>Only devices of this user ID (repeatable).
--yesSend without the confirmation prompt (required in CI).
--jsonPrint the campaign as JSON.
otakit push send --title "New drop" --body "Open the app to see it" --url /shop --topic news

otakit push campaigns

List recent push campaigns with delivery counts.

--limit <n>Number of campaigns (default 10, max 100).
--jsonPrint machine-readable JSON output.
otakit push campaigns

otakit push campaign<campaignId>

Show one campaign: status, devices targeted and accepted by Apple/Google, failures and removed tokens.

--jsonPrint machine-readable JSON output.
otakit push campaign 11dead02-8f6f-4349-8ea3-7667c2a4382c

otakit mcp

Start the local MCP server, bound to one project and organization for its lifetime.

--project-root <path>Project root available to local MCP tools.
--organization-id <id>Advanced organization override for app-less automation.
npx -y @otakit/cli@latest mcp --project-root .

otakit config validate

Validate the OtaKit-related values in capacitor.config.*.

--jsonPrint machine-readable JSON output.
otakit config validate

otakit generate-signing-key

Generate an ES256 key pair for manifest signing.

otakit generate-signing-key

otakit generate-encryption-key

Generate an AES-256 bundle encryption key. Keep it in CI as OTAKIT_ENCRYPTION_KEY and ship it in the app's bundleKeys config.

otakit generate-encryption-key

Troubleshooting

  • Missing app ID: add plugins.OtaKit.appId to capacitor.config.ts, or pass --app-id.
  • Missing index.html: build your web app and verify webDir or the explicit upload path.
  • Need to create an app from automation: use otakit register --slug <slug>.