The Shell
uv run stk shellstk shell python 3.12.12db: sqlite+aiosqlite:////path/to/instance/stk.dbmodels: Activity, OAuth, RateLimitWindow, Role, Session, User, WebAuthn find(Model, **kw) list rows matching equality filters first(Model, **kw) first row matching equality filters count(Model, **kw) row count sql('select 1') run raw SQL, return rows routes('user') print routes, optionally filtered db live AsyncSession (also g.db_session)top-level await works. tab completes, F2 opens the menu, ctrl-d exits.Every model is already in scope by class name, along with app, ext, select,
func, text, delete, update, datetime, timedelta, and execute(statement).
sql() returns rows for a query and the affected row count otherwise. await works at the prompt, so code
copied out of a view runs unchanged.
Examples
Section titled “Examples”>>> await count(User)1
>>> u = await first(User, email="admin@example.com")>>> u.email, u.active('admin@example.com', True)
>>> [r.name for r in await find(Role)]['admin']
>>> await sql("select count(*) from user_sessions where is_active = 1")[(2,)]
>>> routes("wan-register") # which passkey routes exist, and are they guarded?GET,POST /wan-register auth security.wan_registerPOST /wan-register-response auth security.wan_register_responseWriting works too, through the same session your views use:
>>> u.name = "Renamed">>> await db.commit()A failed write cannot wedge the session. When a helper (find, first, count,
sql, execute) hits a session left in a failed state, it rolls back and retries once,
so the next query works instead of raising PendingRollbackError forever. A helper
query that itself fails is rolled back and the error is raised.
One-shot mode
Section titled “One-shot mode”Skip the prompt entirely. The last expression is printed unless it is None, which
makes it useful in scripts and for agents:
uv run stk shell -c "await count(User)"uv run stk shell -c "[u.email for u in await find(User, active=True)]"- With the dev extra installed you get syntax highlighting, fuzzy completion, and fish-style suggestions from history via ptpython. Without it, or when stdin is not a terminal, it falls back to the stdlib console and everything above still works.
- History is kept in
instance/.stk_shell_history. It records what you type, so avoid pasting production secrets into the prompt. - The shell points at whatever
SQLALCHEMY_DATABASE_URIis configured. The banner prints it with the password masked, so you always know what you are about to edit.