Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

appwrite-kotlin科特林应用程序编写

Agent Skill

appwrite-kotlin 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

3,990

周安装

163

GitHub Stars

18

下载量

1,291
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:appwrite-kotlin(科特林应用程序编写)
来源仓库:https://github.com/appwrite/agent-skills
仓库路径:skills/appwrite-kotlin
安装命令:
npx skills add https://github.com/appwrite/agent-skills --skill appwrite-kotlin
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/appwrite/agent-skills --skill appwrite-kotlin

简介

用于查找、检索和筛选 Appwrite Kotlin SDK 相关信息,适合在开发中快速定位用法和配置。

  • 适用于 Android 和 Kotlin JVM 服务端项目,支持客户端和服务端身份验证与数据操作。
  • 通过 npx 安装并参考官方仓库文档,结合 README 了解具体集成步骤和代码示例。
  • 安装前需确认项目环境、依赖版本及 API 密钥权限,避免触发网络请求或敏感操作。
  • appwrite-kotlin 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Appwrite Kotlin SDK

Installation

// build.gradle.kts — Android
implementation("io.appwrite:sdk-for-android:+")

// build.gradle.kts — Server (Kotlin JVM)
implementation("io.appwrite:sdk-for-kotlin:+")

Setting Up the Client

Client-side (Android)

import io.appwrite.Client
import io.appwrite.ID
import io.appwrite.Query
import io.appwrite.enums.OAuthProvider
import io.appwrite.services.Account
import io.appwrite.services.Realtime
import io.appwrite.services.TablesDB
import io.appwrite.services.Storage
import io.appwrite.models.InputFile

val client = Client(context)
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("[PROJECT_ID]")

Server-side (Kotlin JVM)

import io.appwrite.Client
import io.appwrite.ID
import io.appwrite.Query
import io.appwrite.services.Users
import io.appwrite.services.TablesDB
import io.appwrite.services.Storage
import io.appwrite.services.Functions

val client = Client()
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject(System.getenv("APPWRITE_PROJECT_ID"))
    .setKey(System.getenv("APPWRITE_API_KEY"))

Code Examples

Authentication (client-side)

val account = Account(client)

// Signup
account.create(
    userId = ID.unique(),
    email = "user@example.com",
    password = "password123",
    name = "User Name"
)

// Login
val session = account.createEmailPasswordSession(
    email = "user@example.com",
    password = "password123"
)

// OAuth
account.createOAuth2Session(activity = activity, provider = OAuthProvider.GOOGLE)

// Get current user
val user = account.get()

// Logout
account.deleteSession(sessionId = "current")

User Management (server-side)

val users = Users(client)

// Create user
val user = users.create(
    userId = ID.unique(),
    email = "user@example.com",
    password = "password123",
    name = "User Name"
)

// List users
val list = users.list()

// Get user
val fetched = users.get(userId = "[USER_ID]")

// Delete user
users.delete(userId = "[USER_ID]")

Database Operations

Note: Use TablesDB (not the deprecated Databases class) for all new code. Only use Databases if the existing codebase already relies on it or the user explicitly requests it. Tip: Prefer named arguments (e.g., databaseId = "...") for all SDK method calls. Only use positional arguments if the existing codebase already uses them or the user explicitly requests it.
val tablesDB = TablesDB(client)

// Create database (server-side only)
val db = tablesDB.create(databaseId = ID.unique(), name = "My Database")

// Create row
val doc = tablesDB.createRow(
    databaseId = "[DATABASE_ID]",
    tableId = "[TABLE_ID]",
    rowId = ID.unique(),
    data = mapOf("title" to "Hello", "done" to false)
)

// Query rows
val results = tablesDB.listRows(
    databaseId = "[DATABASE_ID]",
    tableId = "[TABLE_ID]",
    queries = listOf(Query.equal("done", false), Query.limit(10))
)

// Get row
val row = tablesDB.getRow(databaseId = "[DATABASE_ID]", tableId = "[TABLE_ID]", rowId = "[ROW_ID]")

// Update row
tablesDB.updateRow(
    databaseId = "[DATABASE_ID]",
    tableId = "[TABLE_ID]",
    rowId = "[ROW_ID]",
    data = mapOf("done" to true)
)

