npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bento-chat

v0.1.0

Published

Drop an AI-quality chatbot onto any website with zero LLM API cost. Bake your knowledge locally with a coding agent, ship one bundle.json, answer in-browser with no API.

Downloads

29

Readme

🍱 bento-chat

Drop an AI-quality chatbot onto any website — with zero LLM API cost.

Bake your knowledge locally with a coding agent (Claude Code, Codex, Gemini). Ship a single bundle.json. The browser answers questions with no API, no server, no per-message billing — just fast, predictable, on-device retrieval.

npm license


Why

Running an LLM on your website means metered, per-message billing that scales with traffic. bento-chat flips it: you already pay a flat subscription for a local coding agent, so do the expensive “make it smart” work once, offline, and serve the result for free forever.

| | LLM-on-website | bento-chat | |---|---|---| | Cost per message | 💸 metered | 0 | | Latency | network round-trip | instant (in-browser) | | Privacy | data leaves the page | 100% on-device | | Answers | can hallucinate | predictable, curated | | Infra | API keys + backend | one static JSON file |

How it works

   ┌─ LOCAL (once, with your agent subscription) ──────────────┐
   │  raw notes / FAQ / docs                                   │
   │        │  Claude Code / Codex / Gemini reads AGENT.md     │
   │        ▼  → rewrites, adds synonyms & paraphrases         │
   │  enriched data/  ──►  bento-chat build  ──►  bundle.json  │
   └───────────────────────────────────────────────────────────┘
                                  │  (commit / upload the one file)
   ┌─ WEBSITE (every visitor, free & instant) ─────────────────┐
   │  <bento-chat src="bundle.json">  →  in-browser engine     │
   │     normalize → BM25 keyword match → curated answer       │
   └───────────────────────────────────────────────────────────┘

The trick: the agent does all the “semantic” work offline — generating the synonyms, paraphrases, and missing questions a real user might type — so a plain keyword engine in the browser feels like an LLM, at zero runtime cost.

Quick start

# 1. scaffold a project (sample data + AGENT.md + config)
npx bento-chat init my-bot && cd my-bot

# 2. bake your data with your agent
#    open AGENT.md in Claude Code / Codex / Gemini and let it enrich ./data
#    (or run `bento-chat agent-prompt` to print the instructions)

# 3. compile the runtime bundle
npx bento-chat build ./data -o ./bundle.json

# 4. smoke-test from the terminal
npx bento-chat ask ./bundle.json "how much is shipping?"

Embed on any page with one script tag and one element — no bundler, no build step:

<!-- English UI -->
<script src="https://unpkg.com/bento-chat/dist/bento-chat.min.js"></script>
<bento-chat src="/bundle.json" lang="en" accent="#4f46e5"></bento-chat>
<!-- Japanese UI -->
<script src="https://unpkg.com/bento-chat/dist/bento-chat.min.js"></script>
<bento-chat src="/bundle.ja.json" lang="ja" accent="#e11d48"></bento-chat>

Pick the UI language at embed time with lang="en" or lang="ja" — it switches the placeholder, send button, greeting, and "not found" message. Point src at the bundle you baked for that language. Every label is also overridable (title, subtitle, placeholder, greeting, fallback).

Or call the engine directly:

import { Chatbot } from "bento-chat";
const bot = Chatbot.fromJSON(await fetch("/bundle.json").then(r => r.json()));
console.log(bot.ask("How much is shipping?").answer);

Data format

[
  {
    "id": "shipping-fee",
    "category": "support",
    "question": "How much is shipping?",
    "answer": "Shipping is a flat $5 nationwide. Orders over $50 ship free.",
    "keywords": ["shipping", "delivery", "postage", "cost", "free", "fee"]
  },
  {
    "id": "pro-plan",
    "entity": "Pro plan",
    "facts": { "price": "$19/month", "members": "up to 10" },
    "keywords": ["pricing", "plan", "upgrade"]
  }
]

JSON, JSONL, and CSV (question,answer,category) are supported. keywords is where the magic lives — that’s what the agent enriches, and what makes keyword retrieval feel semantic.

CLI

| Command | What it does | |---|---| | bento-chat init [dir] | Scaffold data/, bento.config.json, and AGENT.md. | | bento-chat build <dir> -o bundle.json | Compile sources into a runtime bundle. | | bento-chat ask <bundle> "q" | Query a bundle from the terminal. | | bento-chat agent-prompt | Print the agent baking instructions. |

API

  • new Chatbot(bundle) / Chatbot.fromJSON(json) — construct the engine.
  • bot.ask(query, opts?) — synchronous, zero-API. Returns { answer, matched, score, entry, alternatives, method }.
  • bot.askHybrid(query, opts?) — optional embedding-blended search (needs a bundle with embeddings + a query embedder).

score is query-term coverage (0..1); answers below opts.threshold (default 0.34) return the bundle’s fallback.

Multilingual (English / Japanese)

Two independent language layers:

  1. UI language — set at embed time with lang="en" or lang="ja". Switches the widget's built-in labels and messages.
  2. Content language — the bundle itself. Bake one bundle per language locally (e.g. bundle.en.json, bundle.ja.json) and point src at the one you want.

The retrieval engine is language-agnostic: Latin words are stopword-filtered, and CJK (Japanese/Chinese) text is indexed as character bigrams — so Japanese FAQ works out of the box with no morphological analyzer and zero dependencies. See examples/japanese for a full JA demo.

Run this repo

npm install
npm run demo      # builds the package + example bundle, prints how to serve
npx serve .       # then open /examples/basic/index.html
npm run smoke     # end-to-end retrieval test

Roadmap

  • ✅ BM25 keyword engine, multilingual tokenizer, web component, CLI
  • ⏳ Optional in-browser embeddings (transformers.js) for true hybrid search
  • ⏳ YAML sources, multi-bundle routing, click-feedback (analytics-free)
  • bento-chat optimize — agent-in-the-loop keyword tuning from failed queries

License

MIT © tinaba96