# plain.dev **A single command that runs everything you need for local development.** ![Plain dev command example](https://github.com/dropseed/plain/assets/649496/3643bb64-a99b-4a8e-adab-8c6b81791ea9) - [Overview](https://plainframework.com/docs/plain-dev/plain/dev/?llm#overview) - [Commands](https://plainframework.com/docs/plain-dev/plain/dev/?llm#commands) - [`plain dev`](https://plainframework.com/docs/plain-dev/plain/dev/?llm#plain-dev) - [Services](https://plainframework.com/docs/plain-dev/plain/dev/?llm#services) - [Custom processes](https://plainframework.com/docs/plain-dev/plain/dev/?llm#custom-processes) - [`plain dev services`](https://plainframework.com/docs/plain-dev/plain/dev/?llm#plain-dev-services) - [`plain dev logs`](https://plainframework.com/docs/plain-dev/plain/dev/?llm#plain-dev-logs) - [`plain pre-commit`](https://plainframework.com/docs/plain-dev/plain/dev/?llm#plain-pre-commit) - [VS Code debugging](https://plainframework.com/docs/plain-dev/plain/dev/?llm#vs-code-debugging) - [FAQs](https://plainframework.com/docs/plain-dev/plain/dev/?llm#faqs) - [Installation](https://plainframework.com/docs/plain-dev/plain/dev/?llm#installation) ## Overview The `plain dev` command starts everything you need for local development with a single command: ```bash plain dev ``` This will: - Run preflight checks - Execute pending migrations - Start your development server with auto-reload - Build and watch CSS with Tailwind (if installed) - Start required services (like databases) - Run any custom processes you've defined ## Commands ### `plain dev` The [`plain dev`](https://plainframework.com/docs/plain-dev/plain/dev/cli.py?llm#cli) command does several things: - Sets `PLAIN_CSRF_TRUSTED_ORIGINS` to localhost by default - Runs `plain preflight` to check for any issues - Executes any pending model migrations - Starts `gunicorn` with `--reload` - Serves HTTPS on port 8443 by default (uses the next free port if 8443 is taken and no port is specified) - Runs `plain tailwind build --watch`, if [`plain.tailwind`](https://plainframework.com/docs/plain-dev/plain-tailwind/plain/tailwind/README.md?llm) is installed - Any custom process defined in `pyproject.toml` at `tool.plain.dev.run` - Necessary services (ex. Postgres) defined in `pyproject.toml` at `tool.plain.dev.services` #### Services Use services to define databases or other processes that your app _needs_ to be functional. The services will be started automatically in `plain dev`, but also in `plain pre-commit` (so preflight and tests have a database). Ultimately, how you run your development database is up to you. But a recommended starting point is to use Docker: ```toml # pyproject.toml [tool.plain.dev.services] postgres = {cmd = "docker run --name app-postgres --rm -p 54321:5432 -v $(pwd)/.plain/dev/pgdata:/var/lib/postgresql/data -e POSTGRES_PASSWORD=postgres postgres:15 postgres"} ``` #### Custom processes Unlike [services](https://plainframework.com/docs/plain-dev/plain/dev/?llm#services), custom processes are _only_ run during `plain dev`. This is a good place to run something like [ngrok](https://ngrok.com/) or a [Plain job worker](https://plainframework.com/docs/plain-dev/plain-jobs/plain/jobs/README.md?llm), which you might need to use your local site, but don't need running for executing tests, for example. ```toml # pyproject.toml [tool.plain.dev.run] ngrok = {command = "ngrok http $PORT"} ``` ### `plain dev services` Starts your [services](https://plainframework.com/docs/plain-dev/plain/dev/?llm#services) by themselves. Logs are stored in `.plain/dev/logs/services/`. ### `plain dev logs` Show output from recent `plain dev` runs. Logs are stored in `.plain/dev/logs/run/`. ```bash plain dev logs # print last log plain dev logs -f # follow the latest log plain dev logs --pid 1234 plain dev logs --path ``` ### `plain pre-commit` A built-in pre-commit hook that you can install with `plain pre-commit --install`. Runs: - Custom commands defined in `pyproject.toml` at `tool.plain.pre-commit.run` - `plain code check`, if [`plain.code`](https://plainframework.com/docs/plain-dev/plain-code/plain/code/README.md?llm) is installed - `uv lock --locked`, if using uv - `plain preflight` - `plain migrate --check` - `plain makemigrations --dry-run --check` - `plain build` - `plain test` ## VS Code debugging ![Debug Plain with VS Code](https://github.com/dropseed/plain-public/assets/649496/250138b6-7702-4ab6-bf38-e0c8e3c56d06) Since `plain dev` runs multiple processes at once, the regular [pdb](https://docs.python.org/3/library/pdb.html) debuggers don't quite work. Instead, the package provides a remote debugger based on [`DevPdb`](https://plainframework.com/docs/plain-dev/plain/dev/pdb.py?llm#DevPdb) that opens a telnet session for debugging. To use it, add a `breakpoint()` call in your code: ```python class HomeView(TemplateView): template_name = "home.html" def get_template_context(self): context = super().get_template_context() # Add a breakpoint breakpoint() return context ``` When you load the page, a new terminal window will open automatically (on macOS) with a pdb session. You can then step through your code as usual. Alternatively, you can manually connect to the debugger using `plain dev debug` or by running `nc -C localhost 4444` in a terminal. ## FAQs #### How do I stop the development server? You can stop the development server by pressing `Ctrl+C` in the terminal, or by running `plain dev --stop` if it was started in the background. #### Can I run the server on a different port? Yes, use the `--port` or `-p` option: `plain dev --port 8000`. If you don't specify a port, it will use 8443 or the next available port. #### How do I run the server in the background? Use `plain dev --start` to run the server in the background. You can then use `plain dev --stop` to stop it. #### What's the difference between services and custom processes? Services are processes that your app needs to function (like a database). They run during `plain dev` and also during `plain pre-commit`. Custom processes only run during `plain dev` and are typically for development conveniences like ngrok or a job worker. ## Installation Install the `plain.dev` package from [PyPI](https://pypi.org/project/plain.dev/): ```bash uv add plain.dev --dev ``` Note: The `plain.dev` package does not need to be added to `INSTALLED_PACKAGES`.