v0.3.2 is a UX-focused release. No new features, no breaking changes — just the kind of polish that makes a tool feel like it was built for people. Three areas got attention: the first-run setup flow, the terminal output, and the import path handling.
The setup flow: from text input to arrow keys
The old framework prompt used rich.prompt.Prompt.ask(), which showed the choices but required you to type the name. A small friction, but friction at the very first impression sets the tone.
Before:
Which web framework are you using? (fastapi/flask/asgi): _
After:
? Which web framework are you using?
> fastapi
flask
asgiNow powered by questionary, the framework picker is an arrow-key select menu — the same pattern you see in Better Auth, Prisma, and every modern CLI. One keypress instead of typing.
Entry point: what does :app even mean?
The old prompt read Entry point (e.g. app.main:app) with a default of app.main:app. This looks like Uvicorn’smodule:variable convention — but pyrpc’sdev command never used the :app part. It just imports the module to trigger @rpc decorator registration. The app variable is created internally.
The prompt now says Python module to scan for @rpc procedures (e.g. main, app.main)with a default of main. No more colon syntax. No more confusion about what variable name to use. Just the module path.
Why main gave “No module named ‘main’”
This was the bug that triggered the whole release. A user ran pyrpc dev, entered main at the prompt, and got:
Error regenerating types: No module named 'main'
The problem: reload_module() calls importlib.import_module("main")but never ensured the current working directory was on sys.path. The serve command’s _import_module() helperdid add it (sys.path.append(os.getcwd())), but the dev command’s regenerate() went straight toreload_module() without it.
The fix follows Uvicorn’s standard: sys.path.insert(0, os.getcwd())before any user module import. We also changed _import_module()from append to insert(0, ...) for consistency. Now main finds main.py in the current directory, just like uvicorn main:app does.
Terminal output: less noise, more signal
The old pyrpc dev terminal was loud:
Generating initial TypeScript types... (big Panel box) Watching 1 directories for Python changes... pyrpc> type help for commands INFO: Will watch for changes in these directories: [...] INFO: Started reloader process [21332] using WatchFiles INFO: Started server process [14932] INFO: Waiting for application startup. INFO: Application startup complete.
The new output:
✓ Types regenerated (3 procs) pyRPC dev server http://127.0.0.1:8000/rpc Types: node_modules/@pyrpc/types/src/index.ts type help for commands pyrpc>
Specific changes:
- Uvicorn logs suppressed —
--log-level erroron the subprocess kills 6 lines of reloader/server spam. - Panel box gone — replaced with a clean 2-line status block. No borders, no padding, just what you need.
pyrpc>prompt actually renders — was using rawinput()which showed[cyan]pyrpc>[/cyan]as literal text. Now usesconsole.input().- No “Generating initial types” — types generate silently on startup.
- No “Watching X directories” — the user doesn’t need to know.
- Consistent symbol prefixes —
✓for success,âœ-for error,âšfor warning,â-‹for in-progress. Borrowed from the pattern Next.js, tRPC, and Better Auth use — scannable at a glance.
Help text updated everywhere
Every command argument that referenced the old app.main convention was updated to match the new wording: Python module to scan for @rpc procedures (e.g. main, app.main). Consistent across dev, serve, and pull.
Full changelog
- Dependencies: Added
questionary>=2.0.0for interactive CLI prompts. - Setup flow: Framework picker changed from
rich.prompt.Prompt.ask(text input) toquestionary.select(arrow-key menu). Entry point prompt simplified toPython module to scan for @rpc procedures (e.g. main, app.main)with defaultmain. - Import path:
sys.path.insert(0, os.getcwd())added indev()before module import._import_module()changed fromsys.path.appendtosys.path.insert(0, ...). Now matches Uvicorn’s standard--app-dirbehavior. - Terminal DX: Uvicorn subprocess uses
--log-level error. Panel box replaced with minimal status lines.input()replaced withconsole.input()so Rich markup renders. Removed “Generating initial types”, “Watching X directories”, and “Types regenerated” verbose lines. Error/success messages use consistent✓,âœ-,âš,â-‹symbol prefixes. - Help text: Updated
dev,serve, andpullargument descriptions to match new wording.
See the full changelog for details.

pyRPC