К основному содержанию
скилл CX Codex

rpc — скилл для Claude Code: типизированный клиент Vovk.ts

Скилл помогает генерировать и настраивать типизированные RPC-клиенты Vovk.ts. Пригодится, когда нужно вызывать API из клиентского кода или разобраться, почему клиент устарел.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add finom/vovk --skill rpc -a claude-code
Открыть на GitHub

Что делает rpc

Скилл объясняет, как vovk generate создаёт TypeScript-клиенты из схем сегментов: общий для всех сегментов или отдельный для каждого. В нём разобраны пути импорта, параметры RPC-вызова, типы тела запроса и настройка apiRoot. Клиентский метод получает имя из ключа в controllers при вызове initSegment.

Также описаны createFetcher для настройки запросов и интеграция с React Query. Важно: vovk generate читает готовые схемы из .vovk-schema/, но не обновляет их из контроллеров. Если API изменился, сначала обновите схемы через vovk dev или перезапустите npm run dev; иначе клиент может остаться устаревшим.

Какие задачи решает

  • сгенерировать типизированный клиент из схем Vovk.ts
  • выбрать общий клиент или отдельные клиенты по сегментам
  • настроить заголовки и обработку запросов через createFetcher
  • разобраться, почему клиент не видит новый метод
  • передать параметры, тело и query в RPC-вызов

Примеры запросов агенту

  • Объясни, как сгенерировать типизированный RPC-клиент Vovk.ts и импортировать его.
  • Сравни общий и сегментированный клиент и подскажи, где искать модули после генерации.
  • Почему после изменения контроллера клиент не видит новый метод? Разбери порядок обновления схем и генерации.

Как установить rpc

1Через Skills CLI (Vercel)

npx skills add finom/vovk --skill rpc -a claude-code

2Вручную: положить файлы

~/.claude/skills/rpc/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/rpc/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о rpc

Как установить rpc в Claude Code?

Выполните npx skills add finom/vovk --skill rpc -a claude-code. Файл скилла появится по пути ~/.claude/skills/rpc/SKILL.md.

Что делает скилл rpc?

Он помогает генерировать и настраивать типизированные RPC-клиенты Vovk.ts, разбирать их вызовы и подключать React Query.

Почему после vovk generate клиент может оставаться устаревшим?

Команда читает схемы из .vovk-schema/, но не пересоздаёт их по контроллерам. Обновите схемы через vovk dev или перезапустите npm run dev, затем генерируйте клиент.

Исходный текст

SKILL.md · MIT
---
name: rpc
description: Vovk.ts RPC client — how `vovk generate` turns controllers into type-safe client modules, composed vs segmented clients, call shape (`apiRoot`, `params`, `body`, `query`, `meta`, `init`, `disableClientValidation`, `validateOnClient`, `interpretAs`, `transform`, `fetcher`), customizing generation via `outputConfig.imports.fetcher` + `createFetcher` (auth headers, retries, tracing, dynamic `onSuccess` / `onError` subscribers), configuring clients in `vovk.config.mjs` (`composedClient` / `segmentedClient`), error rethrow (`HttpException`, `HttpStatus.NULL`), `VovkInput`/`VovkOutput` against RPC modules, React Query integration (`queryKey`, `streamedQuery`), RPC method surface (`.withDefaults`, `.getURL`, `.queryKey`, `.schema`, `.isRPC`). Use whenever user asks to call API from browser / mobile / other server ("fetch users from the client", "call the API from Next.js client component", "typed API client", "why is my RPC call failing", "add auth token to every request", "custom headers on RPC calls", "retry on 401", "why is the client stale"), regenerate client (`vovk generate`), choose between composed vs segmented clients, or wire up `@/client` imports. Does NOT cover writing procedures / handlers → hand off to `procedure` skill. Does NOT cover segment registration / `initSegment` → hand off to `segment` skill. Does NOT cover JSON Lines streaming clients → hand off to `jsonlines` skill.
---

# Vovk.ts RPC client

