Add Python SDK#2705
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a complete Python Admin SDK (async + sync), a TS genpy CLI to emit Python types, GitHub CI and PyPI publish workflows, Python scaffolding/examples, a sandbox tester, developer tooling (unasync, Makefile), docs, and extensive tests. ChangesPython Admin SDK end-to-end delivery
Estimated code review effort Possibly related PRs
Suggested reviewers
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
|
View Vercel preview at instant-www-js-python-sdk-v1-jsv.vercel.app. |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (2)
.github/workflows/python-publish.yml (1)
10-31: ⚡ Quick winAdd explicit minimal permissions to the build job.
The build job uses default permissions, which are broader than necessary. Explicitly declaring minimal permissions improves security posture by limiting what a compromised step could access.
🛡️ Suggested fix
jobs: build: name: Build wheel + sdist runs-on: ubuntu-latest timeout-minutes: 10 + permissions: + contents: read steps: - name: Check out code uses: actions/checkout@v4🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/python-publish.yml around lines 10 - 31, The build job currently relies on default repo-wide permissions; add an explicit minimal permissions block under the build job (the "build" job) to restrict access — e.g., set permissions: contents: read — so the workflow only has read access to repository contents while running the Build step (working-directory: client/packages/python run: uv build) and the Upload distributions step (uses: actions/upload-artifact@v4). Ensure no extra permissions (like write) are granted unless required.client/packages/python/src/instantdb/_sync/webhooks/receiver.py (1)
113-126: ⚡ Quick winDocument handler signature requirements for sync vs async flavors.
The docstring at lines 114-115 states "Handlers under
AsyncInstantmust beasync def; underInstantthey're plaindef. Mixing flavors is unsupported." However, there is no runtime enforcement. If a user accidentally passes anasync defhandler to the syncWebhooks.process_payload, line 126'shandler(arg)call will silently create an unawaited coroutine rather than raising a clear error.Consider adding a runtime check or expanding the docstring with a concrete example to reduce the risk of this mistake.
Optional: Add runtime check
+import inspect + def process_payload( self, handlers: dict[str, Any], payload: dict[str, Any], ) -> None: """Dispatch each record in the payload to its matching handler. ... """ records_map = self._schema.get("records", {}) if self._schema else {} for record in payload.get("data") or []: namespace = record.get("namespace") action = record.get("action") handler = _resolve_handler(handlers, namespace, action) if handler is None: continue + if inspect.iscoroutinefunction(handler): + raise InstantError( + "Sync Webhooks.process_payload received an async handler. " + "Use AsyncWebhooks for async def handlers." + ) record_model = records_map.get((namespace, action)) arg = record_model.model_validate(record) if record_model else record handler(arg)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@client/packages/python/src/instantdb/_sync/webhooks/receiver.py` around lines 113 - 126, The handler invocation can silently create unawaited coroutines when a user passes an async function to the sync webhook processor; update the sync code path in Webhooks.process_payload to detect wrong-flavored handlers by checking if the resolved handler is a coroutine function (e.g., using asyncio.iscoroutinefunction or inspect.iscoroutinefunction) right before the call to handler(arg) and raise a clear TypeError stating that AsyncInstant handlers (async def) are not allowed in Instant (sync) processing and must be converted to plain def; keep the check adjacent to where _resolve_handler(...) returns handler so the error surfaces immediately and references AsyncInstant vs Instant in the message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@client/packages/cli/src/commands/genpy.ts`:
- Around line 186-189: buildEntityModelsPy and buildTxStubPyi currently emit raw
schema keys (f.name, attrName, link.label) as Python identifiers which can
produce invalid .py/.pyi; create a helper makeSafePyIdent(key) to produce a
valid Python identifier (e.g., replace invalid chars, prefix reserved keywords
with underscore) and use that safe name when emitting class attributes in
buildEntityModelsPy, then preserve the original key by emitting a class-level
mapping like __field_aliases__ = {"safe_name": "raw-key"} so runtimes/tools can
map back; for buildTxStubPyi, switch to the functional TypedDict form when any
key is not a valid identifier (TypedDict("Name", {"raw-key": Type, ...}))
instead of class-syntax fields, falling back to class syntax only when all keys
are valid identifiers; update usages of f.name/attrName/link.label to call
makeSafePyIdent and adjust emitted declarations accordingly.
- Around line 439-446: Sanitize entity names before emitting attributes in
_TxBuilder: when iterating identifierEntities in genpy.ts, transform each
entName into a valid Python identifier (e.g., replace non-alphanumeric chars
with underscores, collapse consecutive underscores, and if it starts with a
digit prefix with an underscore) and use that sanitized identifier as the
attribute key while keeping className(entName) for the type reference; also
ensure sanitized names are unique (append suffix if collision) so generated
lines like ` <sanitized>: _NamespaceBuilder[_${className(entName)}Chunk]`
always produce valid Python syntax.
In `@client/packages/python/pyproject.toml`:
- Around line 38-52: The dynamic Hatch version path ([tool.hatch.version].path)
points to ../version/src/version.ts which is outside the sdist discovery scope,
so sdist-built packages cannot find version.ts; fix by either moving version.ts
into the Python package tree (e.g., under src/instantdb) and updating
[tool.hatch.version].path to the new relative path, or add a
tool.hatch.build.targets.sdist.force-include entry that explicitly includes
../version/src/version.ts (and mirror that change for the wheel config if
necessary) so both wheel and sdist can resolve the version file at build time.
In `@client/packages/python/README.md`:
- Around line 16-22: The header block opens with <p align="center"> but ends
with a stray opening <p> instead of a closing </p>, leaving invalid HTML;
replace the final "<p>" with the correct closing tag "</p>" so the block
properly closes (look for the <p align="center"> line and the trailing lone <p>
in the README.md header).
In `@client/packages/python/scripts/run_unasync.py`:
- Around line 56-59: The REMOVE_BLOCK regex requires a trailing newline after
the "# UNASYNC_REMOVE_END" marker so blocks at EOF without a final newline are
not matched; update REMOVE_BLOCK to allow either a newline OR end-of-file after
the end marker (i.e., make the trailing newline optional and accept EOF) and
apply the same change to the other removal regex later in the file that handles
UNASYNC blocks so marker blocks at EOF are stripped correctly.
In `@client/packages/python/src/instantdb/_async/storage.py`:
- Line 27: The async method AsyncStorage.upload_file calls the synchronous
helper _read_bytes which uses Path.read_bytes() and file.read(), blocking the
event loop; change the implementation so file reading is non-blocking — either
make _read_bytes an async function (rename to _read_bytes_async) that uses an
async file library like aiofiles for Path and file-like objects, or keep a sync
helper but call it via loop.run_in_executor from upload_file to offload I/O to a
thread; ensure both Path and file-like input are supported and update
AsyncStorage.upload_file to await the new async helper or await the executor
future accordingly and adjust any callers.
In `@client/packages/python/src/instantdb/_async/streams/writer.py`:
- Around line 106-112: The assert in async def write(self, chunk: str) should be
replaced with explicit validation: check if self._connection is None or
self._stream_id_future is None and raise an InstantError with a clear message
(e.g., "Stream not opened; use async context manager or call open() before
write()") instead of letting an AssertionError propagate; update the write
method to perform these checks before awaiting self._stream_id_future to provide
a deterministic, descriptive error when write() is called too early.
In `@client/packages/python/src/instantdb/_sync/webhooks/manager.py`:
- Around line 109-115: The disable method currently uses a truthiness check on
reason which drops empty strings; update the construction of body in disable
(method disable in manager.py) to check explicitly for None (e.g., use "if
reason is not None") so that reason="" is preserved and sent to the API when
provided; ensure the rest of the method (_http.post call and return via
_webhook_info) remains unchanged.
In `@client/packages/python/src/instantdb/_webhooks_crypto.py`:
- Around line 90-94: The freshness check currently only rejects old signatures;
compute the age as now - sig.t (using now = int(received_at if received_at is
not None else time.time())) and reject when abs(age) > max_age_seconds so
very-future timestamps also fail; update the InstantError to indicate whether
the signature is too old or too far in the future (include age and tolerance)
and apply this logic in the same function/context where sig.t, now,
max_age_seconds and InstantError are used in _webhooks_crypto.py.
In `@client/sandbox/admin-sdk-python/src/main_sync.py`:
- Line 168: The default sandbox API URI uses the wrong port (9888); update the
api_uri default value in main_sync.py (variable api_uri) to use
"http://localhost:8888" and search for the other occurrence mentioned (the
similar default at the other location around the second occurrence) and change
that default as well so both places match the documented/local sandbox port
8888.
---
Nitpick comments:
In @.github/workflows/python-publish.yml:
- Around line 10-31: The build job currently relies on default repo-wide
permissions; add an explicit minimal permissions block under the build job (the
"build" job) to restrict access — e.g., set permissions: contents: read — so the
workflow only has read access to repository contents while running the Build
step (working-directory: client/packages/python run: uv build) and the Upload
distributions step (uses: actions/upload-artifact@v4). Ensure no extra
permissions (like write) are granted unless required.
In `@client/packages/python/src/instantdb/_sync/webhooks/receiver.py`:
- Around line 113-126: The handler invocation can silently create unawaited
coroutines when a user passes an async function to the sync webhook processor;
update the sync code path in Webhooks.process_payload to detect wrong-flavored
handlers by checking if the resolved handler is a coroutine function (e.g.,
using asyncio.iscoroutinefunction or inspect.iscoroutinefunction) right before
the call to handler(arg) and raise a clear TypeError stating that AsyncInstant
handlers (async def) are not allowed in Instant (sync) processing and must be
converted to plain def; keep the check adjacent to where _resolve_handler(...)
returns handler so the error surfaces immediately and references AsyncInstant vs
Instant in the message.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 9341d838-b8b4-4063-b170-fd34d253d229
⛔ Files ignored due to path filters (1)
client/packages/cli/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (73)
.github/workflows/python-publish.yml.github/workflows/python.ymlclient/packages/cli/src/commands/genpy.tsclient/packages/cli/src/index.tsclient/packages/create-instant-app/__tests__/e2e/create-instant-app.e2e.test.tsclient/packages/create-instant-app/scripts/copyExamples.tsclient/packages/create-instant-app/src/cli.tsclient/packages/create-instant-app/src/env.tsclient/packages/create-instant-app/src/index.tsclient/packages/python/.gitignoreclient/packages/python/Makefileclient/packages/python/README.mdclient/packages/python/pyproject.tomlclient/packages/python/scripts/run_unasync.pyclient/packages/python/src/instantdb/__init__.pyclient/packages/python/src/instantdb/_async/__init__.pyclient/packages/python/src/instantdb/_async/auth.pyclient/packages/python/src/instantdb/_async/client.pyclient/packages/python/src/instantdb/_async/http.pyclient/packages/python/src/instantdb/_async/rooms.pyclient/packages/python/src/instantdb/_async/storage.pyclient/packages/python/src/instantdb/_async/streams/__init__.pyclient/packages/python/src/instantdb/_async/streams/_connection.pyclient/packages/python/src/instantdb/_async/streams/reader.pyclient/packages/python/src/instantdb/_async/streams/writer.pyclient/packages/python/src/instantdb/_async/subscribe.pyclient/packages/python/src/instantdb/_async/webhooks/__init__.pyclient/packages/python/src/instantdb/_async/webhooks/manager.pyclient/packages/python/src/instantdb/_async/webhooks/receiver.pyclient/packages/python/src/instantdb/_errors.pyclient/packages/python/src/instantdb/_http_errors.pyclient/packages/python/src/instantdb/_sync/__init__.pyclient/packages/python/src/instantdb/_sync/auth.pyclient/packages/python/src/instantdb/_sync/client.pyclient/packages/python/src/instantdb/_sync/http.pyclient/packages/python/src/instantdb/_sync/rooms.pyclient/packages/python/src/instantdb/_sync/storage.pyclient/packages/python/src/instantdb/_sync/webhooks/__init__.pyclient/packages/python/src/instantdb/_sync/webhooks/manager.pyclient/packages/python/src/instantdb/_sync/webhooks/receiver.pyclient/packages/python/src/instantdb/_transact.pyclient/packages/python/src/instantdb/_version.pyclient/packages/python/src/instantdb/_webhooks_crypto.pyclient/packages/python/src/instantdb/py.typedclient/packages/python/tests/__init__.pyclient/packages/python/tests/conftest.pyclient/packages/python/tests/test_client.pyclient/packages/python/tests/test_storage.pyclient/packages/python/tests/test_streams_state.pyclient/packages/python/tests/test_subscription_state.pyclient/packages/python/tests/test_sync_client.pyclient/packages/python/tests/test_transact.pyclient/packages/python/tests/test_validation.pyclient/packages/python/tests/test_webhooks_crypto.pyclient/packages/python/tests/test_webhooks_dispatch.pyclient/sandbox/admin-sdk-python/.env.exampleclient/sandbox/admin-sdk-python/.gitignoreclient/sandbox/admin-sdk-python/README.mdclient/sandbox/admin-sdk-python/pyproject.tomlclient/sandbox/admin-sdk-python/src/__init__.pyclient/sandbox/admin-sdk-python/src/main.pyclient/sandbox/admin-sdk-python/src/main_sync.pyclient/www/app/docs/backend/page.mdclient/www/app/docs/start-python/page.mdclient/www/data/docsNavigation.jsexamples/python-script/.env.exampleexamples/python-script/.gitignoreexamples/python-script/.python-versionexamples/python-script/README.mdexamples/python-script/instant.perms.tsexamples/python-script/instant.schema.tsexamples/python-script/main.pyexamples/python-script/pyproject.toml
There was a problem hiding this comment.
♻️ Duplicate comments (1)
client/packages/python/README.md (1)
16-21:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix the unclosed paragraph block in the centered links section.
The block opened on Line 16 uses
<p align="center">but Line 21 has<p>instead of</p>, leaving invalid HTML.Suggested fix
-<p> +</p>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@client/packages/python/README.md` around lines 16 - 21, The centered links paragraph is left with an opening tag "<p align=\"center\">" but closed with "<p>" instead of the correct "</p>"; update the closing tag to "</p>" so the block becomes a properly formed paragraph (locate the block containing "<p align=\"center\">" and replace the erroneous "<p>" with "</p>").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@client/packages/python/README.md`:
- Around line 16-21: The centered links paragraph is left with an opening tag
"<p align=\"center\">" but closed with "<p>" instead of the correct "</p>";
update the closing tag to "</p>" so the block becomes a properly formed
paragraph (locate the block containing "<p align=\"center\">" and replace the
erroneous "<p>" with "</p>").
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a0bff568-f3e0-413e-9def-ee35f1c31924
📒 Files selected for processing (3)
client/packages/cli/src/commands/genpy.tsclient/packages/python/README.mdclient/www/app/docs/start-python/page.md
✅ Files skipped from review due to trivial changes (1)
- client/www/app/docs/start-python/page.md
🚧 Files skipped from review as they are similar to previous changes (1)
- client/packages/cli/src/commands/genpy.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@client/packages/cli/src/commands/genpy.ts`:
- Around line 174-180: The buildEntityModelsPy flow currently uses
safePyIdent(attrName) and pushes into fieldsByEntity[entName] without ensuring
per-entity uniqueness, causing duplicate Python attributes when two different
raw keys sanitize to the same name; update the population logic in
buildEntityModelsPy (where safePyIdent, fieldsByEntity, and the pushed field
objects with name/rawKey/hasDefault are handled) to detect collisions per entity
(e.g., maintain a map from sanitized name → count) and disambiguate by appending
a deterministic suffix (like _1, _2) to the field.name while preserving the
original rawKey for aliasing, and ensure any downstream code that emits the
class uses the disambiguated field.name and rawKey for alias=... so no fields
are overwritten.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 73f3544d-f9b5-47bd-baad-ec98fde5647f
📒 Files selected for processing (15)
.github/workflows/python-publish.ymlclient/packages/cli/src/commands/genpy.tsclient/packages/python/README.mdclient/packages/python/pyproject.tomlclient/packages/python/scripts/run_unasync.pyclient/packages/python/src/instantdb/_async/storage.pyclient/packages/python/src/instantdb/_async/streams/writer.pyclient/packages/python/src/instantdb/_async/webhooks/manager.pyclient/packages/python/src/instantdb/_io.pyclient/packages/python/src/instantdb/_sync/storage.pyclient/packages/python/src/instantdb/_sync/webhooks/manager.pyclient/packages/python/src/instantdb/_webhooks_crypto.pyclient/packages/python/tests/test_storage.pyclient/packages/python/tests/test_webhooks_crypto.pyclient/sandbox/admin-sdk-python/src/main_sync.py
✅ Files skipped from review due to trivial changes (1)
- client/packages/python/README.md
🚧 Files skipped from review as they are similar to previous changes (7)
- client/packages/python/tests/test_storage.py
- client/packages/python/pyproject.toml
- client/packages/python/tests/test_webhooks_crypto.py
- client/packages/python/scripts/run_unasync.py
- client/packages/python/src/instantdb/_async/webhooks/manager.py
- client/packages/python/src/instantdb/_sync/webhooks/manager.py
- client/sandbox/admin-sdk-python/src/main_sync.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@client/packages/python/src/instantdb/_async/_upload_io.py`:
- Around line 58-63: Open the Path before measuring to avoid TOCTOU: call
file.open("rb") into fp first, compute the size from the opened handle (seek to
end and tell, then seek back to start) instead of using file.stat(), then call
_check_size_match(file_size, size, str(file)); ensure that if _check_size_match
(or any pre-return step) raises you close fp before propagating the error, and
finally return _UploadBody(_aiter_file(fp), size, fp.close). Reference: Path,
_aiter_file, _UploadBody, _check_size_match.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: dcab2256-e590-444b-b90b-f9dd836e2be6
📒 Files selected for processing (11)
client/packages/python/scripts/run_unasync.pyclient/packages/python/src/instantdb/_async/_upload_io.pyclient/packages/python/src/instantdb/_async/http.pyclient/packages/python/src/instantdb/_async/storage.pyclient/packages/python/src/instantdb/_io.pyclient/packages/python/src/instantdb/_sync/_upload_io.pyclient/packages/python/src/instantdb/_sync/http.pyclient/packages/python/src/instantdb/_sync/storage.pyclient/packages/python/tests/test_storage.pyclient/sandbox/admin-sdk-python/src/main.pyclient/www/app/docs/start-python/page.md
✅ Files skipped from review due to trivial changes (2)
- client/packages/python/src/instantdb/_sync/http.py
- client/www/app/docs/start-python/page.md
🚧 Files skipped from review as they are similar to previous changes (3)
- client/packages/python/src/instantdb/_async/http.py
- client/packages/python/scripts/run_unasync.py
- client/sandbox/admin-sdk-python/src/main.py
New `examples/python-script/` template: `pyproject.toml` (depends on `instantdb`), `.python-version` (3.10), `.gitignore`, `.env.example`, `README.md`, `instant.schema.ts`, `instant.perms.ts`, `main.py`. Run via `uv run --env-file .env python main.py`. `create-instant-app` adds `python-script` to `Project['base']`, `-b` choices, framework Select options, and a `--python` shorthand flag. `index.ts` branches on `isPython` to skip the package.json read/write block and `runInstallCommand`. Success message swaps the `pkgManager run dev/start` line for `uv sync` + `uv run --env-file .env python main.py`. `env.ts`: `python-script` maps to `INSTANT_APP_ID` (no bundler prefix). Admin-token var name branches: Python writes `INSTANT_ADMIN_TOKEN` (matches the SDK), JS keeps `INSTANT_APP_ADMIN_TOKEN`. `copyExamples.ts`: `python-script` added to `EXAMPLES_TO_COPY` so the template gets bundled into the published npm package. E2e: `scaffolds with --python flag` covers the full flow — exits 0, scaffolds the expected files, omits `package.json`, writes the right env vars (with a negative match on `INSTANT_APP_ADMIN_TOKEN` to catch accidentally writing both). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`docs/start-python/page.md`: comprehensive Python reference, not just a hello-world — install, init, sync vs async, schema=, query, transact, subscribe (async-only), streams (async-only), auth, impersonation, storage, rooms, debug helpers, webhooks (manager + receiver + FastAPI example + typed handlers), plus a "Differences from JS" recap. Leads with sync `Instant`; the subscribe/streams sections show the async flavor. `docsNavigation.js`: "Getting started w/ Python" added under Introduction, after the TanStack Start entry. `docs/backend/page.md`: intro now mentions both SDKs (`@instantdb/admin` for JS, `instantdb` for Python) and links to `start-python`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Streams: track _do_reconnect task in aclose so a mid-handshake cleanup doesn't leak; stash flush/close errors onto writer.error so callers can verify durability after __aexit__. Webhooks: fetch_payloads rejects empty payloadUrl/token (not just missing). Docstrings now explain why (JS-parity for camelCase manager shape; unasync-honesty for sequential dispatch). Tightened exception-stops-remaining test, added falsy-body cases. Codegen: className() PascalCases across non-identifier separators so a hyphenated entity name doesn't produce invalid Python. mapValueType() has a defensive Any fallback. Dropped three implementation-tracing _validate_query_result tests. Scaffold: rewrite [project].name in pyproject.toml to the user's app name (flattens npm-style @org/foo scope). E2e assertion added. Docs: grammar fix on the opening line; FastAPI example uses print() instead of an undefined symbol. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
What it says on the tin!
Docs here: https://instant-www-js-python-sdk-v1-jsv.vercel.app/docs/start-python
You can test this out like so:
Create a new project via
create-instant-appand choosepython-scriptfor the templateUpdate the instantdb package dependency to match what's pushed on this branch. Add the following to pyproject.toml
Now you should be good to install the dependencies and run the starter from the CLI!
There's some changes to
instant-clitoo to make this work seamless with python too so if you are doing pushes/pulls use this branch as wellAnd here's a demo showing off auth, transactions, streams, subscribe_query, and storage,
python-min.mp4