Created
February 7, 2026 08:32
-
-
Save a-n-d-a-i/d88b74bf8a9e824349761a0cfb1fdc01 to your computer and use it in GitHub Desktop.
AI Agent in Telegram
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| // USAGE: Just talk normally to Claude/Codex | |
| // say reset to reset chat | |
| // Start message with $ to run shell commands, e.g. $date | |
| const USE_CLAUDE = true; // false -> use Codex | |
| const ALLOWED_CHAT_IDS = [Number(process.env.MY_TG_CHAT_ID)]; | |
| const os = require('os'); | |
| const { exec } = require('child_process') as typeof import('child_process'); | |
| import { Bot, Context } from 'grammy'; | |
| let RESET_CMD, EXEC_CMD; | |
| if(USE_CLAUDE) { | |
| RESET_CMD = `claude -p '(NOTE: Resetting session. Say "Session reset." and exit.)'` | |
| EXEC_CMD = `claude --dangerously-skip-permissions --continue -p` | |
| } else { | |
| RESET_CMD = `codex exec '(NOTE: Resetting session. Say "Session reset." and exit.)'` | |
| EXEC_CMD = `codex --yolo exec resume --last` | |
| } | |
| function quote_arg(arg) { | |
| const arg_esc = arg.replaceAll('"', '\\"').replaceAll('`','\\`'); | |
| return '"' + arg_esc + '"'; | |
| } | |
| function stripAnsi(str: string): string { | |
| return str.replace(/\x1b[^a-zA-Z]*[a-zA-Z]|\x1b\].*?(?:\x07|\x1b\\)/g, ''); | |
| } | |
| async function main(): Promise<void> { | |
| const token = process.env.TELEGRAM_BOT_TOKEN; | |
| const bot = new Bot(token); | |
| const me = await bot.api.getMe(); | |
| console.log(`Connected: @${me.username}`); | |
| console.log(`Allowed: ${ALLOWED_CHAT_IDS}`); | |
| bot.on('message:text', async (ctx: Context) => { | |
| const text = ctx.message?.text; | |
| const chatId = ctx.chat?.id; | |
| if (!text || !chatId) return; | |
| if (!ALLOWED_CHAT_IDS.includes(chatId)) { | |
| await ctx.reply('Unauthorized'); | |
| return; | |
| } | |
| let cmd; | |
| if (text == 'reset' || text == 'Reset' || text == 'reset.' || text == 'Reset.') { | |
| cmd = RESET_CMD; | |
| } else { | |
| cmd = EXEC_CMD + ' ' + quote_arg(text); | |
| } | |
| if (USE_CLAUDE) cmd = `script -q -c ${JSON.stringify(cmd)} /dev/null`; // Claude needs a TTY | |
| if (text.startsWith('$')) { // run a bash command instead | |
| cmd = text.slice(1); | |
| } | |
| ctx.reply(`Running command: ${cmd}`); // dbg | |
| exec(cmd, (err, stdout, stderr) => { | |
| console.log(stdout + stderr); | |
| let out = stdout; | |
| if (err) { console.error(err); out += stderr; } | |
| if (USE_CLAUDE) out = stripAnsi(out); // remove crap | |
| ctx.reply(out || '(No output)'); | |
| }); | |
| }); | |
| await bot.start(); | |
| } | |
| main().catch(err => { | |
| console.error('Failed:', err); | |
| process.exit(1); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment