RemotiveCLI
0.23.1 - 2026-07-07
Bug fixes
-
Document org/studioRunner role in service-accounts --help
Adds org/studioRunner (can start RemotiveStudio) to the supported-roles help shown by service-accounts create/update, mirroring org/topologyRunner.
0.23.0 - 2026-07-02
Bug fixes
- security: Bumped packages caught by audit
Features
-
auth: Mandatory default organization selection
Require selecting a default organization on login/activate, and restructure the related auth commands around it:
- prompt for and persist a default organization on login/activate, auto-selecting only when the listing returns exactly one org
- auto-set the organization for service accounts, resolving it from the token itself
- validate organization uid input (OPLANE_REQ-00109680)
- split 'auth organization' into print/set subcommands and shim the deprecated 'organizations default' onto it
- drop the --account/--organization column toggles from 'auth list'
- don't fail login/activate when org selection fails; retry invalid selections with a loop instead of recursion
0.22.0 - 2026-06-24
0.21.0 - 2026-06-24
0.20.4 - 2026-06-22
Bug fixes
-
Tab completion with typer>=0.26
Tab-completion silently returned no suggestions on installs resolving Typer 0.26 or newer. Typer began vendoring its own Click in 0.26, which left the cached command tree empty; it is now rebuilt correctly.
0.20.3 - 2026-06-22
Features
-
release: Generate and publish checked-in changelogs for the CLI
The release flow produces two checked-in changelogs via remotive-release (a curated CHANGELOG.md for the docs site and a full CHANGELOG.dev.md, both with commit bodies), replacing the git-changelog setup. A dedicated workflow publishes the checked-in changelog to the docs site on push to main, and DEV.md recommends the basecamp commit-msg hook.
0.20.2 - 2026-06-18
Features
-
Cloud now allows service-accounts to read organization info + features for an organization.
This makes it simpler to use a service-account locally since it can be activated, set default organization and get subscription status in the same way as a personal user.
0.20.1 - 2026-06-17
Bug fixes
- Improve error messages when instance file is missing
Features
- Bump RemotiveStudio to 1.20.0
0.20.0 - 2026-06-17
Bug fixes
-
studio: Verify macOS signature + notarization before install
The macOS install path skipped integrity verification entirely, relying on the no-quarantine extraction trick to run an unsigned/ad-hoc app. Now that the desktop app is Developer ID signed + notarized, verify it instead:
- _verify_macos_bundle runs codesign --verify --deep --strict and spctl --assess --type execute on the mounted .app; either failing aborts the install via _SignatureVerificationError.
- _stage_dmg verifies before copytree, so a tampered/improperly-signed download never reaches /Applications.
- macOS now records signature_verification success/failure (was "skipped"), matching the Linux Ed25519 path.
0.19.0 - 2026-06-16
Bug fixes
- Make index_yaml_to_data non-blocking
Features
-
topology: Add host-gateway mapping for docker runs
-
trace: Add --trace troubleshooting mode
Add a --trace flag that logs the underlying operations the CLI performs for troubleshooting. Supports decorator-based tracing, honest mkdir logging, and tracing of container commands, with secrets redacted from logged container commands.
0.18.0 - 2026-06-12
- The completion cache moves from the legacy location to $XDG_CACHE_HOME/remotive/. Users with shell completions installed may need to regenerate them on first run.
Features
-
topology: Use $id URL for workspace schema
The workspace marker (
remotive.yaml) now references its schema through aschemakey carrying the canonical versioned URL from the schema's$id:replacing the
remotive-topology-workspace:0.1identifier. Generated markers start with a yaml-language-server modeline so editors validate and complete them out of the box, and no longer include an emptydescriptionby default.Schemas are published to releases.remotivelabs.com at their
$idURL, versioned by the schema's own version instead of the CLI release version. -
XDG dirs and topology workspace commands
- BREAKING: The completion cache moves from the legacy location to $XDG_CACHE_HOME/remotive/. Users with shell completions installed may need to regenerate them on first run.
Honors the XDG Base Directory Specification for all CLI state. Configuration, cache, state, and data files now live under $XDG_CONFIG_HOME, $XDG_CACHE_HOME, $XDG_STATE_HOME, and $XDG_DATA_HOME (each sub-keyed by
remotive/); each kind can be overridden via REMOTIVE_CONFIG_DIR, REMOTIVE_CACHE_DIR, REMOTIVE_STATE_DIR, REMOTIVE_DATA_DIR. Existing state files at the legacy location are copied forward on first run with permissions clamped to 0600.Adds a workspace surface that materializes and inspects a
remotive.yaml-marked project root:remotive topology workspace init remotive topology workspace current
The marker file is described by a JSON Schema at
schemas/remotive-topology-workspace.schema.json. Legacy workspaces that only have the.remotive/directory get the marker backfilled on first touch (seesettings/migration/migrate_legacy_workspace_marker.py).Adds binary-dispatched topology lifecycle commands:
remotive topology build [--no-workspace] remotive topology clean remotive topology prune [--all]
buildwrites outputs under<workspace>/.remotive/build/by default; pass a positional<output_path>(must lie inside the workspace, unless--no-workspaceis set) to override.prune --allclears every workspace's topology cache root (reclaims orphans from moved or renamed workspaces).The Studio runtime API resolves the active instance YAML inside a workspace sandbox:
<workspace>/.remotive/instances/(canonical), falling back to<workspace>/.remotive/cache/instances/for workspaces written by older binaries. Symlink escapes from the workspace are refused; the endpoint returns a workspace-relative POSIX string.Container subprocess invocation uses identity-mapped bind-mounts — host and container share the same paths for the workspace, config, and cache — and pins those paths via REMOTIVE_<KIND>_DIR env vars inside the container. Supported on WSL2, macOS, and Linux.
0.17.2 - 2026-06-08
Features
-
studio: Harden desktop install — version validation, interactive-only installs, audit log
- Validate --desktop-version (strict ASCII semver, max 32 chars) via Typer callback, and fail closed on a malformed remotely-resolved "latest" so no unvalidated string reaches asset names, release URLs, or paths.
- Installs are interactive-only: without a TTY nothing is ever downloaded or installed — an existing install launches as-is (no update check), a missing install is an error. Removes --desktop-force-install.
- Append a JSON-line audit entry (0o600, in the install state dir) for every install action: action, version source, version, signature verification result, outcome (completed/failed/aborted/declined/refused), user.
Implements OPLANE_REQ-00085620, OPLANE_REQ-00085622, OPLANE_REQ-00085627.
0.17.1 - 2026-06-08
Bug fixes
- Add no-cache header to studio SPA files
Features
- Added endpoint to check broker/topology health(up/down)
0.16.1 - 2026-06-03
Bug fixes
-
Improved checks to determine if a graphical environment is available on linux
-
Allows to retry the pkce code max 3 times to allow for copy-paste issues
-
User Input Validation for PKCE Verification Code in Token Exchange OPLANE_REQ-00080722
Also printing server response in error instead of guessing.
-
Trust XDG_SESSION_TYPE=x11/wayland as a graphical session fast-path
Skips the xdpyinfo probe when logind reports an unambiguous graphical session. Unset/tty values still fall through to the DISPLAY check and probe, so WSL/containers/non-systemd keep their current behavior.
Follow-up to #291.
-
Always show hint about --no-browser even if we think that a browser window was opened.
0.16.0 - 2026-06-01
Bug fixes
-
cli: Set cache dir for custom topology CLI cmd
Make sure to explicitly set cache dir using REMOTIVE_CACHE_DIR env var when calling topology CLI through remotive CLI with a custom command argument. This forces the cache to be populated in the legacy directory ./remotive/cache
Features
-
Adding --with-metrics flag
Requires support for this in remotive-topology
0.15.1 - 2026-05-22
Bug fixes
-
studio: Repair desktop embedded mode on direct launch (not with cli)
macOS GUI apps launched from Spotlight don't inherit the user's shell env, so REMOTIVE_STUDIO_DESKTOP_ENABLED was missing when the Electron app re-spawned the CLI — embedded mode fell back to HTTP and both the CLI and Electron opened a browser window. Drop the toggle check from _embedded_mode_enabled(); REMOTIVE_CLI_RUN_EMBEDDED alone is enough, since only the Electron spawn path sets it.
Also reject --desktop with click's standard "No such option" error when the feature toggle is off, via an option callback.
0.15.0 - 2026-05-21
Features
-
studio: Install RemotiveStudio Desktop on demand and launch with --desktop
Adds a --desktop flag to
remotive studiothat installs the RemotiveStudio Desktop Electron app (if missing) and spawns it detached, forwarding the workspace path and --broker-url. The desktop app then re-invokes the CLI with REMOTIVE_CLI_RUN_EMBEDDED=1, which serves the SPA over HTTPS using the local cert and emits a JSON {event:"ready", url, version} handshake on stdout for the Electron side to connect on.Installer (studio/app_install.py):
- Linux (x86_64, arm64) and macOS (arm64); native Windows rejected, WSL2 treated as Linux.
- Downloads from releases.beamylabs.com, then on Linux verifies an Ed25519 signature over a SHA-256 sidecar using a public key bundled in the CLI. The key's fingerprint is pinned in source so a swap of just the .pem cannot redirect trust; rotating the signing key requires a CLI release that updates both. The sidecar must name this artifact (guards against replaying a signed hash from a different file) and the digest is checked with hmac.compare_digest.
- macOS: the Linux signing pipeline doesn't cover DMGs yet. The DMG is downloaded over HTTPS, mounted via hdiutil, and copy-installed via shutil.copytree — none of which set com.apple.quarantine, so Gatekeeper never engages and the ad-hoc-signed bundle runs. A user-downloaded DMG opened from Finder would still hit Gatekeeper; the "unsigned but works" property only holds because the CLI is the install path. Real Developer ID signing + notarization is a follow-up if/when the DMG becomes a public-download artifact.
- Install is atomic: stage to a sibling dir, backup-rename the target, rename staging into place, rmtree the backup. A failed download leaves the existing install untouched.
- Linux post-install writes a .desktop entry + icon and refreshes a bin symlink at ~/.local/bin/remotive-studio-desktop — but only if that path is unset or already points into our managed dir. A real user file at that path is never clobbered.
- If the install is current but the .desktop entry, icon, or bin symlink is missing, post-install re-runs to restore them without redownloading.
- Concurrent installers serialize on an flock around the state dir to avoid racing on the atomic-swap rename.
Studio HTTPS serving (studio/start.py):
- Embedded mode listens on https://localhost:<port> using the server-key/full-chain from settings.cert_paths, validated through file_io.validate_restrictive_file before being handed to uvicorn.
- Browser mode is unchanged HTTP.
- Stale-launch detection: with stdio fully detached we have no IPC signal, so we sleep 1.5s and check if Electron is still alive. Heuristic — a slow-crashing launch escapes detection.
Studio API (studio/api/topology_runtime.py):
- Passes the per-broker verify (from broker.lib.helper. resolve_https_localhost_verify) through app state into the grafana probe so https://localhost brokers backed by the self-signed CA validate.
Studio mount (studio_mount.py):
- REMOTIVE_STUDIO_SPA_PATH dev-override: serve a built SPA from a chosen directory instead of the packaged UI, for iterating on the SPA without rebuilding the CLI.
-
studio: Gate desktop app behind REMOTIVE_STUDIO_DESKTOP_ENABLED
Adds a preview-feature toggle for the RemotiveStudio Desktop launcher. The desktop install + spawn path is not ready for GA, so until the toggle is flipped on:
- --desktop is hidden from
remotive studio --help. The Typer option'shidden=is evaluated against the env var at command registration, so the flag only surfaces once the env var is set in the user's environment. - A runtime check rejects --desktop with a clear error if a user discovers and passes the (still-accepted-but-hidden) flag without the env var set. Click accepts hidden options on the command line, so visibility alone isn't enough — the runtime check is what actually gates the feature.
- Embedded mode (REMOTIVE_CLI_RUN_EMBEDDED=1, set by the Electron app when it re-invokes the CLI to serve the SPA over HTTPS) is also gated on the same toggle. Without this, a stray REMOTIVE_CLI_RUN_EMBEDDED in the environment could opt a CLI run into HTTPS embedded mode while the feature is supposed to be off.
The toggle accepts the same truthy values as other CLI feature flags ("true", "1", "yes", "on"). Removing the toggle later is a one-line revert per file.
- --desktop is hidden from
-
tls: Provision local TLS certs and gRPC trust for HTTPS localhost
Generates a self-signed CA + server cert lazily via trustme on first settings access (stored under ~/.config/remotive/certs/ with 0700/0600 on POSIX), then exposes them via Settings.cert_paths. The CA, server cert, and server key are consumed by any localhost HTTPS server we run — the local broker on https://localhost:50443 and the Studio backend serving the SPA over HTTPS in embedded mode.
Wires gRPC to trust both system roots and the local CA in the same process: ensure_grpc_trust_bundle() runs once at CLI bootstrap and writes a combined certifi + local-CA bundle, pointing GRPC_DEFAULT_SSL_ROOTS_FILE_PATH at it. gRPC C-core caches that file on first SSL credential creation, so the bundle has to be in place before any TLS channel is built — handling it once at startup rules out the "did we remember to call configure before opening this channel?" hazard. Operator-supplied GRPC_DEFAULT_SSL_ROOTS_FILE_PATH is honored.
For requests, resolve_https_localhost_verify(url) returns the local CA path for https://localhost endpoints (and True elsewhere) so cloud / corporate-proxy setups remain untouched and REQUESTS_CA_BUNDLE keeps working.
Also adds validate_restrictive_file() — refuses to load a cert/key unless it's a 0600 regular file owned by us, sitting under a 0700 parent dir owned by us. Used before handing key material to a TLS stack. lstat on both the file and the parent guards against symlink swaps.
Bumps remotivelabs-broker to ~=0.13.8 and adds trustme + certifi as runtime deps.
0.14.1 - 2026-05-21
Bug fixes
-
search: Silence luqum PLY LALR warnings on import (luqum #115)
-
studio: Serialize gRPC and subprocess to avoid fork race
The studio FastAPI process had two thread-pool sides racing on fork(): gRPC AIO calls in /runtime/* ran on the event loop while sync subprocess.run() in /files/, /environment, /search/ ran on anyio threadpool workers. When fork() landed while a gRPC RPC was in flight, gRPC C-core's pre-fork handler bailed out ("fork_posix.cc:71 Other threads are currently calling into gRPC, skipping fork() handlers") and the parent could deadlock.
Convert every studio handler that shells out to async def, route the subprocess through asyncio.create_subprocess_exec, and gate both the gRPC RPCs and the fork itself with a process-wide asyncio.Lock on app.state. Lock is held only across the fork instruction (not the full subprocess lifetime) so concurrency is preserved elsewhere.
The sync run_topology path is kept for the Typer CLI; only the studio server takes the new run_topology_async path.
-
studio: Sanitize subprocess errors and add timeouts
Async subprocess calls in the studio API leaked unstructured stderr, stdout, and exception strings into HTTP 500 responses (file paths, stack traces, command args) and had no timeout, so a wedged child could pin a server slot indefinitely. Add a 120s default timeout on run_subprocess_async (600s for the docker pull), kill the child and raise TimeoutExpired on overrun, decode with errors="replace", and log failures server-side. Studio handlers now map TimeoutExpired to HTTP 504 and return generic messages for unparseable stderr — the JSON-structured stderr contract from the topology CLI still forwards as 400.
Closes OPLANE_REQ-00064396.
Refactor
-
studio: Collapse sync topology runner into async wrapper
The fork-race fix introduced parallel sync and async paths through
run_in_container.py(spinner, container runner, top-level dispatcher). Drop the sync versions and route the Typer CLI throughasyncio.run(run_topology_async(..., timeout=None))so there is one implementation. Also trim the verbose lock comments at the studio call sites — the lock's docstring at its definition carries the rationale.
0.14.0 - 2026-05-18
Bug fixes
- Removed old "remotive tui" function
Features
-
mock-broker: In-process gRPC mock broker for TUI workflows
Replaces
search/mock_indexwith a real gRPC server implementing the Network/Restbus/System services. Synthesises namespaces, frames, and distribution streams so the TUI can be exercised end-to-end without a live broker.python -m remotivelabs.cli.mock_broker(orpoe mock-broker) to run it standalone.- Wired into the dev deps (
pytest-xdist,pytest-flakefinder,ipython) and excluded from the wheel viasource-exclude. pytestnow runs with-n autofor parallelism.
-
search: Lucene grammar + unified AST
The TUI gains Lucene query syntax.
name:foo OR -unit:degC, regex/RPM\d+/, ranges, and parens.REST and MCP keep their existing wire contract (
field:value,f1,f2:valuecomma-prefix multi- field,operator=or,substring=true) and we don't pass this to Lucene yet. We adapt a bit to the new things in the AST, this made searching for numbers work, e.g. cycle time as well as getting suggestions for senders/receivers. -
tui: Rebuild the broker explorer end-to-end
Reshapes
remotive broker --uion top of the existing signal browse / live values view:- New capabilities — restbus publish + plan modals, an in-app help
screen, a command palette, and Lucene-syntax search
(
name:foo OR -unit:degC, regex, ranges). - Restructured input — one search bar drives all navigation; marks let you pick signals across multiple queries and feed them into the live view, restbus modal, or publish modal.
- Restructured layout — sidebar, tree, detail, and live view are now independent widgets sharing a single App-owned broker connection, so reconnects, namespace activity, and subscription lifetimes are handled centrally instead of per pane.
- New capabilities — restbus publish + plan modals, an in-app help
screen, a command palette, and Lucene-syntax search
(
Refactor
-
search: Drive SQLite schema from Column dataclass
Adding a searchable/tokenized column is now one line in columns.py instead of edits across schema.py, index.py, and the FTS triggers. Drops the dead in-memory migration loop in the same swing.
0.12.0 - 2026-05-15
Bug fixes
-
Read instance files under two locations, one contains the hash(workspace) id
This is due to a bug in topology-cli that writes it under this location. Lets consider how and when we solve this. Related to cache dir etc due to bazel compatibility
Features
- Added grafana_enabled to runtime environment response
- Bumped to latest topology, topology schema and studio
0.11.4 - 2026-05-08
Bug fixes
-
topology: Force REMOTIVE_CACHE_DIR inside the bind-mounted workspace
The topology binary's recent cache work moved its on-disk cache from
<workspace>/.remotive/cacheto$HOME/.cache/remotive/<workspace-hash>. That works fine when the binary runs natively, but inside the docker container we spawn here$HOMEisn't bind-mounted to the host, so cache writes are discarded on container exit and every build is cold.Force
REMOTIVE_CACHE_DIR=<container_workspace>/.remotive/cacheexplicitly after the genericREMOTIVE_*forwarding loop so the in-container value wins (last-ewins per docker's semantics, even if a host-sideREMOTIVE_CACHE_DIRwas forwarded). The cache lands under the bind-mount and persists to the host, matching the pre-binary-change layout from a user's perspective.Transitional — once the topology binary is bundled directly with the CLI and no longer needs the container hop, this can be dropped.
Adds focused unit tests for
_build_run_command(none existed); they inspect the constructed argv without launching docker. -
Skip time-based JWT checks in feature authorize
Disable exp/nbf/iat verification in the feature-authorize JWT decode so users with skewed clocks aren't locked out. Signature remains the load-bearing security check.
Also joins a single sentence that was split across two list items in the FeatureNotAuthorizedError details.
-
Improve error messages on api/studio/v1/runtime/environment
Features
- Add new endpoint to return environemnt info about the topology runtime
Refactor
- release: Package release flows as remotive_release plugin
0.11.3 - 2026-05-04
Bug fixes
-
Open studio in browser in the same way as login
Verified to work on all platforms
-
Relabel podman bind mounts with :z for SELinux hosts
Without the :z suffix, the topology container cannot access the mounted config and workspace directories on SELinux-enforcing systems, surfacing as a missing-user-consent error.
This was reported by our friends at https://www.machineware.de/
0.11.2 - 2026-05-04
Bug fixes
- In studio file API, allow more file extenstions for video. images and text
- Properly fixed mount and interactive mode when running topology with podman
0.11.1 - 2026-05-04
Bug fixes
- Propagate all envs starting with REMOTIVE_ to docker/podman container running topology
0.11.0 - 2026-04-30
Features
- Using latest remotive-topology 0.23.0
0.10.18 - 2026-04-30
Bug fixes
- New remotive-studio with warning message if hw accelleration is not enabled, required for scichart
Features
-
broker: Add --ui flag for the signal explorer
- remotive broker --ui launches the interactive TUI explorer
- REMOTIVE_MOCK_DB enables mock index mode for offline demos
- Drop the EXPLORE_ENABLED-gated broker explore subcommand
-
grpc: Add payload_size to frame index data
- Expose frame payload size (bits to bytes) in gRPC frame-to-dict mapping
- Enables payload length validation in TUI publish flow
-
search: Add mock signal index for offline/demo mode
- New mock_index package generates a deterministic set of automotive CAN and SOME/IP frames matching the gRPC dict shape, so it can be passed straight into index_signals() without a live broker
- Faker-based provider with domain-aware signal naming
- Excluded from sdist/wheel — demo/dev-only
- Adds faker as a dev dependency
-
tui: Add mark/unmark for signals and frames
- Add ability to mark individual signals, frames, or entire namespaces with m keybinding, clear all marks with M
- Marked items shown with bold asterisk prefix in tree
- Marking a frame also marks all its child signals
- Marks feed into subscribe and publish actions
-
tui: Add signal and frame publish
- Add publish action (p keybinding) for single signal/frame or batch of marked items
- PublishSingleModal for entering a value, PublishValuesModal for batch
- Support hex payload publish for frames with size validation
- Add extract_signal_hints and _format_signal_hints for publish UI hints
-
tui: Add frame state subscription windows
- Add SubscriptionWindow with per-frame signal state display
- Subscribe to marked signals/frames or all signals in a frame
- Expandable signal history with adjustable depth (+/- keys)
- SignalLine widget with click-to-expand interaction
- Seed subscriptions with current cached values on start
-
tui: Mark all frames and signals within a namespace in one action
Press "m" on a namespace node to mark every child frame and signal beneath it (or on the root to toggle all namespaces at once). The namespace label gains a "*" marker whenever any descendant is marked, and clears when the last one is unmarked.
-
tui: Sidebar, unified live view, clickable filter fields, and debounced search
- Collapsible left sidebar with clickable handle (Ctrl+B)
- Unified LiveView widget for the right pane, internally switching between a single-signal chart and a multi-signal frame-state view; app-level "q" closes and cancels the active subscription
- Detail-panel fields become clickable: left-click appends an AND-include filter, right-click opens FilterActionModal with include/exclude and, for numeric fields, comparison operators (>, >=, <, <=) plus an OR-combine toggle
- Query.parse tokenizes with shlex so values containing whitespace or punctuation can be searched by wrapping them in double quotes; between a single-signal chart and a multi-signal frame-state view; app-level "q" closes and cancels the active subscription
- Detail-panel fields become clickable: left-click appends an AND-include filter, right-click opens FilterActionModal with include/exclude and, for numeric fields, comparison operators (>, >=, <, <=) plus an OR-combine toggle
- Query.parse tokenizes with shlex so values containing whitespace or punctuation can be searched by wrapping them in double quotes; detail-field clicks emit quoted terms automatically
- Debounce search input 150 ms and run queries on a worker thread so typing stays responsive on large indexes; preserve expanded frames across tree rebuilds
Refactor
-
tui: Extract modules, use typed dataclasses and BrokerClient
- Split monolithic explore_app.py into formatting.py (Row/FrameRow/SignalRow dataclasses, format_detail, build_tree_data) and widgets.py (DetailPanel, LeftPane)
- Replace raw dicts with typed dataclasses throughout
- Switch from internal Broker to remotivelabs.broker.BrokerClient with async Worker pattern for subscriptions
- Make parse_scalar public in broker/typer.py for reuse
- Replace bare except blocks with logger.debug for diagnosability
0.10.17 - 2026-04-27
Bug fixes
-
Add runtime_id to studio backend /environment endpoint
-
Make reindex_topology async to avoid grpc-aio event loop churn
Calling asyncio.run() per request created and tore down a fresh event loop each time, leaving grpc-aio completion queues dangling and causing recurring BlockingIOError [Errno 35] in PollerCompletionQueue. Awaiting _fetch_async directly on the running loop avoids the leak; index write is offloaded via asyncio.to_thread.
Features
- Add a very simple healthcheck with status and runtime_id for studio backend
0.10.16 - 2026-04-21
Bug fixes
-
Remove erroneous help=help in broker sub-app definitions
Four broker sub-apps passed Python's builtin
helpobject instead of a string to create_typer(help=...). This was masked by add_typer() always overriding the help text.
Features
-
Add LazyTyperGroup and use it across all command levels
Extend TyperGroup with lazy import support: sub-apps are registered as "module.path:attr" strings and only imported when get_command() is called. create_typer() and create_typer_sorted() accept a lazy_imports dict to enable this at any level of the command tree.
Replace eager sub-app imports with lazy_imports dicts at every level: root (6 sub-apps), broker (8), cloud (9), tools (1), topology (2), cloud/recordings (1), and cloud/service-accounts (1). Sub-app modules are now only imported when the user invokes that subcommand.
-
Add cached tab-completion fast path
Introduce a lightweight entry point (main.py) that intercepts tab-completion requests before importing the full CLI. On cache hit uses only json to serve completions from a cached command tree — adding near-zero overhead on top of interpreter startup.
Handles bash, zsh, and fish by inlining the env-var parsing and output formatting. The cache stores help text for both subcommands and options, so zsh and fish show descriptions.
The cache lives at ~/.cache/remotivelabs/cli/completion_cache.json. Invalidation keys off the package directory's mtime (bumped by every pip/uv install that replaces files inside) plus a format-version constant for deliberate schema bumps. Corrupt or stale files are unlinked on read so the next slow-path run starts clean.
On cache miss, main() regenerates the cache and falls through to Typer's native completion. Any failure during regeneration is swallowed so cache-tree bugs never block the user's actual command.
0.10.15 - 2026-04-17
Bug fixes
- Change behaviour of topology search api to return all results if q is empty
0.10.13 - 2026-04-14
Bug fixes
- Studio bug fix where trace raw data field show entire value