# rpc
Call a public `@rpc` method exposed by another runtime. Returns a Future
that resolves to the method's return value when the target finishes. Works
from any runtime — in-panel apps, headless child runtimes (e.g. the shell's
REPL), cluster workers, or standalone scripts.
`rpc` is a runtime-level peer of `pub/*`: available in every host, not just
the TUI.
## Syntax
[rpc runtime-name method-name arg1 arg2 ...]
## Returns
`future` — a pending `ObjFuture` that the caller can `[await]` to get the
method's return value, or ignore for fire-and-forget invocation.
## Identity
The target is addressed by runtime name — the `id` the runtime was
created with. In the TUI, each app panel's runtime is named after its app
(the auto-numbered app name, which is also the panel tag), so the same
string you would pass to `tui/find-panel` is the RPC target:
[rpc "editor" "cmd-open-file" $path] [rpc "diff" "load-diff" $left $right]
For ad-hoc runtimes, the name is whatever was passed to `runtime/spawn` or
`createChild`. Runtime names are unique across live runtimes.
## Usage
The target runtime must have declared the method with `@rpc`:
def get-marked {|| @rpc true @doc "Return the currently marked items." [deref $state~marked] }
Inside an `@async` function or coroutine:
def load {|| @async set marked [await [rpc "files" "get-marked"]] echo "got:" $marked }
For fire-and-forget calls (no return value needed), drop the future:
[rpc "editor" "cmd-open-file" $path]
The shell's REPL supports `await` directly at the prompt:
```
repl:user> await [rpc "files" "get-marked"]
@{...}
````
## Errors
If the target runtime is unknown, the method is not registered, the target
queue is full, or the target eval throws — the future is rejected with a
string error message. Use `[try { ... } catch e { ... }]` around `await`:
try { set result [await [rpc "files" "get-marked"]] } catch e { echo "call failed:" $e }
## How it works
- Arguments are stringified and re-emitted as a deft-level call
(`[method-name arg1 arg2 ...]`) on the target's VM. Only data values
(strings, numbers, bools, nil, keywords) survive the crossing — closures
and opaque references don't.
- The return value round-trips through `deft/stringify` → `deft/parse`,
so structured data (vectors, maps, keywords, tagged maps) is preserved
on the caller side.
- The response Future is allocated on the caller's runtime heap and
resolved by the caller's own event-loop tick. The routing uses a
`Runtime`-level pending-call table that works for AppThread-hosted apps,
loop-driven children, and standalone runtimes alike.
- The registry is keyed by runtime name + method name; dispatch goes to the
owning runtime's driver thread.
- See rpc/methods to list registered methods.