// Delete row
tablesDB.deleteRow(
    databaseId = "[DATABASE_ID]",
    tableId = "[TABLE_ID]",
    rowId = "[ROW_ID]"
)

String Column Types

Note: The legacy string type is deprecated. Use explicit column types for all new columns.
TypeMax charactersIndexingStorage
varchar16,383Full index (if size ≤ 768)Inline in row
text16,383Prefix onlyOff-page
mediumtext4,194,303Prefix onlyOff-page
longtext1,073,741,823Prefix onlyOff-page
  • varchar is stored inline and counts towards the 64 KB row size limit. Prefer for short, indexed fields like names, slugs, or identifiers.
  • text, mediumtext, and longtext are stored off-page (only a 20-byte pointer lives in the row), so they don't consume the row size budget. size is not required for these types.
// Create table with explicit string column types
tablesDB.createTable(
    databaseId = "[DATABASE_ID]",
    tableId = ID.unique(),
    name = "articles",
    columns = listOf(
        mapOf("key" to "title",    "type" to "varchar",    "size" to 255, "required" to true),
        mapOf("key" to "summary",  "type" to "text",                      "required" to false),
        mapOf("key" to "body",     "type" to "mediumtext",                "required" to false),
        mapOf("key" to "raw_data", "type" to "longtext",                  "required" to false),
    )
)

Query Methods

// Filtering
Query.equal("field", "value")             // == (or pass list for IN)
Query.notEqual("field", "value")          // !=
Query.lessThan("field", 100)              // <
Query.lessThanEqual("field", 100)         // <=
Query.greaterThan("field", 100)           // >
Query.greaterThanEqual("field", 100)      // >=
Query.between("field", 1, 100)            // 1 <= field <= 100
Query.isNull("field")                     // is null
Query.isNotNull("field")                  // is not null
Query.startsWith("field", "prefix")       // starts with
Query.endsWith("field", "suffix")         // ends with
Query.contains("field", "sub")            // contains
Query.search("field", "keywords")         // full-text search (requires index)

// Sorting
Query.orderAsc("field")
Query.orderDesc("field")

// Pagination
Query.limit(25)                           // max rows (default 25, max 100)
Query.offset(0)                           // skip N rows
Query.cursorAfter("[ROW_ID]")             // cursor pagination (preferred)
Query.cursorBefore("[ROW_ID]")

// Selection & Logic
Query.select(listOf("field1", "field2"))
Query.or(listOf(Query.equal("a", 1), Query.equal("b", 2)))   // OR
Query.and(listOf(Query.greaterThan("age", 18), Query.lessThan("age", 65)))  // AND (default)

File Storage

val storage = Storage(client)

// Upload file
val file = storage.createFile(
    bucketId = "[BUCKET_ID]",
    fileId = ID.unique(),
    file = InputFile.fromPath("/path/to/file.png")
)

// Get file preview
val preview = storage.getFilePreview(
    bucketId = "[BUCKET_ID]",
    fileId = "[FILE_ID]",
    width = 300,
    height = 300
)

// List files
val files = storage.listFiles(bucketId = "[BUCKET_ID]")

// Delete file
storage.deleteFile(bucketId = "[BUCKET_ID]", fileId = "[FILE_ID]")

InputFile Factory Methods

import io.appwrite.models.InputFile

InputFile.fromPath("/path/to/file.png")              // from filesystem path
InputFile.fromBytes(byteArray, "file.png")           // from ByteArray

Teams

val teams = Teams(client)

// Create team
val team = teams.create(teamId = ID.unique(), name = "Engineering")

// List teams
val list = teams.list()

// Create membership (invite user by email)
val membership = teams.createMembership(
    teamId = "[TEAM_ID]",
    roles = listOf("editor"),
    email = "user@example.com"
)

// List memberships
val members = teams.listMemberships(teamId = "[TEAM_ID]")

// Update membership roles
teams.updateMembership(teamId = "[TEAM_ID]", membershipId = "[MEMBERSHIP_ID]", roles = listOf("admin"))

