Self-hosted human-in-the-loop assistant: a local control plane that talks to OpenAI-compatible chat APIs, runs tools (workspace, terminal, browser, HTTP fetch, life logs), connects to Slack, Discord, Telegram, LINE, Mattermost, and optional universal HTTP bridges—with permissions, approval queues (including interactive Approve/Deny in Slack and Discord), audit logging, automation (cron jobs), RAG over your workspace (embeddings + MMR + optional LLM rerank), and a React web dashboard.
Repository: github.com/thensanity/ChikaBot
- What you need
- Quick start (development)
- Production-style run
- Architecture
- Web dashboard
- Gateway authentication
- Environment variables
- Workspace, profiles, and policy
- Channels (Slack, Discord, Telegram, LINE, Mattermost, HTTP)
- RAG (knowledge index)
- RAG evaluation suite
- Plugins and context packs
- API overview
- Data on disk
- Security notes
- Troubleshooting
- Node.js 20+ (recommended) and npm
- An OpenAI-compatible API key (OpenAI, Azure OpenAI with compatible base URL, or another gateway)
- For browser and fetch tools: network access from the machine running the server; browser automation uses Playwright (
playwright-core); you may need to install browser binaries for your OS if snapshots fail (see Troubleshooting)
From the repository root:
npm install
npm run devThis runs two processes:
| Service | Default URL | Role |
|---|---|---|
| Server | http://127.0.0.1:8787 |
API, WebSocket, channel webhooks |
| Web UI | http://127.0.0.1:5173 |
Dashboard (Vite dev server proxies /api and /ws to the server) |
- Open the web UI in a browser.
- In Settings, enter your API key, base URL, and model (e.g.
gpt-4o-miniorgpt-4ofor vision). - Set workspace folder to an absolute path where the assistant may read/write according to policy.
- Chat in the Chat tab or connect a channel (optional).
Build everything:
npm run buildRun the compiled server only (serve the web app separately or point users at a static build):
npm startThe server runs node server/dist/index.js. For the UI in production, build the web app (npm run build -w web) and host web/dist with any static file server, or continue using Vite preview—ensuring API calls go to the same host or configure CORS and a public gateway URL (see Environment variables).
Typical layout:
- Set
CHIKABOT_PORTif not using8787. - Set
CHIKABOT_PUBLIC_URLto the web app base URL (used in links for channels and pairing). - Set
CHIKABOT_PUBLIC_GATEWAYif the browser must reach the API at a different host than default (e.g. TLS reverse proxy). - Enable gateway lock in Settings (or migrate
CHIKABOT_GATEWAY_SECRETonce—see Gateway authentication). - Prefer
OPENAI_API_KEYon the server for unattended features (RAG index refresh, eval runner); the UI can still paste a session key for chat.
server/— Express API, WebSocket updates, LLM + tools, RAG, sessions, auth, schedulers, channel adapters (TypeScript →dist/).web/— React + Vite SPA: chat, settings, audit, automation, channels, plugins, insights.- Monorepo — Root
package.jsonuses npm workspaces (server,web).
The assistant loop (simplified): user message → policy / approvals → LLM with tools → tool execution (workspace, HTTP, browser, etc.) → optional further turns → reply and audit events.
Main areas (sidebar):
- Chat — Messages, tool approvals, optional image attachments for vision-capable models.
- Settings — API key (session memory), base URL, model, presets, fallback models, RAG LLM rerank, workspace path, gateway lock, channel tokens.
- Policy — Per-tool permission modes: deny / allow / ask.
- Audit — Append-only log of actions.
- Automation — Cron-like jobs that run prompts.
- Channels — Bridge tokens and channel-specific settings.
- Plugins — Enable/disable context packs.
- Insights — Token usage aggregates, ML scope transparency JSON, RAG eval runner output.
If gateway lock is enabled (password stored as a scrypt hash in state.json):
- Clients must log in via the auth API and store a Bearer token (the web UI uses
sessionStorage). - Slack, Discord, LINE, Mattermost, universal bridge, and inbound hook routes are excluded from this middleware where documented in code—treat those URLs as secrets.
One-time migration: if CHIKABOT_GATEWAY_SECRET is set and no hash exists yet, the server hashes it into the store on startup (you can unset the env var afterward).
| Variable | Purpose |
|---|---|
OPENAI_API_KEY |
Default LLM/embeddings key when not only using the UI session key |
OPENAI_BASE_URL |
Default OpenAI-compatible API base |
CHIKABOT_MODEL |
Default model name if not in store |
CHIKABOT_PORT |
Server port (default 8787) |
CHIKABOT_PUBLIC_URL |
Public web URL for links (default dev: http://127.0.0.1:5173) |
CHIKABOT_PUBLIC_GATEWAY |
Public API base if different from http://127.0.0.1:PORT |
CHIKABOT_DATA_DIR |
Override data directory (default: ~/.chikabot on Unix, %USERPROFILE%\.chikabot on Windows) |
CHIKABOT_GATEWAY_SECRET |
Optional one-time plain secret to seed gateway password hash |
CHIKABOT_DISABLE_PARALLEL_TOOLS |
Set to 1 to disable parallel tool calls in LLM requests |
CHIKABOT_RAG_LLM_RERANK |
Set to 1 to force RAG pool LLM rerank (in addition to Settings) |
CHIKABOT_RERANK_MODEL |
Model name for forced rerank when env rerank is on |
Never commit real API keys or tokens; use .env locally (see .gitignore).
- Workspace — Absolute path to the project or documents the bot can access via tools (
read_workspace_file,write_workspace_file,list_workspace,search_workspace,run_terminal, etc.), subject to policy. - Profiles — Multiple named profiles can carry their own workspace and policy; the active profile is selectable in the UI.
- Policy — For each capability, choose deny, allow, or ask (human approval). Sensitive tools (writes, terminal, browser) should stay on ask in production.
The server exposes registry metadata at GET /api/channels/registry.
General expectations:
- Configure tokens/secrets in Settings or environment-specific deployment secrets.
- Slack requires correct Events and Interactivity URLs pointing at this server’s
/api/slack/...routes. - Discord uses bot token + intents; approval buttons use signed tokens.
- Telegram, LINE, and Mattermost each need webhook or outgoing URLs reachable from the vendor’s servers.
- Universal HTTP bridge — Mint a token in the UI; POST JSON payloads to the documented path so external systems can inject messages.
Rate limiting applies to most /api routes; channel webhook paths are typically excluded—still protect tokens.
- Tool
refresh_knowledge_indexembeds text files under the workspace into a local JSON index (OpenAI-style embeddings API). - Tool
query_workspace_knowledgeembeds the query, retrieves top chunks, optionally runs an LLM rerank pass, then MMR for diversity, and returns concatenated excerpts.
In Settings you can enable RAG: LLM rerank and optionally set a rerank model (empty = primary chat model). This costs an extra chat completion per RAG query when enabled.
Golden tests live in eval/cases.json under your data directory (e.g. ~/.chikabot/eval/cases.json).
GET /api/eval/cases— List casesPUT /api/eval/cases— Replace suite:{ "cases": [ { "id", "query", "expectContains": ["substring", ...] } ] }POST /api/eval/run— Run checks (RAG output must contain expected substrings; case-insensitive)
The automated runner uses OPENAI_API_KEY on the server, not the key pasted in the web UI.
The Insights tab can run the suite and show JSON results. Transparency about what is / isn’t in scope for “ML platform” features: GET /api/ml-scope.
Built-in and user-defined packs can extend the system prompt. User packs: ~/.chikabot/plugins/*.json. Enable packs in the Plugins tab; enabled IDs are stored in state.json.
Not exhaustive (see server/src/index.ts for the full list):
| Method | Path | Description |
|---|---|---|
| GET | /api/ping |
Liveness |
| GET | /api/settings |
Current settings/state snapshot (auth if enabled) |
| POST | /api/settings |
Update settings |
| POST | /api/chat |
Chat turn |
| GET | /api/audit |
Audit entries |
| GET | /api/insights |
Usage / channel summary |
| GET | /api/ml-scope |
In-scope vs external ML responsibilities |
| GET | /api/eval/cases |
Eval cases |
| PUT | /api/eval/cases |
Replace eval cases |
| POST | /api/eval/run |
Run RAG eval suite |
| WS | /ws |
Real-time state (dev proxy from Vite) |
Default root: CHIKABOT_DATA_DIR or ~/.chikabot (Windows: user profile .chikabot).
Typical files:
state.json— Persisted settings, profiles, gateway hash, jobs, plugin IDs, etc.audit.jsonl— Audit lograg-index.json— Embedding index for RAGeval/cases.json— RAG eval caseslife/— Life log storage
- Run behind HTTPS and a reverse proxy for any internet-exposed deployment.
- Treat bridge tokens, Slack signing secrets, and bot tokens as credentials.
- The assistant can execute terminal and browser tools if policy allows—isolate the process and workspace accordingly.
- API keys in the UI are kept in server memory for the session; persisted state does not replace long-term key storage—use env vars on servers you control.
- 401 on
/api/*after enabling gateway lock — Log in again from the web UI; ensureAuthorization: Beareris sent for scripted clients. - CORS / network errors from web to API — In dev, use the Vite proxy (open
5173). In production, align origins or configure the app to call the correct API base. - RAG says wrong workspace — Re-run
refresh_knowledge_indexafter changing workspace path. - Browser snapshot failures — Ensure Playwright can launch or download browsers for your OS; run from a machine with a display or use headless-compatible setup.
- Slack/Discord buttons not working — Verify interactivity URLs, signing secrets, and that the server URL is reachable from the vendor cloud.
Specify your license in a LICENSE file if you open-source the project.
Issues and pull requests are welcome on thensanity/ChikaBot.