{"_id":"@capsbharg/agent-connect","_rev":"5-336a4e8514c4b2128dfade48472539d0","name":"@capsbharg/agent-connect","dist-tags":{"latest":"1.3.0"},"versions":{"1.0.0":{"name":"@capsbharg/agent-connect","version":"1.0.0","keywords":["slack","telegram","claude","claude-code","cursor","codex","anthropic","ai-agent","llm","chatops","devops","automation","bullmq","redis","middleware","framework"],"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"license":"MIT","_id":"@capsbharg/agent-connect@1.0.0","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"bin":{"agent-connect":"dist/cli/index.js"},"dist":{"shasum":"9ae9fa903ffa04760ab4af7fb51288fff6241eaa","tarball":"https://registry.npmjs.org/@capsbharg/agent-connect/-/agent-connect-1.0.0.tgz","fileCount":11,"integrity":"sha512-MyvZVk2o0bvSv1Sp67yusmC3uHzMINXhP5LP9q5Mschkq5RQJ2huln1/zK+z44ctMWRGMqh5hanawuz9qNCZQA==","signatures":[{"sig":"MEYCIQDO+PP9oV4Ly/D2wOBP+l/E+doJ1FB+2i56v8jJ5hN2yQIhALaYQS2lSRtDOvOrVlJvWWE1vcHqhMYOYtr4FNNkc14f","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":554499},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"8b1812abdb1e89f14a143117940236bda119766f","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","start":"node --enable-source-maps dist/cli/index.js","format":"prettier --write .","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"_npmVersion":"11.16.0","description":"Universal middleware between messaging platforms (Slack, Telegram, ...) and AI coding agents (Claude Code, Cursor, Codex, ...).","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.24.1","pino":"^9.6.0","bullmq":"^5.34.6","dotenv":"^17.4.2","grammy":"^1.31.0","express":"^5.2.1","ioredis":"^5.4.2","tree-kill":"^1.2.2","@slack/bolt":"^5.0.0","cross-spawn":"^7.0.6","pino-pretty":"^13.0.0","@clack/prompts":"^0.9.1","@slack/web-api":"^8.0.0","@bull-board/api":"^8.3.0","@bull-board/express":"^8.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.18.0","vitest":"^4.1.10","prettier":"^3.4.2","@eslint/js":"^9.18.0","typescript":"^5.7.3","@types/node":"^24.13.3","@types/express":"^5.0.0","typescript-eslint":"^8.19.1","@types/cross-spawn":"^6.0.6","eslint-config-prettier":"^9.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agent-connect_1.0.0_1785575139868_0.8896453014928478","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@capsbharg/agent-connect","version":"1.0.1","keywords":["slack","telegram","claude","claude-code","cursor","codex","anthropic","ai-agent","llm","chatops","devops","automation","bullmq","redis","middleware","framework"],"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"license":"MIT","_id":"@capsbharg/agent-connect@1.0.1","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"homepage":"https://github.com/CapsBharg/agent-connect","bugs":{"url":"https://github.com/CapsBharg/agent-connect/issues"},"bin":{"agent-connect":"dist/cli/index.js"},"dist":{"shasum":"cb2357449a16447fe9776cf6aba68fd2b637f072","tarball":"https://registry.npmjs.org/@capsbharg/agent-connect/-/agent-connect-1.0.1.tgz","fileCount":11,"integrity":"sha512-a0J6FpjHAuVUZNRde8dri4P89j1xiKIvcKy2jKo2kb83ejYYOvg0y/imPTVx1u03Uw+fR3pkCey+CYdroAAYwg==","signatures":[{"sig":"MEUCIQCsAmO3p+wM0fHXjBI1kixmBPmAvFFvdh6bbYu2d3Z6lAIgDMk6rHLDKAxYlZwcz6U8gR34Ksu0J+VNygDwLzsG8Hs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":554654},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"8b1812abdb1e89f14a143117940236bda119766f","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","start":"node --enable-source-maps dist/cli/index.js","format":"prettier --write .","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"repository":{"url":"git+https://github.com/Capsbharg/agent-connect.git","type":"git"},"_npmVersion":"11.16.0","description":"Universal middleware between messaging platforms (Slack, Telegram, ...) and AI coding agents (Claude Code, Cursor, Codex, ...).","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.24.1","pino":"^9.6.0","bullmq":"^5.34.6","dotenv":"^17.4.2","grammy":"^1.31.0","express":"^5.2.1","ioredis":"^5.4.2","tree-kill":"^1.2.2","@slack/bolt":"^5.0.0","cross-spawn":"^7.0.6","pino-pretty":"^13.0.0","@clack/prompts":"^0.9.1","@slack/web-api":"^8.0.0","@bull-board/api":"^8.3.0","@bull-board/express":"^8.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.18.0","vitest":"^4.1.10","prettier":"^3.4.2","@eslint/js":"^9.18.0","typescript":"^5.7.3","@types/node":"^24.13.3","@types/express":"^5.0.0","typescript-eslint":"^8.19.1","@types/cross-spawn":"^6.0.6","eslint-config-prettier":"^9.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agent-connect_1.0.1_1785579266592_0.5645053293516362","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@capsbharg/agent-connect","version":"1.1.0","keywords":["slack","telegram","claude","claude-code","cursor","codex","gemini","gemini-cli","anthropic","ai-agent","llm","chatops","devops","automation","bullmq","redis","middleware","framework"],"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"license":"MIT","_id":"@capsbharg/agent-connect@1.1.0","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"homepage":"https://github.com/CapsBharg/agent-connect","bugs":{"url":"https://github.com/CapsBharg/agent-connect/issues"},"bin":{"agent-connect":"dist/cli/index.js"},"dist":{"shasum":"2167ea767fb670d7a5aa71ee8081dd9e5a37d3ce","tarball":"https://registry.npmjs.org/@capsbharg/agent-connect/-/agent-connect-1.1.0.tgz","fileCount":11,"integrity":"sha512-wMJoa/qjHiMN8Z/7xEJpTmeQqLMwK/A2flw9NVREwhoXDZ38yUjKBoAwnSvNFh0pPJgykuK2CsUdZVROGxSPSA==","signatures":[{"sig":"MEYCIQD9MrxNoleNKLXZh2WyoFMDzxeMcipIF0P7LX/g4htm/QIhAPVDTWSx6ph1+QQm9C+9b7Nxtc676UxDUbIW5MVYUvIS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":709572},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"fe8cc7aca7aafafb1057ef6ae698c2f2ec520786","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","start":"node --enable-source-maps dist/cli/index.js","format":"prettier --write .","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"repository":{"url":"git+https://github.com/Capsbharg/agent-connect.git","type":"git"},"_npmVersion":"11.16.0","description":"Universal middleware between messaging platforms (Slack, Telegram, ...) and AI coding agents (Claude Code, Cursor, Codex, ...).","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.24.1","pino":"^9.6.0","bullmq":"^5.34.6","dotenv":"^17.4.2","grammy":"^1.31.0","express":"^5.2.1","ioredis":"^5.4.2","tree-kill":"^1.2.2","@slack/bolt":"^5.0.0","cross-spawn":"^7.0.6","pino-pretty":"^13.0.0","@clack/prompts":"^0.9.1","@slack/web-api":"^8.0.0","@bull-board/api":"^8.3.0","@bull-board/express":"^8.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.18.0","vitest":"^4.1.10","prettier":"^3.4.2","@eslint/js":"^9.18.0","typescript":"^5.7.3","@types/node":"^24.13.3","@types/express":"^5.0.0","typescript-eslint":"^8.19.1","@types/cross-spawn":"^6.0.6","eslint-config-prettier":"^9.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agent-connect_1.1.0_1788534701304_0.3838379961522844","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@capsbharg/agent-connect","version":"1.2.0","keywords":["slack","telegram","discord","claude","claude-code","cursor","codex","gemini","gemini-cli","anthropic","ai-agent","llm","chatops","devops","automation","bullmq","redis","middleware","framework"],"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"license":"MIT","_id":"@capsbharg/agent-connect@1.2.0","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"homepage":"https://github.com/CapsBharg/agent-connect","bugs":{"url":"https://github.com/CapsBharg/agent-connect/issues"},"bin":{"agent-connect":"dist/cli/index.js"},"dist":{"shasum":"ee00c23c6daafde98562f2c8f512cac01cd507bc","tarball":"https://registry.npmjs.org/@capsbharg/agent-connect/-/agent-connect-1.2.0.tgz","fileCount":11,"integrity":"sha512-Dj5xfkLXqXHDoTw12XSHKbWLdfwrK0QnUDuAdk8ce1jjPotxl1mjjZI0HeOKW1ciBiLJp0NV1HMrOSQ7KZxODQ==","signatures":[{"sig":"MEUCIQDgLWLZA57Q8HLPZt/hlr3IeAX815plFwE2RJ0sd3gCkAIgYxzrLNJQ6WgNLo6Xmxqu/suhL5ZY2frcLOMGmoMHfQ8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":839440},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"bed7495ae2808e82943ed62097e4e4489d64422d","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","start":"node --enable-source-maps dist/cli/index.js","format":"prettier --write .","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"repository":{"url":"git+https://github.com/Capsbharg/agent-connect.git","type":"git"},"_npmVersion":"11.16.0","description":"Universal middleware between messaging platforms (Slack, Telegram, Discord, ...) and AI coding agents (Claude Code, Cursor, Codex, Gemini, ...).","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.24.1","pino":"^9.6.0","bullmq":"^5.34.6","dotenv":"^17.4.2","grammy":"^1.31.0","express":"^5.2.1","ioredis":"^5.4.2","tree-kill":"^1.2.2","discord.js":"^14.27.0","@slack/bolt":"^5.0.0","cross-spawn":"^7.0.6","pino-pretty":"^13.0.0","@clack/prompts":"^0.9.1","@slack/web-api":"^8.0.0","@bull-board/api":"^8.3.0","@bull-board/express":"^8.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.18.0","vitest":"^4.1.10","prettier":"^3.4.2","@eslint/js":"^9.18.0","typescript":"^5.7.3","@types/node":"^24.13.3","@types/express":"^5.0.0","typescript-eslint":"^8.19.1","@types/cross-spawn":"^6.0.6","eslint-config-prettier":"^9.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agent-connect_1.2.0_1788875715058_0.8286818504273818","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@capsbharg/agent-connect","version":"1.3.0","description":"Universal middleware between messaging platforms (Slack, Telegram, Discord, ...) and AI coding agents (Claude Code, Cursor, Codex, Gemini, ...).","type":"module","repository":{"type":"git","url":"git+https://github.com/Capsbharg/agent-connect.git"},"homepage":"https://github.com/CapsBharg/agent-connect","bugs":{"url":"https://github.com/CapsBharg/agent-connect/issues"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"bin":{"agent-connect":"dist/cli/index.js"},"engines":{"node":">=20"},"scripts":{"build":"tsup","dev":"tsup --watch","start":"node --enable-source-maps dist/cli/index.js","test":"vitest run","test:watch":"vitest","lint":"eslint .","lint:fix":"eslint . --fix","format":"prettier --write .","format:check":"prettier --check .","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["slack","telegram","discord","claude","claude-code","cursor","codex","gemini","gemini-cli","anthropic","ai-agent","llm","chatops","devops","automation","bullmq","redis","middleware","framework"],"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"license":"MIT","publishConfig":{"access":"public"},"dependencies":{"@bull-board/api":"^8.3.0","@bull-board/express":"^8.3.0","@clack/prompts":"^0.9.1","@slack/bolt":"^5.0.0","@slack/web-api":"^8.0.0","bullmq":"^5.34.6","cross-spawn":"^7.0.6","discord.js":"^14.27.0","dotenv":"^17.4.2","express":"^5.2.1","grammy":"^1.31.0","ioredis":"^5.4.2","pino":"^9.6.0","pino-pretty":"^13.0.0","tree-kill":"^1.2.2","zod":"^3.24.1"},"devDependencies":{"@eslint/js":"^9.18.0","@types/cross-spawn":"^6.0.6","@types/express":"^5.0.0","@types/node":"^24.13.3","eslint":"^9.18.0","eslint-config-prettier":"^9.1.0","prettier":"^3.4.2","tsup":"^8.3.5","typescript":"^5.7.3","typescript-eslint":"^8.19.1","vitest":"^4.1.10"},"gitHead":"9f32f743e49342f9f6a803fbd7a6e801b7872b25","_id":"@capsbharg/agent-connect@1.3.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-VHJTMKXAhcRO9p6hB9xgWm2MgZEXRjmP7o5sJ40e4A2bq3cryjm1tkcK+et1bbj1+L1pM6MUzyANur/c7C+hcQ==","shasum":"aaa9c767cc02ef18ebc478b6bbdf5cd00c34af89","tarball":"https://registry.npmjs.org/@capsbharg/agent-connect/-/agent-connect-1.3.0.tgz","fileCount":11,"unpackedSize":852010,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBD9VTPskLRHub2Fj6TDc+ee/Gs+U806MmYboHUKZTwHAiA2IDnOBQne6GjiG2jRc14FLpCmGqHjvbylihYmSIhTHw=="}]},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"directories":{},"maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-connect_1.3.0_1788876873871_0.9989982929297041"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-01T09:05:39.735Z","modified":"2026-09-08T14:14:34.203Z","1.0.0":"2026-08-01T09:05:40.046Z","1.0.1":"2026-08-01T10:14:26.756Z","1.1.0":"2026-09-04T15:11:41.464Z","1.2.0":"2026-09-08T13:55:15.220Z","1.3.0":"2026-09-08T14:14:34.034Z"},"bugs":{"url":"https://github.com/CapsBharg/agent-connect/issues"},"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"license":"MIT","homepage":"https://github.com/CapsBharg/agent-connect","keywords":["slack","telegram","discord","claude","claude-code","cursor","codex","gemini","gemini-cli","anthropic","ai-agent","llm","chatops","devops","automation","bullmq","redis","middleware","framework"],"repository":{"type":"git","url":"git+https://github.com/Capsbharg/agent-connect.git"},"description":"Universal middleware between messaging platforms (Slack, Telegram, Discord, ...) and AI coding agents (Claude Code, Cursor, Codex, Gemini, ...).","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"readme":"# ⚡ Agent Connect\n\n**Universal middleware between messaging platforms and AI coding agents.**\n\nMention a bot on Slack, Telegram, or Discord, pick a project, hand it a task — and watch Claude Code, Cursor, Codex, or Gemini work in real time, streamed right back into your conversation.\n\n[![CI](https://github.com/Capsbharg/agent-connect/actions/workflows/ci.yml/badge.svg)](https://github.com/Capsbharg/agent-connect/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n[![Queue: BullMQ](https://img.shields.io/badge/queue-BullMQ-DC382D?logo=redis&logoColor=white)](https://bullmq.io/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](#contributing)\n[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-FFDD00?logo=buymeacoffee&logoColor=black)](https://buymeacoffee.com/capsbharg)\n\n```mermaid\nflowchart LR\n    A[\"💬 Slack / Telegram / Discord\"] --> B[\"🧭 Router\"]\n    B --> C[\"🗂️ Queue\"]\n    C --> D[\"🤖 Claude / Cursor / Codex / Gemini\"]\n    D --> E[\"📡 streamed progress\"]\n    E --> A\n```\n\nEvery messaging platform looks the same to the core. Every AI agent looks the same to the core. Adding a new one of either means implementing a single interface — nothing else changes.\n\n---\n\n## 📚 Table of Contents\n\n- [✨ Features](#features)\n- [📋 Prerequisites](#prerequisites)\n- [🚀 Quick Start](#quick-start)\n- [🤖 Creating Your Slack App](#creating-your-slack-app)\n- [✈️ Creating Your Telegram Bot](#creating-your-telegram-bot)\n- [🎮 Creating Your Discord Bot](#creating-your-discord-bot)\n- [🧠 Setting Up Your Agents](#setting-up-your-agents)\n- [⚙️ Environment Variables](#environment-variables)\n- [📁 Project Registry](#project-registry)\n- [▶️ Running the Application](#running-the-application)\n- [💬 Commands](#commands)\n- [🔄 Example Walkthrough](#example-walkthrough)\n- [🧩 Public API](#public-api)\n- [🛠️ CLI Reference](#cli-reference)\n- [📊 Queue Dashboard](#queue-dashboard)\n- [🏗️ Architecture](#architecture)\n- [🔒 Security Notes](#security-notes)\n- [📝 License](#license)\n- [🤝 Contributing](#contributing)\n- [☕ Support](#support)\n\n---\n\n<a id=\"features\"></a>\n\n## ✨ Features\n\n- 🗂️ **Multi-project support** — register any number of local repos, switch between them per-user with `use <project>`\n- 🤖 **Multi-agent** — Claude Code, Cursor, Codex, and Gemini can all be registered at once; each user picks their active one with `agent <name>`\n- 🌐 **Multi-platform** — Slack, Telegram, and Discord today, behind the same `MessagingAdapter` interface WhatsApp/Teams/etc. would use\n- 📡 **Live streaming** — progress streams into a single, continuously-updated message — no spam\n- 🚦 **Queued & serialized** — one execution per user at a time; extra prompts queue up automatically via BullMQ (or in-memory for local dev)\n- ⛔ **Cancellable** — stop everything with `cancel`, or a single execution by id with `cancel <id>` (`status` lists ids)\n- 🩺 **Health-checked** — every agent's CLI availability is checked on startup, via `agent-connect doctor`, and via the `health` chat command\n- 🚧 **Flood-guarded** — `MAX_QUEUED_PER_IDENTITY` caps how many executions one user can have outstanding at once\n- 🧩 **Plugin system** — hook `beforeMessage`/`afterMessage`/`beforeExecution`/`afterExecution`/`beforeReply`/`afterReply` and register new commands, without touching core\n- 🔒 **Safe by construction** — projects are an exact allowlist (no path traversal), every agent CLI is `spawn`ed with an argv array (never a shell string), executions are timeout-bounded\n- 🛠️ **CLI** — `npx @capsbharg/agent-connect init` scaffolds `.env`/`projects.json`/an example app; `npx @capsbharg/agent-connect doctor` verifies your setup\n\n---\n\n<a id=\"prerequisites\"></a>\n\n## 📋 Prerequisites\n\nBefore you start, make sure you have:\n\n1. **Node.js `>=20`** — check with `node --version`. ([nodejs.org](https://nodejs.org))\n2. **At least one AI agent CLI**, installed and authenticated:\n   - [Claude Code](https://docs.claude.com/en/docs/claude-code/overview) — `npm install -g @anthropic-ai/claude-code`, then `claude` once to log in. Enabled by default.\n   - [Cursor CLI](https://cursor.com/docs/cli) (`cursor-agent`) — optional, needs a `CURSOR_API_KEY`.\n   - [OpenAI Codex CLI](https://developers.openai.com/codex) (`codex`) — optional.\n   - [Gemini CLI](https://github.com/google-gemini/gemini-cli) (`gemini`) — `npm install -g @google/gemini-cli`, then `gemini` once to log in. Optional.\n3. **Redis 5.0+**, for production use — powers the BullMQ execution queue and per-user session storage. Optional for local dev/evaluation (an in-memory fallback is used automatically when `REDIS_URL` is unset — single process only, not for production). Any Redis-compatible server works ([Redis](https://redis.io/), [Memurai](https://www.memurai.com/) on Windows, etc.)\n4. **Credentials for at least one messaging platform** — a Slack app ([walkthrough below](#creating-your-slack-app)), a Telegram bot ([walkthrough below](#creating-your-telegram-bot)), and/or a Discord bot ([walkthrough below](#creating-your-discord-bot)). You can enable more than one at once.\n\n---\n\n<a id=\"quick-start\"></a>\n\n## 🚀 Quick Start\n\nAgent Connect is a normal npm package — install it into any project, no cloning or building required.\n\n**Step 1 — create a project and install the package:**\n\n```bash\nmkdir my-bot && cd my-bot\nnpm init -y\nnpm install @capsbharg/agent-connect\n```\n\n**Step 2 — get your credentials.** Follow [Creating Your Slack App](#creating-your-slack-app), [Creating Your Telegram Bot](#creating-your-telegram-bot), and/or [Creating Your Discord Bot](#creating-your-discord-bot) below — you'll be asked for these in the next step.\n\n**Step 3 — scaffold your config:**\n\n```bash\nnpx @capsbharg/agent-connect init\n```\n\nInteractively asks which platforms/agents to enable, your Slack/Telegram/Discord credentials, and your first project's absolute path — then writes `.env`, `projects.json`, and `agent-connect.example.mjs` into the current directory, and automatically runs `doctor` to verify everything (agent CLI(s) on `PATH`, Redis reachable if configured, platform tokens valid).\n\n**Step 4 — run it:**\n\n```bash\nnode agent-connect.example.mjs\n```\n\n**Step 5 — try it.** In Slack, Telegram, or Discord, message the bot: `use my-app`, then give it a task (see [Example Walkthrough](#example-walkthrough)).\n\n> 🧪 **Want to see it working end-to-end first?** [`demo/`](demo/) in this repo is a complete, self-contained example — Slack adapter, the real Claude Code agent, a Redis-backed BullMQ queue, and the queue dashboard, all wired together. Copy the folder anywhere, `npm install`, fill in `.env`/`projects.json`, and `npm run slack`.\n\n---\n\n<a id=\"creating-your-slack-app\"></a>\n\n## 🤖 Creating Your Slack App\n\nYou'll need a Slack app with **Socket Mode** enabled, three **bot token scopes**, and two **event subscriptions**.\n\n### 1️⃣ Create the app\n\nGo to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App** → **From scratch** → name it (e.g. `Agent Connect`) and pick your workspace.\n\n### 2️⃣ Turn on Socket Mode\n\n- Sidebar → **Socket Mode** → toggle **on**.\n- Generate an **App-Level Token** with the scope `connections:write` (lets the bot open a Socket Mode connection).\n- Copy the token (starts with `xapp-`) → this is `SLACK_APP_TOKEN`.\n\n### 3️⃣ Add Bot Token Scopes\n\n**Features → OAuth & Permissions → Scopes → Bot Token Scopes** → add:\n\n| Scope               | Why                                                   |\n| ------------------- | ----------------------------------------------------- |\n| `app_mentions:read` | See messages that `@mention` the bot                  |\n| `chat:write`        | Post and edit messages (how streaming progress works) |\n| `im:history`        | Receive DMs sent directly to the bot                  |\n\n<details>\n<summary>Optional: respond to plain messages in channels (not just mentions)</summary>\n\nAdd `channels:history` (public channels), `groups:history` (private channels), and/or `mpim:history` (group DMs), and subscribe to the matching event(s) below (`message.channels`, `message.groups`, `message.mpim`). ⚠️ Noisy — every message becomes a potential command/prompt.\n</details>\n\n### 4️⃣ Subscribe to Events\n\n**Features → Event Subscriptions** → enable → **Subscribe to bot events** → add `app_mention` and `message.im` → **Save Changes**.\n\n### 5️⃣ Install the app\n\n**OAuth & Permissions** → **Install to Workspace** (or **Reinstall** if you added scopes after an earlier install) → **Allow**.\n\n### 6️⃣ Collect your credentials\n\n| Value                             | Where to find it                    | Goes in                |\n| --------------------------------- | ----------------------------------- | ---------------------- |\n| Bot User OAuth Token (`xoxb-...`) | OAuth & Permissions → top of page   | `SLACK_BOT_TOKEN`      |\n| Signing Secret                    | Basic Information → App Credentials | `SLACK_SIGNING_SECRET` |\n| App-Level Token (`xapp-...`)      | From step 2                         | `SLACK_APP_TOKEN`      |\n\n### 7️⃣ Say hello 👋\n\n`/invite @your-bot-name` in a channel, or just DM it directly — no invite needed for that.\n\n---\n\n<a id=\"creating-your-telegram-bot\"></a>\n\n## ✈️ Creating Your Telegram Bot\n\n### 1️⃣ Talk to BotFather\n\nOpen [@BotFather](https://t.me/BotFather) in Telegram → `/newbot` → follow the prompts (name, then a unique username ending in `bot`).\n\n### 2️⃣ Copy the token\n\nBotFather replies with a token like `123456789:AAExampleTokenHere`. That's your `TELEGRAM_BOT_TOKEN`.\n\n### 3️⃣ (Optional) tune group behavior\n\nBy default, Telegram's **group privacy mode** means the bot only sees, in groups: commands (`/help`), replies to its own messages, and `@mentions` of it — DMs are unaffected. To have it read every group message instead, message BotFather with `/setprivacy` → select your bot → **Disable**. Most setups should leave this on default (**Enabled**).\n\n### 4️⃣ Say hello 👋\n\nSearch for your bot's username in Telegram and start a private chat, or add it to a group.\n\n---\n\n<a id=\"creating-your-discord-bot\"></a>\n\n## 🎮 Creating Your Discord Bot\n\nYou'll need a Discord application with a bot user, two **privileged gateway intents**, and the right invite scopes.\n\n### 1️⃣ Create the application\n\nGo to the [Discord Developer Portal](https://discord.com/developers/applications) → **New Application** → name it (e.g. `Agent Connect`) → **Bot** in the sidebar → **Add Bot** if it isn't already there.\n\n### 2️⃣ Enable Privileged Gateway Intents\n\nStill on the **Bot** page, scroll to **Privileged Gateway Intents** and turn on:\n\n| Intent            | Why                                                                                            |\n| ----------------- | ---------------------------------------------------------------------------------------------- |\n| `MESSAGE CONTENT` | Without it, every message arrives with empty text                                              |\n| `SERVER MEMBERS`  | Not required for a fresh setup, but harmless to enable if you plan to extend the adapter later |\n\n### 3️⃣ Copy the token\n\n**Bot** page → **Reset Token** (if none is shown yet) → copy it. That's your `DISCORD_BOT_TOKEN`. Treat it like a password — anyone with it can control your bot.\n\n### 4️⃣ Invite the bot to a server\n\n**OAuth2 → URL Generator** → **Scopes**: check `bot` → **Bot Permissions**: check `Send Messages`, `Read Message History`, and `Attach Files` (if you want attachment support) → open the generated URL and pick a server.\n\n### 5️⃣ Say hello 👋\n\n`@your-bot-name` in a server channel it's in, or DM it directly — no invite needed for a DM.\n\n---\n\n<a id=\"setting-up-your-agents\"></a>\n\n## 🧠 Setting Up Your Agents\n\nAt least one agent must be enabled. You can enable more than one — each user picks their active one with `agent <name>`.\n\n### Claude Code (enabled by default)\n\n```bash\nnpm install -g @anthropic-ai/claude-code\nclaude   # run once interactively to authenticate\n```\n\n`.env`: `CLAUDE_ENABLED=true` (default), `CLAUDE_CLI_PATH=claude` (default, or an absolute path).\n\n### Cursor CLI (optional)\n\nInstall per [Cursor's CLI docs](https://cursor.com/docs/cli), then set in `.env`:\n\n```\nCURSOR_ENABLED=true\nCURSOR_API_KEY=your-cursor-api-key\n```\n\n### OpenAI Codex CLI (optional)\n\nInstall per [OpenAI's Codex CLI docs](https://developers.openai.com/codex), then set in `.env`:\n\n```\nCODEX_ENABLED=true\n```\n\n### Gemini CLI (optional)\n\n```bash\nnpm install -g @google/gemini-cli\ngemini   # run once interactively to authenticate\n```\n\n`.env`:\n\n```\nGEMINI_ENABLED=true\n```\n\nRun `npx @capsbharg/agent-connect doctor` after any of the above to confirm the CLI is found on `PATH` and responds to `--version`.\n\n---\n\n<a id=\"environment-variables\"></a>\n\n## ⚙️ Environment Variables\n\nThe full, current list — with defaults and descriptions — lives in [`.env.example`](.env.example). Highlights:\n\n| Variable                                                                 | Description                                                                                                                                          |\n| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `REDIS_URL`                                                              | Redis connection string; unset falls back to in-memory storage/queue (dev only)                                                                      |\n| `PROJECTS_CONFIG_PATH`                                                   | Path to the project registry JSON file (default `./projects.json`)                                                                                   |\n| `DEFAULT_AGENT`                                                          | Which registered agent handles a user's prompts until they run `agent <name>`                                                                        |\n| `AGENT_WORKER_CONCURRENCY`                                               | Max executions processed concurrently across all users (default `4`)                                                                                 |\n| `MAX_QUEUED_PER_IDENTITY`                                                | Max executions (running + queued) a single user may have outstanding at once; further prompts get a reminder instead (default `20`, `0` = unlimited) |\n| `REDIS_KEY_PREFIX`                                                       | Namespaces every Redis key this app owns — set it if `REDIS_URL` points at a Redis instance shared with other apps                                   |\n| `SLACK_BOT_TOKEN` / `SLACK_SIGNING_SECRET` / `SLACK_APP_TOKEN`           | Enable the Slack adapter                                                                                                                             |\n| `TELEGRAM_BOT_TOKEN`                                                     | Enable the Telegram adapter                                                                                                                          |\n| `DISCORD_BOT_TOKEN`                                                      | Enable the Discord adapter                                                                                                                           |\n| `CLAUDE_ENABLED` / `CURSOR_ENABLED` / `CODEX_ENABLED` / `GEMINI_ENABLED` | Enable each agent (Claude is on by default)                                                                                                          |\n| `CLAUDE_SKIP_PERMISSIONS` / `CURSOR_FORCE` / `GEMINI_YOLO`               | Run the CLI headless, bypassing its own per-action confirmation (default `true` for all three — see [Security Notes](#security-notes))               |\n| `ALLOWED_USERS` / `ALLOWED_CHANNELS` / `ALLOWED_GROUPS`                  | Security allowlists (comma-separated; empty = unrestricted — logged loudly as a warning on startup)                                                  |\n| `ADMIN_ENABLED` / `ADMIN_PORT`                                           | Optional queue dashboard (default on, port `3000`)                                                                                                   |\n\n🔐 Never commit `.env` — it's already excluded via `.gitignore`.\n\n---\n\n<a id=\"project-registry\"></a>\n\n## 📁 Project Registry\n\nAn agent only ever runs inside a project directory you've explicitly registered — **never** an arbitrary path. Map project names to absolute local paths in `projects.json`:\n\n```json\n{\n  \"backend-api\": \"/path/to/your/backend-api\",\n  \"frontend-web\": \"/path/to/your/frontend-web\",\n  \"mobile-app\": {\n    \"path\": \"/path/to/your/mobile-app\",\n    \"agent\": \"cursor\",\n    \"model\": \"gpt-5\"\n  }\n}\n```\n\n`projects.json` is gitignored (it contains your local filesystem layout). Entries whose path doesn't exist are skipped at startup with a logged warning. `use <project>` matches names **exactly** against a key in this file — user input is never concatenated into a filesystem path, so there's no path-traversal risk from the project name itself.\n\n**Per-project agent/model overrides.** Each entry can be a plain path string (as above) or an object `{ path, agent?, model? }`:\n\n- `agent` — the default agent for this project (e.g. `\"cursor\"`), overriding `DEFAULT_AGENT`. A user's own `agent <name>` selection always wins over this — the override only kicks in when nobody's explicitly chosen an agent yet.\n- `model` — passed straight through to whichever agent runs, as `--model`/`-m`. Useful for pinning a specific project to a stronger (or cheaper/faster) model than the rest of your projects.\n\nBoth are optional and independent — set either, both, or neither per project.\n\n---\n\n<a id=\"running-the-application\"></a>\n\n## ▶️ Running the Application\n\nFor the entrypoint `npx @capsbharg/agent-connect init` generated for you:\n\n```bash\nnode agent-connect.example.mjs\n```\n\nFor a fuller reference (Slack + real Claude Code agent + Redis-backed queue + dashboard), see [`demo/`](demo/) — self-contained, `npm install` and `npm run slack`.\n\nFor your own entrypoint (`AgentConnect.fromEnv()` or explicit DI — see [Public API](#public-api)):\n\n```bash\nnode your-entrypoint.mjs\n```\n\nOn success you'll see log lines like:\n\n```\n[INFO] Slack adapter connected (Socket Mode)\n[INFO] Telegram adapter connected (long polling)\n[INFO] Discord adapter connected (gateway)\n[INFO] Queue dashboard: http://127.0.0.1:3000/admin/queues\n[INFO] AgentConnect started\n```\n\nStop it with `Ctrl+C` (`SIGINT`) — the example entrypoint handles graceful shutdown.\n\n---\n\n<a id=\"commands\"></a>\n\n## 💬 Commands\n\nSend these as a Slack mention/DM, a Telegram message/`/command`, or a Discord mention/DM. Anything else is treated as a prompt and sent to your active agent.\n\n| Command            | Description                                                              |\n| ------------------ | ------------------------------------------------------------------------ |\n| 🆘 `help`          | List available commands                                                  |\n| 📂 `projects`      | List projects available in the registry                                  |\n| 📍 `current`       | Show your currently active project                                       |\n| 🔀 `use <project>` | Switch your active project                                               |\n| 🤖 `agents`        | List registered agents                                                   |\n| 🔁 `agent [name]`  | Show or switch which agent handles your prompts                          |\n| 📊 `status`        | Show your running/queued executions (with their ids)                     |\n| ⛔ `cancel [id]`   | Stop/clear everything, or cancel just one execution by id (see `status`) |\n| 🩺 `health`        | Check every registered agent's CLI/availability                          |\n| 🧹 `clear`         | Clear your active project selection                                      |\n\nEach user's active project/agent is stored independently and survives a restart. A prompt sent with no active project gets a reminder to run `use <project>` first. Plugins can register additional commands — see [docs/plugin-guide.md](docs/plugin-guide.md).\n\n---\n\n<a id=\"example-walkthrough\"></a>\n\n## 🔄 Example Walkthrough\n\n```\n@your-bot-name use backend-api\n@your-bot-name Implement JWT authentication\n```\n\nThe bot immediately acknowledges the request, then picks it up from the queue, runs your active agent inside `backend-api`'s directory, and streams progress into a single, continuously-updated message:\n\n```\n🤖 Working on: Implement JWT authentication\n\nReading `src/auth.js`...\nEditing `src/middleware/jwt.js`...\nRunning `npm test`...\n\n✅ Done.\n...\n```\n\nOnly one execution runs per user at a time — additional prompts from the same user queue up and run in order. `status` shows what's running/queued; `cancel` stops the current run and clears anything still queued. Want a different agent for this task? `agent cursor` (or `codex`) switches it before your next prompt.\n\n**Multi-turn conversations.** With Claude, Codex, or Gemini, your next prompt in the same project automatically continues the previous conversation instead of starting fresh each time — the agent keeps whatever context it built up. Run `use <project>` again (even re-selecting the project you're already in) to intentionally start a new conversation. If a stored conversation ever becomes stale (expired, pruned by the CLI, lost across an upgrade), the next prompt detects the failed resume and automatically starts a fresh conversation instead of retrying the same broken one forever. Cursor doesn't support this yet — see [docs/architecture.md](docs/architecture.md) for why.\n\n**File attachments.** On Telegram or Discord, attach a file to your message — it's downloaded into the project (under `.agent-connect-attachments/`, cleaned up after each run) and the agent is told where to find it, so it can read the file with its own tools if relevant. Attachments that share the same filename (e.g. two screenshots both named `image.png`) are kept as separate files rather than one overwriting the other.\n\n---\n\n<a id=\"public-api\"></a>\n\n## 🧩 Public API\n\n```js\nimport {\n  AgentConnect,\n  SlackAdapter,\n  TelegramAdapter,\n  DiscordAdapter,\n  ClaudeAgent,\n  CursorAgent,\n  CodexAgent,\n  GeminiAgent,\n} from '@capsbharg/agent-connect';\n\nconst app = new AgentConnect({\n  messaging: [new SlackAdapter(), new TelegramAdapter(), new DiscordAdapter()],\n  agents: [new ClaudeAgent(), new CursorAgent(), new CodexAgent(), new GeminiAgent()],\n});\n\nawait app.start();\n```\n\nOr let it configure itself entirely from `.env`:\n\n```js\nimport { AgentConnect } from '@capsbharg/agent-connect';\n\nconst app = AgentConnect.fromEnv();\nawait app.start();\n```\n\nSee [docs/developer-guide.md](docs/developer-guide.md) for the full options reference and [docs/api-reference.md](docs/api-reference.md) for the complete public surface.\n\n---\n\n<a id=\"cli-reference\"></a>\n\n## 🛠️ CLI Reference\n\n| Command                               | What it does                                                                                                                                                |\n| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `npx @capsbharg/agent-connect init`   | Interactively writes `.env`, `projects.json`, and an example entrypoint into the current directory, then runs `doctor`                                      |\n| `npx @capsbharg/agent-connect doctor` | Checks agent CLIs are on `PATH` (`--version`), pings Redis if configured, and validates Slack (`auth.test`)/Telegram (`getMe`)/Discord (`users/@me`) tokens |\n| `npx @capsbharg/agent-connect --help` | Show usage                                                                                                                                                  |\n\n---\n\n<a id=\"queue-dashboard\"></a>\n\n## 📊 Queue Dashboard\n\nWith `ADMIN_ENABLED=true` (the default) and a Redis-backed queue, starting the app also starts a [Bull Board](https://github.com/felixmosh/bull-board) dashboard at:\n\n```\nhttp://127.0.0.1:3000/admin/queues\n```\n\n(using `ADMIN_PORT`), showing the execution queue's waiting/active/completed/failed/delayed jobs. It's bound to `127.0.0.1` only (no auth of its own) and should never be exposed beyond localhost. Set `ADMIN_ENABLED=false` to disable it. Only available when a Redis-backed queue is in use (not the in-memory fallback).\n\n---\n\n<a id=\"architecture\"></a>\n\n## 🏗️ Architecture\n\nClean Architecture, SOLID, dependency injection, adapter pattern — every messaging platform and every AI agent is a swappable implementation of a small interface. See [docs/architecture.md](docs/architecture.md) for the full flow diagram and module map, [docs/plugin-guide.md](docs/plugin-guide.md) for extending it without touching core, and [docs/migration-guide.md](docs/migration-guide.md) if you're coming from the original Slack-only bot.\n\n---\n\n<a id=\"security-notes\"></a>\n\n## 🔒 Security Notes\n\n- **Agents run headless, with no per-action confirmation.** `ClaudeAgent` always passes `--dangerously-skip-permissions`, `CursorAgent` always passes `--force`, and `GeminiAgent` always passes `--yolo` by default (`CLAUDE_SKIP_PERMISSIONS` / `CURSOR_FORCE` / `GEMINI_YOLO`, all default `true`) — this is what lets them respond to a chat message without a human watching a terminal to approve each file write/command. It also means **any user who is authorized to prompt the bot can direct arbitrary file writes and shell command execution inside whichever project is active**, with no human-in-the-loop gate after that point. `CodexAgent` is comparatively safer by default (`--sandbox workspace-write`).\n- **`ALLOWED_USERS`/`ALLOWED_CHANNELS`/`ALLOWED_GROUPS` are the actual restriction, not headless mode.** Leave them blank and _everyone_ who can message the bot (every member of the Slack workspace/Telegram chat/Discord server it's in) gets the access described above, to every registered project. AgentConnect logs a loud startup warning when all three are empty — set at least `ALLOWED_USERS` before anything beyond solo/local use.\n- `projects.json` and `.env` are both gitignored — they hold your real local paths and platform credentials respectively. Never commit them or paste their contents into an issue/PR.\n- Only entries in your own `projects.json` are ever reachable; `use <project>` matches project names as an exact allowlist lookup, never as a filesystem path built from user input.\n- Every agent CLI is always launched via `spawn` with an argv array — never a shell string — so prompts can never be interpreted as shell commands.\n- `MAX_QUEUED_PER_IDENTITY` (default `20`) caps how many executions a single user can have running/queued at once, so one user flooding the bot with prompts can't monopolize every worker slot.\n- `REDIS_KEY_PREFIX` namespaces this app's keys if you point `REDIS_URL` at a Redis instance shared with other applications.\n- The admin dashboard (`/admin/queues`) is bound to `127.0.0.1` and has no authentication of its own — don't expose it beyond localhost.\n- Found a vulnerability? See [SECURITY.md](SECURITY.md) for how to report it.\n\n---\n\n<a id=\"license\"></a>\n\n## 📝 License\n\n[MIT](LICENSE) — free to use, modify, and distribute.\n\n---\n\n<a id=\"contributing\"></a>\n\n## 🤝 Contributing\n\nIssues and PRs welcome! Adding a new messaging platform or AI agent should only ever require implementing `MessagingAdapter` or `AgentAdapter` (see `src/interfaces/`) — if a contribution needs to touch `core/router`, `core/execution`, or `core/commands` to add a platform/agent, something's off with the abstraction. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow (setup, tests, lint, PR checklist) and [SECURITY.md](SECURITY.md) to report a vulnerability privately.\n\n---\n\n<a id=\"support\"></a>\n\n## ☕ Support\n\nAgent Connect is built by Capsbharg, a small, early-stage startup — no big-company backing, no war chest, just a small team building tools we genuinely wanted to exist and betting that other people want them too.\n\nIf it's saved you an hour of wiring, made your team's workflow a little more magical, or you just want to see it keep growing — more platforms, more agents, more polish — [buying us a coffee](https://buymeacoffee.com/capsbharg) genuinely helps. It's not a paywall and it never will be; everything here stays free and open. But every coffee is a real vote that this is worth keeping alive, and for a young startup, that support is what buys the runway to keep building instead of quietly shelving it.\n\n<a href=\"https://buymeacoffee.com/capsbharg\"><img src=\"https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=☕&slug=capsbharg&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff\" alt=\"Buy Me A Coffee\" /></a>\n\nThank you for using Agent Connect — truly. 🙏\n","readmeFilename":"README.md"}