appwrite-cli

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Appwrite CLI

Appwrite CLI

appwrite <command> --help
already lists flags. Read it instead of guessing.
appwrite <command> --help
已经列出了所有标志。请直接阅读该命令输出,不要自行猜测。

Config vs
client

配置文件 vs
client
命令

A real project (repo, schema, functions, deploys, CI) lives in
appwrite.config.json
. Init once. Pull and push after that. Do not
appwrite client --project-id
on every command — the config already names the project.
A one-off (inspect a user, patch one row, poke a remote you will not return to) uses
appwrite client
. Do not scaffold a project for a single API call.
bash
undefined
正式项目(代码库、架构、函数、部署、CI流程)的配置存储在
appwrite.config.json
中。只需初始化一次,之后使用pull和push命令同步。不要在每个命令中都使用
appwrite client --project-id
——配置文件中已经指定了项目ID。
一次性操作(查看用户信息、修改单行数据、访问不会再使用的远程资源)使用
appwrite client
命令。不要为单次API调用搭建完整项目结构。
bash
undefined

Good — project

推荐操作 — 正式项目流程

appwrite login appwrite list-projects --json appwrite init project --project-id <ID> appwrite pull table
appwrite login appwrite list-projects --json appwrite init project --project-id <ID> appwrite pull table

edit appwrite.config.json, then:

编辑appwrite.config.json后执行:

appwrite push table --force
appwrite push table --force

Bad — project treated as a pile of API calls

不推荐操作 — 将项目当作零散API调用处理

appwrite tablesdb create-table --database-id main --table-id songs ... appwrite tablesdb create-varchar-column --database-id main --table-id songs ...
appwrite tablesdb create-table --database-id main --table-id songs ... appwrite tablesdb create-varchar-column --database-id main --table-id songs ...

the next clone has no record of this

下次克隆项目时,这些操作记录会丢失

Good — one-off (already logged in)

推荐操作 — 一次性操作(已登录状态)

appwrite client --project-id <ID> appwrite users get --user-id <ID> --json
appwrite client --project-id <ID> appwrite users get --user-id <ID> --json

Bad — one-off that litters a repo

不推荐操作 — 在无关仓库中生成项目文件

cd ~/some-unrelated-app && appwrite init project

No session? `appwrite client --endpoint https://<REGION>.cloud.appwrite.io/v1 --key "$APPWRITE_API_KEY" --project-id <ID>`.

`appwrite client --project-id` writes `appwrite.config.json` in this directory (or updates one found walking up). That is how you link a folder quickly. Do not run it at the root of an unrelated repo. `APPWRITE_PROJECT_ID` / `APPWRITE_ENDPOINT` override the file without touching it — use those when you are already inside a project and need a one-shot against something else.
cd ~/some-unrelated-app && appwrite init project

无会话时?使用`appwrite client --endpoint https://<REGION>.cloud.appwrite.io/v1 --key "$APPWRITE_API_KEY" --project-id <ID>`。

`appwrite client --project-id`会在当前目录(或向上遍历找到的目录)中写入/更新`appwrite.config.json`,这是快速关联文件夹的方式。不要在无关仓库的根目录运行该命令。环境变量`APPWRITE_PROJECT_ID`/`APPWRITE_ENDPOINT`会覆盖配置文件内容但不会修改文件——当你已在项目目录中,需要对其他资源执行一次性操作时可以使用这些变量。

Auth is not the project

身份认证与项目是分离的

LayerLives inSet with
Who you are (session or API key)global CLI prefs
appwrite login
or
appwrite client --key
Which project
appwrite.config.json
init project
,
pull
, or
client --project-id
init project
talks to the console. It needs a login session. An API key cannot list organizations.
bash
undefined
层级存储位置设置方式
身份信息(会话或API密钥)全局CLI偏好设置
appwrite login
appwrite client --key
项目归属
appwrite.config.json
init project
pull
client --project-id
init project
命令会与控制台通信,需要登录会话。API密钥无法列出组织信息。
bash
undefined

