Deployment
Self-hosting
“It holds a condensed copy of our systems of record” ends the conversation at a lot of companies unless it runs on their own hardware. So it does, with no plan limits.
Run it
git clone https://github.com/maxbeech/contextely cd contextely export LLM11_API_KEY=... export CONTEXTELY_SELF_HOSTED=1 export CONTEXTELY_ENCRYPTION_KEY=$(openssl rand -base64 32) docker compose up --build # http://localhost:3000
Compose brings up Postgres 17 alongside the app. Apply the schema once with npm run db:push.
Point the tools at it
Nothing in the client surface is pinned to our deployment. An MCP client takes the URL in its config, and the CLI is told once and stays told.
# Your deployment serves its own copy of the CLI. curl -fsSL https://contextely.internal/cli.mjs -o contextely && chmod +x contextely ./contextely config set-url https://contextely.internal ./contextely config set-key ctx_sk_... ./contextely search "acme renewal" # or per call, or from the environment CONTEXTELY_URL=https://contextely.internal ./contextely usage
What you must supply
DATABASE_URL
Any Postgres 14+. Compose provides one. Server-side only, so there is no browser-reachable database.
LLM11_API_KEY
The one genuine LLM dependency, and it has no fallback: without a key, ingest and refresh fail loudly rather than writing a summary some heuristic invented. LLM11_MODEL picks a routing pack or a pinned model; LLM11_BASE_URL points at your own router.
CONTEXTELY_SELF_HOSTED
Set it to 1 to remove the plan limits. Read explicitly rather than inferred from absent Stripe keys: without it, every workspace resolves to the Free plan.
One number stays finite on purpose. 50,000 memory objects bounds what a retrieval scans, and an unbounded value would read your whole store into memory on every query.
CONTEXTELY_ENCRYPTION_KEY
A source credential is replayed on every refresh, so it is encrypted rather than hashed, and this is the key. Generate one with openssl rand -base64 32.
Keep it away from your database backups: storing both together is the same as storing neither. Rotate through CONTEXTELY_ENCRYPTION_KEY_PREVIOUS and scripts/encrypt-existing-secrets.mjs --rewrap.
What is optional, and what you lose without it
AUTH_SECRET
The dashboard signs people in with Better Auth, running inside the app on your own Postgres. It needs a secret of 32 characters or more to sign session cookies. Left unset, it fails every session check closed, so it lets nobody in rather than everybody.
The REST API and the MCP server use API keys and are unaffected, which for an agent-facing deployment is usually all you need.
SENTRY_DSN
Unset means no error reporting leaves your network. Nothing else changes.
STRIPE_*
Irrelevant when self-hosting. Billing is disabled and there are no plan limits.
What leaves your network
Exactly one thing: the content of a record being condensed, sent to whichever model you route LLM11_MODEL at. Retrieval, scoring, entitlement and freshness are all local.
No telemetry, no licence check, no phone-home. With no internet access beyond your model endpoint, Contextely still works.
Your own use, and everyone else's
Free for your own company, with no limits: your staff, your agents, your internal tools, a subsidiary you own.
It stops at resale. Putting Contextely inside a product you sell, or presenting it under another name, is a partner arrangement and needs a signed agreement.
Nothing in the codebase checks; the licence is a promise rather than a lock. The agreement is how you get the provisioning API, pooled billing and somebody to call: write to [email protected].