Every controller procedure with HTTP decorator automatically gets typed client counterpart. `vovk generate` produces these client modules from segment schemas, emitting TypeScript into the project:

- **Composed client** (default): one client for all segments at `composedClient.outDir` (default `./src/client`, or `./client` when the app isn't in `src/app`). Import from `'@/client'` (standard Next.js alias; alias-less projects use a relative path).
- **Segmented client**: per-segment subdirs of `segmentedClient.outDir` (same default dir). Import from `'@/client/<segment>'`.

**Key identity**: client module name = **key** used in `initSegment`'s `controllers` map, regardless of import path.

```ts
// server
initSegment({ controllers: { UserRPC: UserController } });

// client (composed)
import { UserRPC } from '@/client';
await UserRPC.getUser({ params: { id: '42' } });
```

Not `UserControllerRPC`. Not `UserController`. Whatever the key is.

## Generating client

```bash
npx vovk generate
```

What it does:

- Reads `.vovk-schema/**/*.json` for every segment (nested segments live in subdirectories, e.g. `.vovk-schema/customer/static.json`).
- Emits generated code into configured `outDir` using selected `fromTemplates` preset (default `['ts']`).
- Composed client (default): emits `index.ts`, `schema.ts`, `openapi.ts`, `openapi.json` at `outDir` root (default `./src/client`, or `./client` when the app isn't in `src/app`). Project's own tsc handles the files; import from `'@/client'`.
- Segmented client: same four files per segment under `<outDir>/<segment>/`; import from `'@/client/<segment>'`.
- Generated dir is gitignored by `vovk init` and rebuilt by the `prebuild` script (`vovk generate`); no need to commit it.

See "Client layout and import paths" below.

**`vovk generate` does NOT rebuild schemas from controller source.** Schema emission = separate step: `vovk dev` runs alongside Next.js dev server, hits each segment's `_schema_` endpoint (only available when `NODE_ENV === 'development'`), writes JSON into `.vovk-schema/`. `vovk generate` reads whatever's there.

Consequence: if backend changed and client looks stale, running `vovk generate` alone isn't enough — `.vovk-schema/` hasn't been refreshed. One shot: `PORT=<port> npx vovk dev --next-dev --exit` starts Next.js, writes `.vovk-schema/` and the client, stops, and exits with 1 on failure. While developing, `npm run dev` keeps both fresh.

When to run:

- **Automatic**: `prebuild` script installed by `vovk init` runs `vovk generate` before `next build`. During `npm run dev`, dev watcher refreshes `.vovk-schema/` on backend changes, client regenerates.
- **Explicit**: before integration tests, after checking out branch, if client method appears missing ("compiled fine, why is `UserRPC.createUser` undefined?"). If method just written is missing, schema probably stale — run `vovk dev --next-dev --exit` (or restart `npm run dev`) rather than re-running `vovk generate`.

## Call shape

Same signature across every RPC method. Core options first, advanced below:

```ts
await ModuleRPC.methodName({
  // data
  params?: { ... },                 // path params — typed
  query?: { ... },                  // query string — typed
  body?: { ... } | FormData | ...,  // narrows by contentType — see "Body by content type"
  meta?: { [key: string]: any },    // serialized as x-meta header — see meta-isolation gotcha

  // transport
  apiRoot?: string,                 // override the generation-time default
  init?: RequestInit,               // headers, credentials, signal, next.revalidate, etc. — see "init" below

  // validation
  disableClientValidation?: boolean,
  validateOnClient?: ...,           // per-call validator override

  // advanced
  interpretAs?: string,             // force response interpretation, e.g. 'application/jsonl' when server didn't set it
  transform?: (data, response) => any, // post-process the parsed response

  // plus any custom options declared via createFetcher<TOptions>({...}) — see Fetcher section
});
```

Return type = `Promise` of whatever procedure's `output` schema resolves to, or whatever `transform` returns if present. Override per call:

```ts
const user = await UserRPC.updateUser<SomeType>({ /* ... */ });
```

### Body by content type

`body`'s accepted type narrows to procedure's `contentType`: `FormData` for `multipart/form-data`, `URLSearchParams` or `FormData` for `application/x-www-form-urlencoded`, `File` / `Blob` / `ArrayBuffer` / `Uint8Array` for binary (`image/*`, `video/*`, `*/*`). Schema-typed objects always accepted. Full matrix → **`procedure`** skill.

```ts
const form = new FormData();
form.append('file', file);
await UserRPC.uploadAvatar({ body: form }); // multipart/form-data procedure
```

Never hand-set `Content-Type` — fetcher derives it (multipart boundary included). Manual headers = usual HTTP 415 trigger.

### `apiRoot`

`apiRoot` **baked in at generation time**: defaults to `/${rootEntry}` (`rootEntry` defaults to `'api'`, so default baked-in value = `/api`). When `outputConfig.origin` is set, bake produces full URL like `http://localhost:3000/api`. Per-call `apiRoot` fully replaces baked-in value for that call — config-level changes still require `vovk generate`.

In browser, relative `/api` resolves against page origin, so same call works from `/dashboard` and `/settings`. On server (Node, integration tests) relative URLs don't resolve — pass full URL per call, bake one in via `outputConfig.origin`, or use `withDefaults({ apiRoot })`.

### `init`

`RequestInit` forwarded to `fetch` — `headers`, `credentials`, `mode`, `cache`, Next.js-specific `next: { revalidate: number }` all pass through.

**`init.signal` aborts the call.** The fetcher ties it to its own per-call `AbortController` (without `AbortSignal.any`, as in React Native and Safari before 17.4, the signal aborts that controller). A pending JSON call rejects with the signal's reason as is (an `AbortError` when `abort()` gets no reason); a stream stops with an error whose `cause` is the reason. A streaming call's async iterable also exposes `.abortController` (and `abortSilently()`) to stop that one stream.

### `transform`

Receives parsed response data and original `Response`. Return anything — including tuple if you want `Response` exposed to caller:

```ts
const [user, response] = await UserRPC.updateUser({
  /* ... */
  transform: (data, response) => [data, response] as const,
});
response satisfies Response;
```

### `interpretAs`

Forces fetcher's content-type dispatch. Useful when server returns JSON Lines but omits `content-type: application/jsonl` (common behind some proxies or when streaming through Next.js): `interpretAs: 'application/jsonl'` makes client treat response as async iterable anyway.

## Composed vs segmented client

Two top-level config keys — `composedClient` and `segmentedClient` — = **independent toggles**; enable one, the other, or both. Defaults differ because they target different workflows:

| Key               | Default `enabled` | Default `fromTemplates` | Default `outDir`                           | Default import            |
|-------------------|-------------------|--------------------------|---------------------------------------------|---------------------------|
| `composedClient`  | `true`            | `['ts']`                 | `./src/client` (or `./client` without `src/app`) | `'@/client'`              |
| `segmentedClient` | `false`           | `['ts']`                 | same dir, per-segment subdirs               | `'@/client/<segment>'`    |

Both emit into the project source tree. When both are enabled they share `outDir`: composed files at the root, segments in subdirs.

```ts
// vovk.config.mjs
const config = {
  composedClient: {
    enabled: true, outDir: './src/client', fromTemplates: ['ts'],  // all defaults
    prettifyClient: true,                     // default; formats emitted files
    includeSegments: ['public'],              // mutually exclusive with excludeSegments
  },
  segmentedClient: { enabled: true, outDir: './src/client', fromTemplates: ['ts'] },
};
```

`prettifyClient: true` uses the project-installed prettier; if it's not installed, CLI warns once per run and writes unformatted output.

Both keys can carry nested `outputConfig` overriding top-level for that specific output (e.g. segmented SDKs with different OpenAPI block).

**Composed** — one client module re-exports every RPC across every segment. Default case for most projects: `import { UserRPC, PostRPC } from '@/client'`.

**Segmented** — per-segment entries; importing `@/client/admin` keeps other segments out of bundle. Useful when segment boundaries map to independent deploys, versioning, or SDK consumers.

```
src/client/
├── index.ts, schema.ts, openapi.ts, openapi.json    (composed, at the root)
├── root/     (same four files; root segment folder is named "root")
├── admin/    ...
└── customer/
    └── static/    (nested sub-segment)
```

```ts
import { UserRPC } from '@/client/customer';
import { AdminRPC } from '@/client/admin';
```

`@/client` is the standard Next.js `@/*` alias. Custom `outDir` shifts the path; projects without the alias use a relative import. Step-by-step setup → **`init` skill**.

## Fetcher

Fetcher = client's core primitive — function (`VovkFetcher<TFetcherOptions>`) that takes request metadata (endpoint, method, schema, validator) and dispatches actual `fetch`. Default (`import { fetcher } from 'vovk/fetcher'`) already handles JSON and JSON Lines, runs client-side validation, injects `x-meta` header, rethrows `HttpException` on errors.

Response-shape dispatch by content type:

- `application/json` → parsed JSON (typed as procedure's output schema).
- `application/jsonl` / `application/jsonlines` / `application/x-ndjson` → disposable async iterable (see `jsonlines` skill).
- Other content types → raw `Response` object — caller reads text, binary, or streams it.

You **extend** default rather than rewriting via `createFetcher`:

```ts
// src/lib/fetcher.ts
import { createFetcher } from 'vovk/fetcher';

export const fetcher = createFetcher<{
  // Custom per-call options — become typed fields on every RPC method call site.
  useAuth?: boolean;
  successMessage?: string;
}>({
  prepareRequestInit: async (init, { useAuth }) => ({
    ...init,
    headers: {
      ...init.headers,
      ...(useAuth ? { Authorization: `Bearer ${await getToken()}` } : {}),
    },
  }),
  transformResponse: (data, options, info) => data,     // optional
  onSuccess: (data, { successMessage }) => {
    if (successMessage) console.log(successMessage);
  },
  onError: (error, options) => { /* Sentry, retry hooks */ },
});
```

With that fetcher installed, callers get custom options inline:

```ts
await UserRPC.updateUser({
  params: { id: '42' },
  body: { /* ... */ },
  useAuth: true,
  successMessage: 'Updated!',
});
```

### Hooks

All optional; `options` = typed `TOptions` you declared.

- `prepareRequestInit(init, options) => RequestInit | Promise<RequestInit>` — mutate `RequestInit` before `fetch` (headers, credentials, mode, cache, `next.revalidate`). Async OK — fetcher awaits return.
- `transformResponse(data, options, info)` — transform parsed response; `info = { response, init, schema }` gives access to raw `Response`, final `RequestInit`, procedure's schema (same object as `UserRPC.updateUser.schema`; useful for reading `operationObject`).
- `onSuccess(data, options)` — observe successful responses (toasts, analytics).
- `onError(error: HttpException, options)` — observe failures. Both network errors and HTTP-status errors land here; `error.statusCode === 0` (`HttpStatus.NULL`) = either transport failure or client-side validation rejection.

### Event-style subscribers (dynamic)

`onSuccess` and `onError` can also be attached **after** fetcher is created. Useful when callback depends on state not available at creation time (React context value, Zustand store reference, lazily loaded logger). Each registration returns unsubscribe function; multiple subscribers run in order on every call:

```ts
// Somewhere in an app entry point (or a React effect, etc.)
import { fetcher } from '@/lib/fetcher';

const unsubSuccess = fetcher.onSuccess((data, { successMessage }) => {
  if (successMessage) toast.success(successMessage);
});

const unsubError = fetcher.onError((error) => {
  sentryReport(error);
});

// Later
unsubSuccess();
unsubError();
```

Prefer this pattern over baking toasts / store writes into `createFetcher` when dependency graph would otherwise force you to import UI-layer modules from transport layer.

### Point config at fetcher

```ts
// vovk.config.mjs
/** @type {import('vovk').VovkConfig} */
const config = {
  outputConfig: {
    imports: {
      fetcher: './src/lib/fetcher',  // must export `fetcher` (named export)
    },
  },
};
export default config;
```

Generated client imports `fetcher` from that path. After editing config manually, run `vovk generate`.

**Per-segment fetcher**: different segments can use different fetchers (e.g., admin segment needs different auth than public one):

```ts
outputConfig: {
  imports: { fetcher: './src/lib/fetcher' },    // applied to all segments by default
  segments: {
    admin: {
      imports: { fetcher: './src/lib/adminFetcher' },  // overrides for admin
    },
  },
}
```

**Common patterns:**

- **Auth token**: inject `Authorization` header in `prepareRequestInit`, gated on `useAuth` custom option.
- **Retry on 401**: in `onError`, trigger token refresh; wrap call sites in retry helper.
- **Telemetry**: start timer in `prepareRequestInit`, report in `onSuccess` / `onError`.
- **Success toasts**: `successMessage` custom option + dynamic `fetcher.onSuccess(...)` subscriber that reads your toast library.

Keep fetcher focused on transport-layer concerns. Stateful things (request dedup, mutation queuing) belong in layer above.

## Client-side validation

Install `vovk-ajv`, set `outputConfig.imports.validateOnClient: 'vovk-ajv'`. Generated client validates `params` / `body` / `query` against procedure's schema **before** HTTP call — invalid inputs throw `HttpException(HttpStatus.NULL, ...)` locally (i.e. `statusCode === 0`, same as transport failures) instead of round-tripping.

Roll your own validator via `createValidateOnClient` from `vovk/create-validate-on-client` if Ajv isn't fit; point `imports.validateOnClient` at its module path:

```ts
// src/lib/validateOnClient.ts
import { createValidateOnClient, HttpException, HttpStatus } from 'vovk/create-validate-on-client';

export const validateOnClient = createValidateOnClient({
  validate: async (input, schema, meta) => {
    // run your validator; on failure:
    // throw new HttpException(HttpStatus.NULL, 'Validation failed', { /* optional cause */ });
    return input;
  },
});
```

Skip per call:

```ts
await UserRPC.updateUser({
  params: { id: 'malformed' },
  disableClientValidation: true,
});
```

`disableClientValidation` also useful when debugging — bypass local pass to surface server-side validation error verbatim. Override with different validator per call via `validateOnClient`. Neither should be habit in production code paths.

## Error handling

`HttpException` thrown on server rethrown on client with same `statusCode`, `message`, `cause`:

```ts
import { HttpException } from 'vovk';

try {
  await UserRPC.getUser({ params: { id: '42' } });
} catch (e) {
  if (e instanceof HttpException) {
    console.log(e.statusCode); // 404
    console.log(e.message);    // 'User not found'
    console.log(e.cause);      // any extra context passed server-side
  }
}
```

Bare `Error` on server → `HttpException` with status 500 on client. Network failures (no server, DNS error) and client-side validation failures both throw `HttpException` with status 0 (`HttpStatus.NULL`) — same `instanceof HttpException` check covers transport, validation, HTTP-status failures uniformly. Disambiguate by `e.statusCode`.

## Types against RPC modules

`VovkBody`, `VovkQuery`, `VovkParams`, `VovkInput`, `VovkOutput`, `VovkIteration`, `VovkYieldType`, `VovkReturnType` (from `vovk`) work on RPC methods as on controller methods: `type Out = VovkOutput<typeof UserRPC.updateUser>`. Details → **`procedure`** skill, Type inference.

## RPC method surface

Every generated RPC method = more than just callable. Useful properties:

- `.withDefaults(options)` — returns new RPC module with given options **deeply merged** into every call. Handy for per-environment `apiRoot`, persistent `init.headers`, scoped fetcher.
- `.getURL({ params, query, apiRoot })` — compute URL call would hit, without making request. Useful for `<a href>`, `<form action>`, or calling `fetch` directly.
- `.queryKey(key?)` — returns globally unique React Query / TanStack Query cache key. Shape: `[segmentName, controllerPrefix, rpcModuleName, decoratorPath, httpMethod, ...key]`. Optional `key` = array of **extra scalars** to disambiguate similar queries (typically same values passed in `params` / `query`).
- `.apiRoot` — baked-in `apiRoot` string.
- `.schema`, `.controllerSchema`, `.segmentSchema`, `.fullSchema` (`VovkSchema`) — raw schema objects; name a type as `typeof UserRPC.getUser.segmentSchema`. `schema.validation.body` etc. give per-input JSON Schema; `schema.operationObject` gives OpenAPI operation fragment; `fullSchema.meta.config` exposes config subset emitted into client (by default only `libs` and `rootEntry`, e.g. `fullSchema.meta.config.libs.ajv`).
- `.isRPC: true` — type guard (distinguishes RPC modules from raw controllers in tools like `deriveTools`).

```ts
const API = UserRPC.withDefaults({
  apiRoot: 'https://api.example.com/v1',
  init: { headers: { 'x-hello': 'world' } },
});
await API.getUser({ params: { id: '42' } });

const url = UserRPC.getUser.getURL({ params: { id: '42' } });
// => computed URL with params/query baked in
```

### React Query / TanStack Query

```ts
import { useQuery } from '@tanstack/react-query';

// Extra key values disambiguate per-id queries:
useQuery({
  queryKey: UserRPC.getUser.queryKey(['42']),
  queryFn: () => UserRPC.getUser({ params: { id: '42' } }),
});

// Invalidate every query for this RPC module:
queryClient.invalidateQueries({
  queryKey: UserRPC.getUser.queryKey().slice(0, 3),
});
```

JSON Lines streams pair with TanStack's `experimental_streamedQuery` → see `jsonlines` skill.

Mutations reference method directly:

```ts
import { useMutation } from '@tanstack/react-query';

useMutation({ mutationFn: UserRPC.updateUser });
```

## `openapi` and `schema` payloads from client

Composed:

```ts
import { openapi } from '@/client/openapi';   // OpenAPI 3.x, derived from procedures + @operation metadata
import { schema }  from '@/client/schema';    // Raw VovkSchema — all segments
import { schema }  from '@/client';           // Same thing, re-exported from the root
```

Segmented (one OpenAPI + schema per segment, inside each segment's subdir):

```ts
import { openapi } from '@/client/admin/openapi';
import { schema }  from '@/client/admin/schema';
import { schema }  from '@/client/admin';          // Same thing, re-exported from the segment root
```

Import path follows the client's `outDir` — if you changed `segmentedClient.outDir` to something else (e.g. `./sdk`), path = `@/sdk/admin/openapi` etc. Per-segment files exist only when segmented client is enabled.

See `openapi` skill for how spec is built.

## Flows

**"Fetch users on page load (client component)"** — ensure procedure has HTTP decorator, then:
```tsx
'use client';
import { UserRPC } from '@/client';
useEffect(() => { UserRPC.list().then(setUsers); }, []);
```

**"Add auth header to every RPC call"** — `createFetcher({ prepareRequestInit })`, point `outputConfig.imports.fetcher` at it. Don't hand-roll per-call.

**"My new procedure isn't on client"** — `PORT=<port> npx vovk dev --next-dev --exit` (or restart `npm run dev`) to re-emit `.vovk-schema/`. Still missing → check controller is registered in `initSegment({ controllers })` and method has HTTP decorator.

**"Call API from another Node process"** — pass full URL: `UserRPC.list({ apiRoot: 'https://api.example.com/api' })`, or bake via `UserRPC.withDefaults({ apiRoot })`.

**"Consume JSON Lines stream"** — `using stream = await StreamRPC.xxx(...); for await (const chunk of stream) { /* ... */ }`. Full coverage → **`jsonlines` skill**.

## Gotchas

- **Import name mismatch**: `UserRPC` (the `controllers` key), not `UserControllerRPC`. Most common "I can't import my RPC module" cause.
- **Stale client**: `vovk generate` regenerates from `.vovk-schema/`, only refreshed by running dev server. If user edited controller and ran `vovk generate` directly, output stale. Fix: `vovk dev --next-dev --exit` (above).
- **No HTTP decorator = no RPC**. Procedure without `@get`/`@post`/etc. is call-via-`.fn()` only; won't appear on client.
- **Baked-in `apiRoot` defaults to `/api`** (`rootEntry: 'api'` with no `origin`). Works in browser (resolves against page origin), fails outside (Node, integration tests). Pass full URL per call, bake one in via `outputConfig.origin`, or use `withDefaults({ apiRoot })`.
- **Fetcher path changes need regeneration**. Editing fetcher file fine; changing its path in `outputConfig.imports.fetcher` requires `vovk generate` (or dev-watcher restart).
- **`disableClientValidation` only skips *client* validation pass**. Server-side validation still runs (unless procedure disables it, which should be rare).
- **Client `meta` ≠ server `req.vovk.meta()`**. `meta` option serialized as `x-meta` header and lands on server under `xMetaHeader` key — isolated from server-set trusted state (what `authGuard` writes via `req.vovk.meta<AuthMeta>({ user })` is untouched by client). Treat client `meta` as advisory only; never use for auth or authorization decisions.

© finom · MIT · finom/vovk

Похожие скиллы

Все скиллы по теме «Бэкенд и API» →
mcp-builder официальный anthropics Скилл проводит через создание MCP-сервера на TypeScript или Python: от изучения протокола до тестов и оценки качества. 130 949установок claude-api официальный anthropics Справочник по Anthropic SDK и API Claude для генерации кода без устаревших параметров и выдуманных методов. 74 198установок lark-im larksuite Скилл подключает Lark IM к агенту: он отправляет сообщения, ищет историю, управляет чатами и файлами. Подойдёт для задач вокруг командных коммуникаций. CX Codex +1 472 900установок lark-event larksuite Слушает события Lark/Feishu и отдаёт их потоком NDJSON. Подходит для ботов, обработчиков сообщений и долгих подписчиков. CX Codex +1 466 800установок caveman-discover JuliusBrussee Находит точки вызова LLM в репозитории и размечает их воркфлоу для Caveman Cloud, чтобы расходы на токены не сливались в одну общую кучу. CX Codex +1 104 400установок migration JuliusBrussee Скилл задаёт правила безопасных миграций схем, данных и API с обязательным откатом. Пригодится при изменениях, где нельзя терять данные или ломать совместимость. CX Codex +1 103 900установок

Из того же набора10

tools Скилл помогает превращать процедуры Vovk.ts и отдельные функции в инструменты для языковых моделей. Пригодится, когда нужно подключить вызовы инструментов или собрать MCP-сервер. CX Codex +1 ★ 57звёзд репо segment Делит бэкенд на сегменты Vovk.ts: отдельные префиксы API, свои настройки runtime и статические эндпоинты. Пригодится, когда бэкенд разрастается. CX Codex +1 ★ 57звёзд репо python Скилл генерирует типизированный Python-пакет из схем Vovk.ts: RPC-функции, TypedDict, стриминг через JSON Lines. Нужен, когда API уже есть, а Python-клиент писать руками не хочется. CX Codex +1 ★ 57звёзд репо openapi Скилл объясняет, как Vovk.ts собирает спецификацию OpenAPI из процедур и схем валидации. Пригодится, чтобы описать API и показать его документацию через Scalar. CX Codex +1 ★ 57звёзд репо multitenant Скилл для Vovk.ts: разводит несколько тенантов по поддоменам в одном Next.js-приложении — прокси, сегменты, страницы. CX Codex +1 ★ 57звёзд репо jsonlines Скилл помогает настроить потоковую передачу JSON Lines в Vovk.ts: сервер отправляет данные по мере готовности, а клиент читает их как асинхронный поток. CX Codex +1 ★ 57звёзд репо init Разворачивает бэкенд в Next.js через Vovk.ts: проверяет версии, запускает vovk-cli и доводит проект до рабочего состояния. CX Codex +1 ★ 57звёзд репо config Скилл объясняет настройки Vovk.ts и tsconfig.json. Пригодится, когда нужно изменить путь генерации, параметры клиента или настройки TypeScript. CX Codex +1 ★ 57звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой