Client package surface
@forge/react is the headless client: state, reducers and hooks, with no product styling and no
transport assumptions. The host supplies the transport by implementing one interface.
Moved here from the package README, which is a front door rather than a reference.
Modules
| Module | Contains |
|---|---|
types | Re-exports the wire contract from @forge/agentkit, plus client-only view state. Type-only, erased at build time. |
event-buffer | Implemented. Orders and de-duplicates run events across a reconnect. |
hooks | Implemented — all ten: useForgeClient, useConversations, useConversation, useRunSubscription, usePendingInteraction, useSendMessage, useAnswerQuestion, useDecideApproval, useCancelRun, useSessionContext. |
client | The transport port the hooks take. An interface, so the host supplies fetch, SSE or WebSocket and this package assumes none of them. |
reducers | Run events folded into renderable parts. Pure functions, so the ordering guarantees are testable without a DOM. |
context-inspector | What the window holds and what is left of it — the view behind the composer's context meter. |
localization | Locale and timezone resolution for rendered output. |
usage-panel | The spend panel's shaping, separate from its rendering. |
citations | Citation view-model and resolution, React-free, so the same rules serve a DOM renderer and a native one. |
ui/citations | Implemented. Citation markers and expandable source panels: append-only ordering so a mid-stream citation never moves what is on screen, a grounded/ungrounded treatment that uses no colour, and a shipped hue-free stylesheet. |
ui/usage | Implemented. The spend panel: rollup-backed periods with breakdowns, a quota bar whose state comes from the server's own guard, an explanatory empty state rather than a zeroed chart, and a mobile-first hue-free stylesheet. |
event-buffer came first because it backs a specification acceptance criterion —
"subscription reconnect produces no missing or duplicated rendered parts" — and that
behaviour is testable before any transport exists.
The split between shaping and rendering is deliberate throughout: citations,
usage-panel and context-inspector are React-free, so the rules that decide what a
citation marker means or when a quota bar turns amber are held in one place and tested
without a DOM. ui/ renders them.
Why the backend dependency is type-only
Every import from @forge/agentkit is an import type, so nothing survives
compilation. The client owns no copy of the wire contract, and the two halves cannot
drift. TypeScript project references build the backend's declarations first.
Scripts
npm test -w @forge/react
npm run build -w @forge/react # builds @forge/agentkit first
Not yet here
The optional UI component package from specification 06 — chat shell, part renderers, question and approval cards, artifact panel. It depends on this package, never the reverse, and is deliberately not a mobile dependency.
What "headless" costs and buys
The package assumes no fetch, no SSE and no WebSocket — ForgeClient is an interface the host implements.
That is why the same hooks drive a DOM renderer and a native one, and why the reducers are pure functions whose
event-ordering guarantees are testable without a browser.