// Delete team
teams.delete(teamId = "[TEAM_ID]")
Role-based access: Use Role.team("[TEAM_ID]") for all team members or Role.team("[TEAM_ID]", "editor") for a specific team role when setting permissions.

Real-time Subscriptions (client-side)

import io.appwrite.Channel

val realtime = Realtime(client)

// Subscribe to row changes
val subscription = realtime.subscribe(
    Channel.tablesdb("[DATABASE_ID]").table("[TABLE_ID]").row()
) { response ->
    println(response.events)   // e.g. ["tablesdb.*.tables.*.rows.*.create"]
    println(response.payload)  // the affected resource
}

// Subscribe to multiple channels
val multi = realtime.subscribe(
    Channel.tablesdb("[DATABASE_ID]").table("[TABLE_ID]").row(),
    Channel.bucket("[BUCKET_ID]").file()
) { response -> /* ... */ }

// Cleanup
subscription.close()

Available channels:

ChannelDescription
accountChanges to the authenticated user's account
tablesdb.[DB_ID].tables.[TABLE_ID].rowsAll rows in a table
tablesdb.[DB_ID].tables.[TABLE_ID].rows.[ROW_ID]A specific row
buckets.[BUCKET_ID].filesAll files in a bucket
buckets.[BUCKET_ID].files.[FILE_ID]A specific file
teamsChanges to teams the user belongs to
teams.[TEAM_ID]A specific team
membershipsThe user's team memberships
functions.[FUNCTION_ID].executionsFunction execution updates

Response fields: events (array), payload (resource), channels (matched), timestamp (ISO 8601).

Serverless Functions (server-side)

val functions = Functions(client)

// Execute function
val execution = functions.createExecution(
    functionId = "[FUNCTION_ID]",
    body = """{"key": "value"}"""
)

// List executions
val executions = functions.listExecutions(functionId = "[FUNCTION_ID]")

Writing a Function Handler (Kotlin runtime)

// src/Main.kt — Appwrite Function entry point
import io.openruntimes.kotlin.RuntimeContext
import io.openruntimes.kotlin.RuntimeOutput

fun main(context: RuntimeContext): RuntimeOutput {
    // context.req.body        — raw body (String)
    // context.req.bodyJson    — parsed JSON (Map)
    // context.req.headers     — headers (Map)
    // context.req.method      — HTTP method
    // context.req.path        — URL path
    // context.req.query       — query params (Map)

    context.log("Processing: ${context.req.method} ${context.req.path}")

    if (context.req.method == "GET") {
        return context.res.json(mapOf("message" to "Hello from Appwrite Function!"))
    }

    return context.res.json(mapOf("success" to true))    // JSON
    // context.res.text("Hello")                          // plain text
    // context.res.empty()                                // 204
    // context.res.redirect("https://...")                 // 302
}

Server-Side Rendering (SSR) Authentication

SSR apps using Kotlin server frameworks (Ktor, Spring Boot, etc.) use the server SDK to handle auth. You need two clients:

  • Admin client — uses an API key, creates sessions, bypasses rate limits (reusable singleton)
  • Session client — uses a session cookie, acts on behalf of a user (create per-request, never share)
import io.appwrite.Client
import io.appwrite.services.Account
import io.appwrite.enums.OAuthProvider

// Admin client (reusable)
val adminClient = Client()
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("[PROJECT_ID]")
    .setKey(System.getenv("APPWRITE_API_KEY"))

// Session client (create per-request)
val sessionClient = Client()
    .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .setProject("[PROJECT_ID]")

val session = call.request.cookies["a_session_[PROJECT_ID]"]
if (session != null) {
    sessionClient.setSession(session)
}

Email/Password Login (Ktor)

post("/login") {
    val body = call.receive<LoginRequest>()
    val account = Account(adminClient)
    val session = account.createEmailPasswordSession(
        email = body.email,
        password = body.password,
    )

    // Cookie name must be a_session_<PROJECT_ID>
    call.response.cookies.append(Cookie(
        name = "a_session_[PROJECT_ID]",
        value = session.secret,
        httpOnly = true,
        secure = true,
        extensions = mapOf("SameSite" to "Strict"),
        path = "/",
    ))
    call.respond(mapOf("success" to true))
}

Authenticated Requests

