AgentCliBridge
Bridges CLI-based AI agents (Claude, Codex, Gemini) to chat platforms (Telegram, Discord) with scheduled a uto-tasks, autonomous project management, HITL approval, conditional branching, webhook triggers, parallel execution, and ob servability
Install / Use
/learn @Emqo/AgentCliBridgeQuality Score
Category
Development & EngineeringSupported Platforms
README
AgentCliBridge
<p align="center"> <a href="#english">English</a> | <a href="#中文">中文</a> </p><a name="english"></a>
Bridge CLI-based AI agents (claude, codex, gemini) to chat platforms (Telegram, Discord). Spawns the CLI as a subprocess with JSON streaming — no SDK dependency, just raw CLI power.
Features
Core
- Multi-platform: Telegram (raw Bot API long polling) + Discord (discord.js)
- Streaming responses: Real-time message editing as Claude thinks
- Multi-endpoint rotation: Round-robin with auto-cooldown on 429/401/529
- Session persistence: SQLite-backed session resume via
-r <session_id> - Per-user workspace isolation: Each user gets their own working directory
- File uploads: Send files to Claude for analysis
- Access control: User/group whitelist
- Hot reload: Edit
config.yaml, changes apply instantly - i18n: English + Chinese
Skill System (v0.2.0+)
Instead of hardcoded commands, AgentCliBridge injects a skill document into Claude's system prompt. Claude naturally understands it can manage memories, tasks, reminders, and auto-tasks by calling agent-cli-bridge-ctl through the Bash tool. Just talk naturally:
- "remember I like TypeScript" → Claude calls
ctl memory add - "remind me in 5 minutes" → Claude calls
ctl reminder add - "optimize the whole project" → Claude decomposes into multiple auto-tasks
v0.5.0: Agent Gateway Features
- Human-in-the-Loop (HITL): Critical tasks require user approval via inline buttons (Telegram) or commands (Discord) before execution
- Conditional Branching: Scout pattern — task 1 analyzes, saves results, dynamically creates follow-up tasks with
--parentlinking - Webhook Triggers: HTTP API + GitHub webhooks + cron scheduler — trigger auto-tasks from external systems
- Parallel Execution: Multiple
claudeinstances running simultaneously (max_parallelconfig) - Observability:
/statuscommand shows task queue, chain progress, and execution stats
v0.10.0: Dispatcher Architecture (Master-Worker Sessions)
- Dispatcher (Master Session): Every user has a single dispatcher that receives all messages and routes them to the correct sub-session. Users never interact with sub-sessions directly
- Intelligent Routing: Fast path ($0) for 0-1 active sessions; Claude-powered classification with user memories + session summaries for 2+ sessions
- Session Summaries: Each sub-session maintains an auto-generated summary, giving the dispatcher context about what each conversation is doing
- Memory-Aware Dispatch: Dispatcher sees user memories + all active session summaries when classifying, enabling accurate routing even for ambiguous messages
- Concurrent Sub-Sessions: Multiple sub-sessions execute in parallel with per-session locks
Quick Start
Global Install (npm)
npm i -g @emqo/agent-cli-bridge
agent-cli-bridge init # generate config.yaml from template
# edit config.yaml — set endpoints, tokens, whitelist
agent-cli-bridge start -f # foreground
agent-cli-bridge start # background (daemon)
agent-cli-bridge status # check if running
agent-cli-bridge reload # hot reload config
agent-cli-bridge stop # stop daemon
Short aliases: acb = agent-cli-bridge, acb-ctl = agent-cli-bridge-ctl.
acb init && acb start -f # same as above, shorter
From Source
git clone https://github.com/Emqo/AgentCliBridge.git
cd AgentCliBridge
npm install
cp config.yaml.example config.yaml
# edit config.yaml
npm run build
npm start
Configuration
All config lives in config.yaml (full template):
endpoints:
- name: "my-endpoint"
base_url: ""
api_key: "sk-..."
model: "claude-sonnet-4-20250514"
locale: en # "zh" for Chinese
agent:
allowed_tools: [Read, Edit, Bash, Grep, Glob, WebSearch, WebFetch]
permission_mode: "acceptEdits"
max_turns: 50
max_budget_usd: 2.0
max_parallel: 1 # concurrent auto-task execution (1 = sequential)
timeout_seconds: 300
memory:
enabled: true
auto_summary: true
max_memories: 50
skill:
enabled: true
session:
enabled: true
max_per_user: 3
idle_timeout_minutes: 30
dispatcher_budget: 0.05
workspace:
base_dir: "./workspaces"
isolation: true
access:
allowed_users: ["your_user_id"]
allowed_groups: []
platforms:
telegram:
enabled: true
token: "your-bot-token"
chunk_size: 4000
discord:
enabled: false
token: ""
chunk_size: 1900
# Webhook server for external triggers
webhook:
enabled: false
port: 3100
token: "your-bearer-token"
github_secret: ""
# Scheduled auto-tasks
cron:
- schedule_minutes: 60
user_id: "123456"
platform: "telegram"
chat_id: "123456"
description: "Generate daily status report"
Leave endpoints empty to use claude CLI's own authentication.
Platform Commands
| Telegram | Discord | Action | |----------|---------|--------| | /new | !new | Clear session | | /usage | !usage | Your usage stats | | /allusage | !allusage | All users stats | | /history | !history | Recent conversations | | /model | !model | Endpoint info | | /status | !status | Auto task status & progress | | /reload | !reload | Hot reload config | | /help | !help | Show help |
Discord also supports: !approve <id>, !reject <id> for HITL approval.
All other interactions are handled naturally by Claude through the skill system — no command prefix needed.
HITL (Human-in-the-Loop)
When Claude determines a task is critical (deployment, deletion, production changes), it uses ctl auto add-approval instead of ctl auto add. The task enters approval_pending status:
- Telegram: Inline keyboard with Approve / Reject buttons
- Discord: Bot sends approval request, user replies
!approve <id>or!reject <id>
Only after approval does the task enter the execution queue.
Conditional Branching (Scout Pattern)
Tasks can be linked via --parent <id> to form chains:
Task #1 (scout): "Analyze performance bottlenecks"
→ Finds 3 issues, creates child tasks:
Task #2: "Fix N+1 queries" (--parent 1)
Task #3: "Add caching layer" (--parent 1)
Task #4: "Run benchmarks" (--parent 1)
Chain progress is reported automatically: Chain #1 progress: 2/4 done
Results are persisted via ctl auto result <id> "summary" and cross-task context flows through the memory system.
Webhook & Cron
HTTP API
# Health check
curl http://localhost:3100/health
# Create auto-task
curl -X POST http://localhost:3100/api/task \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"user_id":"123","platform":"telegram","chat_id":"123","description":"analyze logs"}'
# Create approval-required task
curl -X POST http://localhost:3100/api/task \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"user_id":"123","platform":"telegram","chat_id":"123","description":"deploy to prod","approval":true}'
GitHub Webhooks
POST http://your-server:3100/webhook/github?user_id=123&platform=telegram&chat_id=123
Configure in GitHub repo Settings → Webhooks. Supports push, pull_request, issues events with HMAC-SHA256 signature verification.
Cron
cron:
- schedule_minutes: 60
user_id: "123"
platform: "telegram"
chat_id: "123"
description: "Check server health and report anomalies"
Parallel Execution
Set max_parallel: N to run N auto-tasks simultaneously. Each spawns an independent claude process with:
- No session sharing (prevents conflicts)
- Shared memories (cross-task context via SQLite)
- Endpoint rotation (distributes load)
agent:
max_parallel: 3 # 3 concurrent claude instances
Architecture
src/
cli.ts CLI: start/stop/status/reload/init with PID management
index.ts Entry point, config loading, hot reload, webhook startup
ctl.ts agent-cli-bridge-ctl: memory/task/reminder/auto ops via SQLite
webhook.ts HTTP server + GitHub webhooks + cron scheduler
core/
agent.ts CLI subprocess spawner via provider system + session summary sync
config.ts YAML config with env fallback
keys.ts Endpoint round-robin with cooldown
lock.ts Per-user/per-session concurrency mutex (Redis or in-memory)
store.ts SQLite (WAL): sessions, usage, history, memories, tasks
router.ts Dispatcher: message routing with memories + session summaries
session.ts Sub-session lifecycle management
permissions.ts Whitelist access control
markdown.ts Markdown → Telegram MarkdownV2
i18n.ts Internationalization (en/zh)
adapters/
base.ts Adapter interface + chunkText utility
telegram.ts Telegram Bot API (raw fetch, long polling, inline buttons)
discord.ts Discord.js (@mentions + DMs + approval commands)
skills/
bridge.ts Skill document generator (bilingual, injected via --append-system-prompt)
Data Flow
User message → Adapter → Access check
↓
Dispatcher (master session)
├─ Fast path: 0-1 sessions → direct route ($0)
└─ Classify: 2+ sessions → Claude call (memories + summaries)
↓
Sub-session execution (per-session lock)
├─ Inject memories + skill doc → spawn claude CLI
├─ Stream response back to adapter
└─ Post: save history, sync summary, auto-summarize to shared memory
Prerequisites
- Node.js 18+
- At least one supported CLI installed
