v0.6.0 completes the distribution story with a proper client-side CLI and cleans up the packaging foundation that’s been accumulating small debts since the earliest releases. Two branches, one release — the first adds new capabilities, the second pays down technical debt.
Client-side distribution: npx pyrpc sync
The distribution model introduced in v0.5.0 defined workspace andserver modes on the server side. This release completes the picture by adding the client-side counterpart — npx pyrpc sync.
When a frontend developer installs @pyrpc/client, the postinstall script now asks one question:
> npm install @pyrpc/client? How are types distributed? workspace (default) - types in node_modules/@pyrpc/types server - types fetched via HTTP
If they choose server, the script prompts for the server URL and creates a pyrpc-client.json file in the project root:
{
"distribution": "server",
"server_url": "http://localhost:8000"
}This file is the client’s config. It’s checked into version control so every developer on the team gets the same setup.
With pyrpc-client.json in place, the developer runs:
> npx pyrpc sync Fetching schema from http://localhost:8000/rpc... Regenerating @pyrpc/types... Done.
The npx pyrpc sync command reads the config, fetchesGET /rpc from the server, and regenerates@pyrpc/types in-place. The client never needs to know about the server’s file system — it pulls types on demand.
This means the full server-mode flow is now:
- Backend:
pyrpc dev --distribution server - Frontend:
npm install @pyrpc/client(postinstall createspyrpc-client.json) - Frontend:
npx pyrpc sync(fetches types from server) - Frontend: Types are ready in
@pyrpc/types
Previously, server-mode users had to manually copy types or set up a separate CI pipeline. Now it’s a single command.
Why a postinstall prompt instead of pyrpc init?
We considered adding a npx pyrpc init command to prompt for the same information, but the postinstall approach is better:
- Zero discoverability problem. The question appears right after
npm install, when the developer is already thinking about setup. They don’t need to know a separate command exists. - Config is created atomically. Every frontend project that installs
@pyrpc/clientgets apyrpc-client.jsonfrom the start. No “forgot to run init” bugs. - Workspace mode is silent. If the developer chooses workspace, the postinstall script creates a minimal config and exits. No friction for the common case.
Package standardization
Alongside the client-side distribution work, we cleaned up several packaging issues that had been lingering across the codebase.
Tests live with their packages
The root tests/ directory has been dismantled. Each Python package now owns its tests:
Before: tests/ After: packages/pyrpc-core/tests/
tests/test_codegen.py packages/pyrpc-codegen/tests/
tests/test_fastapi.py packages/pyrpc-fastapi/tests/
tests/test_flask.py packages/pyrpc-flask/tests/Tests run via pytest from the workspace root, withpyproject.toml pointing testpaths to the package-level directories. The change is invisible to CI but makes the relationship between test and package explicit — especially useful when working on a single package in isolation.
We also renamed test_client.py totest_python_client.py in pyrpc-core to avoid ambiguity with the TypeScript @pyrpc/client test terminology.
pyrpc.dev to pyrpc.com
The domain migrated from pyrpc.dev topyrpc.com. Every reference across the codebase — documentation, links, comments — was updated at once rather than letting old links accumulate. This affected roughly 30 files.
Em dashes and encoding
The codebase had a mix of em dashes (U+2014 —) and regular dashes (-). Some files used em dashes in code strings, which caused subtle issues on Windows systems with cp1252 encoding. We normalized everything to regular dashes. While fixing this, we also repaired four files that had been corrupted by cp1252 and UTF-16 LE encoding issues — remnants of early development on mixed-platform setups.
Package READMEs
Every Python package now has its own README covering what it does, who should use it, and how to install it:
pyrpc-core— The runtime, CLI, and codegen. One install, everything you need.pyrpc-codegen— The TypeScript generation library. Internal dependency, not installed directly.pyrpc-core[fastapi]— FastAPI adapter bundled as an extra.pyrpc-core[flask]— Flask adapter bundled as an extra.
The READMEs serve as the entry point on PyPI, npm, and GitHub for someone exploring a single package.
Framework adapters as extras
pyrpc-core now exposes fastapi andflask extras:
pip install pyrpc-core # runtime + CLI + codegen pip install pyrpc-core[fastapi] # + FastAPI adapter pip install pyrpc-core[flask] # + Flask adapter
The adapter code lives inside the pyrpc-core extras — no separate packages to discover or version to track. This mirrors the pattern we established in v0.3.0 when we merged pyrpc-cliback into pyrpc-core: one package, optional extras, no unnecessary splits.
The install story today
After this release, the package landscape is simpler:
Python: pip install pyrpc-core # runtime + CLI + codegen pip install pyrpc-core[fastapi] # + FastAPI adapter pip install pyrpc-core[flask] # + Flask adapter TypeScript: npm install @pyrpc/client # client + postinstall prompt npx pyrpc sync # fetch types from server
Two languages, three commands, one version number across all packages.
What’s next
The distribution story is now complete: workspace mode for monorepos, server mode for separate repositories, and the client-side tooling that makes both workflows seamless. The packaging cleanup removes the friction points that developers hit when browsing individual packages or contributing on Windows.
Next, we’re turning to documentation and examples — filling in the gaps that new users encounter when they first try pyrpc. Read the full changelogfor the complete list of changes.

pyRPC