electric-shapes

Configure ShapeStream and Shape to sync a Postgres table to the client. Covers ShapeStreamOptions (url, table, where, columns, replica, offset, handle), custom type parsers (timestamptz, jsonb, int8), column mappers (snakeCamelMapper, createColumnMapper), onError retry semantics, backoff options, log modes (full, changes_only), requestSnapshot, fetchSnapshot, subscribe/unsubscribe, and Shape materialized view. Load when setting up sync, configuring shapes, parsing types, or handling sync errors.

25 stars

Best use case

electric-shapes is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Configure ShapeStream and Shape to sync a Postgres table to the client. Covers ShapeStreamOptions (url, table, where, columns, replica, offset, handle), custom type parsers (timestamptz, jsonb, int8), column mappers (snakeCamelMapper, createColumnMapper), onError retry semantics, backoff options, log modes (full, changes_only), requestSnapshot, fetchSnapshot, subscribe/unsubscribe, and Shape materialized view. Load when setting up sync, configuring shapes, parsing types, or handling sync errors.

Teams using electric-shapes 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/electric-shapes/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/electric-sql/electric/electric-shapes/SKILL.md"

Manual Installation

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

How electric-shapes Compares

Feature / Agentelectric-shapesStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Configure ShapeStream and Shape to sync a Postgres table to the client. Covers ShapeStreamOptions (url, table, where, columns, replica, offset, handle), custom type parsers (timestamptz, jsonb, int8), column mappers (snakeCamelMapper, createColumnMapper), onError retry semantics, backoff options, log modes (full, changes_only), requestSnapshot, fetchSnapshot, subscribe/unsubscribe, and Shape materialized view. Load when setting up sync, configuring shapes, parsing types, or handling sync errors.

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.

SKILL.md Source

# Electric — Shape Streaming

## Setup

```ts
import { ShapeStream, Shape } from '@electric-sql/client'

const stream = new ShapeStream({
  url: '/api/todos', // Your proxy route, NOT direct Electric URL
  // Built-in parsers auto-handle: bool, int2, int4, float4, float8, json, jsonb
  // Add custom parsers for other types (see references/type-parsers.md)
  parser: {
    timestamptz: (date: string) => new Date(date),
  },
})

const shape = new Shape(stream)

shape.subscribe(({ rows }) => {
  console.log('synced rows:', rows)
})

// Wait for initial sync
const rows = await shape.rows
```

## Core Patterns

### Filter rows with WHERE clause and positional params

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    where: 'user_id = $1 AND status = $2',
    params: { '1': userId, '2': 'active' },
  },
})
```

### Select specific columns (must include primary key)

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    columns: ['id', 'title', 'status'], // PK required
  },
})
```

### Map column names between snake_case and camelCase

```ts
import { ShapeStream, snakeCamelMapper } from '@electric-sql/client'

const stream = new ShapeStream({
  url: '/api/todos',
  columnMapper: snakeCamelMapper(),
})
// DB column "created_at" arrives as "createdAt" in client
// WHERE clauses auto-translate: "createdAt" → "created_at"
```

### Handle errors with retry

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  onError: (error) => {
    console.error('sync error', error)
    return {} // Return {} to retry; returning void stops the stream
  },
})
```

For auth token refresh on 401 errors, see electric-proxy-auth/SKILL.md.

### Resume from stored offset

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  offset: storedOffset, // Both offset AND handle required
  handle: storedHandle,
})
```

### Get replica with old values on update

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    replica: 'full', // Sends unchanged columns + old_value on updates
  },
})
```

## Common Mistakes

### CRITICAL Returning void from onError stops sync permanently

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  onError: (error) => {
    console.error('sync error', error)
    // Returning nothing = stream stops forever
  },
})
```

Correct:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  onError: (error) => {
    console.error('sync error', error)
    return {} // Return {} to retry
  },
})
```

`onError` returning `undefined` signals the stream to permanently stop. Return at least `{}` to retry, or return `{ headers, params }` to retry with updated values.

Source: `packages/typescript-client/src/client.ts:409-418`

### HIGH Using columns without including primary key

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    columns: ['title', 'status'],
  },
})
```

