npm package: @misbahsy/clawkit-lite
Description: Minimal agent kit — any provider, any channel, any skills
Latest version: 0.1.0

# ClawKit Lite

**Minimal agent kit — any provider, any channel, any skills.**

ClawKit Lite is a ~1,000-line kit for building conversational AI agents. Clone it, pick your channel (Telegram, WhatsApp, ...), pick your provider (Claude, OpenAI Codex, Pi, ...), add skills, and run. No Docker, no framework overhead — just a message bus with pluggable parts.

```
[Channel] → message in → [Runtime] → [Provider] → response → [Channel]
                              ↑
                          [Skills]
                     (instructions + MCP tools)
```

## Quick Start

```bash
git clone https://github.com/misbahsy/ClawKit-lite.git
cd ClawKit-lite
npm install

# Option A: Interactive setup via Claude Code
claude
# then type: /setup

# Option B: Manual setup
cp .env.example .env
# Edit .env with your API keys and tokens
# Edit clawkit.config.ts to pick your channel + provider
npm install grammy                            # for Telegram
npm install @anthropic-ai/claude-agent-sdk    # for Claude
npm run dev
```

## How It Works

### Three Pluggable Interfaces

Everything in ClawKit Lite implements one of three interfaces:

```typescript
// Channel — produces messages, sends responses
interface Channel {
  name: string;
  connect(): Promise<void>;
  disconnect(): Promise<void>;
  onMessage(cb: (msg: IncomingMessage) => void): void;
  sendMessage(to: string, text: string): Promise<void>;
  setTyping?(to: string, isTyping: boolean): Promise<void>;
}

// Provider — takes a prompt, returns streamed responses
interface Provider {
  name: string;
  run(params: {
    prompt: string;
    systemPrompt: string;
    sessionId?: string;
    mcpServers?: Record<string, McpServerConfig>;
  }): AsyncIterable<ProviderEvent>;
}

// Skill — instructions + optional MCP server
interface Skill {
  name: string;
  instructions: string;         // loaded from SKILL.md
  mcpServer?: McpServerConfig;  // optional tool server
}
```

### Configuration

All configuration lives in a single file — `clawkit.config.ts`:

```typescript
import { telegram } from "./src/channels/telegram.js";
import { claude } from "./src/providers/claude.js";

export default {
  name: "my-agent",
  channel: telegram({ token: process.env.TELEGRAM_BOT_TOKEN! }),
  provider: claude({ model: "claude-sonnet-4-20250514" }),
  skills: ["./src/skills/scheduler"],
  systemPrompt: "./workspace/CLAUDE.md",
};
```

To switch to WhatsApp + OpenAI Codex, change two imports:

```typescript
import { whatsapp } from "./src/channels/whatsapp.js";
import { codex } from "./src/providers/codex.js";

export default {
  name: "my-agent",
  channel: whatsapp({ storePath: "./store/whatsapp-auth" }),
  provider: codex({ model: "codex-mini-latest" }),
  skills: ["./src/skills/scheduler"],
  systemPrompt: "./workspace/CLAUDE.md",
};
```

### Environment Variables

Secrets go in `.env` (gitignored), never in config files:

```bash
# Channel tokens
TELEGRAM_BOT_TOKEN=your-bot-token-here
# WHATSAPP_STORE_PATH=./store

# Provider keys
ANTHROPIC_API_KEY=your-key-here
# OPENAI_API_KEY=your-key-here
# PI_API_KEY=your-key-here
# PI_SERVER_URL=http://localhost:8080
```

## Channels

### Telegram

