# Concave

> Skill: concave

- Skill: `udecode/concave` (Agent Skill)
- Install (CLI): `npx skillmds@latest add udecode/concave`
- Raw SKILL.md: https://api.skillmd.com/api/skills/udecode/concave/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: udecode (https://skillmd.com/u/udecode)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/udecode/concave

---


# Concave

## Scope

Use this skill for Concave-specific behavior and Concave-vs-Convex differences in this repo.

Use `concave-parity` when the task is specifically about parity gaps, local
workarounds, or removing Concave-specific bandaids after upstream catches up.

Keep the boundary hard:

- public kitcn CLI supports `backend: "concave"` and `--backend concave`
- public kitcn CLI still defaults to Convex
- `/example` stays on Convex
- the big `convex-test` suites stay on Convex tooling
- Concave is both a real kitcn backend and the repo's preferred agent/CI runtime lane

Do not restate generic Convex docs here. The `convex` skill already owns that.

## Upstream Concave Facts That Actually Matter

These are the Concave-only facts worth keeping in your head.

### Runtime model

- Concave is Convex-compatible, self-hosted, and multi-runtime.
- Supported runtimes marked production upstream:
  - Cloudflare Workers
  - Bun
  - Node.js
- Bun is the default local runtime.
- Node.js requires 22.5+ and `--experimental-sqlite`.
- Cloudflare is the recommended production target.

### Deployment shape

- Cloudflare uses Workers + Durable Objects.
- DO SQLite is the default document store on Cloudflare.
- D1 is optional when you need different scaling characteristics.
- R2 is only needed for `ctx.storage`.
- Self-hosted Bun/Node and desktop embeddings are single-instance by default because SQLite needs exclusive file access.
- `concave build` can compile a standalone Bun-based binary; useful, but still single-instance with SQLite.

### Local dev shape

- `concave dev` auto-picks runtime; `--bun`, `--node`, and `--cf` force it.
- alpha.14 defaults local dev to `3210`.
- Bun/Node local data lives in `./.concave/local`.
- Bun dev binds `0.0.0.0` by default. That is LAN-visible. `127.0.0.1` is the safer local-only bind.
- Local dashboard lives at `/_dashboard`.
- DevTools are web-only and designed around Vite/manual client init, not React Native.

### Configuration / API differences

- `concave.config.ts` is real Concave surface area.
- `convex.json` works now. That matters here because kitcn already uses it.
- Bun/Node use `createConcave(...)`.
- Cloudflare uses explicit `defineConcaveRuntime(...)` wiring.
- Adapter choice is part of the product, not hidden infra:
  - docstore
  - blobstore
  - module loading
  - Cloudflare bindings

### Compatibility gaps

- Vector search is only basic/brute-force in built-in adapters.
- Crons are planned, not done.
- Convex Auth is not supported.
- Streaming exports are not supported.

### Testing stance upstream

- `convex-test` is still valid for isolated function/unit tests.
- Real E2E against Concave is done with `createConcave(...)` plus `ConvexHttpClient`.
- Cross-runtime E2E is a real supported testing strategy upstream.

## Current Repo Usage

We use Concave in two concrete ways.

### Public backend selector

kitcn now resolves backend in this order:

1. `--backend <convex|concave>`
2. `meta["kitcn"].backend` in `concave.json`
3. default `convex`

Public meaning:

- `convex` => drive Convex CLI
- `concave` => drive Concave CLI

Internal meaning:

- public `concave` currently maps to the Bun adapter (`concave-bun`)

Files:

- `packages/kitcn/src/cli/config.ts`
- `packages/kitcn/src/cli/core.ts`
- `packages/kitcn/src/cli/cli.ts`

Command shape:

- kitcn orchestration commands (`init`, `dev`, `codegen`, `deploy`, `migrate`, `aggregate`, `reset`) run on the selected backend
- unknown commands pass through to the selected backend CLI
- `kitcn env sync` stays a kitcn helper
- raw `kitcn env ...` passthrough is Convex-only because Concave has no matching upstream env command

### Concave smoke lane

Use:

```bash
bun run test:concave
```

Files:

- `test/concave/run-smoke.ts`
- `test/concave/fixture/**`

Runtime shape:

- `createConcave(...)`
- `SqliteDocStore(':memory:')`
- `ConvexHttpClient`

Goal:

- generated kitcn runtime contract loads
- one mutation/query roundtrip works end-to-end

Keep it small. This is a smoke lane, not a migration plan.

## Repo-Specific Concave Differences

### Template sync/check uses the public backend selector

`tooling/fixtures.ts` runs local committed starter sync with
`kitcn init -t <next|vite> --backend concave`.

That means:

- committed `fixtures/*/convex/functions/_generated/*` comes from the create
  flow running kitcn codegen against Concave-backed bootstrap
