anyclaude-react
Restylable React UI kit for anyclaude-sdk — hooks + components to build chatbots, AI agents, research assistants, and browser IDEs. Includes built-in serverless "survivor" stream-stitching (long runs span function time-limits transparently) and client-side tool execution (the server-side agent runs bash/file tools in the user's browser). Markdown via streamdown.
Live demo — a full IDE built with this kit, running in your browser.
npm install anyclaude-react anyclaude-sdk react
Quick start (browser / in-process)
Drive the agent in-process by wrapping the SDK's query() in a run function:
import { AgentChat } from 'anyclaude-react'
import 'anyclaude-react/styles.css'
import { query, createOpenAIClient, MemoryFileSystem, NoopCommandExecutor, composeWorkspace } from 'anyclaude-sdk'
const ws = composeWorkspace(new MemoryFileSystem(), new NoopCommandExecutor(), '/work')
const llm = createOpenAIClient({ baseUrl: '…', model: 'gpt-4o', apiKey: KEY })
export default function App() {
return (
<AgentChat
run={({ prompt, sessionId, continueRun }) =>
query({ prompt: continueRun ? '' : prompt, workspace: ws, llm, model: 'gpt-4o',
sessionId, resume: continueRun, continueRun, includePartialMessages: true })}
/>
)
}
Serverless (survivor)
Point at a function that streams NDJSON SDKMessages. When the function pauses
at its time-limit ({type:'system',subtype:'paused'}), the client auto-continues
in a new request with the same sessionId — invisibly:
<AgentChat endpoint="/api/agent" />
Your function runs query({ ..., maxDurationMs, sessionStore, sessionId, resume: continueRun, continueRun }) and writes each message as a JSON line.
Hook
const { messages, streamingText, status, tokens, cost, send, interrupt, clear } =
useAgent({ run /* | endpoint | client */, sessionId })
status:'idle' | 'running' | 'paused'send(text)starts/continues;interrupt()aborts;clear()resets (new session).
Client-side tools (server brain, browser hands)
Run the agent on your server but execute its file/shell tools in the browser — against a WebContainer, an IndexedDB filesystem, OPFS, or memory. Pair query({ clientTools: WORKSPACE_TOOL_NAMES }) server-side with a turnkey executor map here. client_tool_requests are auto-executed and the results streamed back; it reuses the real SDK tool implementations, so behavior matches server-side exactly.
import { useAgent, createWebContainerClientTools, createWorkspaceClientTools } from 'anyclaude-react'
import { DexieFileSystem } from 'anyclaude-sdk/fs'
// real shell + files in a WebContainer:
useAgent({ endpoint: '/api/agent', clientTools: createWebContainerClientTools(wc) })
// or point the file tools at the user's own IndexedDB (no shell):
useAgent({ endpoint: '/api/agent', clientTools: createWorkspaceClientTools(new DexieFileSystem('my-db')) })
// fully overridable per tool:
createWorkspaceClientTools(workspace, { only: ['write_file','read_file'], extra: { bash: myBash } })
You can still hand-write a clientTools map ({ bash: async ({command}) => ({ content }) }) for full control.
Components
Chat
| Component | Purpose |
|---|---|
<AgentChat> |
All-in-one: Transcript + Working + Composer wired to useAgent. |
<ChatPanel> |
Like AgentChat with a header (status / tokens / cost). |
<Transcript messages streamingText> |
Renders messages; pairs tool calls with results. |
<Message> / <MarkdownMessage> |
Chat bubbles; markdown via streamdown (override via render). |
<ToolCall> |
Collapsible tool call + result. |
<Composer onSend> |
Textarea + send (Enter sends, Shift+Enter newline). |
<Working active paused> |
Shimmering "Working…" indicator. |
Lightweight UI (root, no heavy deps)
| Component | Purpose |
|---|---|
<FileExplorer list onOpen> |
Collapsible file tree over any filesystem adapter. |
<AskUser question onAnswer> |
Renders an ask_user_question prompt; pair with the SDK's onAskUser. |
IDE — anyclaude-react/ide subpath (so the root barrel stays dependency-light)
import { Terminal, CodeEditor } from 'anyclaude-react/ide'
| Component | Purpose | Peer dep |
|---|---|---|
<Terminal spawn> |
xterm.js terminal bound to a streaming shell (e.g. a WebContainer process). | @xterm/xterm + @xterm/addon-fit |
<CodeEditor value onChange> |
Controlled CodeMirror 6 editor. | codemirror + @codemirror/* |
The root export (useAgent, chat components, FileExplorer, AskUser, the client/workspace helpers) pulls neither @xterm nor codemirror — install those only if you import from /ide.
Styling
Everything is class-based (.ac-*) with data-role attributes. Import the
optional anyclaude-react/styles.css and override the CSS variables on .ac-chat
(--ac-accent, --ac-bg, --ac-fg, …), or skip it and style with your own
CSS / Tailwind. No emojis — icons are inline SVG.