PocketBase API Rules
API rules and filter expressions for PocketBase access control. Use when setting permissions, writing filter expressions, configuring who can access what, or debugging 403/404 responses. Covers all 5 rule types, filter syntax, operators, request/collection macros, and field modifiers.
Best use case
PocketBase API Rules is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
API rules and filter expressions for PocketBase access control. Use when setting permissions, writing filter expressions, configuring who can access what, or debugging 403/404 responses. Covers all 5 rule types, filter syntax, operators, request/collection macros, and field modifiers.
Teams using PocketBase API Rules should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/pb-api-rules/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How PocketBase API Rules Compares
| Feature / Agent | PocketBase API Rules | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
API rules and filter expressions for PocketBase access control. Use when setting permissions, writing filter expressions, configuring who can access what, or debugging 403/404 responses. Covers all 5 rule types, filter syntax, operators, request/collection macros, and field modifiers.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
ChatGPT vs Claude for Agent Skills
Compare ChatGPT and Claude for AI agent skills across coding, writing, research, and reusable workflow execution.
SKILL.md Source
# PocketBase API Rules & Filter Expressions
## Rule Types
Each collection has 5 rule types. Each rule is a **filter expression** that must evaluate to `true` for the request to proceed.
| Rule | Controls | Locked = | Empty string = |
|------|----------|----------|----------------|
| **List** | `GET /api/collections/{name}/records` | superusers only | everyone can list |
| **View** | `GET /api/collections/{name}/records/{id}` | superusers only | everyone can view |
| **Create** | `POST /api/collections/{name}/records` | superusers only | everyone can create |
| **Update** | `PATCH /api/collections/{name}/records/{id}` | superusers only | everyone can update |
| **Delete** | `DELETE /api/collections/{name}/records/{id}` | superusers only | everyone can delete |
**Critical**: `null`/locked means only superusers can perform the action (regular users and guests are denied). Empty string `""` means EVERYONE including guests. Superusers always bypass API rules entirely — see below.
## Superuser Bypass
Superusers (formerly admins) **always bypass API rules**. Rules only apply to regular auth records and guests.
## Filter Syntax
### Operators
| Operator | Meaning | Example |
|----------|---------|---------|
| `=` | Equal | `status = "active"` |
| `!=` | Not equal | `status != "draft"` |
| `>` | Greater than | `count > 5` |
| `>=` | Greater or equal | `count >= 5` |
| `<` | Less than | `count < 10` |
| `<=` | Less or equal | `count <= 10` |
| `~` | LIKE (contains) | `title ~ "hello"` |
| `!~` | NOT LIKE | `title !~ "spam"` |
| `?=` | Any/has (array contains) | `tags ?= "TAG_ID"` |
| `?!=` | None (array not contains) | `tags ?!= "TAG_ID"` |
| `?>` | Any greater than | `scores ?> 90` |
| `?>=` | Any greater or equal | `scores ?>= 90` |
| `?<` | Any less than | `scores ?< 10` |
| `?<=` | Any less or equal | `scores ?<= 10` |
| `?~` | Any LIKE | `emails ?~ "@gmail.com"` |
| `?!~` | Any NOT LIKE | `emails ?!~ "@test.com"` |
**Critical**: use `?=` (not `=`) for multi-valued fields (multi-select, multi-relation, multi-file). `=` checks the raw JSON string, `?=` checks individual values.
### Logical Operators
```
status = "active" && author = @request.auth.id
status = "active" || status = "featured"
```
Parentheses for grouping: `(a = 1 || b = 2) && c = 3`
### Values
- Strings: `"value"` or `'value'`
- Numbers: `123`, `45.67`
- Booleans: `true`, `false`
- `null` — empty/missing value
- Identifiers: field names, macros
## Request Macros (`@request.*`)
Access the current request context in rules:
| Macro | Type | Description |
|-------|------|-------------|
| `@request.auth.id` | `string` | Current auth record ID (empty if guest) |
| `@request.auth.email` | `string` | Current auth record email |
| `@request.auth.verified` | `bool` | Whether email is verified |
| `@request.auth.collectionId` | `string` | Auth collection ID |
| `@request.auth.collectionName` | `string` | Auth collection name |
| `@request.auth.*` | `any` | Any field from the auth record |
| `@request.body.fieldName` | `any` | Field value from request body |
| `@request.query.paramName` | `string` | URL query parameter |
| `@request.headers.name` | `string` | Request header (lowercase key) |
| `@request.method` | `string` | HTTP method (GET/POST/PATCH/DELETE) |
### Auth record relations
You can traverse relations on the auth record:
```
@request.auth.team.owner = @request.auth.id
```
## Collection Macros (`@collection.*`)
Cross-collection lookups without explicit joins:
```
@collection.memberships.user ?= @request.auth.id &&
@collection.memberships.team ?= team
```
This checks if a record exists in the `memberships` collection where the user matches the current auth user and the team matches the current record's team field.
**Note**: `@collection.*` performs an implicit EXISTS subquery. It's powerful but can be slow on large datasets — add indexes.
## Field Modifiers
Use in create/update rules to validate specific field behaviors:
| Modifier | Works on | Description |
|----------|----------|-------------|
| `:isset` | `@request.body.*` | True if the field was sent in the request (even if empty) |
| `:changed` | record field | True if the field value differs from current stored value (update only) |
| `:length` | `string`/`array` | Returns the length |
| `:each` | `array` | Applies the condition to each element |
| `:lower` | `string` | Lowercased value |
### Examples
```
// Only allow changing status if user is owner
status:changed = false || author = @request.auth.id
// Prevent setting role on create
@request.body.role:isset = false
// Require at least 2 tags
@request.body.tags:length >= 2
// Check each tag is from allowed list
@request.body.tags:each ?= @collection.allowed_tags.id
```
## Datetime Macros
| Macro | Example output |
|-------|----------------|
| `@now` | `2024-01-15 10:30:00.000Z` |
| `@second` | `2024-01-15 10:30:00.000Z` |
| `@minute` | `2024-01-15 10:30:00.000Z` |
| `@hour` | `2024-01-15 10:00:00.000Z` |
| `@day` | `2024-01-15 00:00:00.000Z` |
| `@month` | `2024-01-01 00:00:00.000Z` |
| `@year` | `2024-01-01 00:00:00.000Z` |
| `@todayStart` | `2024-01-15 00:00:00.000Z` |
| `@todayEnd` | `2024-01-15 23:59:59.999Z` |
| `@monthStart` | `2024-01-01 00:00:00.000Z` |
| `@monthEnd` | `2024-01-31 23:59:59.999Z` |
| `@yearStart` | `2024-01-01 00:00:00.000Z` |
| `@yearEnd` | `2024-12-31 23:59:59.999Z` |
Arithmetic: `@now - 7d`, `@now + 1h`, `@now - 30m`
## `geoDistance()`
For location-based filtering:
```
geoDistance(lat, lon, 40.7128, -74.0060) <= 10000
```
Arguments: `geoDistance(latField, lonField, targetLat, targetLon)` — returns meters.
## Common Patterns
### Owner-only access
```
// View/Update/Delete rule:
author = @request.auth.id
```
### Authenticated users only
```
@request.auth.id != ""
```
### Verified users only
```
@request.auth.verified = true
```
### Role-based access
```
@request.auth.role = "admin" || author = @request.auth.id
```
### Team membership
```
@collection.team_members.user ?= @request.auth.id &&
@collection.team_members.team ?= team
```
### Public read, owner write
```
// List/View: "" (empty = everyone)
// Create: @request.auth.id != ""
// Update/Delete: author = @request.auth.id
```
### Prevent field modification
```
// Update rule: prevent changing `owner` after creation
owner:changed = false
```
### Time-limited access
```
expires > @now
```Related Skills
Writing Hookify Rules
This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
PocketBase SDK
JavaScript SDK usage for PocketBase client applications. Use when calling PocketBase from frontend or Node.js, authenticating users, subscribing to realtime events, uploading files, or working with the PocketBase JS/TS SDK. Covers CRUD, auth flows, authStore, realtime SSE, file handling, batch operations, and query syntax.
PocketBase Migrations
Schema migrations and versioning for PocketBase. Use when creating migrations, managing schema versions, syncing collections between environments, using automigrate, or creating collections programmatically. Covers migrate commands, migration file format, snapshot imports, and the _migrations tracking table.
PocketBase Hooks
Server-side JavaScript hooks for PocketBase (pb_hooks). Use when writing custom routes, event hooks, cron jobs, sending emails, making HTTP requests, querying the database, or extending PocketBase with server-side logic. Covers the goja ES5 runtime, routing, middleware, all event hooks, DB queries, record operations, and global APIs.
PocketBase Deploy
Production deployment for PocketBase. Use when deploying PocketBase to a server, setting up Docker, configuring systemd, reverse proxy (nginx/Caddy), TLS, SMTP, backups, S3 storage, rate limiting, or hardening for production. Provides ready-to-use configs.
PocketBase Collections
Collection and schema design for PocketBase. Use when creating collections, designing schemas, adding fields, setting up relations, or choosing between base/auth/view collection types. Prevents wrong field types, documents zero-default behavior, and covers relation cascading.
async-python-patterns
Comprehensive guidance for implementing asynchronous Python applications using asyncio, concurrent programming patterns, and async/await for building high-performance, non-blocking systems.
slack-automation
Automate Slack workspace operations including messaging, search, channel management, and reaction workflows through Composio's Slack toolkit.
linear-automation
Automate Linear tasks via Rube MCP (Composio): issues, projects, cycles, teams, labels. Always search tools first for current schemas.
jira-automation
Automate Jira tasks via Rube MCP (Composio): issues, projects, sprints, boards, comments, users. Always search tools first for current schemas.
gitops-workflow
Complete guide to implementing GitOps workflows with ArgoCD and Flux for automated Kubernetes deployments.
github-automation
Automate GitHub repositories, issues, pull requests, branches, CI/CD, and permissions via Rube MCP (Composio). Manage code workflows, review PRs, search code, and handle deployments programmatically.