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

kai-chat

v0.0.1

Published

A work-oriented chat application where teams communicate with each other, chat with an LLM, and delegate tasks to AI agents that execute real work on their local machines via controlled tools.

Readme

KAI Chat

A work-oriented chat application where teams communicate with each other, chat with an LLM, and delegate tasks to AI agents that execute real work on their local machines via controlled tools.

What it does

  • Human chat — real-time messaging between team members in an org
  • LLM chat — streaming conversations with Claude (Anthropic)
  • Agent execution — agents that can read/write files, capture screens and browse the web on a user's desktop, with explicit capability grants, permission boundaries, and optional human-in-the-loop approval for sensitive operations

Stack

| Layer | Tech | |---|---| | Server | Fastify 5, Drizzle ORM, @fastify/jwt, @fastify/websocket | | LLM | Anthropic Claude (@anthropic-ai/sdk) | | Database | SQLite (better-sqlite3) in dev · PostgreSQL in prod | | Web | Next.js 15 App Router, React 19, TanStack Query, Zustand, Tailwind CSS | | Desktop | Electron (executes local filesystem, screen and browser capabilities) | | Monorepo | npm workspaces + Turborepo |

Getting started

Prerequisites: Node.js 20+, npm 9+

git clone <repo>
cd kai-chat
cp .env.example .env        # fill in JWT_SECRET, JWT_REFRESH_SECRET, SECRETS_KEY, ADMIN_EMAIL, ADMIN_PASSWORD
npm install

Database setup (first time and after schema changes):

npm run db:generate
npm run db:migrate

Run in development:

# All apps at once
npm run dev

# Or individually
npm run dev --workspace=apps/server   # http://localhost:3001
npm run dev --workspace=apps/web      # http://localhost:3000
npm run dev --workspace=apps/desktop  # Electron window

Environment variables

| Variable | Default | Notes | |---|---|---| | DATABASE_URL | — | file:./kai.db for SQLite, or a postgres URL | | JWT_SECRET | — | ≥ 32 characters | | JWT_REFRESH_SECRET | — | ≥ 32 characters | | SECRETS_KEY | — | ≥ 32 characters; encrypts LLM provider API keys stored in the database (openssl rand -base64 32). Don't change it once keys are stored | | ADMIN_EMAIL / ADMIN_PASSWORD | — | Initial platform admin, created on first start when no platform admin exists (password ≥ 8 chars, must be changed at first login). Ignored afterwards | | ADMIN_DISPLAY_NAME / ADMIN_ORG_NAME | Administrator / Default | Name of the initial admin and of the organization they are created in | | PORT | 3001 | | | CORS_ORIGIN | http://localhost:3000 | Comma-separated list of allowed origins (web app, desktop dev renderer) |

Accounts and AI models. There is no self-registration. On first start the server creates the platform admin from ADMIN_EMAIL / ADMIN_PASSWORD; they sign in, set a new password, then use Admin to create organizations and users and to add each organization's AI providers and models (Admin > AI models). Provider API keys live encrypted in the database, not in the environment.

Architecture overview

apps/server          API + WebSocket server + agent runtime
apps/web             Browser frontend
apps/desktop         Electron app — executes local capabilities
packages/shared-types  Shared domain types and WS message contracts
packages/sdk         Typed API + WebSocket client (used by web + desktop)
packages/ui          Shared React component library

Agent security model

Agents operate under explicit grants — capability access is enforced by the server's ToolAuthorizer before any tool runs, regardless of what the LLM requests:

  1. Tool must be registered
  2. Agent's capabilities array must include the required capability (e.g. filesystem.write)
  3. Any matching Rule with enforcement: approval_required pauses execution and asks the user

Where an agent may act is decided on the user's computer, not per agent: the Electron process (electron/capabilities/filesystem.ts) checks every file path against the folders the user allowed in the desktop app's Settings > File access (each read-only or read & write) before any local file I/O.

WebSocket protocol

Connect to ws://localhost:3001/ws?token=<jwt>. All messages are JSON with the shape { type, id, payload }. Key server-sent types: chat.message, execution.status_changed, execution.tool_call, execution.tool_result, execution.approval_requested, capability.request. Key client-sent types: chat.message, capability.response, client.register (desktop only), approval.respond.

Scripts

npm run build       # build all packages
npm run typecheck   # tsc --noEmit across all packages
npm run test        # vitest, in every workspace (server, web, desktop, sdk)
npm run lint        # eslint
npm run format      # prettier
npm run db:generate # generate Drizzle migrations from schema changes
npm run db:migrate  # apply migrations
npm run db:studio   # open Drizzle Studio

Testing

Every feature and bug fix comes with tests. The suites run on in-memory SQLite with the real migrations, against the real Fastify app; only the LLM provider and the desktop app are faked.

npm run test                                  # everything
npm run test --workspace=apps/server          # one workspace
cd apps/server && npx vitest run src/routes/client-contract.spec.ts   # one file
npm run test:watch --workspace=apps/web       # watch mode

See the Testing section of CLAUDE.md for where tests live, the helpers (setupTestApp, the mock LLM, fake sockets) and the conventions.