kkrpc-interop
Use when implementing kkrpc clients or servers in non-TypeScript languages, speaking the stable compact protocol, transports, and reference implementations in Go, Python, Rust, or Swift.
Works with
---
name: kkrpc-interop
description: Use when implementing kkrpc clients or servers in non-TypeScript languages, speaking the stable compact protocol, transports, and reference implementations in Go, Python, Rust, or Swift.
license: MIT
---
# kkrpc Language Interop
Implement kkrpc clients and servers in non-JS languages by speaking the stable compact JSON protocol used by TypeScript kkrpc endpoints. Start with the default value-oriented protocol. Async iterable streaming and remote references are opt-in advanced protocols; implement them only when the interop boundary explicitly needs them.
## Reference Implementations
| Language | Location | Transports |
| -------- | ------------------------------ | ---------------- |
| Go | `interop/go/kkrpc/` | stdio, WebSocket |
| Python | `interop/python/kkrpc/` | stdio, WebSocket |
| Rust | `interop/rust/src/` | stdio, WebSocket |
| Swift | `interop/swift/Sources/kkrpc/` | stdio, WebSocket |
## Core Protocol
Interop uses JSON records. Stdio transports send newline-delimited UTF-8 JSON. WebSocket transports send the same JSON in text frames.
### Request
```json
{
"t": "q",
"id": "a1b2-c3d4",
"op": "call",
"p": ["math", "add"],
"a": [1, 2]
}
```
Fields:
- `t`: message tag, always `q` for requests.
- `id`: unique request identifier.
- `op`: one of `call`, `get`, `set`, or `new`.
- `p`: method or property path as string segments.
- `a`: argument array for calls and constructors.
- `v`: value for property writes.
### Response
```json
{
"t": "r",
"id": "a1b2-c3d4",
"v": 3
}
```
Errors use `e` with compact error fields:
```json
{
"t": "r",
"id": "a1b2-c3d4",
"e": {
"n": "Error",
"m": "Division by zero",
"s": "optional stack"
}
}
```
### Callback Invocation
```json
{
"t": "cb",
"id": "callback-id",
"a": ["progress", 50]
}
```
## Callback Argument Encoding
When sending a callable argument, generate an ID, store the callable locally, and replace the argument with a marker object.
```json
{
"__kkrpc_next_arg__": "callback",
"id": "callback-id"
}
```
When receiving this marker, create a wrapper function. Invoking the wrapper sends `t: "cb"` with the marker ID and argument array.
When receiving callback arguments from JS, unwrap value envelopes before invoking local callbacks.
```json
{
"__kkrpc_next_arg__": "value",
"v": "actual value"
}
```
Default callback invocation is fire-and-forget. If a non-JS implementation needs callback return values, object handles, or `releaseProxy()` behavior, it must also implement the `kkrpc/remote-refs` envelope and internal `op: "ref"` request flow.
## Opt-in Advanced Protocols
`kkrpc/streaming` adds async iterable stream records:
- `t: "sq"` for stream pull/return/throw control requests
- `t: "sr"` for stream value/completion/error responses
`kkrpc/remote-refs` adds explicit `proxy(value)` envelopes with `"__kkrpc_ref__": true` plus internal `op: "ref"` requests for apply/get/set/call/release. Do not assume these features are present when connecting to a default `kkrpc` endpoint.
## UUID Generation
Use any ID generator with low collision risk. IDs only need to match requests and responses within one connection.
```python
import uuid
def generate_uuid() -> str:
return str(uuid.uuid4())
```
## Transport Layer
Every transport should provide these operations:
```text
read() -> string? # Read one message, null/None if closed
write(message) # Write one JSON string
close() # Close connection
```
Stdio transports append `\n` and flush immediately. WebSocket transports send and receive text frames containing a single JSON record.
## Client Algorithm
1. Convert a dotted method name such as `math.add` to `p: ["math", "add"]`.
2. Encode arguments, replacing callables with callback marker objects.
3. Send a request record with `t: "q"`, unique `id`, `op`, `p`, and optional `a` or `v`.
4. Store a pending completion keyed by request ID.
5. In the read loop, resolve pending calls for `t: "r"` records.
6. In the read loop, dispatch `t: "cb"` records to stored callbacks.
## Server Algorithm
1. Read JSON messages from the transport.
2. Ignore records that are not `t: "q"` unless your server also stores callbacks.
3. Dispatch `op: "call"` by joining `p` into the registered method name.
4. Dispatch `op: "get"` and `op: "set"` against registered property handlers if supported.
5. Encode successful results as `{ "t": "r", "id": requestId, "v": result }`.
6. Encode failures as `{ "t": "r", "id": requestId, "e": { "n": name, "m": message } }`.
## Minimal Client Pseudocode
```python
def call(method, *args):
request_id = generate_uuid()
payload = {
"t": "q",
"id": request_id,
"op": "call",
"p": method.split("."),
"a": [encode_arg(arg) for arg in args],
}
transport.write(json.dumps(payload))
response = wait_for_response(request_id)
if "e" in response:
raise RpcError(response["e"].get("m", "RPC error"))
return response.get("v")
```
## Minimal Server Pseudocode
```python
def handle(message):
if message.get("t") != "q":
return
try:
method = ".".join(message.get("p", []))
args = [decode_arg(arg) for arg in message.get("a", [])]
result = api[method](*args)
transport.write(json.dumps({"t": "r", "id": message["id"], "v": result}))
except Exception as exc:
transport.write(json.dumps({
"t": "r",
"id": message["id"],
"e": {"n": exc.__class__.__name__, "m": str(exc)},
}))
```
## Testing Checklist
- Call JS server methods from the non-JS client.
- Call non-JS server methods from a JS client.
- Verify nested method paths.
- Verify property get and set if implemented.
- Verify callback marker encoding and `t: "cb"` dispatch.
- If implemented, verify streaming `t: "sq"`/`t: "sr"` flow control.
- If implemented, verify remote-reference `op: "ref"` apply/get/set/call/release behavior.
- Verify error responses preserve name and message.
- Verify stdio newline framing and WebSocket text framing.
## Common Pitfalls
- Do not send dotted method names in the wire message. Use path arrays in `p`.
- Do not wrap responses in custom result objects. Put successful values in `v`.
- Do not use binary WebSocket frames for the JSON interop protocol.
- Do not forget to unwrap `{ "__kkrpc_next_arg__": "value", "v": ... }` callback arguments.
- Do not rely on JS-specific transfer slots or structured clone in language interop.
- Do not assume async iterables or remote references are part of the default core protocol.
- Do not send `op: "ref"` to a default-core endpoint; only `kkrpc/remote-refs` endpoints implement those requests.More Mobile skills
animation-vocabulary
emilkowalski/skills
Reverse-lookup glossary that turns a vague description of a web animation or motion effect into its exact term ("the bouncy thing when a popover opens" → Pop in; "the iOS rubber-band scroll" → Rubber-banding). Use when the user asks "what's it called when…", or describes a motion effect without knowing its name and wants the right word to prompt an AI or designer with. For naming an effect, not designing or building one.
xcode-project-setup
firebase/agent-skills
Safely modifies Xcode projects (.pbxproj) to add Swift Packages and link files. Use this skill whenever an iOS project needs dependencies installed (e.g. Firebase, Alamofire).
cross-border-ecommerce
nexscope-ai/ecommerce-skills
Cross-border e-commerce expansion advisor. Scores target markets on 8 weighted dimensions (market size, ecommerce penetration, competition, regulatory complexity, logistics infrastructure, payment ecosystem, cultural distance, IP protection), compares 5 fulfillment models with cost and transit data, provides country-by-country tax/duty compliance guides (EU VAT/IOSS, UK VAT, US sales tax, CA GST, AU GST, JP consumption tax), maps local payment preferences by market, and builds a phased expansion roadmap. No API key required.

