> ## Documentation Index
> Fetch the complete documentation index at: https://powersync-docs-cli-environments.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> Manage PowerSync Cloud and self-hosted instances from the command line.

<CardGroup cols={3}>
  <Card title="PowerSync CLI on NPM" icon="npm" href="https://www.npmjs.com/package/powersync">
    Install globally or run via npx
  </Card>

  <Card title="Source Code" icon="github" href="https://github.com/powersync-ja/powersync-cli">
    PowerSync CLI repo on GitHub
  </Card>

  <Card title="Changelog" icon="megaphone" href="https://releases.powersync.com/announcements/powersync-cli">
    Changelog for the CLI
  </Card>
</CardGroup>

The PowerSync CLI lets you manage PowerSync Service instances, deploy sync config (your Sync Streams or Sync Rules), generate client schemas, run diagnostics, and more. It is distributed as the [powersync](https://www.npmjs.com/package/powersync) npm package.

<Note>
  The CLI is currently in [beta](/resources/feature-status). We recommend it for
  new and existing projects.
</Note>

<Tip>
  For a full step-by-step flow using the CLI, use the [Setup
  Guide](/intro/setup-guide): choose the **CLI (Cloud)** or **CLI
  (Self-Hosted)** tab in steps 2–5 to configure your instance, connect the
  source database, deploy sync config, and generate development tokens.
</Tip>

The CLI was overhauled in version 0.9.0. The redesign is based on this [design proposal](https://docs.google.com/document/d/1iqpJF2gog2jB-ZWeN8TBEjcad8aBKNKbue2yJ21q_-s/edit).

<Accordion title="What changed in 0.9.0?">
  **Main improvements:**

  * **Project-based config** — A `powersync/` directory in your repo holds `service.yaml` and `sync-config.yaml`, so you version and review config with your app code.
  * **Self-hosted support** — Most commands work against any linked instance, PowerSyncCloud and self-hosted. You can also use `powersync docker configure` to scaffold a local PowerSync stack with no manual setup.
  * **Better validation** — `powersync validate` checks your config before deploy and reports errors with line and column numbers.
  * **Config Studio** — `powersync edit config` opens a built-in editor with schema validation, autocomplete, inline errors, and more. See the [Config Studio README](https://github.com/powersync-ja/powersync-cli/tree/main/packages/editor).
  * **Browser login** — `powersync login` opens a browser to create or paste a PAT and stores it; in CI use `PS_ADMIN_TOKEN`.
  * **Plugins** — npm-based plugin system ([OCLIF](https://oclif.io)); install with `powersync plugins install <package>` or build with `@powersync/cli-core`.
  * **Open source** — Source and advanced docs are in the [PowerSync CLI repo](https://github.com/powersync-ja/powersync-cli).

    See [Migrating From the Previous CLI](#migrating-from-the-previous-cli) if you used the older flow.
</Accordion>

## Installation

Install globally or run via `npx`:

```bash theme={null}
npm install -g powersync
```

```bash theme={null}
npx powersync@0.9.0  # 0.9.0 is the first version with the new CLI
```

## Authentication (Cloud)

Cloud commands require a PowerSync **personal access token (PAT)**.

**Interactive login (recommended for local use):**

```bash theme={null}
powersync login
```

You can open a browser to [create a token in the PowerSync Dashboard](https://dashboard.powersync.com/account/access-tokens) or paste an existing token. The CLI stores the token in secure storage when available (e.g. macOS Keychain), or in a config file after confirmation.

**CI and scripts:** Set the `PS_ADMIN_TOKEN` environment variable. The CLI uses `PS_ADMIN_TOKEN` when set; otherwise it uses the token from `powersync login`.

```bash theme={null}
export PS_ADMIN_TOKEN=your-personal-access-token
powersync fetch instances --project-id=<project-id>
```

To clear stored credentials: `powersync logout`.

## Config Files

The CLI uses a config directory (default `powersync/`) with YAML files:

| File               | Purpose                                                                     |
| ------------------ | --------------------------------------------------------------------------- |
| `service.yaml`     | Instance configuration: name, region, replication connection, client auth   |
| `sync-config.yaml` | Sync Streams (or Sync Rules)                                                |
| `cli.yaml`         | Link file (written by `powersync link`); ties this directory to an instance |

### Developer Notes

* Use the **`!env`** tag for secrets, e.g. `uri: !env PS_DATABASE_URI` (or `!env VAR::number` / `!env VAR::boolean` for types).
* Edit files in your IDE, then run `powersync validate` and `powersync deploy`. For schema validation and `!env` support in your editor, run **`powersync configure ide`**; or run **`powersync edit config`** to open Config Studio (built-in web-based editor).
* To run commands against several instances from one config directory, define named targets in `cli.yaml`. See [Named Targets](#named-targets). The CLI usage docs cover [other layouts](https://github.com/powersync-ja/powersync-cli/blob/main/docs/usage.md#configuring-multiple-instances-eg-dev-staging-production), such as one directory per instance.
* For Cloud secrets in `service.yaml`, use `password: secret: !env VAR` to supply the value from an environment variable at deploy time; after the first deploy you can switch to `secret_ref: default_password` to reuse the stored secret. [Details](https://github.com/powersync-ja/powersync-cli#cloud-secrets-format-serviceyaml)
* `cli.yaml` records the instance ID along with the organization and project IDs. The organization and project IDs act as a cache: when both are present, the CLI uses them directly instead of looking them up from the instance, saving an API request. If they are missing, the CLI resolves them automatically from the instance ID. If they are present but incorrect for the instance, the CLI reports an error rather than overriding them.

## Cloud Workflows

You can create instances, deploy and pull config, run all Cloud commands.

### Create a New Instance

<Steps>
  <Step title="Log in and scaffold">
    ```bash theme={null}
    powersync login
    powersync init cloud
    ```
  </Step>

  <Step title="Edit config">
    Edit `powersync/service.yaml` (name, region, replication, auth) and sync config; use `!env` for secrets.
  </Step>

  <Step title="Create and link">
    ```bash theme={null}
    powersync link cloud --create --project-id=<project-id>
    ```

    Add `--org-id=<org-id>` if your token has multiple orgs.
  </Step>

  <Step title="Deploy">
    ```bash theme={null}
    powersync validate
    powersync deploy
    ```
  </Step>
</Steps>

Use `--directory=<path>` for a different config folder.

### Use an Existing Instance (Pull)

Pull config from an instance that already exists (e.g. created in the Dashboard):

```bash theme={null}
powersync login
powersync pull instance --instance-id=<instance-id>
```

Then edit `service.yaml` and `sync-config.yaml` as needed, run `powersync validate`, and `powersync deploy`. Run `powersync pull instance` again (no IDs if already linked) to refresh from the cloud.

### Preview a Deploy

Add `--dry-run` to `powersync deploy`, `powersync deploy service-config`, or `powersync deploy sync-config` to see what a deploy would do without changing the instance:

```bash theme={null}
powersync deploy --dry-run
```

The command prints the target instance, runs the same validations as a real deploy, and then summarizes what would change: the `service.yaml` sections that differ from the deployed config, and a diff of the sync config. Nothing is deployed, even when the instance is not provisioned yet.

The service config summary lists section names only, because `service.yaml` holds connection strings and other secrets. To compare the full file, run `powersync pull instance` without `--overwrite`. It writes the deployed config to `service-fetched.yaml` next to your `service.yaml`, so you can diff the two files locally.

<Note>
  Connections that pass a password with `secret` always show `replication` as
  changed, because the value is sent again on every deploy.
</Note>

### Run Commands Without Local Config

To run commands (e.g. `powersync generate schema`, `powersync status`) against an instance managed elsewhere (e.g. Dashboard):

* **Link once:** `powersync link cloud --instance-id=<id>` (writes `cli.yaml`); later commands use that instance.
* **Or pass each time:** `--instance-id`, or set `INSTANCE_ID` in the environment.

<Info>
  The CLI resolves the instance in a fixed order: flags first, then `cli.yaml`
  (the selected target, then the top-level fields), then environment
  variables. For details, see [supplying linking information for Cloud and
  self-hosted
  commands](https://github.com/powersync-ja/powersync-cli/blob/main/docs/usage.md#supplying-linking-information-for-cloud-and-self-hosted-commands)
  in the CLI usage docs.
</Info>

### Named Targets

Named targets let one config directory point at more than one Cloud instance, such as staging and production. Each target is an entry under `targets` in `cli.yaml` with its own instance, organization, and project IDs. The top-level fields stay the default when you do not select a target.

Link an existing instance under a target name, or create a new instance and link it under one:

```bash theme={null}
powersync link cloud --target=staging --instance-id=<instance-id>
powersync link cloud --create --target=staging --project-id=<project-id>
```

The resulting `cli.yaml`:

```yaml theme={null}
type: cloud
instance_id: <production-instance-id>
org_id: <org-id>
project_id: <project-id>
targets:
  staging:
    instance_id: <staging-instance-id>
    org_id: <org-id>
    project_id: <project-id>
```

Select a target with `--target` on a command, or set `POWERSYNC_TARGET` for scripts and CI:

```bash theme={null}
powersync pull instance --target=staging
powersync deploy --target=staging
powersync status --target=staging
POWERSYNC_TARGET=staging powersync deploy sync-config
```

`--instance-id` takes precedence over `POWERSYNC_TARGET`. You cannot combine `--target` with `--instance-id` in one command. `powersync fetch instances` lists the targets of each linked directory. Before `deploy`, `stop`, `destroy`, and `compact` change anything, the CLI prints the instance name and IDs, plus the target name when one is selected.

<Note>
  Deploy writes the `name` from `service.yaml` to the instance it targets.
  Instances deployed from one `service.yaml` end up with the same name in the
  Dashboard, so tell them apart by target name or instance ID rather than
  by instance name.
</Note>

## Self-Hosted Workflows

Support is limited: you **link** to an existing PowerSync API and run a **subset of commands**. The CLI does not create, deploy to, or pull config from your server; you manage the server and its config yourself. For local development, use **Docker** to run a PowerSync Service (and optional DB/storage) in containers.

### Authenticate

<Steps>
  <Step title="On the server">
    In your PowerSync instance config, define API tokens in `service.yaml`:

    ```yaml theme={null}
    api:
      tokens:
        - dev-token-do-not-use-in-production   # or !env MY_API_TOKEN
    ```
  </Step>

  <Step title="Link the CLI">
    ```bash theme={null}
    powersync link self-hosted --api-url <url>
    ```

    Writes `cli.yaml` with the API URL.
  </Step>

  <Step title="Set the API key">
    In `cli.yaml` set `api_key: !env PS_ADMIN_TOKEN` (or a literal value matching a server token), or set the **`PS_ADMIN_TOKEN`** environment variable. If both are set, the environment variable takes precedence.

    ```yaml theme={null}
    # powersync/cli.yaml (self-hosted)
    type: self-hosted
    api_url: https://powersync.example.com
    api_key: !env PS_ADMIN_TOKEN   # or a literal value matching one of the tokens in service.yaml
    ```
  </Step>
</Steps>

### Scaffold and Link (No Docker)

When you already have a running PowerSync API:

```bash theme={null}
powersync init self-hosted
# Edit powersync/service.yaml with instance details and api.tokens
powersync link self-hosted --api-url https://powersync.example.com
powersync status
```

Use `--directory=<path>` for a different config folder.

### Supported Commands (Self-Hosted)

Only these commands apply to self-hosted instances: **`powersync status`**, **`powersync generate schema`**, **`powersync generate token`**, **`powersync validate`**, **`powersync fetch instances`** (scans current directory for folders with `cli.yaml`).

Cloud-only commands (**`powersync deploy`**, **`powersync pull instance`**, **`powersync fetch config`**, **`powersync destroy`**, **`powersync stop`**, **`powersync compact`**) do not apply.

### Docker (Local Development)

Run a PowerSync Service (and optional DB/storage) in containers on your machine—no remote server.

```bash theme={null}
powersync init self-hosted
powersync docker configure    # links to the local API automatically
powersync docker start
```

Then use the same commands as any self-hosted instance (`powersync status`, `powersync generate schema`, etc.). To stop: **`powersync docker stop`** (add `--remove` to remove containers, `--remove-volumes` to reset so init scripts run again). For a clean setup: **`powersync docker reset`** (stop and remove, then start).

<Tip>
  For the full Docker workflow, all flags (`--database`, `--storage`,
  `--remove`, `--remove-volumes`), and how the template layout and init scripts
  work, see [Docker
  usage](https://github.com/powersync-ja/powersync-cli/blob/main/docs/usage-docker.md)
  in the CLI repo. Run `powersync docker --help` for command options.
</Tip>

## Common Commands

| Command                                                         | Description                                                                         |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `powersync login`                                               | Store PAT for Cloud (interactive or paste token); use `PS_ADMIN_TOKEN` in CI        |
| `powersync logout`                                              | Remove stored token                                                                 |
| `powersync init cloud`                                          | Scaffold Cloud config directory                                                     |
| `powersync init self-hosted`                                    | Scaffold self-hosted config directory                                               |
| `powersync configure ide`                                       | IDE: YAML schema validation and `!env` support                                      |
| `powersync link cloud --instance-id=<id>`                       | Link to existing Cloud instance                                                     |
| `powersync link cloud --create --project-id=<id>`               | Create new Cloud instance and link                                                  |
| `powersync link cloud --target=<name> --instance-id=<id>`       | Link an instance as a named target in `cli.yaml`                                    |
| `powersync link self-hosted --api-url=<url>`                    | Link to self-hosted instance                                                        |
| `powersync pull instance --instance-id=<id>`                    | Download Cloud config to local files                                                |
| `powersync deploy`                                              | Deploy full config to linked Cloud instance                                         |
| `powersync deploy service-config`                               | \[Cloud] Deploy only service config                                                 |
| `powersync deploy sync-config`                                  | \[Cloud] Deploy only sync config                                                    |
| `powersync deploy --dry-run`                                    | \[Cloud] Validate and preview what a deploy would change, without deploying         |
| `powersync deploy --target=<name>`                              | \[Cloud] Deploy to a named target. `--target` works on every instance command       |
| `powersync validate`                                            | Validate config and Sync Streams/Rules                                              |
| `powersync edit config`                                         | Open Config Studio (Monaco editor)                                                  |
| `powersync status`                                              | Instance diagnostics (Cloud and self-hosted)                                        |
| `powersync generate schema --output=ts --output-path=schema.ts` | Generate client schema                                                              |
| `powersync generate token --subject=user-123`                   | Generate development JWT                                                            |
| `powersync fetch instances`                                     | List Cloud and linked instances                                                     |
| `powersync fetch config`                                        | \[Cloud] Print instance config (YAML/JSON)                                          |
| `powersync migrate sync-rules`                                  | Migrate Sync Rules to Sync Streams                                                  |
| `powersync destroy --confirm=yes`                               | \[Cloud] Permanently destroy instance                                               |
| `powersync stop --confirm=yes`                                  | \[Cloud] Stop instance (restart with deploy)                                        |
| `powersync compact`                                             | \[Cloud] Trigger [bucket compacting](/maintenance-ops/compacting-buckets) on demand |

Run `powersync --help` or `powersync <command> --help` for flags. Full [command reference](https://github.com/powersync-ja/powersync-cli/blob/main/cli/README.md#commands) in the CLI repo.

## Deploying From CI (e.g. GitHub Actions)

You can automate sync config (and full config) deployments using the CLI in CI. Use the config directory as the source of truth: keep `service.yaml` and `sync-config.yaml` in the repo (with secrets via `!env` and CI secrets), then run `powersync deploy` (or `powersync deploy sync-config`).

**Secrets:** Set `PS_ADMIN_TOKEN` to your PowerSync personal access token. If the workflow does not use a linked directory, also set `INSTANCE_ID`. If the linked directory defines [targets](#named-targets), set `POWERSYNC_TARGET` to pick one. For self-hosted, `API_URL` can specify the PowerSync API base URL.

The CLI prints the target instance name and IDs before a deploy starts, so the job log shows which instance changed. For pull request checks, run `powersync deploy --dry-run` to validate the config and preview the changes without deploying.

<Card title="GitHub Actions Demo" icon="github" href="https://github.com/powersync-community/github-actions-demo" horizontal>
  Example: deploy sync config on push to main
</Card>

## Migrating From the Previous CLI

If you used the older PowerSync CLI (e.g. `npx powersync init` to set token and org/project, then `powersync instance set`, `powersync instance deploy`, etc.), the new CLI uses a different flow. Version 0.9.0 and above are **not backwards compatible** with 0.8.0. If you are not ready to migrate, you can stay on the old CLI:

```bash theme={null}
npm install -g @powersync/cli@0.8.0
```

Otherwise, upgrade to the latest **powersync** npm package and follow the mapping below.

| Previous CLI                                                | New CLI                                                                                                                                                                                             |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `npx powersync init` (enter token, org, project)            | **`powersync login`** (token only). Then **`powersync init cloud`** to scaffold config, or **`powersync pull instance --instance-id=...`** to pull an existing instance.                            |
| `powersync instance set --instanceId=<id>`                  | **`powersync link cloud --instance-id=<id>`** (writes `cli.yaml` in config directory). Or use `--directory` for a specific folder, or `--target=<name>` to keep several instances in one directory. |
| `powersync instance deploy` (interactive or long flag list) | Edit **`powersync/service.yaml`** and **`powersync/sync-config.yaml`**, then **`powersync deploy`**. Config is in files, not command args.                                                          |
| `powersync instance config`                                 | **`powersync fetch config`** (output as YAML or JSON with `--output`).                                                                                                                              |
| Deploy only Sync Streams/Rules                              | **`powersync deploy sync-config`**.                                                                                                                                                                 |
| `powersync instance schema`                                 | **`powersync generate schema --output=... --output-path=...`** (and/or **`powersync status`** for diagnostics).                                                                                     |
| Org/project stored by init                                  | Not required separately. The CLI determines the organization and project from the instance ID and caches their IDs in `cli.yaml`. For CI, set **`PS_ADMIN_TOKEN`** and **`INSTANCE_ID`**.           |

**Summary:** Authenticate with **`powersync login`** (or `PS_ADMIN_TOKEN` in CI). Use a **config directory** with `service.yaml` and `sync-config.yaml` as the source of truth. **Link** with **`powersync link cloud`** or **`powersync pull instance`**, then run **`powersync deploy`** or **`powersync deploy sync-config`**. No more setting “current instance” separately from config—the directory and `cli.yaml` define the target.

## Additional Documentation (CLI Repository)

More information is available in the [PowerSync CLI repository](https://github.com/powersync-ja/powersync-cli).

| Resource                                                                                                   | Description                                                                                                                                                                                              |
| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [CLI README](https://github.com/powersync-ja/powersync-cli/blob/main/cli/README.md)                        | Getting started, Cloud and self-hosted overview, and full **command reference** with all flags.                                                                                                          |
| [General usage](https://github.com/powersync-ja/powersync-cli/blob/main/docs/usage.md)                     | **How the CLI works**: local config vs linking, resolution order (flags → `cli.yaml` → env vars), and **configuring multiple instances** (named targets in `cli.yaml`, separate directories, or `!env`). |
| [Docker (local development)](https://github.com/powersync-ja/powersync-cli/blob/main/docs/usage-docker.md) | Self-hosted Docker workflow, configure/start/stop/reset, database and storage modules, and template layout.                                                                                              |
| [Config Studio (editor)](https://github.com/powersync-ja/powersync-cli/tree/main/packages/editor)          | Built-in Monaco-powered editor for `service.yaml` and `sync-config.yaml` (`powersync edit config`), schema validation, and local development.                                                            |
| [Examples](https://github.com/powersync-ja/powersync-cli/blob/main/examples/README.md)                     | Sample projects initialized with the CLI (e.g. Cloud pull, self-hosted Postgres, self-hosted Supabase).                                                                                                  |

## Known Issues and Limitations

* When secure storage is unavailable, `powersync login` may store the token in a plaintext config file after explicit confirmation.
* Self-hosted: the CLI does not create or manage instances on your server, or deploy config to it; it only links to an existing API and runs a subset of commands (status, generate schema/token, validate). The sole exception is **Docker**: it starts a local PowerSync Service (and optional DB/storage) in containers on your machine for development — not a remote or production instance.
* Some validation checks require a connected instance to complete successfully; validation of an unprovisioned instance may show errors that resolve after the first deployment.

## Reference

<Card title="npm: powersync" icon="npm" href="https://www.npmjs.com/package/powersync" horizontal>
  Package and version history
</Card>

<Card title="Manage your access tokens" icon="key" href="https://dashboard.powersync.com/account/access-tokens" horizontal>
  Create or revoke tokens in the PowerSync Dashboard
</Card>

<Card title="PowerSync CLI Repo" icon="github" href="https://github.com/powersync-ja/powersync-cli" horizontal>
  Source code, usage docs, Docker usage, and examples
</Card>
