Imported from cinatra-ai/cinatra (
AGENTS.md). Install upstream withnpx skills add cinatra-ai/cinatra. Copyright stays with the author.
AGENTS.md
A map of this repository for contributors and coding agents. For product concepts, guides, and reference material, see docs.cinatra.ai.
What Cinatra is
Cinatra is an open source AI workspace for teams — a shared, persistent, browser-based environment where people, AI assistants, and autonomous agents work together. It turns isolated prompts into durable workflows with state, tooling, handoffs, approvals, and real operational outputs. Agents, connectors, skills, objects, and dashboards live in one capability fabric, exposed through a Model Context Protocol (MCP) server and composed into long-running, background workflows.
Cinatra is under active development and is not production ready. Run it for evaluation, local development, and self-hosted experimentation. APIs, schemas, and the extension contract may change without notice.
Repository layout
| Path | What lives here |
|---|---|
src/ |
The Next.js application (App Router): pages, server components, API routes, and host wiring (src/lib/). |
packages/ |
The workspace packages — the platform's building blocks (see below). Each is a @cinatra-ai/* package with its own README.md. |
scripts/ |
Setup, dev-server, validation, and audit tooling (setup.sh, dev-server.mjs). |
contracts/ |
Cross-surface contract fixtures used by end-to-end tests. |
migrations/ |
Versioned migrations for the core store schema: node-pg-migrate code modules under migrations/core/ (core__NNNN_description.mjs + manifest entry, pgmigrations ledger); the legacy one-shot NNNN_description.sql artifacts are retained append-only. Convention in migrations/README.md. |
docs/ |
README.md points to the documentation site (source: cinatra-ai/docs); docs/internals/ holds the in-repo engineering/agent documentation — architecture, contracts, decisions, governance, records (index). |
config/ |
Machine-consumed config/data (build-config manifest, sync/read inventories) — not documentation. |
docker-compose.yml, Makefile |
The local development stack (PostgreSQL, Redis, and optional supporting services) and the dev-loop entry points. |
tests/ (Playwright configs under tests/e2e/config/) |
End-to-end test suites. Unit tests are package-local. |
Root config of note: package.json (workspace + scripts), pnpm-workspace.yaml,
tsconfig.json (path aliases), next.config.ts, eslint.config.mjs,
vitest.config.ts.
Where files go
- Product documentation (user/admin/hosting/developer guides) → the
cinatra-ai/docsrepository, published at docs.cinatra.ai — never this repo. - In-repo engineering/agent documentation (architecture, contracts the code
enforces, decision/governance records) →
docs/internals/(index). - Machine-consumed config/data (inventories, manifests, matrices) →
config/— notdocs/. - PR render/screenshot evidence → an evidence branch, linked by commit-SHA permalink from the PR — NEVER the product tree.
Packages
The platform is split into ~35 workspace packages under packages/*. Each has a
README.md and a package.json description — read those for the authoritative
surface. Grouped overview:
- Agent core —
agents(template/version/run lifecycle, workflow compilation, triggers, orchestration),workflows(a versioned, scheduled DAG engine over Postgres),triggerandtrigger-email-send(run triggers),a2aandagent-ui-protocol(Agent-to-Agent calling and UI event streaming). - LLM —
llm(the unified orchestration layer: provider adapters, MCP tool injection, skill delivery, usage telemetry). - MCP —
mcp-server(the mountable MCP server: Streamable HTTP transport, OAuth 2.0, admin UI) andmcp-client(server-only client + in-process transport for invoking primitives). - Connectors —
connectors(the installed-connector index grid),connectors-catalog(dependency-free built-in connector descriptors),google-oauth-connection(Google OAuth runtime facade). - Marketplace & registries —
registries(registry client + dependency resolution with lockfiles and integrity checks),marketplace-sync,marketplace-mcp-client,marketplace-application-reconcile. - Extensions —
extensions(host-side lifecycle dispatcher, installed manifest, runtime capability discovery, safety gates),extension-types,sdk-extensions(the author-facing extension ABI). - Objects, projects, permissions —
objects(typed-object substrate with taxonomy, classification, andobjects_*primitives),projects(four-tier ownership + N:M project access),permissions(members, roles, grants). - Dashboards, notifications, chat —
dashboardsandsdk-dashboard(dashboards glue + extraction-ready SDK over drizzle-cube),notifications(Postgres-backed, SSE-streamed),chat(the conversational assistant UI). - Skills & metrics —
skills(the catalog for agentSKILL.mdfiles),metric-usage-api(captures token/usage events),metric-cost-api(prices events, persists to Postgres, serves the cost dashboard). - SDKs, design, CLI, infra —
sdk-ui(design-strict React primitives),design(tokens, fonts, brand assets),artifacts(binary artifact storage contracts),errors(Sentry helpers), andcli(thecinatracommand-line tool for setup and operations). - Memory —
memory(the filesystem side of agent-authored memory: an OKF 0.1 bundle library and the localmemoryCLI, pure and offline).
Architecture at a glance
- Next.js app (
src/). App Router with server components and server actions. Route files delegate to per-package screens viasrc/app/plugins-registry.tsx/plugins-routes.tsx. API routes live undersrc/app/api/(auth, agents, chat, dashboards, extensions, webhooks, and more). - MCP server. Every agent and platform capability is exposed as an MCP
primitive. The server mounts at
src/app/api/mcp/route.ts(from@cinatra-ai/mcp-server); the same primitives are called internally in-process through@cinatra-ai/mcp-client. Primitives use underscore-separated names (e.g.objects_list). - LLM orchestration. Provider access is centralized in
@cinatra-ai/llm— callers never reach provider SDKs directly. The layer injects the Cinatra MCP tool, delivers skills, and records usage telemetry across OpenAI, Anthropic, and Gemini adapters. - Background jobs. Long-running agent and workflow executions run on BullMQ
over Redis (
src/lib/background-jobs.ts), so work survives page reloads and resumes across network drops. - Persistence. PostgreSQL via Drizzle ORM (
src/lib/drizzle-store.ts,src/lib/database.ts). Authentication is handled by Better Auth (src/lib/auth.ts); the first user to register becomes the platform admin.
Memory conventions
Everything between the markers below is generated from
docs/internals/workflows/memory-conventions.md and must not be edited here.
Regenerate it with MEMORY_SEED_WRITE=1 pnpm --filter @cinatra-ai/memory test.
When your host has given you a Memory bundle, you have persistent memory: read its
index.mdfirst, and recall from the bundle before you act. A repository bundle sits at.memory/, and--dir <bundle-dir>reaches one that lives elsewhere. Write one concept file per durable insight, and read the memory conventions before your first write. Where no bundle is present yet,memory initcreates one, and these conventions govern it from its first concept.
The conventions behind that pointer have exactly one authority. This block
carries the pointer and routes for the rest. In a Cinatra checkout, read
docs/internals/workflows/memory-conventions.md. It covers what qualifies as a
concept, one concept per insight, the frontmatter type choice, the duplicate
check against index.md, the credential prohibition, and recall before acting.
The same rules ship as concepts in the seed bundle
packages/memory/seed/conventions, so an agent with no checkout reads them
through the CLI instead: memory list --dir <seed-bundle> and
memory recall --dir <seed-bundle> <query>.
The command surface comes from the @cinatra-ai/memory workspace package. No
subcommand makes a model call. Every subcommand except sync is also local and
offline; sync is the one that talks to a Cinatra server.
| Command | Use it for |
|---|---|
memory init |
Create a bundle and its stable identity. |
memory add --type <kind> --title <t> |
Author one concept. |
memory list [--type <kind>] [--json] |
See what the bundle already holds. |
memory recall <query> [--json] |
Lexical search before you act or write. |
memory check [--json] |
Conformance diagnostics; non-zero on an error. |
memory sync [--dry-run] [--json] |
Push the bundle into shared memory. |
Every subcommand takes --dir <bundle-dir>. Omit it to use the nearest
.memory/bundle.yaml at or above the working directory.
memory sync is one-way. It writes local concepts into shared memory and never
edits a concept file or bundle.yaml, never deletes a remote row, and never
narrows one. Run memory sync --dry-run first: it prints the create / update /
skip decision for every concept and writes nothing. The endpoint comes from
--url or CINATRA_MCP_URL and must be https unless it is a loopback host;
the credential comes from CINATRA_MCP_TOKEN only, so it never reaches your
shell history. The server re-derives every rule for itself, so a concept it
refuses is refused for a reason your bundle cannot override.
A sync run that wrote something leaves one file behind: sync-ledger.json at
the bundle root. It records the object id and content digest of what the last
run pushed, which is how a later run reports a row that drifted since. Do not
commit it. It is a per-checkout cache, the object ids in it are minted per
organization by whichever server answered, and nothing reads it as authority —
the preflight decides what to write, and the ledger only reports disagreement.
memory init writes a .gitignore next to it that already excludes it; a
bundle created before that line needs the entry added by hand.
Local development
Prerequisites: Node.js 24.x, pnpm (pinned in the repo — use
corepack pnpm), and Docker with Compose for the bundled PostgreSQL and
Redis services.
git clone https://github.com/cinatra-ai/cinatra.git
cd cinatra
make setup # install deps, start supporting services, configure the app
make dev # bring up infrastructure and start the Next.js dev server
Open http://localhost:3000. Other useful make targets: make down (stop
services, keep data), make reset (soft reset of app/auth data), make logs,
and make clean (wipe Docker volumes).
Nothing to clean up after a dev session or a lane. No provider credential is
ever written to this checkout: the knowledge-graph indexer receives its key
through the environment of the docker compose command that creates it
(npm run kg:up, which make dev and npm run services end with), so
docker/graphiti/.graphiti.env is never present and no file under docker/
may contain a key-shaped value. A leftover from the old road is deleted on every
generator run and announced. See
docs/internals/contracts/no-provider-key-at-rest.md.
Validation
Run these before opening a pull request:
pnpm typecheck # fast type check (must pass cleanly)
pnpm lint # ESLint
pnpm build # Next.js production build
Unit tests are package-local — run them with pnpm --filter <package> test
where a package has them. End-to-end suites use Playwright (pnpm test:e2e:*).
How to contribute
Bug reports, agents, connectors, skills, documentation, and code are all welcome. Read CONTRIBUTING.md for the full development setup, branching, and pull-request flow. Please also review the Code of Conduct.
For security issues, do not open a public issue — follow the private disclosure path in SECURITY.md.
Docs
Everything beyond this map lives at docs.cinatra.ai: