appwrite-cli
Original:🇺🇸 English
Translated
How to use the Appwrite CLI well. Covers when to use appwrite.config.json vs `appwrite client`, pull/push vs one-shot service calls, type-safe SDK and model generation, query flags, CI auth, Cloud regional endpoints, function/site variables, and traps that `--help` will not mention. Does not catalog commands — run `appwrite <command> --help` for flags. Use whenever running `appwrite`, deploying or pulling functions/sites/tables, generating application code from a table schema, initializing or linking a project, scripting Appwrite, or when the user mentions the Appwrite CLI, appwrite.config.json, `appwrite generate`, `appwrite types`, or `appwrite client`.
38installs
Sourceappwrite/skills
Added on
NPX Install
npx skill4agent add appwrite/skills appwrite-cliTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Appwrite CLI
appwrite <command> --helpConfig vs client
clientA real project (repo, schema, functions, deploys, CI) lives in . Init once. Pull and push after that. Do not on every command — the config already names the project.
appwrite.config.jsonappwrite client --project-idA one-off (inspect a user, patch one row, poke a remote you will not return to) uses . Do not scaffold a project for a single API call.
appwrite clientbash
# 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 projectNo session? .
appwrite client --endpoint https://<REGION>.cloud.appwrite.io/v1 --key "$APPWRITE_API_KEY" --project-id <ID>appwrite client --project-idappwrite.config.jsonAPPWRITE_PROJECT_IDAPPWRITE_ENDPOINTAuth is not the project
| Layer | Lives in | Set with |
|---|---|---|
| Who you are (session or API key) | global CLI prefs | |
| Which project | | |
init projectbash
# 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 insideEnv beats the config: , , . Check in the config (no secrets). Put keys in the environment.
APPWRITE_PROJECT_IDAPPWRITE_ENDPOINTAPPWRITE_ORGANIZATION_ID--forcePass --force instead--forceappwrite login --switchappwrite client --debugappwrite client --resetCloud endpoints
appwrite whoamihttps://cloud.appwrite.io/v1https://fra.cloud.appwrite.io/v1init projectclient --project-idbash
# 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 onSchema vs rows
| Pull / push (config) | Service commands (not in the config) |
|---|---|
| settings, functions, sites, tables and columns, buckets, teams, webhooks, topics | rows, 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 or bypasses the file the next / expects.
tablesdb create-*functions createpullpushdatabasestablesdbpush tableIf the change table shows remote values against empty local, the config is missing those fields. Pull that resource, then push. Do not through it, and do not pull everything as a ritual — is slow.
--forcepull settingstext
id │ key │ remote │ local
───────────────┼─────────────────┼────────┼───────
Service │ account │ true │
Auth method │ email-password │ true │bash
# 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 --forcepush all --all --forcepush function --function-id apiunique()$idType-safe application code
When writing application code against TablesDB, inspect 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.
appwrite.config.jsonIf the remote schema is the source of truth, update the config first with . Do not pull over local, unpushed schema edits. If the local config is ahead, generate from it as-is.
appwrite pull tableFor TypeScript, prefer . 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.
appwrite generatebash
appwrite generateUse 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, for a table takes its , which may differ from its . Let compilation expose a misspelled table, column, or wrong query value. Run the project's type checker after generation.
.use()name$idgenerateAPPWRITE_API_KEYappwrite generate --helpFor another supported language, or when the project deliberately uses the regular SDK directly, use . It supports TypeScript (), JavaScript (), PHP (), Kotlin (), Swift (), Java (), Dart (), and C# (). Pass these short values to ; names such as and are not the command's accepted values. Generated files type row data, but they do not type-check raw database/table IDs or calls:
appwrite types <output-directory>tsjsphpkotlinswiftjavadartcs--languagetypescriptcsharpQueryFor TypeScript, pass a destination when the result will be imported as a module. Passing a directory instead creates inside it.
.tsappwrite.d.tsbash
appwrite types ./src/appwrite-types.ts --language tstypescript
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 as “full type safety.” It only converts field names to the target language's naming conventions. Use when a fully typed TypeScript table API is the goal.
types --strictgenerateGenerated code is derived output. Do not patch it to fix a schema or naming problem; fix 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.
appwrite.config.jsonFunctions and sites
Variables live in , not in . replaces the remote set from that file. Omit it unless you intend to sync secrets.
<path>/.envappwrite.config.json--with-variablesbash
# 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--asyncappwrite run functionQueries and output
Prefer , / , , , . is deprecated. only for Query JSON the flags cannot express.
--filter--sort-asc--sort-desc--limit--select--cursor-after--where--queriesbash
# Good
appwrite users list \
--filter 'emailVerification=true' \
--sort-desc '$createdAt' \
--limit 20 \
--json
# Bad
appwrite users list --queries '[{"method":"equal","attribute":"emailVerification","values":[true]}]'--filtertruefalsenull--cursor-after <lastId>--offset--json--raw--show-secretsThe config file itself
The CLI walks up from cwd looking for (or the legacy ). from still hits the project root. A stray config in a parent directory will capture you.
appwrite.config.jsonappwrite.jsonpushfunctions/api/Split large projects with — each value is a relative array. A resource cannot be both inline and included. Function and site values resolve relative to the include file, not the repo root.
includes.jsonpathDo not invent the file from memory. or writes a valid one. Then edit.
init projectpull