Documentation
CrescoDB is a local-first backend toolkit: a database, an auto-generated REST API, auth with roles, file storage, realtime subscriptions and an admin dashboard, on SQLite, PostgreSQL or MySQL. It runs on your machine, and deploys to a server you own.
Install
CrescoDB is a CLI. It needs Node 20 or newer: Node 22 LTS is the safest choice. (CrescoDB uses a native SQLite module that ships prebuilt binaries only for supported Node versions; on anything older the CLI stops with a clear message rather than a compiler error.)
On an older Node, install a current one first. nvm install 22 && nvm use 22 (macOS/Linux), nvm install 22.21.0 && nvm use 22.21.0 (nvm-windows), or grab the LTS installer from nodejs.org.
Quickstart
A new project starts empty: add tables with cresco create, the dashboard's schema editor, or by describing them in plain English. (Want demo tables? cresco init --starter.) Open the dashboard at http://localhost:3000/studio to browse data, edit schema, see a live schema diagram (ERD), run SQL, upload files, and watch changes live.
Your app is served too: cresco dev includes a built-in live server at http://localhost:3000/app: it serves your project folder (your index.html, CSS, JS) and auto-reloads the page whenever you save, so you build your frontend right next to its API. Secrets (config.json, .env, database files) are never served.
Video walkthrough
A full end-to-end walkthrough: starting a project, designing the schema, and deploying it to a real server with a custom domain and automatic HTTPS.
Coming shortly: the walkthrough is being recorded. Until it lands, the written Quickstart and Deploy to a server you own sections cover the same ground step by step.
CLI reference
- cresco login: sign in to your CrescoDB account · logout · whoami
- cresco init: scaffold a new (empty) project · --starter for demo tables
- cresco dev: run the API server + dashboard (-p to set the port)
- cresco start: the production server: API + auth only, no admin surfaces
- cresco generate: sync schema.cresco → tables
- cresco ai "…": natural language → schema
- cresco create <feature>: write a feature as full editable code (auth, blog, payments) · --express / --next
- cresco add <module>: install a managed module: bundled or from the registry
- cresco publish: publish a module from this folder to the registry
- cresco orgs: list your teams · cresco org create <slug> · org add <slug> <email> · org members <slug>
- cresco link: share this project with your team · cresco projects (list) · cresco open <slug> (open a teammate's)
- cresco deploy: prepare this project to run online (Dockerfile + host configs), or push it to one of your servers with --server. Runs the access audit first and refuses on a critical finding · --allow-public to override
- cresco eject: write a folder that runs this project without CrescoDB: your code, your data as plain SQL, the engine vendored, Dockerfile + compose · --out · --db · --force
- cresco audit: access control + dependency vulnerabilities · --access-only · --deps-only. Exits non-zero on a critical finding, so it works in CI
- cresco install <pkg>: add npm packages · cresco fund
The CLI sends its version with every request to the hosted platform. Releases below the supported minimum are refused with a clear upgrade message rather than failing in confusing ways, and npm install -g crescodb@latest fixes it. Nothing is sent for projects running fully offline.
Schema
Your data lives in schema.cresco: JSON models with typed fields (string, text, number, boolean, uuid, date, json). It's the single source of truth; the dashboard and AI edit the same file.
Databases (SQLite · PostgreSQL · MySQL)
SQLite is the zero-config default: perfect for local development and read-heavy apps, with nothing to install. Pick a different engine from dashboard → Settings → Connection → Database engine (or set dialect in config.json). Your schema.cresco and the entire REST API stay identical across engines.
PostgreSQL, two ways, no DBA required
- Zero-config local Postgres. Choose PostgreSQL and leave the connection blank. CrescoDB downloads and runs a real Postgres server for you (data kept in .cresco/pgdata, so it persists). No install, no credentials, just like SQLite. cresco dev prints the local port so you can also connect pgAdmin/psql to it.
- Your own / hosted server. Already have Postgres, a local install, docker run postgres, or a managed host like Railway, Neon, or Supabase? Paste its connection string and CrescoDB connects to that instead (it honors sslmode=require for managed hosts). This is also how a whole team shares one live database.
MySQL, bring your own
Choose MySQL and provide a connection string to a MySQL server (a local install or one line of Docker: docker run -e MYSQL_ROOT_PASSWORD=pass -p 3306:3306 -d mysql).
Switching engines & your data
- Your first switch is safe. Moving off the default SQLite carries your schema over and leaves your existing cresco.db file untouched, nothing is deleted.
- Switching again later doesn't migrate data automatically (engines store data differently). To carry data across a later switch: Export your project as .sql (Settings → Connection), switch, then Import it into the new engine.
- After changing the engine, restart cresco dev to connect.
REST API
Every model gets full CRUD automatically: GET/POST/PUT/PATCH/DELETE /:model, plus /:model/:id, bulk insert, and ?limit/?offset/?where. No routing to write.
Auth & roles
Two ways to get auth, both real:
- cresco create auth: writes complete auth code you own (register.js, login.js, middleware.js, jwt.js) wired to your project database. Read it, edit it, extend it.
- cresco add auth: enables the built-in managed auth: JWT register/login/me plus role-based access control, roles guest · user · mod · admin and a per-table access policy enforced on every request. Models can also declare a rowOwner column for per-row security: users only ever see and touch their own rows.
Manage users and policies from the dashboard's Users page either way.
Access control
Tables are private by default. A model that declares no access block requires a signed-in user to read it. Nothing is served to anonymous callers unless you say so.
This changed in 1.0. Before that the default was read: ["*"], meaning any model you hadn't thought about was readable by anyone on the internet once deployed. That is the same default behind the wave of AI-built apps found serving their user tables through a public key, and it was wrong. If you have a project from an earlier version, run cresco audit before you upgrade, anything that relied on the old default will now return 401.
The defaults:
- read · create · update: any signed-in user
- delete: admin only
Public is still completely supported, it just has to be a decision you typed. A price list or a blog post should be readable by anyone:
{
"name": "Post",
"access": { "read": ["*"], "write": ["authenticated"], "delete": ["admin"] },
"fields": [ ... ]
}
Roles are guest · user · mod · admin. "*" means anyone with no token; "authenticated" means any signed-in user. Add rowOwner to scope rows to the user who owns them, without it, any signed-in user can read every row in the table, which is right for an internal tool and wrong for a SaaS.
cresco audit
Answers one question offline, from the schema in your repo: who can read this table?
cresco audit # access control + dependencies
cresco audit --access-only # just the access review
It ranks by what is actually exposed, not merely by whether something is exposed. A public table holding an email column is critical. A public price list is a note. It also flags tables holding personal data with no rowOwner, and warns when auth is switched off entirely.
It exits non-zero when it finds something critical, so it works in CI as-is.
cresco deploy runs it first and refuses to proceed on a critical finding: no Dockerfile, no host configs, nothing written. Deploying is the moment a mistake stops being cheap, so that is where the gate lives. If your API really is meant to be open, say so:
cresco deploy --allow-public
Most scanners for this problem work from the outside: you give them a live URL and they probe your tables the way an attacker would. That only helps after you have already shipped the mistake. Because CrescoDB owns your schema, this runs before anything is deployed.
Your AI agent, over MCP
An agent is only as good as the feedback loop it can close. Against a hosted backend it is writing blind: the database is remote, the schema is behind a dashboard, and it cannot call the API it just generated. Here everything is a file on the machine the agent is already sitting on, so it can read the real schema, change it, run the real API and run the real audit.
The server ships inside the CLI. There is nothing extra to install.
--print gives you the config in the shape that client actually wants, and tells you which file it belongs in.
Claude Code
One line, run in the project folder. It writes .mcp.json, which is committed with the repo, so your whole team gets it.
Codex
Codex reads TOML, not JSON. Add this to ~/.codex/config.toml, or to .codex/config.toml in a trusted project. codex mcp add does the same thing interactively.
Cursor
.cursor/mcp.json, under an mcpServers key. Restart Cursor afterwards.
VS Code, Copilot agent mode
.vscode/mcp.json, and the root key is servers, not mcpServers. Getting that wrong writes a valid-looking file that silently does nothing. Needs VS Code 1.99 or newer with agent mode on.
Claude Desktop
claude_desktop_config.json, under mcpServers. Fully quit and reopen the app, not just the window.
The VS Code extension writes the JSON ones for you in one click and keeps the MCP servers you already had. Codex is TOML, so copy the block above rather than letting anything merge it for you.
It speaks standard MCP over stdio, protocol 2024-11-05, so any compliant client works and not only the four above.
The 14 tools
- Read: project_info · schema_read · rows_list
- Verify: access_audit · api_request
- Auth: auth_enable · auth_create_user
- Change: schema_add_model · schema_add_field · schema_set_access · schema_drop_model · db_sync · sql_query · data_export
Worth asking it
- "Read my schema and tell me if anything here is unsafe to deploy."
- "Add a bookings table where a customer can only see their own rows."
- "Create a test user, log in as them, and prove they cannot read anyone else's data."
That last one is the interesting one. The agent creates the second user, calls your real API with their real token, and shows you the empty array. It is not claiming per-user isolation works, it is demonstrating it.
VS Code extension
Install CrescoDB from the VS Code marketplace, or from Open VSX for Cursor, Windsurf and VSCodium, which cannot reach the Microsoft one.
It drives the cresco CLI, so install that first. It only does anything in a project that has a schema.cresco, including one in a subfolder, and it wakes up on its own when you run cresco init.
It is not another database GUI. The dashboard already is one, and Open dashboard opens it in your browser rather than a panel. What the extension does is the part only an editor can:
- Findings on the line. Save schema.cresco and a table anyone can read gets underlined, with the reason in the hover. Same cresco audit that cresco deploy runs, so the editor and the deploy can never disagree.
- Fixes from the lightbulb. Make it signed-in only, scope rows to their owner using a column you actually have, restrict deletes to admins, or swap "public" for the wildcard "*" that actually means anyone. With several criticals, one action fixes them all. Only the access block's bytes change, so your formatting survives.
- One-click agent connect. Writes the MCP config for whichever client you use, keeping any servers already in the file.
- A schema tree in the Explorer. A lock for private tables, an open lock for public ones, and per-user tables name the column that scopes them. Click a model to jump to it.
- A status bar shield with the critical count, and autocomplete plus validation on schema.cresco.
Settings: crescodb.auditOnSave (on by default), crescodb.cliPath if cresco is not on your PATH, and crescodb.studioUrl if the dev server is not on the port in your config.json. If the audit cannot run, the status bar says so rather than looking clean, and CrescoDB: Show logs says why.
Assistant & coding agent
The dashboard's AI page has two tabs. Chat designs schema and data around your actual project, describe what you're building, review the proposal, hit Apply to DB. Code is the coding agent: it reads and writes your project's files and runs commands (each command asks for your approval first; file edits show a diff with undo). Both need cresco dev running, the AI works on your real project.
- Conversations: the sidebar keeps your history like ChatGPT: chats on the Chat tab, builds on the Code tab. Start new ones freely; old ones stay until you delete them. History lives in the project's own database, per project.
- Attachments: the clip button sends images and code/text files with your message (screenshots of a schema, a CSV to model, an error log).
- Edit & stop: edit a sent message to rewind the chat and resend; the send button becomes Stop while the AI works.
- Settings tab: per-project preferences saved to config.json: reply tone, project memory (whether the AI sees your schema and sample data), review-every-file-edit mode, and auto-run commands for trusted projects.
The assistant and agent run on CrescoDB's hosted keys and are metered in Cresco tokens on your account, so you never bring a provider key. cresco login connects the CLI to your account.
Scaffolds with cresco create
Writes a feature into your project as full, editable code: real files, not a package. Models merge into your schema, endpoints go live on cresco dev immediately, and every file is yours to change.
- auth: register / login / me, JWT + scrypt, middleware for your own routes
- blog: posts + comments, a slugged public feed and comment API, plus a ready-made blog website (home + post pages) served at /app
- payments: Paystack + Flutterwave checkout & verify, recorded in a payments table. No keys yet? It runs in dev mode (instant fake success) so you can build the flow first.
- store: products, cart and checkout with a storefront UI; the total is computed on the server (never the client) and composes with the payments feature automatically.
- chat: a sign-in-gated, Slack/Discord-style realtime chat: servers, channels and live messages over SSE, with a full chat UI. Bring your own email provider to verify sign-ups.
- todo: a complete full-stack to-do app (list UI + API) that syncs live across tabs, the fastest end-to-end starter.
Modules
cresco add installs managed, database-aware modules, they merge models into your schema, drop in code, and record a migration. Use create when you want to own the code; use add for managed installs and community modules from the registry.
File storage
Every project has bucket-based file storage at /storage: uploads, folders, public or private buckets, and a file browser in the dashboard. Locally files live in .cresco/storage; in production point config.storage at any S3-compatible store (AWS S3, Cloudflare R2).
Public buckets serve files at a plain URL; private buckets require auth. Toggle visibility from the dashboard's Storage page.
Realtime
Subscribe to live row changes, every create, update and delete streams to connected clients over SSE, with table access rules and per-row security respected. The dashboard's Realtime page shows the live feed.
The JS SDK, cresco-js
A zero-dependency client for browsers and Node 18+: auth, fluent CRUD, storage, and realtime in one import.
Production with cresco start
The production server serves only your API, auth, storage, realtime and custom routes, every admin surface (SQL editor, schema DDL, AI, dashboard) is absent, not just disabled. Configure with env vars: DATABASE_URL, PORT, CRESCO_AUTH_SECRET, CRESCO_CORS_ORIGIN; pending migrations run at boot. Server-to-server callers can use the project API key for full access.
Deploy to a server you own
CrescoDB Cloud is a deployment control plane: it builds and runs your project on infrastructure you own, and you manage it from the dashboard's Cloud area. Your app and its database live on your server or provider. CrescoDB orchestrates the deployment; it doesn't host your data. Three ways to deploy:
- Your own server (BYO-VPS). Connect any Ubuntu/Debian VPS with a one-line installer, it creates a locked-down deploy user and installs Docker. Then cresco deploy --server <name> ships your local project, or deploy a repo from the dashboard.
- Git auto-deploy. In Cloud → Deploy a repo, install the CrescoDB GitHub app on the repos you pick, choose a repo + branch, and deploy. Every push to that branch redeploys automatically; toggle auto-deploy per app.
- Managed PaaS (one-click). Connect your Render or Railway account (an API key, stored encrypted) and deploy a repo there in one step. The provider builds, hosts, and auto-deploys on push; the dashboard links out to it for logs and env. This route doesn't need the GitHub app: the provider clones the repo itself, so you can just type owner/repository. (A private repo needs GitHub connected inside your provider account.)
Each deployed app has its own Overview, Deployments, Environment, Domains, Logs, Database, and Settings. Environment variables and secrets are encrypted at rest; custom domains get automatic HTTPS via Caddy on a BYO-VPS. You can also edit a live deployment's data and schema from the dashboard, open a live app and its Tables / SQL editor operate on the running database.
Live progress, not polling. Deploy status, build logs, and a server's first check-in stream to the dashboard as they happen, so you watch a build move through queued → building → deploying → live in real time.
Connecting your first server, start to finish
If you have never rented a server before, this is the whole process. It takes about five minutes and none of it requires knowing Linux.
- Rent a box. Hetzner, DigitalOcean, Vultr and Linode all rent one for roughly $5 a month. Choose Ubuntu (any recent version) and the smallest size. You will be shown an IP address and either a password or an SSH key. That IP is your server.
- Add it in the dashboard. Cloud → Servers → Connect a server. Give it a name you will recognise later, like web-1. We generate a key pair for it and show you one command.
- Paste that command into your server. Log in to the box (your provider has a "Console" button in the browser if you would rather not use a terminal) and paste. It looks like this:
$ curl -fsSL .../connect.sh | sudo bash -s -- --token ... --url ... --pubkey '...' # the dashboard fills all three in for you, copy the whole lineIt installs Docker if the box does not have it, creates a dedicated non-root cresco user with no sudo access (it is added to the docker group so it can manage containers), authorises our key for that one user, and reports back. We never ask for and never store your root password. The only credential we hold is a key that logs in as cresco, and it is encrypted at rest on our side.
- Watch it turn green. The server appears as online in the dashboard within a few seconds, along with its OS, CPU count and memory.
- Deploy. From your project folder: cresco deploy --server web-1. Your project is sent up, built on the box, health-checked, and switched over. If the health check fails, the previous version keeps serving and you get told why.
The connect command carries a single-use token that stops working the moment the server checks in, so a copy of it left in your shell history is worthless. If a connect goes wrong, re-issue a fresh command from the server's page; the old one dies instantly.
Plan limits. Two things count against your plan: connected servers and apps deployed to them.
- Free: 1 server, 1 app
- Pro: 5 servers, 15 apps
- Team: 20 servers, 75 apps
- Enterprise: unlimited
Redeploying an app you already have is always allowed, so a cap can never block a fix to something already live. Apps you deploy to a managed PaaS are not capped, because the provider hosts those, so we don't meter them. Local development is not capped by anything, ever.
Leaving, with cresco eject
Every platform says it has no lock-in. Here is ours, as a command you can run right now before you have committed anything to us.
cresco eject
That writes a folder next to your project that runs it without CrescoDB. No account, no connection to our servers, and no dependency on us continuing to publish anything:
myapp-ejected/
schema.cresco your models
data.sql every table and every row, as plain SQL
vendor/crescodb-1.0.3.tgz the engine itself, packaged into the folder
Dockerfile builds from that file, not from the internet
docker-compose.yml your app and a real database, wired together
README.md
…the rest of your project, as it was
Then:
cd myapp-ejected
docker compose up --build
Your API is on http://localhost:3000. That is the whole procedure.
What this actually guarantees, and what it does not
Being precise here matters more than sounding good, because this is the promise people check.
- It is not an airgapped bundle. docker compose up still downloads a Node base image and still lets npm fetch ordinary third-party packages, the same as any Docker build anywhere.
- What it removes is the dependency on us. The engine is inside the folder as a packaged file, so your app keeps building even if CrescoDB is gone from npm, this CLI is uninstalled, and the company no longer exists. Everything else it needs belongs to somebody else and does not care whether we do.
- And underneath that, your data is plain SQL. data.sql is not a proprietary snapshot only we can read. psql, mysql and sqlite3 all load it, and so does anything else that speaks SQL. If you decide to stop using CrescoDB altogether, your data walks out with you and you need neither our permission nor our software to read it.
Export for a different engine with --db. This is also the clean way to move a SQLite project onto Postgres, because the schema is translated properly rather than dumped in the dialect it happened to start in:
cresco eject --db postgres
If the data export fails for any reason, eject writes nothing at all and tells you why. A bundle whose data.sql is missing or empty fails the way an untested backup does: you find out on the day you needed it. Same reasoning as the restore checks.
Two things to change before you put a bundle anywhere real, both called out in its README: the database password in docker-compose.yml is a placeholder that is identical in every ejected bundle, and CRESCO_AUTH_SECRET has to be set if your project uses auth.
The dashboard has the data half of this too, at Settings → Connection → Export, including exporting for a different engine. cresco eject is that plus everything needed to actually run.
Custom domains & DNS
This is the step that stops most people, so it is worth being plain about what is actually happening. A domain is just a name that points at a number. Your server has a number (its IP address). To put your app on app.yoursite.com, you tell your domain provider "this name lives at that number". That is the whole job.
Open your app in the dashboard, go to Domains, and type the domain you want. We then show you the exact record to create, filled in with your server's address:
Type A
Name app (just the part before your domain, not the whole thing)
Value 203.0.113.40 (your server's IP, filled in for you)
TTL Auto (or 300)
Proxy DNS only
Paste that into whichever provider holds your domain. Cloudflare, Namecheap, GoDaddy, Porkbun, they all have the same five fields under a heading like "DNS" or "Manage DNS". The dashboard has step-by-step directions for the common ones behind the ? next to the record.
Two things people get wrong constantly, so we check both for you:
- The Name field is not the whole domain. For app.yoursite.com you type app, not app.yoursite.com. Providers add the rest. For the bare domain, type @.
- Cloudflare's orange cloud must be off. If the record is set to "Proxied" (the orange cloud) instead of "DNS only" (grey), Cloudflare answers on your behalf, your server never sees the certificate check, and you get a 522 error. We detect this specific case and say so by name, instead of leaving you staring at a timeout.
Press Check DNS and we look up the name from the outside and tell you one of: nothing resolves yet, it points somewhere else (with where), it is proxied through Cloudflare, or it is pointing at your server and certificates can issue. New records usually work within a few minutes.
Once it resolves, HTTPS is automatic. Caddy requests a free Let's Encrypt certificate and renews it forever. You do nothing.
Keeping Cloudflare's proxy on (DNS-01)
Some people want the orange cloud: it hides your server's IP and absorbs traffic. You can have both, but the certificate then has to be verified a different way, through your DNS records instead of through your website. That is called a DNS-01 challenge, and it needs permission to write a record on your behalf.
In Domains → Advanced, pick Cloudflare and paste an API token. Create it at Cloudflare → My Profile → API Tokens → Create Token, using the "Edit zone DNS" template scoped to that domain's zone. A Global API Key is not the same thing and will not work.
We then swap in a Caddy build that speaks Cloudflare, store your token on your server with 0600 permissions, and validate the whole configuration before replacing the running one. If any step fails, the previous working setup is put back and Caddy keeps serving. Your token is never written to a log.
Cloudflare is the only DNS-01 provider today. Everyone else should leave the record on "DNS only", which is the default and needs no token at all.
Server & app health
Open a server in Cloud and you get live numbers read off the box itself, not estimates:
- CPU: real utilisation, sampled twice a second apart. This is not load average, which is a different number that confuses everyone. Time spent waiting on the disk is counted as idle, because the processor is.
- Memory: used, available and total. "Available" is the honest figure: Linux uses spare memory for disk cache and gives it back on demand, so a box that looks 90% full is usually fine.
- Disk: used and free on the root filesystem, plus what Docker itself is holding in images, containers and volumes. A full disk is the single most common way a small VPS dies, and it is almost always old Docker images.
- Uptime, load, kernel, OS, Docker version, and how many containers are running versus stopped.
Each app has its own panel: its container's CPU and memory, its restart count, its published port, and its database container's size on disk.
Restart count is the one to watch. A container that crashes and immediately restarts reports itself as "running" to every tool that asks, because it just started. It will do that forever while serving nothing. We report the honest status and the restart count, and alert you on paid plans.
Languages
Your app can be written in any language: it just talks to the REST API over HTTP (the CLI needs Node installed to run, like Docker for a database). Scaffold code is currently provided for:
- Node: available now (auth, blog, payments, store, chat, todo), plus Express and Next.js variants
- Python, Go, PHP are on the way
Accounts & sign-in
A CrescoDB account unlocks the hosted features, the AI coding agent, cloud backups, publishing, and shared projects. The dashboard requires a signed-in account; the CLI and API work offline once you're set up.
Sign up with an email and password, or with GitHub or Google. Accounts start on the free plan; you can upgrade from Settings at any time.
cresco login uses a device-authorization flow: it shows a short code, opens crescodb.com/activate, and once you approve it (while signed in) the CLI is connected. The token is stored in ~/.cresco/config.json. Paid features are checked against your plan on the server.
Two-factor authentication
Turn it on in Settings → Security. It uses TOTP, so it works with 1Password, Bitwarden, Google Authenticator, Aegis, or anything else that scans a standard setup key. No SMS, and no emailed codes.
Emailed codes are the common choice and they're weaker than they look: they protect against a leaked password but not against the attack that actually happens, which is the mailbox itself being taken over. If the password-reset link and the second factor both land in the same inbox, the second factor is a rename of the first. TOTP also works with no signal.
- Setup is two steps: we hand you a key, and 2FA only switches on after you enter a working code. Abandon it halfway and nothing has changed, you can't lock yourself out.
- You get 10 single-use recovery codes, shown once. Store them somewhere that is not the phone running your authenticator, because that phone is what they exist for.
- Turning 2FA on or off, and regenerating recovery codes, all require your password again. A stolen browser session can't enrol its own authenticator or strip the protection off.
Passwords need at least 10 characters and are checked against known breach corpora (only a 5-character hash prefix ever leaves the server, your password is never sent anywhere). There are no "must contain a symbol" rules: length is what survives an offline crack, and composition rules mostly produce Password1! reused on ten sites. A long passphrase is accepted; a short one full of symbols is not.
Backups, restore checks & rollback
Every host tells you "backup succeeded". That only ever means a file was written: not that it's complete, not that it's valid, not that it can be loaded back. The gap between those is where people lose their data, and it stays invisible until the day it matters.
So we restore it and look.
- Restore checks take your latest backup, load it into a throwaway database container on your server, count what came out, then destroy the container. Your live database is never touched. The app page reports the result: Restored into a clean database: 12 tables, 48,120 rows. Took 4.2s.
- A backup that loads cleanly but contains nothing is reported as a failure, not a pass. An empty file is not a backup.
- Rehearsals run automatically about once a week per app, and you can run one any time from Overview → Safety net → Test now. They're paced deliberately: a real restore costs CPU and disk on your server, and a check that slows your box is one you'd switch off.
- Rollback checks confirm the previous image is still on the server and still boots, before you need it. They also warn when migrations have run since that image, because rolling back code without rolling back the database is its own outage.
Until a backup has actually been rehearsed, the dashboard says "Never tested" rather than showing a green tick. That state is deliberate, treating "no news" as good news is the whole problem.
Alerts
We host it, so we tell you when it breaks. Every few minutes we check that your container is running and that your app answers its health check, and message you when that changes. Alerts reach you by email or WhatsApp on paid plans.
- Deploy failed: with a note that your previous version is still serving traffic.
- Container stopped: including the exit code.
- Not responding: running, but the health check fails. This is the one that looks fine in docker ps.
- Backup problems: a scheduled backup that didn't complete, or a restore rehearsal that failed.
You get one alert per problem, not one per check. An app that's been down for six hours sends a single email, not seventy-two. Recovery is shown in the dashboard and not emailed at 4am.
Alerts are included on paid plans (Pro 200/month, Team 750, Enterprise unlimited) and are not part of the free plan. Turn them off per account in notification settings.
Publishing modules
Anyone on a paid plan can publish modules to the registry. Describe the module with a cresco.module.json in its folder, then run cresco publish:
Install any published module with cresco add <name>: it merges the models and drops the code, just like a bundled module. Public modules install for anyone; private (scoped @org/name) and paid modules are gated to entitled accounts.
Modules are just files: frontend code publishes like backend code. Ship a UI kit, a set of React components, or a full login page as a module: put the files in the module folder, publish, and cresco add copies them into whichever project needs them (it never overwrites files you already have). Models are optional, a pure-frontend module has none.
Teams
An org (team) is a shared workspace with its own private module scope. Create one and the slug becomes your @scope; members can install the org's private modules.
Publish a private module to the org with a scoped name (@acme/billing), only admins/owners can publish, and any member can cresco add @acme/billing. A private registry requires a Team plan.
Shared live projects
Beyond modules, a whole project can be shared so teammates anywhere work against the same live database. Point the project at a shared Postgres/MySQL (a Railway/Neon/Supabase or your own server. Settings → Connection), then:
Anyone in the org (signed in to their own CrescoDB account, anywhere in the world) can cresco open it; access is checked server-side on every open. The shared connection lives in the project's config, local SQLite/embedded projects share their schema but not their data, so use a shared server for a true shared-live project. Re-running cresco link syncs the latest schema.
Plans & billing
Local development is free forever. Plans differ by capability, not just usage limits. The short version: everything on your own machine is free, and you pay for the things that run while you are asleep.
- Free: everything local plus AI chat, and 1 app deployed to 1 server. No safety net: no scheduled backups, no restore rehearsals, no alerts. That is deliberate and the dashboard says so plainly rather than hiding it.
- Pro: the AI coding agent with smart model routing, nightly backups with restore rehearsals (25 stored, 7 days), alerts by email or WhatsApp (200/month), 15 apps across 5 servers, 10 shared projects, registry publishing, 48-hour email support.
- Team (per seat), everything in Pro plus team workspaces, shared live projects, a full audit trail, the private @org registry, 100 backups at 30 days, 750 alerts, 75 apps across 20 servers, 50 shared projects, 12-hour priority support. (Pro users can join a team; creating one needs Team.)
- Enterprise: our most capable model first on every big task, unlimited servers, apps, projects and stored backups, 90 days of retention, uncapped alerts, a named contact with a 4-hour response.
Two different things are counted and it is easy to mix them up: apps are deployments running on a server you own, while projects are projects registered to share with a team via cresco link. Deploying does not consume a project, and sharing does not consume an app.
Assistant and agent usage is measured in Cresco tokens. Every plan includes a monthly amount (see pricing); each request deducts tokens based on its size, small requests use a few, large agent tasks use more. Usage also has daily and weekly ceilings within the month. Model selection is automatic. Your token balance is shown in the dashboard.
Billing is managed from dashboard → Settings → Billing. Prices are shown in USD; you pick your currency at checkout.