Uses [grammy](https://grammy.dev/). Requires a bot token from [@BotFather](https://t.me/BotFather).

```bash
npm install grammy
```

```typescript
import { telegram } from "./src/channels/telegram.js";

telegram({ token: process.env.TELEGRAM_BOT_TOKEN! })
```

Features:
- Polling-based (no webhook setup needed)
- Automatic message chunking (4096 char limit)
- Typing indicators
- Group chat support
- Outgoing message queue with retry on disconnect

### WhatsApp

Uses [Baileys](https://github.com/WhiskeySockets/Baileys). Authenticates via QR code scan.

```bash
npm install baileys @hapi/boom pino qrcode-terminal
```

```typescript
import { whatsapp } from "./src/channels/whatsapp.js";

whatsapp({ storePath: "./store/whatsapp-auth" })
```

Features:
- QR code authentication (displayed in terminal)
- Session persistence (survives restarts)
- LID-to-phone JID translation
- Exponential backoff reconnection (up to 30s)
- Markdown-to-WhatsApp formatting conversion
- Typing/presence indicators
- Group chat support

### Adding a Custom Channel

Create `src/channels/my-channel.ts`:

```typescript
import type { Channel } from "../types.js";

export function myChannel(config: { /* your config */ }): Channel {
  return {
    name: "my-channel",
    async connect() { /* connect to service */ },
    async disconnect() { /* cleanup */ },
    onMessage(cb) { /* wire up message listener, call cb() */ },
    async sendMessage(to, text) { /* send response */ },
    async setTyping(to, isTyping) { /* optional typing indicator */ },
  };
}
```

## Providers

All providers are **agent SDKs** — full coding agent runtimes, not raw LLM APIs. They handle tool use, file access, and bash execution natively.

### Claude (Agent SDK)

Uses [@anthropic-ai/claude-agent-sdk](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk). The same SDK that powers Claude Code.

```bash
npm install @anthropic-ai/claude-agent-sdk
```

```typescript
import { claude } from "./src/providers/claude.js";

claude({
  model: "claude-sonnet-4-20250514",  // default
  maxTurns: 10,                        // max agent turns per message
  permissionMode: "bypassPermissions", // autonomous operation
  cwd: "/path/to/workspace",           // optional working directory
})
```

Features:
- Session resume (conversations persist across messages)
- MCP server passthrough (skill tools available to agent)
- Built-in tools: Bash, Read, Write, Edit, Glob, Grep, WebSearch
- Auth: `ANTHROPIC_API_KEY` env var or `claude login` (OAuth)

### OpenAI Codex CLI

Uses [@openai/codex](https://www.npmjs.com/package/@openai/codex). OpenAI's agent with built-in sandboxed execution.

```bash
npm install @openai/codex
```

```typescript
import { codex } from "./src/providers/codex.js";

codex({
  model: "codex-mini-latest",  // default
})
```

Features:
- Single-call execution (prompt in, response out)
- Built-in sandbox for bash
- Flexible response parsing
- Auth: `OPENAI_API_KEY` env var

### Pi Agent

HTTP-based streaming agent used by [OpenClaw](https://openclaw.org). Supports self-hosted or cloud Pi servers.

```bash
npm install @mariozechner/pi-agent-core
```

```typescript
import { pi } from "./src/providers/pi.js";

pi({
  model: "pi-default",
  baseUrl: "http://localhost:8080",     // Pi server URL
  maxTokens: 4096,
  modelFailover: ["fallback-model"],    // try these if primary fails
  compactionThreshold: 100,             // summarize after N messages
})
```

Features:
- Server-sent events (SSE) streaming
- Model failover (automatic fallback)
- Session compaction (summarizes old messages)
- Auth: `PI_API_KEY` and `PI_SERVER_URL` env vars

### Adding a Custom Provider

Create `src/providers/my-provider.ts`:

```typescript
import type { Provider, ProviderEvent } from "../types.js";

export function myProvider(config: { /* your config */ }): Provider {
  return {
    name: "my-provider",
    async *run({ prompt, systemPrompt, sessionId, mcpServers }) {
      // Call your agent SDK here
      const response = await callMyAgent(prompt);
      yield { type: "text", text: response };
      yield { type: "done", sessionId: "new-session-id" };
    },
  };
}
```

## Skills

Skills extend your agent with instructions and tools. Each skill is a directory with:

```
src/skills/my-skill/
├── SKILL.md          # Instructions the agent reads (added to system prompt)
└── server.ts         # Optional MCP server providing tools
```

### Built-in: Scheduler

Schedule recurring tasks with cron expressions.

```
src/skills/scheduler/
├── SKILL.md          # Tells agent how to use scheduling tools
└── server.ts         # MCP server: schedule_task, list_tasks
```

Example interactions:
- "Remind me every morning at 9am to check email" → creates cron job `0 9 * * *`
- "Every Friday at 5pm, send a weekly summary" → creates cron job `0 17 * * 5`
- "What tasks are scheduled?" → lists all active tasks

### Adding a Custom Skill

1. Create the directory:
   ```bash
   mkdir -p src/skills/my-skill
   ```

2. Write instructions in `SKILL.md`:
   ```markdown
   ## My Skill

   You can do X, Y, Z.

   ### Available tools
   - **my_tool**: Does something useful
     - `param1`: Description
   ```

3. Optionally create an MCP server in `server.ts`:
   ```typescript
   import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
   import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
   import { z } from "zod";

   const server = new McpServer({ name: "my-skill", version: "1.0.0" });

   server.tool("my_tool", "Does something useful", {
     param1: z.string().describe("Description"),
   }, async ({ param1 }) => {
     return { content: [{ type: "text", text: `Result: ${param1}` }] };
   });

   const transport = new StdioServerTransport();
   server.connect(transport);
   ```

4. Register in config:
   ```typescript
   skills: ["./src/skills/scheduler", "./src/skills/my-skill"],
   ```

5. Restart: `npm run dev`

## Project Structure

```
clawkit-lite/
├── src/
│   ├── index.ts              # Entry point
│   ├── runtime.ts            # Message bus (channel → provider → channel)
│   ├── types.ts              # Channel, Provider, Skill interfaces
│   ├── config.ts             # Load .env + config file
│   ├── db.ts                 # SQLite: messages, sessions, tasks
│   ├── channels/
│   │   ├── telegram.ts       # Telegram adapter (grammy)
│   │   └── whatsapp.ts       # WhatsApp adapter (baileys)
│   ├── providers/
│   │   ├── claude.ts         # Claude Agent SDK adapter
│   │   ├── codex.ts          # OpenAI Codex CLI adapter
│   │   └── pi.ts             # Pi Agent adapter
│   └── skills/
│       └── scheduler/
│           ├── SKILL.md      # Scheduling instructions
│           └── server.ts     # MCP server: schedule_task, list_tasks
├── workspace/
│   └── CLAUDE.md             # System prompt (agent identity + rules)
├── setup/
│   ├── bootstrap.sh          # Environment checks
│   └── index.ts              # Setup step runner
├── tests/
│   ├── helpers.ts            # Mock channel, provider, message factories
│   ├── db.test.ts            # Database layer tests
│   └── runtime.test.ts       # Runtime integration tests
├── store/                    # Auth state, SQLite database (gitignored)
├── clawkit.config.ts         # User configuration
├── .env.example              # Environment variable template
├── .env                      # Your secrets (gitignored)
├── package.json
└── tsconfig.json
```

## Runtime Details

### Message Bus

The runtime (`src/runtime.ts`) handles:

1. **Skill loading** — reads `SKILL.md` files, detects MCP servers
2. **System prompt building** — concatenates `workspace/CLAUDE.md` + skill instructions
3. **Message routing** — channel message in → provider → response back to channel
4. **Conversation history** — loads last 30 messages from SQLite for context
5. **Session persistence** — saves/restores provider session IDs per sender
6. **Per-sender queue** — ensures one agent turn per sender at a time (concurrent across senders)
7. **Scheduled tasks** — polls cron-based tasks every 60s, executes due tasks via provider
8. **Graceful shutdown** — cleans up intervals, disconnects channel

### Database

SQLite via [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) with WAL mode. Three tables:

| Table | Purpose |
|-------|---------|
| `messages` | Conversation history per session (sender/group) |
| `sessions` | Maps senders to provider session IDs |
| `tasks` | Scheduled tasks (prompt, cron, target, last_run) |

Stored at `./store/clawkit.db` (gitignored).

### Dependencies

**Always installed** (core):
```
better-sqlite3    — message/session/task storage
cron-parser       — scheduled task expressions
dotenv            — environment variable loading
```

**Install per channel** (pick one):
```
grammy                        — Telegram
baileys @hapi/boom pino qrcode-terminal  — WhatsApp
```

**Install per provider** (pick one):
```
@anthropic-ai/claude-agent-sdk    — Claude Code
@openai/codex                     — OpenAI Codex CLI
@mariozechner/pi-agent-core       — Pi Agent
```

**Install if skills use MCP**:
```
@modelcontextprotocol/sdk zod     — MCP server implementation
```

Base install: 3 core deps + 1 channel + 1 provider = ~4-5 packages.

## Commands

```bash
npm run dev       # Run with tsx (development, auto-loads .ts)
npm run build     # Compile TypeScript to dist/
npm start         # Run compiled version (production)
npm test          # Run tests
```

## Interactive Setup

If you have [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed, the `/setup` skill provides a guided wizard:

```bash
claude
# type: /setup
```

The wizard will:
1. Check your environment (Node.js 20+, dependencies)
2. Ask which channel you want (Telegram / WhatsApp)
3. Ask which provider you want (Claude / Codex / Pi)
4. Walk you through authentication (bot token, QR code, API keys)
5. Ask for your agent's name
6. Generate `clawkit.config.ts` and `.env`
7. Install the right dependencies
8. Optionally set up a background service (launchd/systemd)
9. Verify everything works

## How It Compares

| | Full ClawKit | ClawKit Lite | Official Nanoclaw |
|-|-------------|-------------|-------------------|
| Code | ~5k lines + registry | **~1,000 lines** | ~6,900 lines |
| Provider | Multi (typed interfaces) | **Multi (swap one file)** | Claude only |
| Channels | Multi (typed interfaces) | **Multi (swap one file)** | WA + Telegram hardcoded |
| Extensibility | Component categories | **Skills + adapter swap** | SKILL.md only |
| Docker | No | **No** | Required |
| Philosophy | Framework | **Kit** | Opinionated app |

## Testing

```bash
npm test
```

31 tests covering:
- Database: message CRUD, session persistence, task management
- Runtime: message flow, typing indicators, history context, session resume, error handling (yielded + thrown), streaming, per-sender queue serialization, group messages, skill loading, MCP server detection, system prompt building, config variations

## License

MIT