description: A Django + React framework that stays a versioned dependency: declare models and access, and the API, admin, permissions, tests, seed data and React screens follow.¶
Karni¶
Karni is a framework, not boilerplate: it stays a versioned dependency you upgrade, and it is built so an AI coding agent extends it instead of reinventing it. You declare models and access; the API, admin, permissions, tests, seed data and the React screens follow from those declarations.
class Event(BaseModel):
title = models.CharField(max_length=200)
starts_at = models.DateTimeField()
organizer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class EventViewSet(BaseViewSet):
model = Event
access = Access(read=Public(), write=Owned("organizer"))
That is a complete, documented REST resource with filtering, search,
pagination, ?expand=, an N+1-free query plan, an admin page, a generated
form and table in the frontend, and a test that proves the whole surface in
one line (assert_crud). The reference application,
EventHub, is an event ticketing platform with payments, a
Celery email and four roles in 593 lines of project code, measured.
Where to go¶
| You want to | Read |
|---|---|
| See it run in ten minutes | Quickstart |
| Build a real app step by step | Tutorial — EventHub |
| Drive Karni from Claude Code, Cursor or another agent | Building with an AI agent, Karni for AI agents |
| Build by hand, command by command | Building without one |
| Look something up | the Reference section: Models, API, the karni command, Error codes, … |
| Understand a design decision | the Concepts section, starting with why serializers are generated |
| Upgrade | Stability promise, then karni upgrade |
The shape of a Karni project¶
myproject/
config/settings.py karni_settings(globals()) — one call, env-driven
events/models.py BaseModel subclasses
events/viewsets.py BaseViewSet + access — the whole permission system
events/listeners.py @on_created / @on_updated — events, queued or inline
events/seeds.py demo data for `karni seed`
events/tests/ assert_crud, assert_isolated
frontend/src/pages/ ResourceTable / ResourceForm / ResourceDetail compositions
Everything generic lives in the karni package, @karni/ui and the
karni command. If something would be written in more than one project, it
belongs there — and when it is missing, Karni's own reference app records it
in FRICTION.md
and the next release fixes it.