Cloud launching May 2026. The library is MIT and shipping today.
kavachOS

Remix quickstart

Remix. Loaders. Actions.

Works with the web standards Remix already uses. Loaders get sessions, actions mint tokens, nothing leaks into components that do not need it.

RemixNode · Vercel · Cloudflareships today

Install

Install the core library and the Remix adapter in one step.

terminalbash
pnpm add kavachos @kavachos/remix

Configure the auth module

Remix runs on any fetch-capable runtime, so the Remix adapter is a thin wrapper over the core.

app/auth.server.tsts
import { createAuth } from "kavachos";
import { remixAdapter } from "@kavachos/remix";
import { postgresAdapter } from "kavachos/adapters/postgres";
import { db } from "./db.server";

export const auth = remixAdapter(
  createAuth({
    secret: process.env.KAVACHOS_SECRET!,
    baseUrl: process.env.APP_URL!,
    database: postgresAdapter(db),
    providers: [
      { id: "github", clientId: process.env.GITHUB_ID!, clientSecret: process.env.GITHUB_SECRET! },
    ],
  })
);

Mount the auth route

A single splat route handles every callback, sign-in, and sign-out URL.

app/routes/auth.$action.tsts
import { auth } from "~/auth.server";
import type { LoaderFunctionArgs, ActionFunctionArgs } from "@remix-run/node";

export async function loader({ request, params }: LoaderFunctionArgs) {
  return auth.handle(request, params.action!);
}

export async function action({ request, params }: ActionFunctionArgs) {
  return auth.handle(request, params.action!);
}

Guard a loader

Call auth.require() from any loader to redirect anonymous visitors and type the session.

app/routes/dashboard.tsxtsx
import { auth } from "~/auth.server";
import type { LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export async function loader({ request }: LoaderFunctionArgs) {
  const session = await auth.require(request);
  return { name: session.user.name };
}

export default function Dashboard() {
  const { name } = useLoaderData<typeof loader>();
  return <h1>Hello, {name}</h1>;
}

Mint an agent token

In a Remix action, take the current session and create a scoped agent delegation.

app/routes/agents.new.tsxts
import { auth } from "~/auth.server";
import type { ActionFunctionArgs } from "@remix-run/node";

export async function action({ request }: ActionFunctionArgs) {
  const session = await auth.require(request);
  const agent = await auth.agents.create({
    parent: session.subject.id,
    name: "research.assistant",
    scopes: ["tools:call:search"],
    ttl: "15m",
  });
  const token = await auth.agents.issueToken(agent.id, {
    audience: "https://your.mcp.server",
  });
  return Response.json({ token });
}

What is next

You have a working flow. Now pick the next layer based on what you are building: agent identity, MCP OAuth, SCIM, or enterprise SSO.

Ship the rest of the stack.

Library is open source. Cloud is in early access. Wire the next layer when you need it.