К основному содержанию
скилл CX Codex

appwrite-rust — скилл для Claude Code: что делает и как установить

Учит ИИ-агента писать серверный код на Rust с SDK Appwrite: настраивать клиент Tokio, работать с TablesDB и управлять пользователями.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add appwrite/skills --skill appwrite-rust -a claude-code
Открыть на GitHub

Что делает appwrite-rust

Скилл передаёт агенту шаблоны и правила вызовов для пакета appwrite из crates.io. Он объясняет конвенции асинхронного Rust: позиционные аргументы в методах и обязательную передачу None в Option<T> для незаполненных параметров. Внутри разбираются подключение к API через переменные окружения, работа с сервисом Users и генерация идентификаторов через ID::unique().

Для баз данных скилл ориентирует на API TablesDB, исключая устаревший Databases. Он разграничивает типы колонок: инлайновый varchar до 16 383 символов расходует лимит строки в 64 КБ, а длинные text, mediumtext и longtext хранятся вне страницы без ограничений по размеру строки. Без рантайма tokio и крейта serde_json клиент работать не сможет.

Какие задачи решает

  • Сконфигурировать асинхронный клиент Appwrite на базе Tokio и API-ключей
  • Создавать таблицы и строки через TablesDB с учётом лимита строки в 64 КБ
  • Фильтровать и агрегировать данные через методы Query
  • Управлять учётными записями пользователей и правами доступа

Примеры запросов агенту

  • Напиши функцию на Rust для создания пользователя в Appwrite через сервис Users
  • Создай таблицу в TablesDB с колонками varchar и mediumtext, используя Appwrite SDK
  • Собери запрос с фильтрацией по статусу и пагинацией через Query в Rust

Как установить appwrite-rust

1Через Skills CLI (Vercel)

npx skills add appwrite/skills --skill appwrite-rust -a claude-code

2Вручную: положить файлы

~/.claude/skills/appwrite-rust/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/appwrite-rust/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о appwrite-rust

Как установить appwrite-rust в Claude Code?

Выполните команду npx skills add appwrite/skills --skill appwrite-rust -a claude-code. Также можно вручную поместить файл в ~/.claude/skills/appwrite-rust/SKILL.md.

Что делает скилл appwrite-rust?

Он обучает ИИ-помощника генерировать серверный код на Rust для Appwrite. Скилл содержит паттерны асинхронных вызовов, работу с TablesDB, фильтры Query и управление пользователями.

В чём разница между типами колонок varchar и text в TablesDB?

Тип varchar хранится прямо в строке и ограничен общим лимитом 64 КБ на строку, но допускает полный индекс при длине до 768 знаков. Типы text, mediumtext и longtext хранятся вне страницы и не тратят этот лимит.

Исходный текст

SKILL.md · BSD-3-Clause
---
name: appwrite-rust
description: Appwrite Rust SDK skill. Use when building server-side Rust applications with Appwrite. Covers async client setup with API keys, user management, TablesDB database/table/row operations, file storage, function executions, permissions, queries, and error handling. Uses the crates.io `appwrite` package and Tokio.
---


# Appwrite Rust SDK

## Installation

```bash
cargo add appwrite
cargo add tokio --features full
cargo add serde_json
```

## Setting Up the Client

The Rust SDK is async. Use it from a Tokio runtime and authenticate server-side with an API key.

```rust
use appwrite::Client;
use std::env;

let client = Client::new()
    .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")
    .set_project(env::var("APPWRITE_PROJECT_ID")?)
    .set_key(env::var("APPWRITE_API_KEY")?);
```

### Complete server skeleton

```rust
use appwrite::query::Query;
use appwrite::services::Users;
use appwrite::Client;
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new()
        .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")
        .set_project(env::var("APPWRITE_PROJECT_ID")?)
        .set_key(env::var("APPWRITE_API_KEY")?);

    let users = Users::new(&client);
    let _list = users
        .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))
        .await?;

    Ok(())
}
```

## Code Examples

### User Management

```rust
use appwrite::id::ID;
use appwrite::query::Query;
use appwrite::services::Users;

let users = Users::new(&client);

// Create user
let _user = users
    .create(
        ID::unique(),
        Some("[email protected]"),
        None,
        Some("password123"),
        Some("User Name"),
    )
    .await?;

// List users
let _list = users
    .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))
    .await?;

// Get user
let _fetched = users.get("[USER_ID]").await?;

// Delete user
users.delete("[USER_ID]").await?;
```

### Database Operations

> **Note:** Use `TablesDB` for new code. Only use `Databases` if the existing project explicitly depends on the legacy Databases API.
>
> **Rust SDK calling convention:** Methods are async, use positional parameters, and represent optional API parameters as `Option<T>`. Pass `None` for optional values you are not setting.

```rust
use appwrite::id::ID;
use appwrite::permission::Permission;
use appwrite::query::Query;
use appwrite::role::Role;
use appwrite::services::TablesDB;
use serde_json::json;

let tables_db = TablesDB::new(&client);

// Create database
let _database = tables_db
    .create(ID::unique(), "My Database", Some(true))
    .await?;

// Create table
let _table = tables_db
    .create_table(
        "[DATABASE_ID]",
        ID::unique(),
        "articles",
        Some(vec![
            Permission::read(Role::any()).to_string(),
            Permission::create(Role::users(None)).to_string(),
        ]),
        Some(true),
        Some(true),
        None,
        None,
    )
    .await?;

// Create row
let _row = tables_db
    .create_row(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        ID::unique(),
        json!({
            "title": "Hello World",
            "done": false
        }),
        None,
        None,
    )
    .await?;

// Query rows
let _rows = tables_db
    .list_rows(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        Some(vec![
            Query::equal("done", false).to_string(),
            Query::limit(10).to_string(),
        ]),
        None,
        Some(true),
        None,
    )
    .await?;

// Get row
let _row = tables_db
    .get_row("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]", None, None)
    .await?;

// Update row
let _updated = tables_db
    .update_row(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        "[ROW_ID]",
        Some(json!({ "done": true })),
        None,
        None,
    )
    .await?;

// Delete row
tables_db
    .delete_row("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]", None)
    .await?;
```

#### String Column Types

> **Note:** The legacy `string` column type is deprecated. Use explicit string column types for new tables.

| Type | Max characters | Indexing | Storage |
|------|---------------|----------|---------|
| `varchar` | 16,383 | Full index (if size <= 768) | Inline in row |
| `text` | 16,383 | Prefix only | Off-page |
| `mediumtext` | 4,194,303 | Prefix only | Off-page |
| `longtext` | 1,073,741,823 | Prefix only | Off-page |

- `varchar` is stored inline and counts toward the 64 KB row size limit. Prefer it for short, indexed fields like names, slugs, and identifiers.
- `text`, `mediumtext`, and `longtext` are stored off-page, so they do not consume the row size budget. `size` is not required for these types.

```rust
use appwrite::enums::{OrderBy, TablesDBIndexType};

// Short, indexed string
let _title = tables_db
    .create_varchar_column(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        "title",
        255,
        true,
        None,
        None,
        None,
    )
    .await?;

// Off-page longer text
let _summary = tables_db
    .create_text_column("[DATABASE_ID]", "[TABLE_ID]", "summary", false, None, None, None)
    .await?;

let _body = tables_db
    .create_mediumtext_column("[DATABASE_ID]", "[TABLE_ID]", "body", false, None, None, None)
    .await?;

let _raw_data = tables_db
    .create_longtext_column("[DATABASE_ID]", "[TABLE_ID]", "raw_data", false, None, None, None)
    .await?;

// Index only the varchar column fully.
let _index = tables_db
    .create_index(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        "title_idx",
        TablesDBIndexType::Key,
        vec!["title"],
        Some(vec![OrderBy::Asc]),
        Some(vec![255]),
    )
    .await?;
```

### Query Methods

`TablesDB` methods accept `Option<Vec<String>>` for queries. Convert each `Query` to a string.

```rust
use appwrite::query::Query;
use serde_json::Value;

let queries = vec![
    Query::equal("status", "published").to_string(),
    Query::not_equal("archived", true).to_string(),
    Query::greater_than("views", 100).to_string(),
    Query::less_than_equal("priority", 5).to_string(),
    Query::between("score", 1, 100).to_string(),
    Query::is_not_null("publishedAt").to_string(),
    Query::search("title", "rust appwrite").to_string(),
    Query::contains("tags", "rust").to_string(),
    Query::order_desc("$createdAt").to_string(),
    Query::limit(25).to_string(),
    Query::offset(50).to_string(),
];

let multi_value = Query::equal(
    "status",
    Value::Array(vec![
        Value::String("draft".to_string()),
        Value::String("published".to_string()),
    ]),
)
.to_string();

let related = Query::relationship(
    "comments",
    vec![
        Query::equal("approved", true).to_string(),
        Query::limit(25).to_string(),
    ],
)
.to_string();

// Aggregations (pass "" for no alias)
let aggregations = vec![
    Query::count("*", "total").to_string(),
    Query::sum("amount", "revenue").to_string(),
    Query::avg("score", "avgScore").to_string(),
    Query::min("price", "minPrice").to_string(),
    Query::max("price", "maxPrice").to_string(),
];

// Grouping
let grouping = vec![
    Query::group_by(["status", "year"]).to_string(),
    Query::having([Query::greater_than("total", 1).to_string()]).to_string(),
    Query::distinct().to_string(),
];

// Joins (table id, left key, right key, operator, alias; "" for no alias)
let joins = vec![
    Query::join("orders", "$id", "customerId", "=", "").to_string(),
    Query::left_join("orders", "$id", "customerId", "=", "ord").to_string(),
    Query::left_join_on(
        "orders",
        "ord",
        [
            Query::on("$id", "customerId", "=").to_string(),
            Query::equal("ord.status", "paid").to_string(),
        ],
    )
    .to_string(),
];

// Fluent builder. Pass build() into list methods.
let queries = Query::builder()
    .equal("status", "published")
    .left_join("orders", "$id", "customerId", "=", "ord")
    .count("*", "total")
    .group_by(["status"])
    .limit(25)
    .build();

let _rows = tables_db
    .list_rows("[DATABASE_ID]", "[TABLE_ID]", Some(queries), None, None, None)
    .await?;
```

### File Storage

```rust
use appwrite::id::ID;
use appwrite::input_file::InputFile;
use appwrite::permission::Permission;
use appwrite::query::Query;
use appwrite::role::Role;
use appwrite::services::Storage;

let storage = Storage::new(&client);

// Create bucket
let _bucket = storage
    .create_bucket(
        ID::unique(),
        "Uploads",
        Some(vec![
            Permission::read(Role::any()).to_string(),
            Permission::create(Role::users(None)).to_string(),
        ]),
        Some(true),
        Some(true),
        Some(30_000_000),
        Some(vec!["jpg".to_string(), "png".to_string(), "pdf".to_string()]),
        None,
        Some(true),
        Some(true),
        Some(true),
    )
    .await?;

// Upload from disk
let input = InputFile::from_path("avatar.png", Some("image/png")).await?;
let _file = storage
    .create_file(
        "[BUCKET_ID]",
        ID::unique(),
        input,
        Some(vec![Permission::read(Role::any()).to_string()]),
    )
    .await?;

// Upload from bytes
let input = InputFile::from_bytes(b"hello".to_vec(), "hello.txt", Some("text/plain"));
let _file = storage.create_file("[BUCKET_ID]", ID::unique(), input, None).await?;

// List files
let _files = storage
    .list_files("[BUCKET_ID]", Some(vec![Query::limit(10).to_string()]), None, Some(true))
    .await?;

// Download file bytes
let _content = storage
    .get_file_download("[BUCKET_ID]", "[FILE_ID]", None)
    .await?;

// Delete file
storage.delete_file("[BUCKET_ID]", "[FILE_ID]").await?;
```

### Functions

```rust
use appwrite::enums::ExecutionMethod;
use appwrite::query::Query;
use appwrite::services::Functions;
use serde_json::json;

let functions = Functions::new(&client);

// List functions
let _functions = functions
    .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))
    .await?;

// Execute function
let _execution = functions
    .create_execution(
        "[FUNCTION_ID]",
        Some(r#"{"hello":"world"}"#),
        Some(false),
        Some("/jobs/sync"),
        Some(ExecutionMethod::POST),
        Some(json!({ "content-type": "application/json" })),
        None,
    )
    .await?;

// Get execution
let _execution = functions
    .get_execution("[FUNCTION_ID]", "[EXECUTION_ID]")
    .await?;
```

### Permissions

