parad
Encrypted local-first SQLite with Telegram cloud sync — a git-like, zero-cost workflow database. Telegram is the disk: every change you commit becomes a version-stored snapshot you can revert to anytime.
Install
pip install parad
Quick Start
Python SDK (developer workflow — auto-sync on by default)
Connect with a postgres-like connection string, write SQL offline, and the sync daemon version-stores your changes automatically. No manual push needed.
from parad import connect
# Auto-login (email:password), auto-provision project + database on the
# gateway, open/create the local encrypted SQLite file.
db = connect(url="parad://alice@example.com:secretpw@local/myproj/mydb?passphrase=secret")
# Build SQL offline like any SQLite database ...
db.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
db.execute("INSERT INTO users (name) VALUES (?)", ("alice",))
db.commit()
# ... and it's already pushed to the cloud as a new snapshot version (~2s).
# Revert anytime (from the CLI):
# !parad rollback 1
db.close()
Offline? Keep writing — changes are flagged dirty and batch-pushed as new
versions the moment you reconnect. On conflicts your local data always wins
(never silently dropped).
Local-only is just as easy:
db = connect("mydb", passphrase="secret", auto_sync=False)
CLI
# Create a new encrypted database and print the canonical URL deliberately
parad auth login
parad init mydb --project myproject --print-database-url
# Retrieve the existing canonical URL without remote mutation
parad url
parad url --print-database-url
# Push to cloud
parad push
# Pull latest
parad pull
# Check status
parad status
# Interactive SQL
parad shell
Commands
| Command | Description |
|---|---|
parad init <name> |
Create encrypted DB + register with gateway; emit canonical DATABASE_URL |
parad push |
Push database to Telegram cloud |
parad pull [version] |
Pull latest or specific version |
parad sync |
Push then pull |
parad status |
Local vs remote version |
parad versions |
List all remote versions |
parad rollback <ver> |
Rollback to previous version |
parad exec <sql> |
Run raw SQL |
parad insert <table> <json> |
Insert a row |
parad select <table> [where] |
Query rows |
parad update <table> <set> <where> |
Update rows |
parad delete <table> <where> |
Delete rows |
parad shell |
Interactive SQL REPL |
parad config show/set |
Manage config; secret-bearing fields are redacted |
parad url [name] |
Retrieve the canonical database_url |
parad database-url [name] |
Alias for parad url |
Canonical DATABASE_URL first
Use one canonical connection value for new applications and deployments. After parad init provisions the project/database, it persists database_url in ~/.paradox/config.json and prints a redacted URL by default:
parad auth login
parad init mydb --project myproject
Print the complete secret-bearing value only when intentionally copying it into a secret manager:
parad init mydb --project myproject --print-database-url
For an existing database, retrieve the saved canonical value without opening, syncing, or mutating the remote database:
parad url
parad url --print-database-url
Retrieval checks DATABASE_URL, then persisted database_url, then reconstructs and persists a canonical URL from legacy split fields when a passphrase is available. If the passphrase is missing, it stops instead of inventing a replacement. New projects should use only DATABASE_URL; split fields remain supported for legacy applications.
Applications can use the same single value:
import os
from parad import connect
db = connect(url=os.environ["DATABASE_URL"])
An explicit url argument is strongest. Explicit name or db_path options remain available for legacy target selection.
SQLAlchemy
Install the optional integration with pip install "parad[sqlalchemy]", then use the same canonical URL with create_engine("parad://..."). The ORM, Core, DB-API, and encrypted lifecycle examples are documented in docs/SQLALCHEMY.md.
Configuration
Config lives at ~/.paradox/config.json:
{
"database_url": "parad://<api-key>@local/project/mydb?gateway=https%3A%2F%2F...&passphrase=...",
"database_path": "~/.paradox/data.db",
"sync": {
"gateway_url": "https://paradox-db.onrender.com/v1",
"api_key": "pk_..."
}
}
Security
- AES-256-CBC encryption at rest
- PBKDF2-HMAC-SHA512 key derivation (256k iterations)
- Your passphrase never leaves your machine
Metadata
Release files for parad 2.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| parad-2.2.4.tar.gz | 48.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| parad-2.2.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 97.3 kB
Release files / parad-2.2.4.tar.gz
| Download URL | parad-2.2.4.tar.gz |
|---|---|
| Size | 48.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e993c86cbb1f4ab9c9f3bd2aa3797092475a15033b36b5901763eb5f5703c530
|
|
BLAKE2b-256 checksum How to use checksums |
7e27bd542ec9198ca76a1cefe95dad90a5e5782b7dc7db371c7e53a9cb3e9ee5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / parad-2.2.4-py3-none-any.whl
| Download URL | parad-2.2.4-py3-none-any.whl |
|---|---|
| Size | 48.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7659962b2c1d40ec029d4f90dd25b8e544e0016a99e8c2bfbe23a0c3b752ddf6
|
|
BLAKE2b-256 checksum How to use checksums |
a66c40f58209e0ea1680fb629139cf6cbbad26b15058b852e9943aa4e408d49d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|