Good — CI against a checked-in config

推荐操作 — CI流程使用已提交的配置文件

appwrite client --key "$APPWRITE_API_KEY" appwrite push function --force
appwrite client --key "$APPWRITE_API_KEY" appwrite push function --force

Bad — CI that bakes the key into the repo

不推荐操作 — CI流程将密钥硬编码到仓库

appwrite client --key 'standard_....'
appwrite client --key 'standard_....'

and commits appwrite.config.json with secrets inside

并提交包含密钥的appwrite.config.json


Env beats the config: `APPWRITE_PROJECT_ID`, `APPWRITE_ENDPOINT`, `APPWRITE_ORGANIZATION_ID`. Check in the config (no secrets). Put keys in the environment.

`--force` skips prompts. Agents and CI have no TTY, so a push that needs confirmation fails without it (`Pass --force instead`). Ask the user, then pass `--force`. Do not use it to skip a change table whose local column is empty.

`appwrite login --switch` rotates saved accounts. `appwrite client --debug` prints the effective endpoint/project with credentials masked. `appwrite client --reset` signs out of everything.

环境变量优先级高于配置文件:`APPWRITE_PROJECT_ID`、`APPWRITE_ENDPOINT`、`APPWRITE_ORGANIZATION_ID`。提交配置文件时不要包含敏感信息,密钥应存储在环境变量中。

`--force`参数会跳过确认提示。代理和CI环境没有交互终端,因此需要确认的push操作如果不加该参数会失败(提示`Pass --force instead`)。在需要确认用户操作后再使用该参数,不要用它跳过本地列为空的表格变更。

`appwrite login --switch`可切换已保存的账户。`appwrite client --debug`会打印生效的端点/项目信息,并隐藏凭证。`appwrite client --reset`会登出所有账户。

Cloud endpoints

Cloud区域端点

appwrite whoami
showing
https://cloud.appwrite.io/v1
is the account login host. Leave it. Project API calls use the region host (
https://fra.cloud.appwrite.io/v1
, and so on).
init project
and
client --project-id
pin that region into the config. Self-hosted: one endpoint for both.
bash
undefined
appwrite whoami
显示的
https://cloud.appwrite.io/v1
账户登录主机,无需修改。项目API调用使用区域主机(如
https://fra.cloud.appwrite.io/v1
等)。
init project
client --project-id
会将该区域信息写入配置文件。自托管部署:账户和项目使用同一个端点。
bash
undefined

Good — project work uses the config's regional endpoint

推荐操作 — 项目操作使用配置文件中的区域端点

cat appwrite.config.json # "endpoint": "https://fra.cloud.appwrite.io/v1"
cat appwrite.config.json # "endpoint": "https://fra.cloud.appwrite.io/v1"

Bad — "fixing" whoami

不推荐操作 — 错误修改whoami的端点

appwrite client --endpoint https://fra.cloud.appwrite.io/v1
appwrite client --endpoint https://fra.cloud.appwrite.io/v1

now login/session calls go to a region host they do not belong on

现在登录/会话请求会发送到区域主机,这不符合设计逻辑

undefined
undefined

Schema vs rows

架构与数据行

Pull / push (config)Service commands (not in the config)
settings, functions, sites, tables and columns, buckets, teams, webhooks, topicsrows, users, files, executions, messages
If it should survive a fresh clone, it belongs in the config. Edit the file, then push. Creating the same resources with
tablesdb create-*
or
functions create
bypasses the file the next
pull
/
push
expects.
databases
is deprecated. Use
tablesdb
and
push table
.
If the change table shows remote values against empty local, the config is missing those fields. Pull that resource, then push. Do not
--force
through it, and do not pull everything as a ritual —
pull settings
is slow.
text
   id            │ key             │ remote │ local
  ───────────────┼─────────────────┼────────┼───────
   Service       │ account         │ true   │
   Auth method   │ email-password  │ true   │
bash
undefined
Pull / push(配置文件同步)服务命令(不写入配置文件)
设置、函数、站点、表与列、存储桶、团队、Webhook、主题数据行、用户、文件、执行记录、消息
如果资源需要在全新克隆项目后保留,就应该存入配置文件。编辑配置文件后执行push。使用
tablesdb create-*
functions create
创建的资源不会被后续的pull/push命令识别。
databases
命令已废弃,请使用
tablesdb
push table
如果变更表显示远程有值但本地为空,说明配置文件缺少这些字段。先pull该资源,再执行push。不要用
--force
强制跳过,也不要习惯性pull所有资源——
pull settings
速度较慢。
text
   id            │ key             │ remote │ local
  ───────────────┼─────────────────┼────────┼───────
   Service       │ account         │ true   │
   Auth method   │ email-password  │ true   │
bash
undefined

Good — local column was empty, so sync first, then push

推荐操作 — 本地列为空时先同步,再push

appwrite pull settings appwrite push settings --force
appwrite pull settings appwrite push settings --force

Bad — empty local, forced through

不推荐操作 — 本地为空时强制push

appwrite push settings --force

`push all --all --force` pushes every resource. Scope it (`push function --function-id api`) unless you mean that.

`unique()` is fine for a one-shot row or user. Resources you will push need a **stable** `$id` in the config so the next pull matches.
appwrite push settings --force

`push all --all --force`会推送所有资源。除非确实需要,否则请限定范围(如`push function --function-id api`)。

`unique()`适合一次性数据行或用户创建。需要push的资源在配置文件中需要**稳定**的`$id`,这样后续pull才能匹配。

Type-safe application code

类型安全的应用代码

When writing application code against TablesDB, inspect
appwrite.config.json
before inventing interfaces, database IDs, table IDs, or column names. The generators read the local config; they do not inspect the remote schema. A stale config produces stale code.
If the remote schema is the source of truth, update the config first with
appwrite pull table
. Do not pull over local, unpushed schema edits. If the local config is ahead, generate from it as-is.
For TypeScript, prefer
appwrite generate
. It emits a complete TablesDB wrapper: database and table choices, create/update payloads, returned rows, query fields, and query values are checked by TypeScript. This is stronger than generated model interfaces alone.
bash
appwrite generate
Use the generated API instead of dropping back to raw string IDs and handwritten payload types:
typescript
import { databases, type Songs } from "./generated/appwrite/index.js";

// Database lookup uses its ID; table lookup uses its name from the config.
const songs = databases.use("main").use("Songs");

const page = await songs.list({
  queries: (query) => [
    query.equal("published", true),
    query.orderDesc("createdAt"),
    query.limit(20),
  ],
});

const first: Songs | undefined = page.rows[0];
Do not guess the literals in that example: read the generated types or the config. In particular,
.use()
for a table takes its
name
, which may differ from its
$id
. Let compilation expose a misspelled table, column, or wrong query value. Run the project's type checker after generation.
generate
currently provides the full wrapper for TypeScript. It detects client versus server output from the installed Appwrite package. Server output reads
APPWRITE_API_KEY
; never put that key in generated constants or commit it. Override language, import source, module extension, or client/server mode only when detection is wrong—read
appwrite generate --help
for those flags.
For another supported language, or when the project deliberately uses the regular SDK directly, use
appwrite types <output-directory>
. It supports TypeScript (
ts
), JavaScript (
js
), PHP (
php
), Kotlin (
kotlin
), Swift (
swift
), Java (
java
), Dart (
dart
), and C# (
cs
). Pass these short values to
--language
; names such as
typescript
and
csharp
are not the command's accepted values. Generated files type row data, but they do not type-check raw database/table IDs or
Query
calls:
For TypeScript, pass a
.ts
destination when the result will be imported as a module. Passing a directory instead creates
appwrite.d.ts
inside it.
bash
appwrite types ./src/appwrite-types.ts --language ts
typescript
import { Client, TablesDB } from "appwrite";
import type { Songs } from "./appwrite-types.js";

