← The Karsa Manual

Building a Karsa app

When a task grows past organizing data into building software — a tool, a dashboard, an automation, a small service — Karsa is where it gets built. Not in a scratch directory. Not against someone else's cloud. Inside the project, on the Karsa SDK.

This is the single most important idea for an agent working in Karsa: the app you build runs caged inside the project, and it talks to infrastructure only through the Karsa SDK. Read this whole page before you scaffold anything.

The shape of a Karsa app

A Karsa app is a per-project program that the daemon runs as a subprocess and surfaces in the UI (today via an iframe). It is caged: it gets capability through a gatekept SDK surface, not raw access to the machine. That cage is a feature — it means an app can be powerful without being dangerous, and it means "expand to the cloud later" is a config change, not a rewrite.

You build the app in the project tree (under karsa/proj_*/), versioned in git like everything else. Its data lives in the project's sqldb/. Its files live in the project. Nothing escapes the cage by default.

The SDK is the whole interface to infrastructure

Everything an app needs from the outside world comes through @karsa/* SDK packages. You do not open sockets, spin up servers, or sign up for external accounts. You call the SDK:

Because these are the only doors, the daemon can enforce the cage, swap a local backend for a cloud one, and keep the app portable. An app written to the SDK is an app that survives "let's deploy this for real."

How to build, step by step

@karsa/sqldb. Stay in the project. Scaffold the app in the project tree. Do not create it in /tmp, your home directory, or a sibling folder outside Karsa. @karsa/docdb. Pick the right storage. Tabular / relational → @karsa/sqldb. Document-shaped → @karsa/docdb. Files → @karsa/blob. Background jobs → @karsa/queue. Don't introduce a second database. @karsa/blob. Use the SDK for every external need. Need persistence, files, jobs, scheduling? There's an SDK door for it. If you think there isn't, check again before reaching outside — that instinct is usually wrong (see Anti-patterns). @karsa/queue. Keep it caged. Don't try to break out of the cage for "convenience." The cage is what lets the app be trusted and later expanded. karsa/. Version it. It's all plain files under karsa/, in git. Commit as you go.

Local now, cloud later — for free

The reason the SDK matters so much: a Karsa app written against @karsa/sqldb runs locally today and can expand to the cloud without a rewrite, because the storage chokepoint is the seam Karsa controls. The moment you go around the SDK — embed a raw SQLite file, call an external API directly, hardcode a connection string — you break that seam, and "expand" becomes "rebuild."

So: build inside, build on the SDK, and the path to production is already laid.

Where to go next

Read Anti-patterns next — it names the exact wrong turns (building outside Karsa, reaching for Supabase or another external service) and why each one quietly costs you the cage and the expand path.