Install
$ agentstack add skill-appwrite-agent-skills-appwrite-rust ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Appwrite Rust SDK
Installation
cargo add appwrite
cargo add tokio --features full
cargo add serde_json
Or add dependencies manually:
[dependencies]
appwrite = "0.3.0"
tokio = { version = "1", features = ["full"] }
serde_json = "1"
Setting Up the Client
The Rust SDK is async. Use it from a Tokio runtime and authenticate server-side with an API key.
use appwrite::Client;
use std::env;
let client = Client::new()
.set_endpoint("https://.cloud.appwrite.io/v1")
.set_project(env::var("APPWRITE_PROJECT_ID")?)
.set_key(env::var("APPWRITE_API_KEY")?);
Complete server skeleton
use appwrite::query::Query;
use appwrite::services::Users;
use appwrite::Client;
use std::env;
#[tokio::main]
async fn main() -> Result> {
let client = Client::new()
.set_endpoint("https://.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
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("user@example.com"),
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. Pass None for optional values you are not setting.
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 > for queries. Convert each Query` to a string.
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();
File Storage
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
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
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
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);
}
}
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
awaitservice calls. - Pass
Nonefor optional parameters you are not using. - Use
TablesDB, not legacyDatabases, for new database code. - Convert queries with
.to_string()before passing them to APIs that expectOption>. - Use
serde_json::json!({...})for row data and JSON bodies. - Use
InputFile::from_path(...).await?orInputFile::from_bytes(...)for uploads.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: appwrite
- Source: appwrite/agent-skills
- License: BSD-3-Clause
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.