// Read these values from appwrite.config.json and expose them through the
// application's existing configuration mechanism.
const client = new Client()
  .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
  .setProject("<PROJECT_ID>");
const tablesDB = new TablesDB(client);

const page = await tablesDB.listRows<Songs>({
  databaseId: "main", // still an unchecked string
  tableId: "songs",  // still an unchecked string
});
Do not describe
types --strict
as “full type safety.” It only converts field names to the target language's naming conventions. Use
generate
when a fully typed TypeScript table API is the goal.
Generated code is derived output. Do not patch it to fix a schema or naming problem; fix
appwrite.config.json
or the generator inputs and regenerate. After every table or column change, rerun the same generation command the repository uses and run its formatter/type checker. Preserve the repository's existing output path and check-in convention.
当针对TablesDB编写应用代码时,先查看
appwrite.config.json
,不要自行定义接口、数据库ID、表ID或列名。代码生成器读取本地配置文件,不会检查远程架构。过时的配置文件会生成过时的代码。
如果远程架构是可信来源,先执行
appwrite pull table
更新配置文件。不要覆盖本地未推送的架构修改。如果本地配置文件更新更及时,可以直接基于它生成代码。
对于TypeScript,优先使用
appwrite generate
。它会生成完整的TablesDB包装器:数据库和表选择、创建/更新负载、返回数据行、查询字段和查询值都会被TypeScript校验。这比仅生成模型接口更可靠。
bash
appwrite generate
使用生成的API,不要退回到原始字符串ID和手写负载类型:
typescript
import { databases, type Songs } from "./generated/appwrite/index.js";

// 数据库查找使用ID;表查找使用配置文件中的名称。
const songs = databases.use("main").use("Songs");

const page = await songs.list({
  queries: (query) => [
    query.equal("published", true),
    query.orderDesc("createdAt"),
    query.limit(20),
  ],
});

const first: Songs | undefined = page.rows[0];
不要猜测示例中的字面量:查看生成的类型或配置文件。特别注意,表的
.use()
方法接受的是表的
name
,可能与其
$id
不同。让编译过程检测拼写错误的表、列或错误的查询值。生成代码后运行项目的类型检查器。
generate
目前仅为TypeScript提供完整包装器。它会根据已安装的Appwrite包自动检测客户端或服务端输出。服务端输出会读取
APPWRITE_API_KEY
;绝对不要将该密钥放入生成的常量或提交到仓库。只有当自动检测错误时才需要覆盖语言、导入源、模块扩展名或客户端/服务端模式——请查看
appwrite generate --help
获取这些标志。
对于其他支持的语言,或项目刻意直接使用常规SDK时,使用
appwrite types <output-directory>
。它支持TypeScript(
ts
)、JavaScript(
js
)、PHP(
php
)、Kotlin(
kotlin
)、Swift(
swift
)、Java(
java
)、Dart(
dart
)和C#(
cs
)。请将这些短值传递给
--language
参数;
typescript
csharp
等名称不是命令接受的值。生成的文件会为行数据添加类型,但不会对原始数据库/表ID或
Query
调用进行类型校验:
对于TypeScript,如果结果将作为模块导入,请传递
.ts
目标路径。传递目录会在其中创建
appwrite.d.ts
文件。
bash
appwrite types ./src/appwrite-types.ts --language ts
typescript
import { Client, TablesDB } from "appwrite";
import type { Songs } from "./appwrite-types.js";

// 从appwrite.config.json读取这些值,并通过应用现有的配置机制暴露。
const client = new Client()
  .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
  .setProject("<PROJECT_ID>");
const tablesDB = new TablesDB(client);

const page = await tablesDB.listRows<Songs>({
  databaseId: "main", // 仍是未校验的字符串
  tableId: "songs",  // 仍是未校验的字符串
});
不要将
types --strict
描述为“完全类型安全”。它仅会将字段名转换为目标语言的命名规范。当目标是获得完全类型化的TypeScript表API时,请使用
generate
生成的代码是衍生输出。不要通过修改生成代码来修复架构或命名问题;请修改
appwrite.config.json
或生成器输入后重新生成。每次修改表或列后,运行仓库中使用的生成命令,并执行格式化/类型检查。保留仓库现有的输出路径和提交规范。

