Plain is headed towards 1.0! Subscribe for development updates →

The full-stack Python framework designed for humans and agents.

A fork of Django that has gone way, way too far.

$ mkdir my-app && cd my-app && \
  claude "$(curl -sSf https://plainframework.com/start.md)"

Why Plain?

Explicit, typed, and predictable. What's good for humans is good for AI.

app/users/models.py
from plain import models
from plain.models import types
from plain.passwords.models import PasswordField

@models.register_model
class User(models.Model):
    email: str = types.EmailField()
    password: str = PasswordField()
    display_name: str = types.CharField(max_length=100)
    is_admin: bool = types.BooleanField(default=False)
    created_at: datetime = types.DateTimeField(auto_now_add=True)
app/users/urls.py
from plain.urls import Router, path
from . import views

class UsersRouter(Router):
    namespace = "users"
    urls = [
        path(
            "<int:pk>/",
            views.UserDetail,
        ),
    ]
app/users/views.py
from plain.views import DetailView
from .models import User

class UserDetail(DetailView):
    template_name = "users/detail.html"

    def get_object(self):
        return User.query.get(
            pk=self.url_kwargs["pk"],
        )

Agent tooling

Rules, docs, skills, and CLI — four layers your agent uses to write correct code.

claude "Add email login to the users app"
Rules auto-loaded
Reading .claude/rules/plain-models.md
- Model.query not Model.objects
- UniqueConstraint not unique=True
- atomic() for multi-step writes
... 3 more rules
Docs on-demand
$ plain docs passwords --section setup
## Setup
Add PasswordField to your user model.
Import from plain.passwords.models...
$ plain docs models --api QuerySet
QuerySet.filter(**kwargs) -> QuerySet
QuerySet.get(**kwargs) -> Model
QuerySet.exists() -> bool
Skills slash commands
$ /plain-install plain-passwords
Added plain-passwords to pyproject.toml
Added PasswordLoginViewRouter to urls.py
Added PasswordField to User model
Done. Run migrations to apply changes.
CLI verify & fix
$ plain check
Preflight checks passed
Migration checks passed
1 test failing: test_user_login
$ plain fix
Running ruff format...
Running ruff check --fix...
All checks passed.

20 years of Django
with a fresh take on what's next

Plain is a fork of Django, driven by ongoing development at PullApprove. No backwards compatibility to maintain means we can break things, iterate fast, and build for the agentic era without compromise.