Skip to content

Ask AI

Ask anything about Destesi — setup, products, APIs.

Powered by Claude. Answers may be wrong — always verify against the docs.

Reference

The complete Snap surface: CLI commands, REST endpoints, the in-session SQL meta-commands, and the proxy’s own environment variables for self-hosting.

All Snap commands live under dst snap. They act in your active workspace — set it once with dst workspace switch <name>. Install with:

Terminal window
curl -fsSL https://get.destesi.io/install.sh | sh

dst snap remote postgres <dsn> — register a Postgres database as a remote.

Flag Description
--name Optional display name
--tunnel-mode none (default) or ssh
--tunnel-bastion-host SSH bastion hostname
--tunnel-bastion-user SSH bastion user
--tunnel-remote-host Database host reachable from the bastion
--tunnel-remote-port Database port reachable from the bastion
--tunnel-key-path Local path to an SSH private key (.pem)
--tunnel-key-secret-ref Reference to a pre-uploaded SSH key (secret://…)
--output text (default) or json

dst snap remote s3 <bucket> — register an S3-compatible bucket as a remote.

Flag Description
--name Optional display name
--region S3 region (defaults to us-east-1, or $AWS_REGION)
--endpoint Custom endpoint for S3-compatible storage (MinIO, R2)
--access-key-id Access key (or $AWS_ACCESS_KEY_ID)
--secret-access-key Secret key (or $AWS_SECRET_ACCESS_KEY)
--path-style Use path-style addressing (for MinIO)
--output text (default) or json

dst snap remote list — list remotes in the active workspace. dst snap remote show <id> — show one remote’s details. dst snap remote remove <id> — remove a remote from the workspace.

dst snap try <postgres-url> — one-shot: register a remote, create a branch, wait for it, and print the DSN.

Flag Description
--as Name for the new branch (default: auto-generated)
--wait-timeout Max time to wait for provisioning (default 5m)
--quiet Print only the final DSN (for eval $(…))

dst snap create <name> — create a branch by cloning from a remote or forking from a branch.

Flag Description
--connector-id Remote to clone from (required unless --from-snap)
--from-snap Fork from an existing branch instead (inherits its remote)
--max-lag Maximum acceptable source sync lag, in seconds
--at-checkpoint Pin to a specific checkpoint ID
--override Column override table.column=sql_expr, repeatable
--overrides-file Path to a JSON file with the full override spec

dst snap list — list branches in the active workspace. dst snap status <id> — show a branch’s status and endpoint DSN. dst snap switch <id> — set the active branch and save its DSN to local config. dst snap delete <id> — delete a branch and release its resources. dst snap trace <snap-id> — print recent SQL trace events from a branch’s proxy. Requires SNAP_TRACE_SQL=1 on the branch; uses psql if present, otherwise prints the command to run. --print only prints the command.

dst snap fixture save <snap-id> — pin a ready branch as a named fixture.

Flag Description
--name Fixture name, unique within the workspace (required)
--desc Optional description

dst snap fixture list — list fixtures in the active workspace. dst snap fixture show <id-or-name> — show a fixture by ID or name. dst snap fixture restore <id-or-name> — fork a new branch from a fixture.

Flag Description
--as Name for the new branch (required)
--max-lag Maximum acceptable source sync lag, in seconds

dst snap fixture delete <id-or-name> — delete a fixture. The source branch is unaffected.

Override rules rewrite specific columns as rows are copied from the source — for PII masking, flipping feature flags, or filtering to one tenant. Rules are attached at branch-create time and baked into the sandbox; they cannot be changed later.

Terminal window
dst snap create agent/safe-sandbox \
--connector-id conn_a1b2c3d4 \
--override "users.email='me@example.com'" \
--override "users.is_admin=false"

Each set value is a raw SQL expression evaluated against the source row — quote string literals ('...'), use false / NULL, or reference other columns (first_name || '@example.com'). The optional where predicate scopes which rows get masked; every source row is still copied, and non-matching rows keep their original values. --override flags merge with --overrides-file, and flags win on conflict.

The CLI stores config under ~/.destesi/: the API URL and auth token, the active workspace, and the active branch DSN (set by dst snap switch).

All endpoints are JSON over HTTPS at https://api.destesi.io. Protected endpoints require a Bearer token:

Authorization: Bearer <your-token>

List endpoints are scoped by an identity_workspace_id query parameter.

Method Path Description
POST /v1/connectors Register a connector (Postgres or S3)
GET /v1/connectors?identity_workspace_id=… List connectors in a workspace
GET /v1/connectors/{id} Get connector details
DELETE /v1/connectors/{id}?identity_workspace_id=… Remove the connector from a workspace
Method Path Description
POST /v1/snaps Create a branch (clone or fork)
GET /v1/snaps?identity_workspace_id=… List branches in a workspace
GET /v1/snaps/{id} Get a branch’s details and DSN
DELETE /v1/snaps/{id} Delete a branch
POST /v1/snaps/{id}/switch Mark a branch active
POST /v1/snaps/{id}/promote Pin a ready branch as a fixture
Method Path Description
GET /v1/fixtures?identity_workspace_id=… List fixtures in a workspace
GET /v1/fixtures/{id} Get fixture details
DELETE /v1/fixtures/{id} Delete a fixture
POST /v1/fixtures/{id}/instantiate Fork a new branch from a fixture
Method Path Description
GET /v1/checkpoints?connector_id=… List checkpoints for a connector
GET /v1/checkpoints/{id} Get checkpoint details
GET /v1/operations/{id} Poll an operation (pending, running, completed, failed)
// POST /v1/snaps
{
"identity_workspace_id": "ws_abc123",
"connector_id": "conn_a1b2c3d4",
"name": "agent/migration-test"
}
// 201 Created
{
"id": "snap_e5f6g7h8",
"status": "provisioning",
"operation_id": "op_aabbcc"
}

To fork from another branch, send parent_snap_id instead of (or alongside) connector_id — the remote is inherited from the parent. Pass overrides, max_lag, or checkpoint_id to apply masking, a freshness bound, or a pinned checkpoint.

// POST /v1/snaps
{
"identity_workspace_id": "ws_abc123",
"connector_id": "conn_a1b2c3d4",
"name": "agent/safe-sandbox",
"overrides": {
"tables": [
{
"table": "users",
"set": { "email": "'me@example.com'", "is_admin": "false" },
"where": "role = 'customer'"
}
]
}
}

Overrides are immutable once the branch is created; branch again to change them.

Errors return a JSON body with an error.code and error.message and the matching HTTP status.

Status Meaning
400 Validation error — invalid or missing parameters
403 Forbidden — caller is not a member of the target workspace
404 Not found
409 Conflict — duplicate name, or a state conflict (e.g. source not healthy)
429 OPERATIONAL_CAPACITY — too many branches provisioning at once (five per workspace by default), or quota_exceeded — the workspace used up the branch allowance its plan enforces
500 Internal error
503 quota_policy_unavailable — the plan allowance could not be read, so the request was refused rather than admitted blindly

A quota_exceeded body carries the numbers behind the refusal:

{
"error": {
"code": "quota_exceeded",
"message": "Snap branch limit reached",
"details": { "capability": "max_branches", "used": 5, "limit": 5, "remaining": 0 }
}
}

A 403 on create means the workspace itself is barred (workspace_suspended or entitlement_required), not that you lack access to the connector.

A branch mirrors every user schema in the source, not just public. Postgres’ own catalogs and Snap’s internal _snap_* schemas are excluded, and each mirrored schema gets its own private holding area so same-named tables in different schemas never collide.

Two rules when you query a branch:

  • Qualify tables outside public. Snap resolves an unqualified table name as public, so SET search_path alone will not redirect it — write billing.invoices.
  • _snap_* is reserved. Any statement referencing those schemas is rejected, including a search_path that names one.

Run these from any Postgres client connected to a branch:

Command Description
SNAP STATUS Summary of your mutations (table, operation, count)
SNAP DIFF Full audit log with before/after row data
SNAP RESET Reverse all tracked changes, restoring the sandbox to source state
SNAP TRACE Recent SQL trace events (requires SNAP_TRACE_SQL=1 on the branch)

The Snap proxy is configured entirely through environment variables (or a .env file in its working directory). These apply when running the proxy yourself; the hosted service manages them for you.

Variable Default Description
SNAP_LISTEN_ADDR 0.0.0.0 Proxy listen address
SNAP_LISTEN_PORT 15432 Proxy listen port
Variable Default Description
SNAP_POSTGRES_SOURCE_HOST localhost Source host
SNAP_POSTGRES_SOURCE_PORT 5432 Source port
SNAP_POSTGRES_SOURCE_USER postgres Source user
SNAP_POSTGRES_SOURCE_PASSWORD (empty) Source password
SNAP_POSTGRES_SOURCE_DB postgres Source database
SNAP_POSTGRES_SOURCE_SSLMODE prefer SSL mode for the source connection
SNAP_POSTGRES_PORT 15433 Host port for the auto-managed sandbox container
SNAP_POSTGRES_CONTAINER_NAME snap_pg_auto Sandbox container name
SNAP_POSTGRES_IMAGE postgres:16-alpine Sandbox Postgres image
SNAP_POSTGRES_DB_USER (source user) Client-facing username
SNAP_POSTGRES_DB_PASSWORD (source password) Client-facing password
SNAP_POSTGRES_DB_NAME (source database) Client-facing database name
SNAP_READ_MATERIALIZE_ASYNC true Hydrate non-RLS first reads in the background instead of blocking
SNAP_READ_MATERIALIZE_MAX_CONCURRENT 2 Max concurrent background hydrations per session
SNAP_OVERRIDES_JSON (empty) JSON override rules applied at materialization
Variable Default Description
SNAP_S3_SOURCE_ENDPOINT (empty) S3-compatible endpoint URL
SNAP_S3_SOURCE_REGION us-east-1 AWS region
SNAP_S3_SOURCE_BUCKET (empty) Source bucket
SNAP_S3_SOURCE_ACCESS_KEY (empty) Source access key
SNAP_S3_SOURCE_SECRET_KEY (empty) Source secret key
SNAP_S3_SOURCE_USE_SSL true Use SSL for the source connection
SNAP_S3_SOURCE_PATH_STYLE false Use path-style addressing (for MinIO)
SNAP_S3_ACCESS_KEY (random) Client-facing access key; a random key is generated when unset
SNAP_S3_SECRET_KEY (random) Client-facing secret key; a random key is generated when unset
SNAP_S3_OVERLAY_DIR /tmp/snap-s3-overlay Local overlay storage directory

Set these to have the proxy own an ssh -N -L … forward when the source is reachable only through a bastion, then point SNAP_POSTGRES_SOURCE_PORT at the forwarded local port.

Variable Default Description
SNAP_POSTGRES_SOURCE_SSH_ENABLE false Start and manage an SSH tunnel before connecting
SNAP_POSTGRES_SOURCE_SSH_LOCAL_PORT (source port) Local port bound by ssh -L
SNAP_POSTGRES_SOURCE_SSH_REMOTE_HOST (empty) Database host reachable from the bastion
SNAP_POSTGRES_SOURCE_SSH_REMOTE_PORT 5432 Database port reachable from the bastion
SNAP_POSTGRES_SOURCE_SSH_BASTION_USER (empty) SSH user on the bastion
SNAP_POSTGRES_SOURCE_SSH_BASTION_HOST (empty) Bastion hostname or IP
SNAP_POSTGRES_SOURCE_SSH_KEY_PATH (empty) Path to the private key (ssh -i)
SNAP_POSTGRES_SOURCE_SSH_STRICT_HOST_KEY_CHECKING accept-new Passed to ssh -o StrictHostKeyChecking=…