One signed binary. Every feature compiled in. Free to run. Install Crowkis →

SDKs

Node.js / TypeScript SDK

Cache any model. Crowkis is model-agnostic, wrap the call you already make to OpenAI, Anthropic, a local model, or whatever comes next, and Crowkis serves the repeats for free. Fully async, TypeScript typings included.

Install#

One command. The base client has no runtime dependencies.

shell
npm install @crowkis/client

The one idea#

Crowkis doesn't care which model you call. You wrap the call you already make; Crowkis remembers the answer by meaning, so the next time someone asks the same thing in different words it's served instantly and for free.

Connect#

typescript
import { Crowkis } from "@crowkis/client";

const cache = new Crowkis({ host: "127.0.0.1", port: 6379, tenant: "my-app" });

Cache any model, the wrapper#

cache.cached() wraps any async function whose first argument is the prompt, and matches on meaning, so rephrased prompts hit too. The function inside can call any provider.

typescript
const answer = cache.cached(
  async (prompt: string) => myModel(prompt),   // OpenAI, Claude, local, anything
  { ttl: 3600 },
);

await answer("How do refunds work?");         // miss → your model runs, result cached
await answer("What's the refund process?");   // semantic HIT → no model call

Cache any model, explicit form#

typescript
const text = await cache.ask(
  "How do refunds work?",
  async (prompt) => myModel(prompt),   // any model
  { ttl: 3600 },
);

Lookup & store directly#

typescript
const hit = await cache.lookup("what's the refund timeline?");
if (hit) {
  console.log(hit.text, hit.similarity, hit.confidence);
} else {
  await cache.store("what's the refund timeline?", "5-7 business days.", { ttl: 3600 });
}

Streaming with async iteration#

typescript
for await (const chunk of cache.stream(
  "Explain vector caches",
  async (prompt) => myModelStream(prompt),
  { ttl: 3600 },
)) {
  process.stdout.write(typeof chunk === "string" ? chunk : chunk.toString());
}

LangChain.js#

Matches on meaning, so rephrased prompts hit, unlike an exact-match cache. Drops into LangChain's cache option, no chain changes.

typescript
import { CrowkisCache } from "@crowkis/client/langchain";
import { OpenAI } from "@langchain/openai";

const llm = new OpenAI({ cache: new CrowkisCache({ tenant: "my-app", ttl: 3600 }) });

Agent memory#

Durable, semantic, per-user memory for agents (LangGraph.js or any loop). Every recall is scoped to its agent and user.

typescript
import { CrowkisMemory } from "@crowkis/client/memory";

const mem = new CrowkisMemory("support-bot", { user: "alice" });
await mem.remember("Alice prefers email over phone");
await mem.recall("how should I contact Alice?");   // semantic recall

Method reference#

Grouped by purpose. The high-level methods cover most apps; the rest are on the Crowkis client for direct control.

caching, model-agnostic
cache.cached(fn, { ttl, threshold })   // wrap any async model call in a semantic cache
cache.ask(prompt, compute, opts)       // recall, else run compute() and cache it
cache.stream(prompt, compute, opts)    // same, as an async iterator of chunks
cache.lookup(prompt)                   // → { text, similarity, confidence } | null
cache.store(prompt, answer, { ttl })   // write an answer for a prompt
cache.similar(prompt, { k })           // k most similar cached prompts
cache.embed(text)                      // raw embedding vector
cache.flush()                          // clear this tenant's cache
agent memory, new CrowkisMemory(agent, { user })
mem.remember(fact, { ttl })   // store a fact
mem.recall(query, { k })      // semantic recall
mem.extract(conversation)     // pull facts from a transcript
mem.history(query, { k })     // recall including superseded versions
mem.forget({ query })         // forget matching facts
mem.link(subj, rel, obj)      // knowledge-graph edge
mem.graph(entity, { depth })  // walk the graph
sessions · quality · cost · ops
cache.csessionAdd(session, role, text)   cache.csessionRecent(session, { n })
cache.cpin(query, answer)                cache.cflag(query, badAnswer)
cache.cguard(text)                       cache.coutcheck(text)
cache.cbudgetSet(tenant, { dailyUsd })   cache.ckeylimitSet(tenant, { rpm })
cache.cpiiReport(tenant)                 cache.csave(dest)   cache.creload()
Ships index.d.ts typings; the RESP reader handles partial and RESP3 push frames. Sensible timeout/retry/backoff defaults match the Python SDK. The embedding model lives server-side, so the client uses whatever model the server runs.