@nothumanwork/grok-build-sdk
v0.1.0
Published
High-quality, multi-environment TypeScript client SDK for Grok Build via the Agent Client Protocol (ACP). Supports stdio, WebSocket (local/remote), browser, Cloudflare Workers, Node/Bun, with full x.ai/* extension typing and streaming ergonomics.
Maintainers
Readme
@nothumanwork/grok-build-sdk
A high-quality, multi-environment TypeScript client SDK for Grok Build via the Agent Client Protocol (ACP). Targets Node, Bun, browsers, React Native / Expo, and Cloudflare Workers from a single package.
Installation
bun add @nothumanwork/grok-build-sdk
# or
npm install @nothumanwork/grok-build-sdkQuick Start — WebSocket against grok agent serve
- Start Grok in server mode:
grok agent serve --bind 127.0.0.1:2419 --secret my-secret- Drive the agent from your code:
import { createGrokClient } from "@nothumanwork/grok-build-sdk";
const client = await createGrokClient({
transport: "ws",
ws: { endpoint: "127.0.0.1:2419", serverKey: "my-secret" },
yolo: true,
// Optional when multiple UI clients share one agent process.
targetClientId: "web-chat",
});
const session = await client.newSession();
for await (const update of session.promptStream("List the top-level dirs.")) {
if (update.type === "thought_finalized") console.log("🧠", update.text);
if (update.type === "message_chunk") process.stdout.write(update.text);
if (update.type === "tool_call") console.log("🔧", update.title, update.status);
if (update.type === "stop_reason") console.log("[done]", update.reason);
}
await client.close();The SDK builds the canonical ws://host:port/ws?server-key=... URL for you when given { endpoint, serverKey }. You can also pass a full url, or rely on the GROK_SERVE_URL and GROK_AGENT_SECRET environment variables.
promptStream() also accepts ACP structured content blocks when you need to
send linked or embedded context:
await session.promptStream([
{ type: "text", text: "Use this context while answering." },
{
type: "resource_link",
uri: "file:///repo/src/index.ts",
name: "src/index.ts",
mimeType: "text/typescript",
},
]);Stdio
import { createGrokClient } from "@nothumanwork/grok-build-sdk";
const client = await createGrokClient({
transport: "stdio",
yolo: true,
stdio: {
model: "grok-build",
reasoningEffort: "high",
leader: true,
},
});The high-level client lazy-loads the stdio transport only when
transport: "stdio" is selected. The @nothumanwork/grok-build-sdk/stdio subpath exports the
raw StdioTransport for advanced integrations, and it is the only public path
that touches node:child_process.
stdio accepts typed Grok startup options for sandbox, allow, deny,
tools, disallowedTools, disableWebSearch, noPlan, noSubagents,
noMemory, experimentalMemory, permissionMode, systemPromptOverride,
model, reasoningEffort, reauth, agentProfile, leader, yolo, and
alwaysApprove; the SDK places top-level Grok flags before agent and
agent-level flags before stdio. Raw args remain available for future CLI
flags.
Grok exposes auth methods during ACP initialization when local credentials need
attention. The SDK keeps those on client.authMethods, and forwards ACP
authentication through client.authenticate(methodId):
for (const method of client.authMethods) {
console.log(method.id, method.name);
}
await client.authenticate("cached_token");Headless Scripting
For CI and scripting flows that should run grok -p and exit, import the
Node/Bun-only helpers from the stdio subpath:
import { runGrokHeadless, streamGrokHeadless } from "@nothumanwork/grok-build-sdk/stdio";
const result = await runGrokHeadless({
prompt: "Review staged changes for obvious bugs.",
outputFormat: "json",
yolo: true,
tools: ["read_file", "grep"],
disallowedTools: ["run_terminal_cmd"],
maxTurns: 3,
});
for await (const event of streamGrokHeadless({
prompt: "Summarize this repository.",
yolo: true,
})) {
console.log(event);
}Features
- Streaming-aware
GrokSession—promptStream()accepts plain text or ACPContentBlock[], thought chunks are accumulated and finalised as one block, and the iterator ends on the real ACPStopReason(end_turn,max_tokens,max_turn_requests,refusal,cancelled). - Permission round-trip —
yolo: trueauto-approves;onPermissionRequest(req)lets you decide; without either the SDK answerscancelledso the agent never hangs. - Headless scripting helpers —
runGrokHeadless()andstreamGrokHeadless()in@nothumanwork/grok-build-sdk/stdiowrap documentedgrok -pJSON and streaming-JSON automation flows. - ACP authentication — advertised
authMethodsare exposed after connect, andclient.authenticate(methodId)forwards to the official ACPauthenticaterequest. - ACP provider controls —
client.listProviders(),client.setProvider(...),client.disableProvider(...), andclient.logout()forward the official experimental provider and logout requests. - ACP editor and NES controls —
client.startNes(),client.suggestNes(...),client.acceptNes(...), andclient.didOpenDocument(...)expose the official experimental next-edit and document lifecycle surface. - Extension escape hatch —
client.callExtension("x.ai/...", params)round-trips through the official ACPextMethod. SettargetClientIdonce to attach Grok's_meta.targetClientIdrouting hint to outgoing x.ai calls in shared-agent setups. Agent-issued notifications surface asext_notificationupdates, while documented search, worktree, filesystem, session, hook, and memory events are also normalized into typed stream updates. - Ready-to-use x.ai helpers — call
client.xai.fs.readFile(...),client.xai.git.status(...),client.xai.worktree.createIsolatedSubagent(...),client.xai.session.rename(...),client.xai.plan.toggle(...),client.xai.rewind.points(...),client.xai.background.killTask(...),client.xai.mcp.list(...),client.xai.plugins.action(...),client.xai.marketplace.list(...), orclient.xai.experimental.*directly; the underlyingXaiFs,XaiGit,XaiWorktree,XaiTerminal,XaiSession,XaiConversation,XaiAuth,XaiSearch,XaiCode,XaiPlan,XaiRewind,XaiBackground,XaiMcp,XaiHooks,XaiPlugins,XaiMarketplace, andXaiSkillsclasses remain exported for explicit composition. - Worktree-isolated subagent sessions —
XaiWorktree.createIsolatedSubagent()creates a git worktree, forks the parent session, and returns aGrokSessionscoped to the isolated checkout. - Real filesystem bridge —
readTextFile/writeTextFileare wired tonode:fs/promiseson Node/Bun; gated out ofclientCapabilitieseverywhere else (or you can supply your own bridge). - Terminal bridge gating — ACP
terminalsupport is advertised only when you provide a completeterminalbridge forcreate,output,wait_for_exit,kill, andrelease. - Session lifecycle and controls —
client.newSession(),client.loadSession({ sessionId, cwd }),client.resumeSession({ sessionId, cwd }),client.listSessions(filters),session.cancel(),session.close(),session.setMode(modeId),session.setModel(modelId),session.setConfigOption(option), plusclient.signal/client.closedfor production cancellation. - Reconnect before next turn — after a transport close, the next session operation reconnects and sends
session/resumefor the known session ID before continuing. In-flight prompts are not replayed automatically, avoiding duplicate tool execution.
Examples
examples/serve-ws.ts— recommended WebSocket demo, works against a realgrok agent serve.examples/browser-chat/— Vite browser chat UI using the package browser condition.examples/node-cli/— high-level stdio CLIs plus one raw wire reference.examples/cloudflare-worker/— WorkerPOST /promptserver-sent events proxy to a remote or localgrok agent serve.examples/react-native/— hook and screen using the high-level browser-safe API.examples/expo-grok-demo/— Expo / React Native demo driven through the WebSocket relay.
Development
bun install
mise run setup
mise run check # lint + typecheck + x.ai catalog audit + tests
bun run build
mise run verify:workerRecorded ACP traces can be captured from a live grok agent stdio process and
replayed in CI through tests/harness/replay-trace.ts:
bun run record:acp -- --out tests/fixtures/live-basic-session.jsonl \
--prompt "Reply with OK only."
bun test tests/unit/replay-trace.test.tsLicense
Apache-2.0