- template-mode Concave codegen intentionally uses `concave codegen --static`
- `tooling/fixtures.ts` itself must not shell out to raw `kitcn codegen`

### `_generated/*` drift is expected

Concave-generated `_generated/*` output is not guaranteed to match Convex-generated output byte-for-byte.

Read the diff before calling it a bug.

### `staticDataModel` mismatch is still real

Current repo finding:

- `fixtures/next/convex.json` sets `codegen.staticDataModel: true`
- Concave-generated `fixtures/next/convex/functions/_generated/dataModel.d.ts` is still dynamic

So today, in this repo path, Concave is not honoring that flag.

### `api.d.ts` override is gone

Current repo truth:

- alpha.14 emits the same `api.d.ts` shape our old source-backed override used
  to force
- kitcn no longer post-writes `_generated/api.d.ts`

Meaning:

- if `api.d.ts` drifts again, treat it as a fresh upstream regression
- do not quietly resurrect the old overwrite helper

### Use plain `bun`, not `bun test`, for the smoke lane

Root `bun test` preloads Happy DOM here.
That poisoned `ConvexHttpClient` behavior for the Concave smoke lane.

Keep the smoke entry as:

```bash
bun ./test/concave/run-smoke.ts
```

### Keep the adapter tiny

Do not invent a second fake runtime layer on top of `backend`.

The right model is:

- one public selector: `backend`
- one internal mapping: `concave` -> current Bun adapter
- native backend flags stay native

## Read Before Editing

Start with repo wiring:

- `packages/kitcn/src/cli/backend-core.ts`
- `packages/kitcn/src/cli/commands/init.ts`
- `packages/kitcn/src/cli/commands/init.test.ts`
- `tooling/fixtures.ts`
- `tooling/fixtures.test.ts`
- `tooling/scenarios.ts`
- `tooling/scenarios.test.ts`
- `test/concave/run-smoke.ts`
- `test/concave/fixture/**`
- `.github/workflows/ci.yml`

Then read Concave docs starting from:

- `https://docs.concave.dev/llms.txt`

## Do Not

- do not add a second selector like `--runtime concave`
- do not switch `/example` to Concave
- do not migrate the big `convex-test` suites just because Concave exists
- do not document generic Convex APIs here
- do not assume Concave codegen output equals Convex codegen output

## Verification

When touching Concave repo-runtime wiring, run:

```bash
bun test packages/kitcn/src/cli/commands/init.test.ts ./tooling/fixtures.test.ts ./tooling/scenarios.test.ts
bun test packages/kitcn/src/cli/cli.test.ts
bun run test:concave
bun run fixtures:check
bun run scenario:check
```

If package code changed too, also run:

```bash
bun --cwd packages/kitcn build
bun lint:fix
bun typecheck
```

## Skill Sync

When Concave docs or repo usage changes, update this skill with this exact loop.

### 1. Re-read current repo wiring

```bash
rg -n "backend|concave-bun|test:concave|createConcave|@concavejs|Concave|--backend" \
  package.json \
  packages/kitcn/src/cli/backend-core.ts \
  packages/kitcn/src/cli/config.ts \
  packages/kitcn/src/cli/cli.ts \
  packages/kitcn/src/cli/commands/init.ts \
  packages/kitcn/src/cli/commands/init.test.ts \
  tooling/fixtures.ts \
  tooling/fixtures.test.ts \
  tooling/scenarios.ts \
  tooling/scenarios.test.ts \
  test/concave \
  .github/workflows/ci.yml \
  -g '!**/_generated/**'
```

### 2. Re-fetch the upstream Concave doc index

```bash
mkdir -p /tmp/concave-docs-fetch
curl -fsSL -A 'Mozilla/5.0' https://docs.concave.dev/llms.txt \
  | tee /tmp/concave-docs-fetch/llms.txt
```

### 3. Re-fetch every linked page from `llms.txt`

```bash
awk '
  match($0, /(https:\\/\\/docs\\.concave\\.dev[^) ]+)/, m) { print m[1] }
' /tmp/concave-docs-fetch/llms.txt \
  | nl -ba \
  | while read -r n url; do
      curl -fsSL -A 'Mozilla/5.0' "$url" >"/tmp/concave-docs-fetch/${n}.md"
    done
```

### 4. Rewrite this file with Concave-only facts

Rules:

- keep only Concave-specific behavior or Concave-vs-Convex differences
- keep repo-specific usage and mismatches
- do not restate generic Convex docs

### 5. Regenerate agent docs

```bash
bunx skiller@latest apply
```

### 6. Validate the skill wiring

```bash
bun run intent:validate
bun run intent:stale
```

If `.claude/AGENTS.md` changes, that is expected. It is generated from `.claude/**`.

