Skip to main content

Introduction

What is Keq?​

Keq is a TypeScript HTTP client designed for the AI programming era. Built on the Fetch API, it combines Koa's middleware architecture with SuperAgent's chainable API experience.

Unlike traditional HTTP clients, Keq turns OpenAPI documents into structured knowledge that AI can search directly, and has request code generated by tooling instead of written by hand — so your AI assistant can locate endpoints precisely and get types that match the API definition.

Built for AI Programming​

Tell the AI what you want, and the code writes itself​

When your AI programming assistant integrates with Keq, the development experience becomes:

👤 Developer: Build me a cat adoption page showing adoptable cats with breed filtering

🤖 AI Assistant:
   → Searching APIs: "cats", "breeds"
   → Found: GET /cats (catService#getCats)
   → Found: GET /breeds (catService#getBreeds)
   → Generating request code and building the page...
import { getCats, getBreeds } from "./apis/cat_service"

export function AdoptionPage() {
  const [breed, setBreed] = useState("")

  const breeds = await getBreeds()
  const cats = await getCats({ breed, status: "adoptable" })
  //                           ^^^^^ Parameter types inferred from OpenAPI docs — typos caught at compile time

  return (/* render cat list... */)
}

This code contains no hand-written URLs, parameter types, or response shapes: getCats / getBreeds get their signatures from the OpenAPI document, and the AI only composes them into the page. The generator maintains the request-layer types, while the page code focuses on business logic.

Install Keq Skills for your AI assistant​

Run this in your project root:

npx skills add keq-request/skills

Once installed, your AI assistant loads Keq's coding guidance when needed, giving it the ability to:

  • 🔍 Natural language search — Describe the endpoint you need in any language; the AI matches it through keq search
  • 🏗️ On-demand code generation — The AI runs keq build based on .keqrc to generate type-safe TypeScript request functions
  • 📋 Filter rule management — The AI maintains .keqfilter, generating code only for endpoints the project actually uses
  • 🔄 Change awareness — Regenerates when OpenAPI documents change, so the AI works with the latest endpoint information

See Vibing Code for the full guide.

Why does AI programming need Keq?​

The hard part of AI-written HTTP code is rarely sending the request. It is keeping the code aligned with the API definition as the project evolves. AI can easily produce code that "looks like it runs," but it often mishandles three things: API context, type constraints, and API changes.

Wasted context: the AI does not know which APIs exist, so it reads raw documents​

Without API context, the AI can only read large Swagger/OpenAPI JSON documents or search the backend code for routes. That consumes a lot of context and makes it easy to pick the wrong endpoint.

Keq turns OpenAPI documents into structured knowledge the AI can search directly:

  • keq search "cats breed": find an endpoint with natural language
  • keq apis: list modules, endpoints, and data structures
  • keq describe operation: inspect the full request and response schema of one endpoint

The AI reads only the endpoint information the current task needs, instead of putting the whole API document or backend code into context.

Type drift: types get changed to any to make the code pass​

The problem with hand-written types is that they are a one-time copy of the API definition. Once a field changes, the copy goes stale; to keep the build passing, the AI tends to loosen the types rather than fix every call site.

Keq request functions are compiled from OpenAPI documents by @keq-request/cli. Parameter, return, and request body types come from the API definition. The AI calls the generated functions instead of writing types by hand, and generated files should not be edited.

Changes stay visible: incompatible updates break every affected call site​

APIs do not stand still: renamed fields, tightened types, and new required parameters all affect existing calls. With hand-written requests, those effects are scattered across files, and the AI may fix the code in front of it while missing other call sites.

Keq request functions are generated from the API definition. After an incompatible change, regenerating the code makes every affected call site surface at TypeScript compile time: missing arguments, mismatched types, and incorrect response usage all become concrete errors in concrete files. The compiler errors form a complete to-fix list, and the AI can work through it one by one.

One keeps it from digging through raw documents, one keeps the AI from hand-writing types, and one leaves incompatible changes nowhere to hide — the three foundations Keq provides for AI coding.

Core Features​

⚡ Chainable API​

A fluent API design that makes both handwritten and AI-generated code intuitive and readable:

await request
  .post("/cats")
  .send({ name: "mimi", age: 3 })
  .set("Content-Type", "application/json")
  .timeout(5000)
  .retry(2);

🧩 Onion Model Middleware​

Compose complex functionality through middleware, with official packages ready to use:

Why middleware instead of interceptors?

Interceptors have a limited ceiling — they split request and response into isolated hooks that cannot share context. Some scenarios (conditional retry, request timing, follow-up requests based on responses) simply cannot be implemented. Middleware is more complex to write, but it provides an architectural model with a much higher capability ceiling. In the AI programming era, writing complexity is no longer a bottleneck — having an architecture with sufficient flexibility matters more than lowering the barrier for hand-coding.

📘 Full-Chain TypeScript Type Inference​

Types flow seamlessly from request parameters to response body:

// Response body type is automatically inferred
const cat = await request.get<Cat>("/cats/1");
//    ^? Cat

// Functions generated by @keq-request/cli have strictly validated parameter types
await getCats({ breed: "siamese" });
//              ^^^^^^ Undefined parameters trigger compile-time errors

🎨 Flexible Routing System​

Precisely control the scope of middleware application:

request
  .apply(authMiddleware()).forRoutes({ host: "api.example.com" })
  .apply(adminAuth()).forRoutes({ pathname: "/admin/**" })
  .apply(logMiddleware()).forRoutes({ method: "POST" });

🌐 Cross-Platform​

Built on the standard Fetch API, use the same code in both browsers and Node.js (≥20).

Design Philosophy​

  1. AI Collaboration First — Enable AI assistants to precisely understand and operate your project's API layer
  2. Elegant API — Chainable calls make code more readable and writable
  3. Composability — Compose complex functionality through middleware, not bloated configurations
  4. Type Safety — Leverage TypeScript fully to catch issues at compile time
  5. Developer Efficiency — Reduce repetitive work through CLI tools and AI integration
  6. Flexible & Controllable — Provide sufficient extension points to meet any customization need