Skip to content
Agentmart
Submit a tool

AGENTS.md · appwrite/appwrite

AGENTS.md from appwrite/appwrite: 335 lines covering Commands, Stack, Layout, Console and more.

Template by appwrite

IndexedBSD-3-Clause★ 57,761
Write a review

Chalk Labs

Need help deploying AGENTS.md · appwrite/appwrite?

Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.

Book a call

Install

Works with Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code. Read the repository before you give any tool access to your data.

curl -fsSL https://raw.githubusercontent.com/appwrite/appwrite/main/AGENTS.md -o AGENTS.md

Read it and adapt it to your project before use.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

The AGENTS.md file that appwrite/appwrite (57,761 stars) keeps for coding agents. It has 335 lines in 14 sections: Commands; Stack; Layout; Console; Libraries; Modules; HTTP actions; Lifecycle; Reuse; Conventions; Collections; Tests; SDK specs; Releases. Use it as a model for your own project's instructions.

Use cases: prompt-engineering

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

What's in it

An AGENTS.md file: instructions coding agents (Codex, Cursor, Copilot, Gemini CLI and others) read before working in a repo.

For
Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code
Length
335 lines
File
AGENTS.md

Sections

  1. Commands
  2. Stack
  3. Layout
  4. Console
  5. Libraries
  6. Modules
  7. HTTP actions
  8. Lifecycle
  9. Reuse
  10. Conventions
  11. Collections
  12. Tests
  13. SDK specs
  14. Releases

First lines (shown under the repo's BSD-3-Clause license)

# Appwrite

Self-hosted Backend-as-a-Service. Hybrid monolithic-microservice architecture on PHP 8.5+ and Swoole 6, delivered as Docker containers.

## Commands

| Command | Purpose |
|---------|---------|
| `docker compose up -d --force-recreate --build` | Build and start all services (combined worker + scheduler by default) |
| `docker compose -f docker-compose.yml -f docker-compose.separate.yml --profile separate up -d` | Start per-queue worker and scheduler containers instead |
| `docker compose exec appwrite test tests/e2e/Services/[Service]` | Run E2E tests for a service |
| `docker compose exec appwrite test tests/e2e/Services/[Service] --filter=[Method]` | Run a single test method |
| `docker compose exec appwrite test tests/unit/` | Run unit tests |
| `composer format` | Auto-format code (Pint, PSR-12) |
| `composer format <file>` | Format a specific file |
| `composer lint <file>` | Check formatting of a file |
| `composer analyze` | Static analysis (PHPStan 2, level 4) |
| `composer check` | Same as `analyze` |
| `composer refactor:check` | Rector dry-run over `tests/` (CI "Refactor" check) |
| `composer refactor` | Apply Rector fixes |
| `bin/monorepo validate` | Check every `packages/<name>` against the standard shape and the root autoload wiring |
| `bin/monorepo check <name> [--fix]` | Pint, PHPStan (package `phpstan.neon`) and Rector for one package |
| `bin/monorepo test <name> [--linked]` | Package unit tier (`composer test`), plus `test:e2e` against its compose file when defined |
| `bin/monorepo absorb <name> [url]` | Import a library with history, strip hoisted QA, write mirror plumbing |
| `bin/monorepo split <name> --dry-run` | Synthesize the mirror history and print its head without pushing |
| `bin/monorepo release <name> <version>` | Tag `<name>/<version>` and push it; CI mirrors the tag and publishes the release |

`composer check` / `composer analyze` over the whole project is very slow. Prefer specific files during development.

## Stack

- PHP 8.5+, Swoole 6.x (async runtime, replaces PHP-FPM)
- Utopia PHP (HTTP routing, CLI, DI, queue)
- PostgreSQL (default platform DB); adapters: postgresql, mariadb, mongodb via utopia-php/database. DocumentsDB defaults to mongodb; VectorsDB to postgresql
- Redis 7.x (cache, queue, pub/sub); Docker + Traefik 3.x
- PHPUnit 12, Pint 1 (PSR-12), PHPStan 2 (level 4), Rector 2

## Layout

- **src/Appwrite/** -- domain libraries (one directory per problem). Key libraries:
  - **Auth** -- keys, OAuth, MFA
  - **Event** -- queue publishers (functions, mails, webhooks, deletes, …)
  - **Network** -- CORS, origin, DNS, client platforms
  - **SDK** -- spec and SDK method metadata
  - **Migration** -- versioned data migrations
  - **GraphQL** -- schema and resolvers
  - **Messaging**, **Realtime**, **PubSub** -- realtime fan-out
  - **Database** -- platform/project DB factory
  - **Vcs** -- Git provider helpers
  - **Deployment** -- build and deploy helpers
  - **Usage** -- metrics
  - **Utopia** -- extensions of Utopia libraries, `src/Appwrite/Utopia/{Lib}` (`Database`, `Fetch`, `Messaging`, `Request`, `Response`, `WebSocket`, …); see [Libraries](#libraries)
  - **Extend** -- shared exceptions
- **src/Appwrite/Platform/** -- HTTP modules, workers, CLI tasks. Register modules in `src/Appwrite/Platform/Appwrite.php`. See [Modules](#modules).
- **src/Executor/** -- Open Runtimes executor HTTP client (create/run/delete function and site runtimes)
- **packages/** -- Utopia libraries absorbed into this repository and autoloaded directly (`agents`, `bus`); each is an independent Composer package mirrored to `utopia-php/<name>`, managed with `bin/monorepo`. See [rfc/monorepo.md](rfc/monorepo.md)
- **apps/** -- deployable applications with their own runtime, image, and release (`console`: the web Console, Bun + TanStack Start, shipped as `appwrite/new`). Not Utopia packages: no Composer autoload, no split mirror. Do not confuse with `app/`, the PHP server. See [apps/README.md](apps/README.md) and [Console](#console).
- **app/config/** -- static product config (collections, locales, SDKs, runtimes, scopes, errors, OAuth, storage)
- **app/assets/** -- bundled data (fonts, common-password dictionary)
- **app/views/** -- server-side templates (installer, errors, proxy)
- **app/init.php** -- bootstrap; **app/init/** -- constants, models, registers, resources, span, database filters/formats
- **app/http.php**, **app/worker.php**, **app/realtime.php**, **app/cli.php** -- process entry harnesses
- **app/controllers/** -- leftover HTTP controllers; new endpoints go in modules
- **bin/** -- CLI entry points (`worker`, `worker-*`, `schedule`, `schedule-*`, `queue-*`, plus `doctor`, `install`, `migrate`, `realtime`, …)
- **docs/** -- references, tutorials, SDK getting-started notes, [release process](docs/releases.md)
- **tests/e2e/**, **tests/unit/** -- tests; **public/** -- fonts, images, generated SDKs

## Console

Console and UI work uses the code in `apps/console`. Follow [apps/console/AGENTS.md](apps/console/AGENTS.md) for that app's agent guidance.

## Libraries

`src/Appwrite/` is domain libraries, not a dumping ground. Each directory solves **one problem**. Do not grow a library into a second concern; add a new directory instead. See [Layout](#layout) for the current set.

Keep Appwrite-specific domain here (product events, SDK specs, GraphQL, usage, migrations, platform modules). If a library is **generic enough to build any kind of app** — validators, storage, cache, queues, HTTP, databases, locks, DNS — it is a Utopia package, not `src/Appwrite/` code. Packages already absorbed live under `packages/<name>` in the standard shape described in [rfc/monorepo.md](rfc/monorepo.md) and are loaded directly through the root autoload; the rest are still Composer dependencies until their absorb PR lands.

Code that extends, subclasses, adapts or wraps a Utopia library goes in `src/Appwrite/Utopia/{Lib}/` (namespace `Appwrite\Utopia\{Lib}`), mirroring the library name: [`Utopia/Database/Validator`](src/Appwrite/Utopia/Database/Validator), [`Utopia/Database/Documents/User.php`](src/Appwrite/Utopia/Database/Documents/User.php), [`Utopia/Request`](src/Appwrite/Utopia/Request), [`Utopia/Response`](src/Appwrite/Utopia/Response). Appwrite-domain logic stays in its own domain namespace or platform module, not under `Utopia/`. Behavior any app would need belongs in the Utopia library itself: fix the library instead of adding an app-side gap-filler.

## Modules

Each module under `src/Appwrite/Platform/Modules/` owns one domain: HTTP endpoints, optional workers, and rarely CLI tasks. Generally each API service is its own module; put related code under one roof. Register new modules in `src/Appwrite/Platform/Appwrite.php`.

A module contains:

- `Module.php` -- registers services from `Services/`
- `Http/` -- HTTP endpoints
- `Services/` -- `Http.php`, optionally `Workers.php` / `Tasks.php`
- `Workers/` -- optional module-specific workers
- `Tasks/` -- optional; most CLI tasks live in `src/Appwrite/Platform/Tasks/`

Directly under `Http/` there are only service directories. A single-service module uses one directory named after the service (`Modules/Account/Http/Account`). A multi-service module uses one per service (`Modules/Databases/Http/Databases` and `Modules/Databases/Http/TablesDB`).

Nest resources and properties as directories. Top-level resources in the same module are **siblings**, not nested under the parent resource folder. Template deployments live at `Modules/Functions/Http/Deployments/Template/Create.php` (`Deployments/` is a sibling of `Functions/`; `template` is a property). Action file names and constructor methods: [HTTP actions](#http-actions). Init/shutdown/error hooks: [Lifecycle](#lifecycle).

```
src/Appwrite/Platform/Modules/Functions
├── Module.php
├── Workers
│   └── Builds.php
├── Http
│   ├── Functions
│   │   ├── Create.php
│   │   ├── XList.php
│   │   ├── Update.php
│   │   ├── Delete.php
│   │   └── Get.php
│   └── Deployments
│       ├── XList.php
│       ├── Delete.php
│       ├── Get.php
│       └── Template
│           └── Create.php
└── Services
    ├── Http.php
    └── Workers.php
```

## HTTP actions

Action files must be `Get.php`, `Create.php`, `Update.php`, `Delete.php`, or `XList.php` (`List` is reserved). Model non-CRUD work as a property update (`Teams/Http/Memberships/Status/Update.php` → `PATCH /v1/teams/:teamId/memberships/:membershipId/status`). Never RPC-style files (`Verify.php`, `Block.php`).

| REST verb | HTTP | File | SDK `name` | Example |
|-----------|------|------|------------|---------|
| `create` | POST | `Create.php` | `create` | `POST /v1/account/verifications` |
| `get` | GET | `Get.php` | `get` | `GET /v1/teams/:teamId` |
| `list` | GET | `XList.php` | `list` | `GET /v1/teams` |
| `update` | PATCH / PUT | `Update.php` | `update` | `PATCH /v1/account/sessions/:sessionId` |
| `delete` | DELETE | `Delete.php` | `delete` | `DELETE /v1/teams/:teamId` |

Path, directory, action class, `getName()`, and SDK `Method` `name` describe the same REST operation. SDK `name` is a REST verb, plus a qualifier when needed (`createStringColumn`, `updateStatus`). Never RPC verbs (`verify`, `block`, `send`). `getName()` is a stable registered id (legacy values like `createTeam` exist); new code should match the REST verb (+ qualifier).

Skeleton (full example: `src/Appwrite/Platform/Modules/Teams/Http/Teams/Create.php`):

```php
class Create extends Action
{
    public static function getName(): string { return 'create'; }

    public function __construct()
    {
        $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
            ->setHttpPath('/v1/teams')
            ->label('scope', 'teams.write')
            ->inject('response')->inject('dbForProject')
            ->callback($this->action(...));
    }
}
```

Common injections: `$response`, `$request`, `$dbForProject`, `$dbForPlatform`, `$user`, `$project`, `$queueForEvents`, `$queueForMails`, `$queueForDeletes`.

HTTP actions `use Utopia\Platform\Scope\HTTP`. Constructor methods (chain on `$this`):

| Method | Role |
|--------|------|
| `setHttpMethod()` | `HTTP_REQUEST_METHOD_GET` / `POST` / `PATCH` / `PUT` / `DELETE` |
| `setHttpPath()` | Route, with `:param` segments (`/v1/teams/:teamId`) |
| `httpAlias()` | Extra path that hits the same action (legacy URLs) |
| `desc()` | Short human description |

Signals

Stars
57,761
Forks
5,822
Open issues
368
Last commit (this folder)
Oct 15, 2026 (15 days ago)
Last release
Oct 24, 2026 (6 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
BSD-3-Clause
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from appwrite

Done for you

Rather not set it up yourself?

Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.

See how we build AI agents →Read the case studies

Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.

launches shipped
50+
launches shipped
media placements
500+
media placements
founders on every account
2
founders on every account

Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block

Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.

Get AGENTS.md · appwrite/appwrite running in your business

Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying AGENTS.md · appwrite/appwrite?

CallGet help
Cite this page

AGENTS.md · appwrite/appwrite. Agent Mart. https://agentmart.dev/templates/appwrite-appwrite-agents-md (last updated 2026-10-24)