management

New in 2.4.0!

Spiderweb ships with a built-in management CLI — a single command you can use to start the dev server, explore your routes, open an interactive shell, and run startup checks. If you've ever used Django's manage.py, this will feel familiar.

After installing the package, the web command is available in your environment:

web --help

pointing the CLI at your app

All commands (except version) need to know which SpiderwebRouter instance to work with. There are three ways to tell them, in order of priority:

1. The --app flag

Pass the app location directly on the command line as module:attribute:

web --app myapp:app serve

2. The SPIDERWEB_APP environment variable

This is helpful for CI pipelines of for folks who like to have everything set in the shell.

export SPIDERWEB_APP=myapp:app
web serve

3. pyproject.toml

Add a [tool.spiderweb] section to your project's pyproject.toml. The CLI walks up from your current directory until it finds one:

[tool.spiderweb]
app = "myapp:app"

With that in place you can use any command bare, with no flags at all:

web serve

commands

version

Prints the installed version of spiderweb.

$ web version
spiderweb-framework 2.4.0

new

Scaffolds a new Spiderweb project. It creates a new directory containing a minimal app.py and a pyproject.toml configured for your app. Like version, this command doesn't need an app to run.

$ web new my_project

You can also scaffold into the current directory by passing .:

$ web new .

If the target directory already has a pyproject.toml, it will append the [tool.spiderweb] section without overwriting your existing config.

serve

Starts the development server. By default it runs in WSGI mode on whatever address and port your app was configured with (localhost:8000 unless you changed them).

web serve

Switch to ASGI mode with --asgi:

web serve --asgi

Override the bind address or port without touching your source code:

web serve --addr 0.0.0.0 --port 9000

If your project always runs in ASGI mode, set asgi = true in [tool.spiderweb]:

[tool.spiderweb]
app = "myapp:app"
asgi = true

You can still override it on the command line in either direction — --asgi forces ASGI, --wsgi forces WSGI regardless of what pyproject.toml says.

shell

Opens an interactive Python interpreter with your app already loaded as app. Great for poking around at runtime state, testing a database query, or trying out a piece of logic before committing it.

$ web shell
Spiderweb 2.4.0 shell
Available names: app
Type "exit()" or Ctrl-D to quit.

>>> app.addr
'localhost'
>>> with app.get_db_session() as session:
...     # query away
...     pass

If IPython is installed in your environment, the shell will use it automatically. Otherwise, it falls back to the standard library code.interact.

routes

Prints a table of every URL route your app has registered — path, allowed methods, optional name, and the view function.

$ web routes
path            methods                              name   view
-----------------------------------------------------------------------
/               POST, GET, PUT, PATCH, DELETE               index
/about          POST, GET, PUT, PATCH, DELETE               about
/posts/{slug}   POST, GET, PUT, PATCH, DELETE        posts  get_post

Routes that haven't restricted their methods show the full default set. If you pass allowed_methods=["GET"] to @app.route(), only that method appears in the table. Handy for double-checking that a new route was picked up correctly, or for tracking down a duplicate.

check

Re-runs all middleware startup checks and tells you whether everything looks healthy.

$ web check
System check passed.

If any check fails, a StartupErrors exception group is raised — you'll see a one-frame traceback listing every failing check. Useful in CI or as a quick sanity check after a config change.

makemigrations

Generates a new Alembic migration by comparing your current models against the database schema.

web makemigrations
web makemigrations -m "add users table"

The first time you run this command the CLI scaffolds a migrations/ directory next to your pyproject.toml (or in the current directory if no pyproject.toml is found):

migrations/
    env.py           ← configure your model metadata here
    script.py.mako   ← template for generated migration files
    versions/        ← individual migration scripts live here

By default, Alembic compares spiderweb's own internal tables against the live database. To include your own models, open migrations/env.py and add your Base to target_metadata:

from myapp.models import Base as _AppBase

target_metadata = [_SpiderwebBase.metadata, _AppBase.metadata]

Options

Flag Description
-m MESSAGE / --message MESSAGE Short description embedded in the migration filename.
--empty Create a blank migration without running autogenerate. Useful for hand-written data migrations.

migrate

Applies pending migrations to the database. Without arguments it upgrades to the latest revision (head).

web migrate

Pass a specific revision ID, a relative step, or the special value zero to target a particular point in the migration history:

web migrate abc123de          # upgrade (or already at this rev: no-op)
web migrate +1                # apply the next pending migration
web migrate -1                # roll back the most recent migration
web migrate zero              # roll back every migration (equivalent to `base`)

Options

Flag Description
REVISION Target revision (default: head).
--fake Stamp the database at the target revision without executing any SQL — useful for marking existing schemas as migrated.

custom commands

You can register your own management commands on the router using the @app.command() decorator. Every custom command receives three arguments:

  • app — the SpiderwebRouter instance, so you can access the database, routes, config, etc.
  • args — an argparse.Namespace containing only .app and .command (the values the CLI's own pre-parser resolved). It does not contain any flags you pass after the command name.
  • extra — a plain list[str] of every token that appeared after the command name on the command line. Parse this yourself if your command accepts flags.

A command with no extra flags:

from spiderweb import SpiderwebRouter
from spiderweb.response import HttpResponse

app = SpiderwebRouter()

@app.route("/")
def index(request):
    return HttpResponse("hello!")

@app.command("seed")
def seed_database(app, args, extra):
    """Populate the database with initial data."""
    with app.get_db_session() as session:
        # ... insert seed records ...
        session.commit()
    print("Database seeded.")

if __name__ == "__main__":
    app.start()

A command that accepts its own flags — parse extra with argparse:

import argparse

@app.command("seed")
def seed_database(app, args, extra):
    p = argparse.ArgumentParser(prog="spiderweb seed")
    p.add_argument("--dry-run", action="store_true")
    opts = p.parse_args(extra)

    if opts.dry_run:
        print("Dry run — no changes written.")
        return

    with app.get_db_session() as session:
        session.commit()
    print("Database seeded.")
web seed --dry-run

Run any custom command the same way as a built-in:

web --app myapp:app seed

Or, with pyproject.toml configured, just:

web seed

You can register as many custom commands as you like. Pick meaningful names; they'll show up in the error message if someone types an unrecognised command, so short and descriptive is best.

configuration reference

Option Description
--app MODULE:ATTR The app to use, in module:attribute form. Overrides SPIDERWEB_APP and pyproject.toml.
SPIDERWEB_APP Environment variable. Overrides pyproject.toml, overridden by --app.
[tool.spiderweb] app pyproject.toml key. Lowest priority; used when neither of the above is set.
[tool.spiderweb] asgi pyproject.toml boolean. When true, serve defaults to ASGI mode. Overridden by --asgi / --wsgi.
[tool.spiderweb] migrations_dir Path to the Alembic migrations directory, relative to pyproject.toml. Defaults to migrations.

serve options

Flag Description
--asgi Start in ASGI mode via uvicorn instead of WSGI.
--wsgi Force WSGI mode even when asgi = true is set in pyproject.toml.
--addr ADDR Bind address. Overrides the value stored in the app.
--port PORT Port number. Overrides the value stored in the app.

makemigrations options

Flag Description
-m MESSAGE / --message MESSAGE Short description for the migration.
--empty Create a blank migration without autogenerate.

migrate options

Flag Description
REVISION Target revision (default: head). Accepts revision IDs, +N/-N relative specs, zero, or base.
--fake Stamp the database at the target revision without running SQL.