get("/user") {
    val session = call.request.cookies["a_session_[PROJECT_ID]"]
        ?: return@get call.respond(HttpStatusCode.Unauthorized)

    val sessionClient = Client()
        .setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
        .setProject("[PROJECT_ID]")
        .setSession(session)

    val account = Account(sessionClient)
    val user = account.get()
    call.respond(user)
}

OAuth2 SSR Flow

// Step 1: Redirect to OAuth provider
get("/oauth") {
    val account = Account(adminClient)
    val redirectUrl = account.createOAuth2Token(
        provider = OAuthProvider.GITHUB,
        success = "https://example.com/oauth/success",
        failure = "https://example.com/oauth/failure",
    )
    call.respondRedirect(redirectUrl)
}

// Step 2: Handle callback — exchange token for session
get("/oauth/success") {
    val account = Account(adminClient)
    val session = account.createSession(
        userId = call.parameters["userId"]!!,
        secret = call.parameters["secret"]!!,
    )

    call.response.cookies.append(Cookie(
        name = "a_session_[PROJECT_ID]", value = session.secret,
        httpOnly = true, secure = true,
        extensions = mapOf("SameSite" to "Strict"), path = "/",
    ))
    call.respond(mapOf("success" to true))
}
Cookie security: Always use httpOnly, secure, and SameSite=Strict to prevent XSS. The cookie name must be a_session_<PROJECT_ID>.
Forwarding user agent: Call sessionClient.setForwardedUserAgent(call.request.headers["User-Agent"]) to record the end-user's browser info for debugging and security.

Error Handling

import io.appwrite.AppwriteException

try {
    val row = tablesDB.getRow(databaseId = "[DATABASE_ID]", tableId = "[TABLE_ID]", rowId = "[ROW_ID]")
} catch (e: AppwriteException) {
    println(e.message)     // human-readable message
    println(e.code)        // HTTP status code (Int)
    println(e.type)        // error type (e.g. "document_not_found")
    println(e.response)    // full response body (Map)
}

Common error codes:

CodeMeaning
401Unauthorized — missing or invalid session/API key
403Forbidden — insufficient permissions
404Not found — resource does not exist
409Conflict — duplicate ID or unique constraint
429Rate limited — too many requests

Permissions & Roles (Critical)

Appwrite uses permission strings to control access to resources. Each permission pairs an action (read, update, delete, create, or write which grants create + update + delete) with a role target. By default, no user has access unless permissions are explicitly set at the document/file level or inherited from the collection/bucket settings. Permissions are arrays of strings built with the Permission and Role helpers.

import io.appwrite.Permission
import io.appwrite.Role

Database Row with Permissions

val doc = tablesDB.createRow(
    databaseId = "[DATABASE_ID]",
    tableId = "[TABLE_ID]",
    rowId = ID.unique(),
    data = mapOf("title" to "Hello World"),
    permissions = listOf(
        Permission.read(Role.user("[USER_ID]")),     // specific user can read
        Permission.update(Role.user("[USER_ID]")),   // specific user can update
        Permission.read(Role.team("[TEAM_ID]")),     // all team members can read
        Permission.read(Role.any()),                 // anyone (including guests) can read
    )
)

File Upload with Permissions

val file = storage.createFile(
    bucketId = "[BUCKET_ID]",
    fileId = ID.unique(),
    file = InputFile.fromPath("/path/to/file.png"),
    permissions = listOf(
        Permission.read(Role.any()),
        Permission.update(Role.user("[USER_ID]")),
        Permission.delete(Role.user("[USER_ID]")),
    )
)
When to set permissions: Set document/file-level permissions when you need per-resource access control. If all documents in a collection share the same rules, configure permissions at the collection/bucket level and leave document permissions empty.
Common mistakes: - Forgetting permissions — the resource becomes inaccessible to all users (including the creator) - Role.any() with write/update/delete — allows any user, including unauthenticated guests, to modify or remove the resource - Permission.read(Role.any()) on sensitive data — makes the resource publicly readable

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

38.1%
按下载量换算492

Claude

27.62%
按下载量换算357

Cursor

17.5%
按下载量换算226

Gemini CLI

10.43%
按下载量换算135

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills