Skip to content

Commit 73b5ac7

Browse files
htekdevCopilot
andauthored
article: Who Needs OpenClaw When You Have Copilot CLI Extensions? (#120)
Tells the story of building a Telegram bridge to Copilot CLI in one file, the bugs we hit, the OpenClaw comparison, and the future vision with NVIDIA OpenShell for Safe OpenClaw. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9d7c4a0 commit 73b5ac7

1 file changed

Lines changed: 142 additions & 0 deletions

File tree

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: "Who Needs OpenClaw When You Have GitHub Copilot CLI Extensions?"
3+
description: >-
4+
I built a Telegram bridge to GitHub Copilot CLI in one file. ~420 lines. No
5+
gateway, no daemon, no framework. Here's how the extension SDK makes full
6+
agent frameworks feel like overkill — and what happens when you add NVIDIA
7+
OpenShell to the mix.
8+
pubDate: 2026-04-03
9+
tags:
10+
- AI
11+
- GitHub Copilot
12+
- Telegram
13+
- Developer Tools
14+
- NVIDIA OpenShell
15+
draft: false
16+
---
17+
18+
I was lying in bed last night thinking about [OpenClaw](https://github.com/openclaw/openclaw) — the open-source personal AI assistant framework that connects to 20+ messaging channels (WhatsApp, Telegram, Slack, Discord, Signal, iMessage, Teams, IRC, Matrix...). It's an impressive project. Gateway daemon, WebSocket control plane, custom agent runtime, multi-agent routing, onboarding wizard, companion apps, voice wake words, live canvas. Thousands of lines of infrastructure code.
19+
20+
Then I thought: **what if I could do the core thing — chat with an AI coding agent from my phone — in a single file?**
21+
22+
Turns out, you can.
23+
24+
## The Extension
25+
26+
GitHub Copilot CLI has an extension system. You drop an `.mjs` file in `.github/extensions/`, and it gets forked as a child process with access to the full session via JSON-RPC. The SDK gives you everything:
27+
28+
- **`session.send()`** — inject prompts programmatically
29+
- **`session.on("assistant.message")`** — capture responses in real-time
30+
- **Custom tools** — register new tools the agent can call
31+
- **Lifecycle hooks** — react to session start, end, errors
32+
- **Full Node.js runtime**`fetch`, `fs`, timers, whatever you need
33+
34+
With these primitives, bridging Telegram to a Copilot CLI session is trivial.
35+
36+
## How It Works
37+
38+
```
39+
📱 Telegram → Long Polling → Extension → session.send() → Copilot CLI
40+
41+
📱 Telegram ← sendMessage ← Extension ← assistant.message event
42+
```
43+
44+
The extension uses Telegram's [long polling](https://core.telegram.org/bots/api#getupdates) — an HTTP request to `getUpdates` with a `timeout` parameter. Telegram holds the connection open and returns **instantly** when a new message arrives. No webhooks, no public URL, no infrastructure. Just an open HTTP request.
45+
46+
When a message comes in, `session.send()` injects it as a user prompt. When the agent responds, the `assistant.message` event fires and we forward it back via `sendMessage`. The entire bridge is bidirectional and near-real-time.
47+
48+
## The Build Session
49+
50+
I built this live in a single Copilot CLI session. The whole thing — research, implementation, debugging, iteration — happened in about an hour. Here's the interesting part: the bugs were more educational than the code.
51+
52+
### Bug 1: The Conflict Problem
53+
54+
Telegram only allows **one** `getUpdates` consumer per bot token. When Copilot CLI reloads extensions (which happens on `/clear` or code changes), it kills the old process and starts a new one. But the old process's HTTP request was still hanging — 25 seconds of long poll timeout. The new instance starts polling before the old connection dies.
55+
56+
```
57+
⚠️ Telegram API error: Conflict: terminated by other getUpdates request;
58+
make sure that only one bot instance is running
59+
```
60+
61+
The fix was multi-layered:
62+
- Reduced poll timeout from 25s to 10s (old connections release faster)
63+
- Added conflict detection with silent 3s backoff retry
64+
- Added a 2s startup delay for new instances
65+
66+
### Bug 2: Duplicate Polling
67+
68+
`onSessionStart` fires on every session transition — not just the first one. Each fire spawned a new polling loop. Multiple consumers fighting over the same bot token.
69+
70+
The fix was dead simple: **move polling out of `onSessionStart` entirely**. Start it immediately when the script loads, right after `joinSession()`. One script execution = one poll loop.
71+
72+
### Bug 3: Windows Signal Handling
73+
74+
We initially added `SIGTERM`/`SIGINT` handlers to abort the poll request on process exit. Except on Windows, Node.js doesn't fire these handlers. The CLI communicates with extensions over stdio (JSON-RPC), so the real signal that the parent disconnected is `stdin.close`. We added that listener, but ultimately found it simpler to just remove all the signal handlers and let the conflict backoff handle it gracefully.
75+
76+
## The Result
77+
78+
One file. ~420 lines. Zero dependencies beyond what Copilot CLI already provides. And it **works**:
79+
80+
```
81+
[Telegram from Hector]: Can you tell me what stuff I have been working on?
82+
```
83+
84+
Copilot checks my session history, queries my GitHub PRs, and sends back a detailed summary — all from Telegram. Full access to the codebase, terminal, git, GitHub APIs, MCP servers, everything. This isn't a chatbot wrapper. It's the real Copilot CLI, remote-controlled from my phone.
85+
86+
## OpenClaw vs. One File
87+
88+
Here's the comparison that makes the point:
89+
90+
| | OpenClaw | This Extension |
91+
|---|---------|----------------|
92+
| **Setup** | npm install, onboarding wizard, gateway daemon, systemd service | Drop one `.mjs` file, add bot token to `.env` |
93+
| **Infrastructure** | Gateway server, WebSocket control plane, session model, media pipeline | Nothing. The CLI *is* the infrastructure |
94+
| **Agent runtime** | Custom Pi agent runtime with RPC, tool streaming | GitHub Copilot — already the best coding agent available |
95+
| **Lines of code** | Thousands | ~420 |
96+
97+
The trade-off is real: OpenClaw is a **product** — polished, multi-channel, multi-user, always-on. This extension is a **hack** — single-channel, single-user, runs while your terminal is open. But for the use case of "I want to talk to my coding agent from my phone," the hack wins on simplicity by a mile.
98+
99+
And adding another channel? Just write another extension file. Same pattern, different API.
100+
101+
## The Future: Safe OpenClaw
102+
103+
Here's where it gets interesting. This project is step one. Step two is [one PR away](https://github.com/NVIDIA/OpenShell-Community/pull/60).
104+
105+
[NVIDIA OpenShell](https://github.com/NVIDIA/OpenShell) is the runtime environment for autonomous agents — sandboxed execution with a policy engine, L7 proxy with credential injection, and network-level security. Think Docker for AI agents, but with enterprise-grade isolation.
106+
107+
PR #60 adds GitHub Copilot API endpoints to OpenShell's base sandbox policy. Once merged, Copilot CLI can run **inside an OpenShell sandbox** with:
108+
109+
- L7 proxy credential injection (no API keys stored in the sandbox)
110+
- Network policy enforcement (only Copilot API endpoints are reachable)
111+
- Full sandboxed filesystem (agent can't escape)
112+
- Already verified end-to-end: `/models`, `/chat/completions`, `/mcp/readonly` all working
113+
114+
Combine the three layers:
115+
116+
| Layer | Technology | Role |
117+
|-------|-----------|------|
118+
| **Agent** | GitHub Copilot CLI | The actual AI coding agent |
119+
| **Sandbox** | NVIDIA OpenShell | Secure, isolated execution |
120+
| **Interface** | This Telegram extension | Remote access from your phone |
121+
| **Auth** | OpenShell L7 proxy | Credential injection, zero stored keys |
122+
123+
That's OpenClaw's entire value proposition — a personal AI assistant accessible from messaging apps — but built on the best coding agent available, running inside NVIDIA's security infrastructure, controlled from Telegram with a single-file extension.
124+
125+
**Safe OpenClaw.** No gateway daemon. No custom agent runtime. No framework. Just proven infrastructure composed together.
126+
127+
## Try It Yourself
128+
129+
The full source is on GitHub: [htekdev/gh-cli-telegram-extension](https://github.com/htekdev/gh-cli-telegram-extension)
130+
131+
Setup takes 2 minutes:
132+
133+
1. Create a bot via [@BotFather](https://t.me/BotFather) on Telegram
134+
2. Drop the extension in `.github/extensions/telegram-bridge/`
135+
3. Add your bot token to `.env`
136+
4. Start a Copilot CLI session
137+
138+
Send `/start` to your bot. You're in.
139+
140+
---
141+
142+
*Built live in a single Copilot CLI session. The extension was written, debugged, and iterated entirely through the CLI — including from Telegram itself once the bridge was working. Proof that the tool can build its own interfaces.*

0 commit comments

Comments
 (0)