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.

24,269 stars

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

$curl -o ~/.claude/skills/pb-api-rules/SKILL.md --create-dirs "https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/skills/pocketbase/pb-api-rules/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/pb-api-rules/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How PocketBase API Rules Compares

Feature / AgentPocketBase API RulesStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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

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

24269
from davila7/claude-code-templates

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

24269
from davila7/claude-code-templates

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

24269
from davila7/claude-code-templates

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

24269
from davila7/claude-code-templates

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

24269
from davila7/claude-code-templates

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

24269
from davila7/claude-code-templates

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

24269
from davila7/claude-code-templates

Comprehensive guidance for implementing asynchronous Python applications using asyncio, concurrent programming patterns, and async/await for building high-performance, non-blocking systems.

slack-automation

24269
from davila7/claude-code-templates

Automate Slack workspace operations including messaging, search, channel management, and reaction workflows through Composio's Slack toolkit.

linear-automation

24269
from davila7/claude-code-templates

Automate Linear tasks via Rube MCP (Composio): issues, projects, cycles, teams, labels. Always search tools first for current schemas.

jira-automation

24269
from davila7/claude-code-templates

Automate Jira tasks via Rube MCP (Composio): issues, projects, sprints, boards, comments, users. Always search tools first for current schemas.

gitops-workflow

24269
from davila7/claude-code-templates

Complete guide to implementing GitOps workflows with ArgoCD and Flux for automated Kubernetes deployments.

github-automation

24269
from davila7/claude-code-templates

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.