```rust
use appwrite::permission::Permission;
use appwrite::role::Role;

let permissions = vec![
    Permission::read(Role::any()).to_string(),
    Permission::create(Role::users(None)).to_string(),
    Permission::update(Role::user("[USER_ID]", None)).to_string(),
    Permission::delete(Role::team("[TEAM_ID]", Some("owner"))).to_string(),
];
```

### Error Handling

```rust
match users.get("[USER_ID]").await {
    Ok(user) => {
        let _user = user;
    }
    Err(error) if error.status_code() == 404 => {
        eprintln!("User not found: {}", error.get_message());
    }
    Err(error) => {
        eprintln!("Appwrite error {}: {}", error.status_code(), error.get_message());
        return Err(Box::new(error) as Box<dyn std::error::Error>);
    }
}
```

## Common Pitfalls

- The Rust SDK is currently a server-side SDK. Prefer TypeScript/Web, Flutter, Apple, Android, or React Native SDKs for browser/mobile client auth flows.
- Always `await` service calls.
- Pass `None` for optional parameters you are not using.
- Use `TablesDB`, not legacy `Databases`, for new database code.
- Convert queries with `.to_string()` before passing them to APIs that expect `Option<Vec<String>>`.
- Use `serde_json::json!({...})` for row data and JSON bodies.
- Use `InputFile::from_path(...).await?` or `InputFile::from_bytes(...)` for uploads.

© appwrite · BSD-3-Clause · appwrite/skills

Похожие скиллы

Все скиллы по теме «Бэкенд и API» →
mcp-builder официальный anthropics Скилл проводит через создание MCP-сервера на TypeScript или Python: от изучения протокола до тестов и оценки качества. 130 949установок claude-api официальный anthropics Справочник по Anthropic SDK и API Claude для генерации кода без устаревших параметров и выдуманных методов. 74 198установок lark-im larksuite Скилл подключает Lark IM к агенту: он отправляет сообщения, ищет историю, управляет чатами и файлами. Подойдёт для задач вокруг командных коммуникаций. CX Codex +1 472 900установок lark-event larksuite Слушает события Lark/Feishu и отдаёт их потоком NDJSON. Подходит для ботов, обработчиков сообщений и долгих подписчиков. CX Codex +1 466 800установок caveman-discover JuliusBrussee Находит точки вызова LLM в репозитории и размечает их воркфлоу для Caveman Cloud, чтобы расходы на токены не сливались в одну общую кучу. CX Codex +1 104 400установок migration JuliusBrussee Скилл задаёт правила безопасных миграций схем, данных и API с обязательным откатом. Пригодится при изменениях, где нельзя терять данные или ломать совместимость. CX Codex +1 103 900установок

Из того же набора11

appwrite-dart Подсказывает агенту, как работать с Appwrite из Dart: авторизация, база, файлы, realtime и серверное администрирование. CX Codex +1 1 100установок appwrite-python Подсказывает агенту, как писать серверный код на Python с Appwrite SDK: пользователи, таблицы, хранилище файлов, функции. CX Codex +1 1 100установок appwrite-go Скилл учит агента работать с официальным Appwrite Go SDK. Он помогает настраивать клиент, управлять пользователями, строить запросы и манипулировать таблицами в TablesDB. CX Codex +1 899установок appwrite-kotlin Подсказывает агенту, как писать код на Kotlin SDK Appwrite: авторизация, база, файлы, realtime и серверные админ-вызовы. CX Codex +1 862установок appwrite-swift Настраивает работу с Appwrite Swift SDK в приложениях под iOS, macOS или сервер. Помогает писать запросы к TablesDB, настраивать сессии и управлять пользователями. CX Codex +1 850установок appwrite-php Скилл подсказывает агенту, как писать серверный PHP под Appwrite: пользователи, таблицы, файлы, функции. Пригодится в Laravel и Symfony. CX Codex +1 847установок appwrite-ruby Подсказывает агенту, как работать с Appwrite из Ruby: пользователи, таблицы, файлы, команды. Пригодится в Rails и Sinatra. CX Codex +1 796установок appwrite-dotnet Скилл для работы с Appwrite .NET SDK: подсказывает агенту, как писать серверный код на C# — пользователи, таблицы, файлы, функции. CX Codex +1 544установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой