docs
TypeScript SDKReference

Hooks

API reference for @urun-sh/react hooks

API reference for the hooks exported from @urun-sh/react. Every hook is a thin, render-safe view over the core Session primitives (streams / docs / phase) — the session owns the state; hooks project it into React.

Public API at a glance

NameDescription
useApp()The deployed app proxy configured by UrunProvider
useUrunAuth()The current auth context (mode + token resolver)
useRequest(session, options?)Single request/response over session.request (mutation-style)
useCompletion(session, options?)Streamed text completion over session.requestStream
useChat(session, options?)Multi-turn chat with streaming assistant messages
useInputPresence(session, options?)Continuous keyboard/mouse input over awareness presence
useSessionDoc(session, key, selector?)Reactive view of a named session doc
useDocStore(session, key)Zustand-style store bound to a session doc (selector-granular)
useStreamMessages(session, name, options?)Bounded tail of a named stream's data lane
useSessionTrack(session, name)Latest inbound MediaStreamTrack for a named stream
useUrunAudioLevel(source, options?)Audio level metering for a track/stream
useSessionPhase(session)The current SessionPhase, reactively
useSessionWake(session)Live "waking (Ns)" view of the pre-live wait
useSessionEndsAt(session)The session deadline (Date | null)
useSessionIdle(session)The server-raised inactivity warning, or null
useActivation(session, streamName?)First-media activation progress for a named stream
useUrunPrewake(options)Advisory scale-to-zero warm-up ping while a page is mounted

For patterns and narrative, see React Providers and Session lifecycle.


useApp()

function useApp(): ReactApp

Returns the deployed app proxy. Each property is a deployed Python function; calling it returns a render-safe Session. Must be used inside a UrunProvider.

import { useApp, useSessionTrack } from '@urun-sh/react'

function Player() {
  const app = useApp()
  const session = app.generate({ prompt: 'a sunset' })   // render-safe
  const track = useSessionTrack(session, 'video')

  useEffect(() => {
    if (track && ref.current) ref.current.srcObject = new MediaStream([track])
  }, [track])

  return <video ref={ref} autoPlay muted />
}

useApp() memoizes by function name + args: the same app.generate(args) during re-renders reuses one session. session.stream(name) and session.doc(name) return stable, render-safe handles. The session surface matches the App reference.


useUrunAuth()

function useUrunAuth(): UrunAuthContextValue

Returns the auth context established by the active auth bridge (UrunWorkOSProvider, UrunAuthProvider, or UrunJwtProvider). Use it to read the current auth mode or trigger a token refresh; most apps never call it directly because UrunProvider consumes it for you.


useRequest()

function useRequest<TRes, TReq>(session, options?: UseRequestOptions): UseRequestResult<TRes, TReq>

Single request/response calls over session.request, shaped like react-query's useMutation: { mutate, mutateAsync, data, error, isPending, reset }. Each call gets its own AbortController; a newer call or unmount aborts the older one so stale responses never clobber fresh state. Options: timeout, onSuccess, onError.


useCompletion()

function useCompletion(session, options?: UseCompletionOptions): UseCompletionResult

Stream a single text completion over session.requestStream, accumulating deltas into completion. Returns { completion, isStreaming, error, complete, stop }; stop() cancels, unmount cancels and suppresses late writes.


useChat()

function useChat(session, options?: UseChatOptions): UseChatResult

Multi-turn chat over session.requestStream: appends a user message plus a streaming assistant placeholder, accumulates deltas into it, and sends full conversation history to the runtime. Returns { messages, input, setInput, sendMessage, isStreaming, error, stop }; seed history with options.initialMessages.


useInputPresence()

function useInputPresence(session, options?: UseInputPresenceOptions): InputPresenceControls

Captures keyboard/mouse behind pointer lock (or touch engagement) and publishes it as ephemeral awareness presence on the session — the platform contract for continuous input (default field "input", default 30 Hz). Returns { engage, engageTouch, release, engaged, heldKeys, pressKey, releaseKey, movePointer }. On disconnect the peer's presence state clears automatically.


useSessionDoc()

function useSessionDoc<T>(session, key): { snapshot: T | null; synced: boolean; set(patch): void }
function useSessionDoc<T, U>(session, key, selector: (state: DocState<T>) => U): U

Reactive view of a named session document, backed by the doc store — the doc (vanilla Yjs) owns state and sync. Without a selector it returns { snapshot, synced, set } and re-renders on every doc change; with a selector it re-renders only when the selected slice changes.

useDocStore()

function useDocStore<T>(session, key): DocStore<T>

The underlying Zustand-style binding for a session doc: a read-projection + write-through with selector-granular re-renders. Prefer it over useSessionDoc when you select repeatedly off one doc.


useStreamMessages()

function useStreamMessages(session, name, options?: { cap?: number }): StreamMessageEntry[]

A bounded, time-ordered tail of a named stream's data lane. Consuming subscribes this peer to the stream (session.stream(name).messages() opt-in semantics); each entry is { at, payload }, oldest dropped past cap. Cancels cleanly on unmount or name change.


useSessionTrack()

function useSessionTrack(session, name): MediaStreamTrack | null

Latest inbound MediaStreamTrack for a named session stream, or null until the runtime produces it. Thin over session.stream(name).track + .on('track'); needs no provider.


useUrunAudioLevel()

function useUrunAudioLevel(source: MediaStream | MediaStreamTrack | null, options?): UrunAudioLevel

Samples an audio source's level through the SDK's shared AudioContext (analysis only — never routes it to the speakers). Options: fftSize (512), intervalMs (100), speakingThreshold (0.02). Returns silence for a null source and during SSR.


Session-state hooks

The building blocks behind Session lifecycle — each pairs with a drop-in component:

function useSessionPhase(session): SessionPhase | null   // pairs with UrunSessionStatus / UrunSessionGate
function useSessionWake(session): SessionWake            // pairs with UrunSessionWaking
function useSessionEndsAt(session): Date | null          // pairs with UrunSessionClock / UrunSessionEnded
function useSessionIdle(session): SessionIdleState | null // pairs with UrunIdleWarning
  • useSessionPhase — the current phase snapshot, reactively (9 phases; see Types).
  • useSessionWake{ waking, phase, state?, reason?, since?, seconds }: a live elapsed-seconds view of the pre-live wait (queued/unavailable/provisioning), counted from phase.wakingSince as one continuous clock.
  • useSessionEndsAt — the session's declared deadline, or null when the app declared no maximum length.
  • useSessionIdle — the server-raised inactivity warning ({ warning, deadlineEpochS, idleSinceEpochS }) read from the control doc, or null in the steady state. Confirm presence with session.touch().
  • useActivation — the live-but-no-media-yet half of the honest lifecycle: follows the core activation watchdog's per-stream progression (activating → still-activating → cold-boot → degraded → first-media) as ActivationProgress; pairs with UrunActivationOverlay, which renders it over the video until the element's first decoded frame clears it.

useUrunPrewake()

function useUrunPrewake(options: { app?: string; function: string; intervalS?: number }): PrewakeResult | null

The scale-to-zero intent signal: while a page that will start a session is mounted, pings the advisory POST /api/sessions/prewake on mount and every intervalS (default 60), so capacity is already warming by the time the user clicks start. Advisory by contract — never throws, never affects a session flow; returns the latest PrewakeResult (or null) for an honest "warming your GPU…" affordance. app defaults to the surrounding UrunProvider's appId.


Component-registry hooks

The built-in components also export headless hooks — useProgressCard, useStatusBadge, useTextStream, useImageFrame, useMetricsPanel — see Component Registry.

On this page