关于 appwrite-cli
介绍如何使用 Appwrite CLI 管理项目、配置、部署和生成类型。指南区分持久化项目操作与一次性 API 调用,并说明安全同步和 CI 使用方式。
主要功能
- 01项目配置与资源同步
- 02身份验证、端点和环境变量管理
- 03按范围部署资源
- 04生成 TypeScript API 与类型
- 05筛选、JSON 输出和分页
适用场景
- 01根据配置同步项目架构和函数
- 02在 CI 中部署指定资源
- 03根据项目配置生成类型化 TablesDB 封装
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ appwrite/ skills --skill appwrite-cli安装后在 Claude Code 中输入/appwrite-cli确认已加载。
详细介绍
Appwrite CLI
appwrite <command> --help 已列出标志。请先查看,而不是猜测。
配置与 client
真实项目(代码库、架构、函数、部署、CI)存储在 appwrite.config.json 中。初始化一次即可。之后执行拉取和推送。不要在每条命令上都运行 appwrite client --project-id——配置文件已经指定了项目。
一次性操作(检查用户、修改一行数据、临时调用不会再用到的远程服务)使用 appwrite client。不要为了单次 API 调用搭建项目。
# Good — project
appwrite login
appwrite list-projects --json
appwrite init project --project-id <ID>
appwrite pull table
# edit appwrite.config.json, then:
appwrite push table --force
# Bad — project treated as a pile of API calls
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
# Bad — one-off that litters a repo
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 可以覆盖配置文件,且不会修改该文件——如果你已在某个项目中,但需要对其他项目进行一次性操作,请使用这些变量。
身份验证不等于项目
| 层 | 存储位置 | 设置方式 |
|---|---|---|
| 你的身份(会话或 API 密钥) | CLI 全局首选项 | appwrite login 或 appwrite client --key |
| 所属项目 | appwrite.config.json | init project、pull 或 client --project-id |
init project 会与控制台通信,需要登录会话。API 密钥无法列出组织。
# Good — CI against a checked-in config
appwrite client --key "$APPWRITE_API_KEY"
appwrite push function --force
# Bad — CI that bakes the key into the repo
appwrite client --key 'standard_....'
# and commits appwrite.config.json with secrets inside
环境变量优先于配置文件:APPWRITE_PROJECT_ID、APPWRITE_ENDPOINT、APPWRITE_ORGANIZATION_ID。将配置文件提交到代码库(不含密钥)。将密钥放入环境变量中。
--force 会跳过提示。Agent 和 CI 没有 TTY,因此需要确认的推送若不使用该标志就会失败(请传入 --force)。先询问用户,再传入 --force。不要用它跳过本地列为空的变更表。
appwrite login --switch 会切换已保存的账号。appwrite client --debug 会显示生效的端点/项目,并屏蔽凭据。appwrite client --reset 会退出所有账号。
云端点
appwrite whoami 显示 https://cloud.appwrite.io/v1 时,这是账号登录主机。请保留它。项目 API 调用使用区域主机(例如 https://fra.cloud.appwrite.io/v1)。init project 和 client --project-id 会将该区域固定到配置文件中。自托管时,两者使用同一个端点。
# Good — project work uses the config's regional endpoint
cat appwrite.config.json # "endpoint": "https://fra.cloud.appwrite.io/v1"
# Bad — "fixing" whoami
appwrite client --endpoint https://fra.cloud.appwrite.io/v1
# now login/session calls go to a region host they do not belong on
架构与数据行
| 拉取 / 推送(配置) | 服务命令(不在配置中) |
|---|---|
| 设置、函数、站点、表和列、存储桶、团队、Webhook、主题 | 数据行、用户、文件、执行、消息 |
如果某项内容应该在全新克隆后仍然存在,就应将其放入配置文件中。编辑文件,然后推送。使用 tablesdb create-* 或 functions create 创建相同资源,会绕过下次 pull / push 所依赖的文件。
databases 已弃用。请使用 tablesdb 和 push table。
如果变更表显示远程值对应的本地空值,说明配置文件缺少这些字段。拉取该资源,然后推送。不要用 --force 强行通过,也不要把拉取所有内容当作例行操作——pull settings 很慢。
id │ key │ remote │ local
───────────────┼─────────────────┼────────┼───────
Service │ account │ true │
Auth method │ email-password │ true │
# Good — local column was empty, so sync first, then push
appwrite pull settings
appwrite push settings --force
# Bad — empty local, forced through
appwrite push settings --force
push all --all --force 会推送所有资源。请限定范围(例如 push function --function-id api),除非你确实需要推送全部资源。
对于一次性的数据行或用户操作,使用 unique() 没问题。需要推送的资源必须在配置文件中拥有稳定的 $id,以便下次拉取时能够匹配。
类型安全的应用代码
编写针对 TablesDB 的应用代码时,请先检查 appwrite.config.json,再定义接口、数据库 ID、表 ID 或列名。生成器会读取本地配置,不会检查远程架构。过期的配置会生成过期的代码。
如果远程架构是事实来源,请先使用 appwrite pull table 更新配置。不要覆盖本地尚未推送的架构更改。如果本地配置更新,则直接根据它生成代码。
对于 TypeScript,优先使用 appwrite generate。它会生成完整的 TablesDB 封装:数据库和表选项、创建/更新载荷、返回的行、查询字段和查询值都会经过 TypeScript 检查。这比单独生成模型接口更可靠。
appwrite generate
请使用生成的 API,而不要退回到原始字符串 ID 和手写的载荷类型:
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];
不要猜测示例中的字面值:请查看生成的类型或配置。尤其是,表的 .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。
appwrite types ./src/appwrite-types.ts --language ts
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
});
不要将 types --strict 描述为“完全类型安全”。它只会将字段名转换为目标语言的命名约定。如果目标是获得完整类型化的 TypeScript 表 API,请使用 generate。
生成的代码属于派生输出。不要通过修改它来修复架构或命名问题;请修复 appwrite.config.json 或生成器输入,然后重新生成。每次更改表或列后,都要重新运行仓库使用的同一生成命令,并运行其格式化工具/类型检查器。保留仓库现有的输出路径和提交约定。
Functions 和 sites
变量存放在 <path>/.env 中,而非 appwrite.config.json 中。--with-variables 会用该文件替换远程变量集合。除非有意同步密钥,否则请省略它。
# Good — ship code, leave remote vars alone
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
# Good — deploy without switching live traffic
appwrite push function --function-id api --activate=false --force
--async 会在构建完成前返回。本地运行:appwrite run function。
查询和输出
优先使用 --filter、--sort-asc / --sort-desc、--limit、--select、--cursor-after。--where 已弃用。仅当标志无法表达相应的 Query JSON 时,才使用 --queries。
# Good
appwrite users list \
--filter 'emailVerification=true' \
--sort-desc '$createdAt' \
--limit 20 \
--json
# Bad
appwrite users list --queries '[{"method":"equal","attribute":"emailVerification","values":[true]}]'
--filter 会解析 true / false / null、数字和 JSON 数组。重复使用该标志表示 AND。列表页最多返回 100 条;与其使用较大的 --offset,不如优先使用 --cursor-after <lastId>。
脚本使用 --json(空字段会被省略)。使用 --raw 获取未经筛选的载荷。除非使用 --show-secrets,否则密钥会保持隐藏。
配置文件本身
CLI 会从当前工作目录向上查找 appwrite.config.json(或旧版 appwrite.json)。在 functions/api/ 中运行 push,仍会找到项目根目录。父目录中多余的配置文件会让 CLI 使用该配置。
使用 includes 拆分大型项目——每个值都是相对路径的 .json 文件数组。资源不能同时内联并被包含。函数和站点的 path 值相对于包含文件解析,而非相对于仓库根目录。
不要凭记忆编写此文件。init project 或 pull 会生成有效的配置文件。然后再编辑。