# Openbot Data Access

Governs how the OpenBot browser app reads and writes server data, every request goes...

- Repository: https://github.com/CopilotKit/OpenBot (9467 stars)
- Category: Design
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add CopilotKit/OpenBot --skill openbot-data-access -g -a claude-code -y`
Codex: `npx skills add CopilotKit/OpenBot --skill openbot-data-access -g -a codex -y`
Cursor: `npx skills add CopilotKit/OpenBot --skill openbot-data-access -g -a cursor -y`
Gemini CLI: `npx skills add CopilotKit/OpenBot --skill openbot-data-access -g -a gemini-cli -y`

## Description

Governs how the OpenBot browser app reads and writes server data, every request goes through `client` in app/src/lib/client.ts, every read is a queryOptions factory in app/src/lib/<entity>/queries.ts, every write is a mutationOptions factory in app/src/lib/<entity>/mutations.ts, and components consume them through useQuery/useMutation. Use when adding or changing a screen that loads server data, calling a /api/... endpoint from the browser, adding a query key, writing a create/update/delete flow, deciding where a fetch belongs, or reviewing a diff that contains the word fetch under app/src. Don't use for server-side route handlers under server/ (that is not browser code), for form validation schemas (those live in lib/<entity>/form.ts), for page layout and Item rows, or for the AG-UI stream itself, which the runtime carries rather than the client.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# OpenBot Data Access

## When To Use

This skill applies to any change under `app/src` that moves data between the browser and the API
server. It fires on new screens, new endpoints, new query keys, and on any diff that introduces
`fetch` anywhere but `app/src/lib/client.ts`.

It does not cover server handlers under `server/`, zod form schemas (`lib/<entity>/form.ts`), or page
layout. It does cover `lib/copilot/`: the conversation itself streams over AG-UI, but the tool calls a
Bot makes during a turn are ordinary authenticated requests and go through the client like everything
else.

## The Shape

Every entity the browser knows about owns a directory under `app/src/lib/`:

```
app/src/lib/
  client.ts      # the only fetch in the app
  <entity>/
    queries.ts   # read types, key factory, queryOptions factories
    mutations.ts # input type, mutationOptions factories
    form.ts      # zod schema (a different skill's territory)
```

`client.ts` owns the transport: credentials, the JSON content type, body serialisation, and turning a
failed status into an `Error` carrying the server's own message. It owns nothing about meaning, the
envelope key and the sentence a person reads stay at the call site, because those are facts about one
endpoint rather than about requests in general.

```ts
client<T>(path, key, options?): Promise<T>    // parsed, and `key` unwrapped
client(path, options?): Promise<Response>     // for a caller that only needed it to work
tryClient(path, options?): Promise<Response>  // never throws; the status is the answer
```

`options` is `{ method?, body?, fallback?, signal? }`. `body` is serialised by the client, which is
also what sets the content type, so a caller passes an object, never a string. Passing
`JSON.stringify(x)` sends a JSON string of a JSON string, which no endpoint accepts.

### Three kinds of request

Not everything crossing the wire is cached state, and the shape follows from which kind it is.

The rest: https://github.com/CopilotKit/OpenBot/blob/HEAD/.claude/skills/openbot-data-access/SKILL.md
