diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..013a35c --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +layout node +use node +[ -f .env ] && dotenv \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8e486f6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.cmd text eol=crlf +*.bat text eol=crlf diff --git a/.github/workflows/onPushToMain.yml b/.github/workflows/onPushToMain.yml new file mode 100644 index 0000000..eedc76f --- /dev/null +++ b/.github/workflows/onPushToMain.yml @@ -0,0 +1,60 @@ +name: release on push to main + +on: + push: + branches: [main] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'pnpm' + - run: pnpm install --frozen-lockfile + - name: Check if CLI version already exists + id: version-check + run: | + package_version=$(node -p "require('./cli/package.json').version") + exists=$(gh api repos/${{ github.repository }}/releases/tags/v$package_version >/dev/null 2>&1 && echo "true" || echo "") + + if [ -n "$exists" ]; + then + echo "Version v$package_version already exists" + echo "::warning file=cli/package.json,line=1::Version v$package_version already exists - no release will be created." + echo "skipped=true" >> $GITHUB_OUTPUT + else + echo "Version v$package_version does not exist. Creating release..." + echo "skipped=false" >> $GITHUB_OUTPUT + echo "tag=v$package_version" >> $GITHUB_OUTPUT + fi + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + - name: Setup git + if: ${{ steps.version-check.outputs.skipped == 'false' }} + run: | + git config --global user.email ${{ secrets.GH_EMAIL }} + git config --global user.name ${{ secrets.GH_USERNAME }} + - name: Generate OCLIF README (cli) + if: ${{ steps.version-check.outputs.skipped == 'false' }} + run: | + pnpm run build + cd cli && pnpm exec oclif readme + cd .. + if [ -n "$(git status --porcelain)" ]; then + git add . + git commit -am "chore: update README.md" + git push -u origin ${{ github.ref_name }} + fi + - name: Create GitHub Release + uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 + if: ${{ steps.version-check.outputs.skipped == 'false' }} + with: + name: ${{ steps.version-check.outputs.tag }} + tag: ${{ steps.version-check.outputs.tag }} + commit: ${{ github.ref_name }} + token: ${{ secrets.GH_TOKEN }} + skipIfReleaseExists: true diff --git a/.github/workflows/onRelease.yml b/.github/workflows/onRelease.yml new file mode 100644 index 0000000..67374f5 --- /dev/null +++ b/.github/workflows/onRelease.yml @@ -0,0 +1,22 @@ +name: publish on release + +on: + release: + types: [released] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'pnpm' + - run: pnpm install --frozen-lockfile + - run: pnpm run build + # - name: Publish @powersync/cli to npm + # run: pnpm publish -- --no-git-checks --access public + # env: + # NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..84705ca --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,26 @@ +name: tests + +on: + push: + branches-ignore: [main] + +jobs: + unit-tests: + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + node_version: [24] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'pnpm' + - run: pnpm install --frozen-lockfile + - name: Check formatting + run: pnpm exec prettier --check . + - run: pnpm run build + - run: pnpm run test diff --git a/.gitignore b/.gitignore index 9a5aced..2504c3d 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,12 @@ dist # Vite logs files vite.config.js.timestamp-* vite.config.ts.timestamp-* + +# Playground for testing cli commands +playground/ + +# PNPM +.pnpm-store/ + +# MacOS +.DS_Store \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..0c1f9be --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +if git diff --cached --quiet --diff-filter=ACMR; then + exit 0 +fi + +git diff --cached --name-only -z --diff-filter=ACMR \ + | xargs -0 pnpm prettier --write --ignore-unknown + +if git diff --cached --name-only --diff-filter=ACMR -- '*.js' '*.cjs' '*.mjs' '*.ts' '*.tsx' | grep -q .; then + git diff --cached --name-only -z --diff-filter=ACMR -- '*.js' '*.cjs' '*.mjs' '*.ts' '*.tsx' \ + | xargs -0 pnpm eslint --fix +fi + +git diff --cached --name-only -z --diff-filter=ACMR \ + | xargs -0 git add -- diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a4965ac --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +pnpm-lock.yaml +**/pnpm-lock.yaml +**/*.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..23c42d1 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "bracketSameLine": true, + "useTabs": false, + "endOfLine": "lf", + "printWidth": 120, + "trailingComma": "none" +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..241d5aa --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# Agent Guidelines + +## Environment Variables + +- Do not read `process.env` directly in application code. +- Use typed env helpers (for example, `env` from `@powersync/cli-core`) so environment access is centralized and testable. +- Keep environment resolution logic in one place; command and service code should consume resolved values. + +## Testing Environment Behavior + +- Prefer mocking env helpers/modules in tests instead of relying on direct `process.env` reads in production code. +- Tests may set temporary env values when needed, but should primarily validate behavior through mocked env access points. +- Reset env-related mocks/state between tests to avoid leakage. + +## File Naming Conventions + +- Choose the filename based on the file's primary responsibility so agents can infer intent without opening the file. +- If the main export is a class or a type/interface, the filename must exactly match that export name (for example, `ServiceCloudConfig.ts`, `AccountsHubClientSDKClient.ts`). +- Use this class/type naming rule even if the file also contains small helper functions; the primary exported symbol takes precedence. +- If the file's purpose is utility logic (single function or a group of helper methods), use action-style kebab-case names in the form `do-this-action.ts` (for example, `ensure-service-type.ts`, `resolve-config-path.ts`). +- Utility filenames should describe what the code does, not what it is. Prefer verb-led names such as `load-*`, `parse-*`, `validate-*`, `write-*`, `ensure-*`. +- Avoid generic utility names like `helpers.ts`, `utils.ts`, or `common.ts` unless the file is intentionally a broad shared entry point. diff --git a/README.md b/README.md new file mode 100644 index 0000000..93dbe8b --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# PowerSync CLI + +Monorepo for the PowerSync CLI and related tooling. Built with [pnpm](https://pnpm.io) workspaces and [OCLIF](https://oclif.io). + +## Requirements + +- **Node**: LTS v24+ (see [.nvmrc](./.nvmrc); use `nvm use` to switch) +- **Package manager**: pnpm + +## Monorepo structure + +The workspace is split into the main CLI, shared **packages**, and optional **plugins**: + +| Package | Path | Description | +| ---------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------- | +| [**@powersync/cli**](./cli) | `cli/` | Main CLI — manage instances, config, sync config, cloud and self-hosted | +| [**@powersync/cli-core**](./packages/cli-core) | `packages/cli-core/` | Core types and base commands shared by the CLI and plugins | +| [**@powersync/cli-schemas**](./packages/schemas) | `packages/schemas/` | Shared config schemas (cli.yaml, service.yaml, etc.) | +| [**@powersync/cli-plugin-docker**](./plugins/docker) | `plugins/docker/` | Docker plugin — self-hosted PowerSync with Compose (configure, reset, start, stop) | + +``` +├── cli/ # @powersync/cli — main CLI (commands, cloud/self-hosted, templates) +├── packages/ +│ ├── cli-core/ # @powersync/cli-core — base commands & YAML utils (used by CLI + plugins) +│ └── schemas/ # @powersync/cli-schemas — config validation (LinkConfig, CLIConfig) +├── plugins/ +│ └── docker/ # @powersync/cli-plugin-docker — docker configure, reset, start, stop +├── examples/ # Sample projects initialized with the CLI (see examples/README.md) +│ ├── cloud/ +│ └── self-hosted/ +└── docs/ + ├── usage.md # General CLI usage (Cloud, self-hosted, linking, auth) + └── usage-docker.md # Docker plugin (configure, reset, start, stop, templates) +``` + +- **cli** depends on **cli-core**, **cli-schemas**, and **@powersync/cli-plugin-docker**. It loads the docker plugin and re-exports base command types from cli-core. +- **plugin-docker** (in **plugins/docker**) depends on **cli-core** and **cli-schemas**. No dependency on the CLI package. +- **cli-core** depends on **schemas**. It provides `SelfHostedInstanceCommand`, YAML helpers (`!env`), and shared types for plugins. + +Workspace roots are listed in [pnpm-workspace.yaml](./pnpm-workspace.yaml): `cli`, `packages/*`, `plugins/*`. + +## OCLIF plugins + +We rely on standard [OCLIF plugin loading](https://oclif.io/docs/plugins/) so plugins can register new commands or hook into command execution. The main CLI ships with a Docker plugin under [plugins/docker](./plugins/docker), and any other OCLIF-compatible plugin can be installed the same way. + +For PowerSync-specific plugins, the optional [@powersync/cli-core](./packages/cli-core) package exposes base command helpers and shared types. The Docker plugin consumes these helpers and adds Docker-focused commands as a reference implementation. + +Users can manage their own installed plugins dynamically at runtime. Run `powersync plugins --help` for install, uninstall, and inspection options. + +## Getting started + +```bash +nvm use # use Node from .nvmrc (optional) +pnpm install +pnpm build +``` + +Run the CLI from the repo root: + +```bash +powersync --help +``` + +### Self-hosted with Docker + +From the repo root, create the Docker layout and run the stack: + +```bash +powersync docker configure +powersync docker start +``` + +See [plugins/docker](./plugins/docker/README.md) and [docs/usage-docker.md](./docs/usage-docker.md) for details. + +## Examples + +The [**examples/**](./examples) folder contains basic projects initialized with the CLI. See [examples/README.md](./examples/README.md) for the full list and links to each example's README. + +## Documentation + +- [**Usage**](./docs/usage.md) — How the CLI works: Cloud and self-hosted, linking, auth, supplying instance info +- [**Usage (Docker)**](./docs/usage-docker.md) — Docker plugin: configure, reset, start, stop, templates, flags +- [**CLI documentation conventions**](./docs/cli-documentation-conventions.md) — How we document commands (description, summary, examples, flags, topics) +- [CLI package README](./cli/README.md) — Install, usage, and command reference diff --git a/cli/.gitignore b/cli/.gitignore new file mode 100644 index 0000000..aa9b0e5 --- /dev/null +++ b/cli/.gitignore @@ -0,0 +1,5 @@ +/dist +/tmp +oclif.manifest.json + + diff --git a/cli/.prettierrc.json b/cli/.prettierrc.json new file mode 100644 index 0000000..1e6fece --- /dev/null +++ b/cli/.prettierrc.json @@ -0,0 +1 @@ +"../.prettierrc.json" diff --git a/cli/README.md b/cli/README.md new file mode 100644 index 0000000..17729d5 --- /dev/null +++ b/cli/README.md @@ -0,0 +1,1501 @@ +# powersync + +CLI for PowerSync + +[![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io) +[![Version](https://img.shields.io/npm/v/@powersync/cli.svg)](https://npmjs.org/package/@powersync/cli) +[![Downloads/week](https://img.shields.io/npm/dw/@powersync/cli.svg)](https://npmjs.org/package/@powersync/cli) + + + +- [powersync](#powersync) +- [Getting Started](#getting-started) +- [Overview](#overview) +- [Cloud](#cloud) +- [Self-hosted](#self-hosted) +- [powersync/service.yaml (self-hosted instance config)](#powersyncserviceyaml-self-hosted-instance-config) +- [powersync/cli.yaml (self-hosted)](#powersynccliyaml-self-hosted) +- [Known Limitations](#known-limitations) +- [OCLIF plugins](#oclif-plugins) +- [list installed plugins](#list-installed-plugins) +- [install a published plugin](#install-a-published-plugin) +- [link a local plugin during development](#link-a-local-plugin-during-development) +- [inspect a plugin](#inspect-a-plugin) +- [Usage](#usage) +- [Commands](#commands) + + +# Getting Started + +Install globally or run via `npx`: + +```bash +npm install -g powersync +``` + +```bash +npx powersync --version +``` + +# Overview + +The PowerSync CLI lets you manage PowerSync instances and run commands (generate schemas, tokens, validate config, fetch status, and more). Support is split into two modes: + +- **Cloud** – Full support for [PowerSync Cloud](https://powersync.com). You can create new instances, deploy and pull config from the Dashboard, and run all Cloud commands. Authenticate with **`powersync login`** (or the `PS_ADMIN_TOKEN` env var), then use **`powersync init cloud`** / **`powersync link cloud`** or **`powersync pull instance`** to work with projects. +- **Self-hosted** – Limited support for your own PowerSync Service. You link to an existing running instance and can run a subset of commands (e.g. **`powersync status`**, **`powersync generate schema`**, **`powersync validate`**). The CLI does not create, deploy to, or pull config from self-hosted instances; you manage the server and its config yourself. We also expose a [PowerSync Docker topic](../plugins/docker/README.md) for local self-hosted development. + +The sections below go into detail for [Cloud](#cloud) and [Self-hosted](#self-hosted). + +# Cloud + +The CLI supports **PowerSync Cloud** for creating instances, deploying config, pulling config, and running commands. Cloud workflows use a **config directory** (default `powersync/`) containing **`service.yaml`**, **`sync-config.yaml`**, and optionally **`cli.yaml`** (the link file written by **powersync link cloud**). All PowerSync YAML files support the **`!env`** custom tag (e.g. `!env MY_VAR` or `!env MY_VAR::number`) for secrets and environment-specific values. + +## Login + +Cloud commands require a PowerSync **personal access token (PAT)**. You can authenticate in two ways: + +**1. Interactive login (recommended for local use)** +Run **`powersync login`**. You can either open a browser to create a token in the [PowerSync Dashboard](https://dashboard.powersync.com/account/access-tokens/create) or paste an existing token. + +- If secure storage is available, the token is saved there (for example, macOS Keychain). +- If secure storage is unavailable, the CLI asks for confirmation before storing the token in plaintext at **`$XDG_CONFIG_HOME/powersync/config.yaml`** (or **`~/.config/powersync/config.yaml`** when `XDG_CONFIG_HOME` is unset). +- If you decline, login exits without storing a token. + +**2. Environment variable (CI, scripts, or non-persistent use)** +Set **`PS_ADMIN_TOKEN`** to your PAT. The CLI uses **`PS_ADMIN_TOKEN`** when set; otherwise it uses the token from **`powersync login`**. Example: + +```sh +export PS_ADMIN_TOKEN=your-personal-access-token +powersync fetch instances --project-id= +``` + +To stop using stored credentials, run **`powersync logout`**. This clears the stored token from the active backend (secure storage or config-file fallback). + +## Creating a new instance + +Run **`powersync init cloud`** to scaffold the config directory. Configure **`service.yaml`** (name, region, replication, optional client auth) and sync config; use **`!env`** for all secrets. Then run **`powersync link cloud --create`** with `--project-id` to create the instance and write **`cli.yaml`**. (Add `--org-id` only if your token has access to multiple organizations.) After that you can run **`powersync deploy`** and manage config from the project (or switch to managing it externally if you prefer). + +```sh +powersync init cloud + # then edit powersync/service.yaml and sync config +powersync login +powersync link cloud --create --project-id= # add --org-id if token has multiple orgs +powersync deploy +``` + +Use `--directory` for a different config folder. The **powersync init cloud** command has a `--vscode` flag to configure your workspace for YAML custom tag support. + +## Cloud secrets format (`service.yaml`) + +For Cloud config, secret-backed fields use an object shape. For example, the replication connection password is configured as `replication.connections[].password`. + +Use `secret: !env ...` when you want to provide the value from an environment variable during deploy: + +```yaml +replication: + connections: + - type: postgresql + password: + secret: !env POWERSYNC_DATABASE_PASSWORD +``` + +After an initial deploy, you can keep using the same stored value by switching to `secret_ref` and referencing the default password secret: + +```yaml +replication: + connections: + - type: postgresql + password: + secret_ref: default_password +``` + +This avoids re-supplying the raw password in subsequent deploys while reusing the previously stored secret. + +## Using an existing instance (pull) + +Run **`powersync pull instance`** with the instance identifiers (from the PowerSync Dashboard URL or **`powersync fetch instances`**). This creates the config directory, writes **`cli.yaml`**, and downloads **`service.yaml`** and **`sync-config.yaml`**. Edit as needed, then run **`powersync deploy`**. + +```sh +powersync login +powersync pull instance --project-id= --instance-id= # add --org-id if multiple orgs + # then edit powersync/service.yaml and sync-config.yaml as needed +powersync deploy +``` + +To refresh local config after external edits from the cloud when already linked, run **`powersync pull instance`** again. + +## Running commands against externally managed instances + +You can run CLI commands (e.g. **`powersync generate schema`**, **`powersync generate token`**, **`powersync status`**) against a Cloud instance whose configuration is managed elsewhere—for example in the PowerSync Dashboard. No local config directory or link file is required. + +Specify the instance using **environment variables** or **CLI flags** (flags take precedence): `--instance-id` and `--project-id` (or `INSTANCE_ID`, `PROJECT_ID`). **`--org-id` is optional**: when omitted, the CLI uses the token’s single organization if the token has access to exactly one; if the token has multiple orgs, you must pass **`--org-id`** (or set `ORG_ID`). + +```sh +powersync login +powersync generate schema --instance-id= --project-id= --output-path=schema.ts --output=ts # add --org-id if multiple orgs + # or with env vars (set ORG_ID only if your token has multiple orgs): +export PROJECT_ID= +export INSTANCE_ID= +powersync generate schema --output-path=schema.ts --output=ts +``` + +**Tip:** To avoid passing instance params on every command, run **`powersync link cloud`** (e.g. `powersync link cloud --instance-id= --project-id=`) once. The CLI writes `cli.yaml` in the current directory, and subsequent commands use that instance without flags or env vars. + +# Self-hosted + +The CLI can run a subset of commands against **self-hosted** PowerSync instances (your own API). Self-hosted support is more limited than Cloud: you link to an existing running API and use the same config directory concept, but only certain commands apply (e.g. **`powersync status`**, **`powersync generate schema`**, **`powersync generate token`**, **`powersync validate`**). There is no **deploy** or **pull instance** for self-hosted; you manage config on the server yourself. + +## Authentication + +For any self-hosted instance (local or remote), you must link the running API to the CLI and configure an API key. On the **server** (your PowerSync instance config), define the tokens that are valid in **`service.yaml`**: + +```yaml +# powersync/service.yaml (self-hosted instance config) +api: + tokens: + - dev-token-do-not-use-in-production # or use !env MY_API_TOKEN for secrets +``` + +Then tell the CLI which token to use when running commands. Run **`powersync link self-hosted --api-url `** to write **`cli.yaml`** with the API URL, and either set the **`PS_ADMIN_TOKEN`** environment variable or set **`api_key`** in **`cli.yaml`**: + +```yaml +# 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 +``` + +The CLI resolves **`!env PS_ADMIN_TOKEN`** from the `PS_ADMIN_TOKEN` environment variable at runtime. If both are set, the environment variable takes precedence. + +## Creating a self-hosted project and limitations + +Run **`powersync init self-hosted`** to scaffold a config directory. Edit **`service.yaml`** with your instance details and use **`!env`** for secrets. This gives you a **partial** project: the CLI does not create or provision a self-hosted instance. You must already have a running PowerSync API. The CLI cannot deploy config to or pull config from a self-hosted instance; you manage **`service.yaml`** and **`sync-config.yaml`** on the server yourself. Use the CLI to link (**`powersync link self-hosted --api-url `**), then run the supported commands (e.g. **`powersync status`**, **`powersync generate schema`**) against that API. + +```sh +powersync init self-hosted + # then edit powersync/service.yaml +powersync link self-hosted --api-url https://powersync.example.com +powersync status +``` + +Use `--directory` for a different config folder. + +## PowerSync Docker topic for local development + +We expose a [PowerSync Docker topic](../plugins/docker/README.md) for running a self-hosted stack locally. Use **`powersync docker configure`** then **`powersync docker start`** to run the stack. Use **`powersync docker reset`** only when you need to start from a clean state (stop and remove, then start). + +## Command support + +Only some CLI commands work with self-hosted instances. Supported commands include **`powersync status`**, **`powersync generate schema`**, **`powersync generate token`**, **`powersync validate`**, and **`powersync link self-hosted`**. Cloud-only commands such as **`powersync deploy`**, **`powersync destroy`**, **`powersync pull instance`**, **`powersync fetch config`**, and **`powersync fetch instances`** do not apply to self-hosted. + +# Known Limitations + +- **Plaintext fallback storage**: When secure storage is unavailable, login can store the token in plaintext config (`$XDG_CONFIG_HOME/powersync/config.yaml` or `~/.config/powersync/config.yaml`) only after explicit confirmation. + +# OCLIF plugins + +The CLI honors standard [OCLIF plugin behavior](https://oclif.io/docs/plugins/), so plugins can register commands or hook into command lifecycles. The bundled PowerSync Docker topic (`@powersync/cli-plugin-docker`) is implemented this way and serves as a reference. + +For PowerSync-specific plugins, the optional `@powersync/cli-core` package exposes base command helpers and shared types; the PowerSync Docker topic consumes these helpers to add its Docker-focused commands. + +You can manage plugins dynamically at runtime: + +```sh +# list installed plugins +powersync plugins + +# install a published plugin +powersync plugins install @example/powersync-plugin-foo + +# link a local plugin during development +powersync plugins link ../my-plugin + +# inspect a plugin +powersync plugins:inspect @example/powersync-plugin-foo +``` + +# Usage + + + +```sh-session +$ npm install -g powersync +$ powersync COMMAND +running command... +$ powersync (--version) +powersync/0.0.0 darwin-arm64 node-v24.13.0 +$ powersync --help [COMMAND] +USAGE + $ powersync COMMAND +... +``` + + + +## Environment variables + +You can supply instance and auth context via environment variables (useful for CI or scripts): + +- **`PS_ADMIN_TOKEN`** — PowerSync personal access token for Cloud commands. [Learn more](https://docs.powersync.com/usage/tools/cli#personal-access-token). +- **`ORG_ID`** — Organization ID (optional for Cloud). Omit when your token has a single organization; required when it has multiple. +- **`PROJECT_ID`** — Project ID (Cloud). +- **`INSTANCE_ID`** — Instance ID (Cloud). Get IDs from the [PowerSync Dashboard](https://dashboard.powersync.com) or **`powersync fetch instances`**. +- **`API_URL`** — Self-hosted PowerSync API base URL (e.g. `https://powersync.example.com`). + +Example (Cloud): + +```sh +PS_ADMIN_TOKEN=your-token PROJECT_ID=456 INSTANCE_ID=789 powersync status +``` + +See [docs/usage.md](../docs/usage.md) for full usage and resolution order (flags, env, cli.yaml). + +# Commands + + + +- [`powersync autocomplete [SHELL]`](#powersync-autocomplete-shell) +- [`powersync commands`](#powersync-commands) +- [`powersync deploy`](#powersync-deploy) +- [`powersync deploy service-config`](#powersync-deploy-service-config) +- [`powersync deploy sync-config`](#powersync-deploy-sync-config) +- [`powersync destroy`](#powersync-destroy) +- [`powersync docker configure`](#powersync-docker-configure) +- [`powersync docker reset`](#powersync-docker-reset) +- [`powersync docker start`](#powersync-docker-start) +- [`powersync docker stop`](#powersync-docker-stop) +- [`powersync fetch config`](#powersync-fetch-config) +- [`powersync fetch instances`](#powersync-fetch-instances) +- [`powersync fetch status`](#powersync-fetch-status) +- [`powersync generate schema`](#powersync-generate-schema) +- [`powersync generate token`](#powersync-generate-token) +- [`powersync help [COMMAND]`](#powersync-help-command) +- [`powersync init cloud`](#powersync-init-cloud) +- [`powersync init self-hosted`](#powersync-init-self-hosted) +- [`powersync link cloud`](#powersync-link-cloud) +- [`powersync link self-hosted`](#powersync-link-self-hosted) +- [`powersync login`](#powersync-login) +- [`powersync logout`](#powersync-logout) +- [`powersync migrate sync-rules`](#powersync-migrate-sync-rules) +- [`powersync plugins`](#powersync-plugins) +- [`powersync plugins add PLUGIN`](#powersync-plugins-add-plugin) +- [`powersync plugins:inspect PLUGIN...`](#powersync-pluginsinspect-plugin) +- [`powersync plugins install PLUGIN`](#powersync-plugins-install-plugin) +- [`powersync plugins link PATH`](#powersync-plugins-link-path) +- [`powersync plugins remove [PLUGIN]`](#powersync-plugins-remove-plugin) +- [`powersync plugins reset`](#powersync-plugins-reset) +- [`powersync plugins uninstall [PLUGIN]`](#powersync-plugins-uninstall-plugin) +- [`powersync plugins unlink [PLUGIN]`](#powersync-plugins-unlink-plugin) +- [`powersync plugins update`](#powersync-plugins-update) +- [`powersync pull instance`](#powersync-pull-instance) +- [`powersync status`](#powersync-status) +- [`powersync stop`](#powersync-stop) +- [`powersync validate`](#powersync-validate) + +## `powersync autocomplete [SHELL]` + +Display autocomplete installation instructions. + +``` +USAGE + $ powersync autocomplete [SHELL] [-r] + +ARGUMENTS + [SHELL] (zsh|bash|powershell) Shell type + +FLAGS + -r, --refresh-cache Refresh cache (ignores displaying instructions) + +DESCRIPTION + Display autocomplete installation instructions. + +EXAMPLES + $ powersync autocomplete + + $ powersync autocomplete bash + + $ powersync autocomplete zsh + + $ powersync autocomplete powershell + + $ powersync autocomplete --refresh-cache +``` + +_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.2.40/src/commands/autocomplete/index.ts)_ + +## `powersync commands` + +List all powersync commands. + +``` +USAGE + $ powersync commands [--json] [-c id|plugin|summary|type... | --tree] [--deprecated] [-x | ] [--hidden] + [--no-truncate | ] [--sort id|plugin|summary|type | ] + +FLAGS + -c, --columns=