Functions and sites

函数与站点

Variables live in
<path>/.env
, not in
appwrite.config.json
.
--with-variables
replaces the remote set from that file. Omit it unless you intend to sync secrets.
bash
undefined
变量存储在
<path>/.env
中,而非
appwrite.config.json
--with-variables
参数会替换远程端的变量集合。除非有意同步敏感信息,否则不要使用该参数。
bash
undefined

Good — ship code, leave remote vars alone

推荐操作 — 仅部署代码,保留远程变量

appwrite push function --function-id api --activate --force
appwrite push function --function-id api --activate --force

Bad — remote vars you did not list locally are gone

不推荐操作 — 本地未列出的远程变量会被删除

appwrite push function --function-id api --with-variables --force
appwrite push function --function-id api --with-variables --force

Good — deploy without switching live traffic

推荐操作 — 部署但不切换流量

appwrite push function --function-id api --activate=false --force

`--async` returns before the build finishes. Local: `appwrite run function`.
appwrite push function --function-id api --activate=false --force

`--async`参数会在构建完成前返回结果。本地测试使用`appwrite run function`。

Queries and output

查询与输出

Prefer
--filter
,
--sort-asc
/
--sort-desc
,
--limit
,
--select
,
--cursor-after
.
--where
is deprecated.
--queries
only for Query JSON the flags cannot express.
bash
undefined
优先使用
--filter
--sort-asc
/
--sort-desc
--limit
--select
--cursor-after
--where
已废弃。仅当标志无法表达复杂查询时才使用
--queries
传递JSON格式的Query。
bash
undefined

Good

推荐操作

appwrite users list
--filter 'emailVerification=true'
--sort-desc '$createdAt'
--limit 20
--json
appwrite users list
--filter 'emailVerification=true'
--sort-desc '$createdAt'
--limit 20
--json

Bad

不推荐操作

appwrite users list --queries '[{"method":"equal","attribute":"emailVerification","values":[true]}]'

`--filter` parses `true` / `false` / `null`, numbers, and JSON arrays. Repeat the flag to AND. List pages cap at 100; prefer `--cursor-after <lastId>` over a large `--offset`.

`--json` for scripts (empty fields dropped). `--raw` for the unfiltered payload. Secrets stay redacted unless `--show-secrets`.
appwrite users list --queries '[{"method":"equal","attribute":"emailVerification","values":[true]}]'

`--filter`可解析`true`/`false`/`null`、数字和JSON数组。重复该标志表示逻辑AND。列表分页上限为100条;优先使用`--cursor-after <lastId>`而非大数值的`--offset`。

脚本中使用`--json`(空字段会被忽略)。`--raw`用于获取未过滤的负载。敏感信息会被自动屏蔽,除非使用`--show-secrets`。

The config file itself

配置文件本身

The CLI walks up from cwd looking for
appwrite.config.json
(or the legacy
appwrite.json
).
push
from
functions/api/
still hits the project root. A stray config in a parent directory will capture you.
Split large projects with
includes
— each value is a relative
.json
array. A resource cannot be both inline and included. Function and site
path
values resolve relative to the include file, not the repo root.
Do not invent the file from memory.
init project
or
pull
writes a valid one. Then edit.
CLI会从当前目录向上遍历查找
appwrite.config.json
(或旧版
appwrite.json
)。在
functions/api/
目录执行push仍会找到项目根目录的配置文件。父目录中的无关配置文件可能会干扰操作。
大型项目可使用
includes
拆分配置——每个值是相对路径的
.json
数组。资源不能同时存在于主配置和引入配置中。函数和站点的
path
值相对于引入文件解析,而非仓库根目录。
不要凭记忆编写配置文件。
init project
pull
会生成有效的配置文件,之后再进行编辑。