Correct:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    columns: ['id', 'title', 'status'],
  },
})
```

Server returns 400 error. The `columns` list must always include the primary key column(s).

Source: `website/docs/guides/shapes.md`

### HIGH Setting offset without handle for resumption

Wrong:

```ts
new ShapeStream({
  url: '/api/todos',
  offset: storedOffset,
})
```

Correct:

```ts
new ShapeStream({
  url: '/api/todos',
  offset: storedOffset,
  handle: storedHandle,
})
```

Throws `MissingShapeHandleError`. Both `offset` AND `handle` are required to resume a stream from a stored position.

Source: `packages/typescript-client/src/client.ts:1997-2003`

### HIGH Using non-deterministic functions in WHERE clause

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/events',
  params: {
    table: 'events',
    where: 'start_time > now()',
  },
})
```

Correct:

```ts
const stream = new ShapeStream({
  url: '/api/events',
  params: {
    table: 'events',
    where: 'start_time > $1',
    params: { '1': new Date().toISOString() },
  },
})
```

Server rejects WHERE clauses with non-deterministic functions like `now()`, `random()`, `count()`. Use static values or positional params.

Source: `packages/sync-service/lib/electric/replication/eval/env/known_functions.ex`

### HIGH Not parsing custom Postgres types

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/events',
})
// createdAt will be string "2024-01-15T10:30:00.000Z", not a Date
```

Correct:

```ts
const stream = new ShapeStream({
  url: '/api/events',
  parser: {
    timestamptz: (date: string) => new Date(date),
    timestamp: (date: string) => new Date(date),
  },
})
```

Electric auto-parses `bool`, `int2`, `int4`, `float4`, `float8`, `json`, `jsonb`, and `int8` (→ BigInt). All other types arrive as strings — add custom parsers for `timestamptz`, `date`, `numeric`, etc. See [references/type-parsers.md](references/type-parsers.md) for the full list.

Source: `AGENTS.md:300-308`

### MEDIUM Using reserved parameter names in params

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    cursor: 'abc', // Reserved!
    offset: '0', // Reserved!
  },
})
```

Correct:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: {
    table: 'todos',
    page_cursor: 'abc',
    page_offset: '0',
  },
})
```

Throws `ReservedParamError`. Names `cursor`, `handle`, `live`, `offset`, `cache-buster`, and all `subset__*` prefixed params are reserved by the Electric protocol.

Source: `packages/typescript-client/src/client.ts:1984-1985`

### MEDIUM Mutating shape options on a running stream

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  params: { table: 'todos', where: "status = 'active'" },
})
// Later...
stream.options.params.where = "status = 'done'" // No effect!
```

Correct:

```ts
// Create a new stream with different params
const newStream = new ShapeStream({
  url: '/api/todos',
  params: { table: 'todos', where: "status = 'done'" },
})
```

Shapes are immutable per subscription. Changing params on a running stream has no effect. Create a new `ShapeStream` instance for different filters.

Source: `AGENTS.md:106`

## References

- [WHERE clause supported types and functions](references/where-clause.md)
- [Built-in type parsers](references/type-parsers.md)

See also: electric-proxy-auth/SKILL.md — Shape URLs must point to proxy routes, not directly to Electric.
See also: electric-debugging/SKILL.md — onError semantics and backoff are essential for diagnosing sync problems.

## Version

Targets @electric-sql/client v1.5.10.

Related Skills

electric-yjs

25
from ComeOnOliver/skillshub

Set up ElectricProvider for real-time collaborative editing with Yjs via Electric shapes. Covers ElectricProvider configuration, document updates shape with BYTEA parser (parseToDecoder), awareness shape at offset='now', LocalStorageResumeStateProvider for reconnection with stableStateVector diff, debounceMs for batching writes, sendUrl PUT endpoint, required Postgres schema (ydoc_update and ydoc_awareness tables), CORS header exposure, and sendErrorRetryHandler. Load when implementing collaborative editing with Yjs and Electric.

electric-schema-shapes

25
from ComeOnOliver/skillshub

Design Postgres schema and Electric shape definitions together for a new feature. Covers single-table shape constraint, cross-table joins using multiple shapes, WHERE clause design for tenant isolation, column selection for bandwidth optimization, replica mode choice (default vs full for old_value), enum casting in WHERE clauses, and txid handshake setup with pg_current_xact_id() for optimistic writes. Load when designing database tables for use with Electric shapes.

electric-proxy-auth

25
from ComeOnOliver/skillshub

Set up a server-side proxy to forward Electric shape requests securely. Covers ELECTRIC_PROTOCOL_QUERY_PARAMS forwarding, server-side shape definition (table, where, params), content-encoding/content-length header cleanup, CORS configuration for electric-offset/electric-handle/ electric-schema/electric-cursor headers, auth token injection, ELECTRIC_SECRET/SOURCE_SECRET server-side only, tenant isolation via WHERE positional params, onError 401 token refresh, and subset security (AND semantics). Load when creating proxy routes, adding auth, or configuring CORS for Electric.

electric-postgres-security

25
from ComeOnOliver/skillshub

Pre-deploy security checklist for Postgres with Electric. Checks REPLICATION role, SELECT grants, CREATE on database, table ownership, REPLICA IDENTITY FULL on all synced tables, publication management (auto vs manual with ELECTRIC_MANUAL_TABLE_PUBLISHING), connection pooler exclusion for DATABASE_URL (use direct connection), and ELECTRIC_POOLED_DATABASE_URL for pooled queries. Load before deploying Electric to production or when diagnosing Postgres permission errors.

electric-orm

25
from ComeOnOliver/skillshub

Use Electric with Drizzle ORM or Prisma for the write path. Covers getting pg_current_xact_id() from ORM transactions using Drizzle tx.execute(sql) and Prisma $queryRaw, running migrations that preserve REPLICA IDENTITY FULL, and schema management patterns compatible with Electric shapes. Load when using Drizzle or Prisma alongside Electric for writes.

electric-new-feature

25
from ComeOnOliver/skillshub

End-to-end guide for adding a new synced feature with Electric and TanStack DB. Covers the full journey: design Postgres schema, set REPLICA IDENTITY FULL, define shape, create proxy route, set up TanStack DB collection with electricCollectionOptions, implement optimistic mutations with txid handshake (pg_current_xact_id, awaitTxId), and build live queries with useLiveQuery. Also covers migration from old ElectricSQL (electrify/db pattern does not exist), current API patterns (table as query param not path, handle not shape_id). Load when building a new feature from scratch.

electric-deployment

25
from ComeOnOliver/skillshub

Deploy Electric via Docker, Docker Compose, or Electric Cloud. Covers DATABASE_URL (direct connection, not pooler), ELECTRIC_SECRET (required since v1.x), ELECTRIC_INSECURE for dev, wal_level=logical, max_replication_slots, ELECTRIC_STORAGE_DIR persistence, ELECTRIC_POOLED_DATABASE_URL for pooled queries, IPv6 with ELECTRIC_DATABASE_USE_IPV6, Kubernetes readiness probes (200 vs 202), replication slot cleanup, and Postgres v14+ requirements. Load when deploying Electric or configuring Postgres for logical replication.

electric-debugging

25
from ComeOnOliver/skillshub

Troubleshoot Electric sync issues. Covers fast-loop detection from CDN/proxy cache key misconfiguration, stale cache diagnosis (StaleCacheError), MissingHeadersError from CORS misconfiguration, 409 shape expired handling, SSE proxy buffering (nginx proxy_buffering off, Caddy flush_interval -1), HTTP/1.1 6-connection limit in local dev (Caddy HTTP/2 proxy), WAL growth from replication slots (max_slot_wal_keep_size), Vercel CDN cache issues, and onError/backoff behavior. Load when shapes are not receiving updates, sync is slow, or errors appear in the console.

ElectricSQL

25
from ComeOnOliver/skillshub

## Overview

Electric SQL — Sync Engine for Postgres

25
from ComeOnOliver/skillshub

You are an expert in Electric SQL, the sync engine that streams Postgres data to local apps in real-time. You help developers build local-first applications where data syncs from Postgres to client-side SQLite/PGlite automatically — enabling instant reads, offline support, and real-time multi-user collaboration using Postgres as the single source of truth with Shape-based partial replication.

Daily Logs

25
from ComeOnOliver/skillshub

Record the user's daily activities, progress, decisions, and learnings in a structured, chronological format.

Socratic Method: The Dialectic Engine

25
from ComeOnOliver/skillshub

This skill transforms Claude into a Socratic agent — a cognitive partner who guides