Cloud Shell →
Pi → Telegram

Google Cloud Shell ထဲမှာ Pi ကိုတင်၊ ပြီးတော့ Telegram ကနေ owner-only အနေနဲ့ ခိုင်းနိုင်ဖို့ copy–paste လမ်းညွှန်။

01Install & configure Pi
02Run private Telegram bridge
!
စမ်းသပ်ရန်အတွက်ပဲ 24/7 မဟုတ်ပါ။ Google Cloud Shell က inactive ဖြစ်ရင် VM နဲ့ bot ပိတ်သွားမယ်။ Official limit အရ non-interactive session က 40 မိနစ်အတွင်း အလိုအလျောက်ပိတ်နိုင်ပြီး session တစ်ခုလုံးက 12 နာရီ cap ရှိတယ်။ ဖိုင်တွေကတော့ $HOME 5 GB ထဲမှာ ဆက်ရှိမယ်။

မင်းရဲ့ value တွေ ထည့်ပါ

Browser ထဲတွင်သာ ခဏသုံးသည် · secret မထည့်ရ

Bot token နဲ့ RelayModels API key ကို ဒီ website ထဲ မထည့်ပါနဲ့။ အောက်က hidden terminal prompt နဲ့ပဲ ထည့်မယ်။

01 BEFORE YOU START

အရင်ဆုံး boundary ကို သတ်မှတ်ပါ

Pi က built-in permission system မပါဘဲ၊ သူ run နေတဲ့ Linux user ရဲ့ permission အတိုင်း file နဲ့ command တွေကို ကိုင်နိုင်တယ်။ ဒီအဆင့်မှာ Cloud Shell ထဲက သီးသန့် test directory တစ်ခုအတွင်းမှာပဲ စမ်းပါ။

1Google Cloud Shell ဖွင့်ပြီး terminal ကို အသင့်ထားပါ။
2RelayModels key နဲ့ Telegram BotFather token ကို နောက်ပိုင်း terminal မှာ hidden prompt နဲ့ ထည့်မယ်။
Production access မပေးသေးပါနဲ့

Bot မှားပြောတာ၊ model မှားနားလည်တာကြောင့် ဖိုင်တွေ ထိနိုင်တယ်။ Test directory သုံးပြီး workflow ကို နားလည်သွားမှ access တိုးပါ။

02 INSTALL PI

Cloud Shell ထဲမှာ Pi ကို တင်ပါ

Official installer က Linux မှာ Pi နဲ့ လိုအပ်တဲ့ Node.js version ကို စစ်ပြီး တင်ပေးနိုင်တယ်။ Install ပြီးရင် terminal အသစ်ဖွင့် သို့မဟုတ် shell profile ကို reload လုပ်ပါ။

cloud-shell · bash
curl -fsSL https://pi.dev/install.sh | sh
source ~/.bashrc 2>/dev/null || true
pi --version
pi --help | head -30
အောင်မြင်ကြောင်း စစ်ရန်

pi --version မှာ version ပေါ်ရမယ်။ command not found ဆို terminal tab အသစ်တစ်ခု ဖွင့်ပြီး ထပ်စစ်ပါ။

03 CONNECT MODEL

RelayModels ကို custom provider အဖြစ် ချိတ်ပါ

Pi က OpenAI-compatible endpoint ကို ~/.pi/agent/models.json မှာ ထည့်လို့ရတယ်။ Key ကို JSON ထဲ တိုက်ရိုက်မရေးဘဲ environment variable သုံးထားမယ်။

Provider config ဖန်တီးရန်

cloud-shell · bash
mkdir -p ~/.pi/agent
chmod 700 ~/.pi ~/.pi/agent 2>/dev/null || true
cat > ~/.pi/agent/models.json <<'JSON'
{
  "providers": {
    "relaymodels": {
      "baseUrl": "https://api.relaymodels.com/v1",
      "api": "openai-completions",
      "apiKey": "$RELAYMODELS_API_KEY",
      "models": [
        { "id": "claude-sonnet-5", "name": "Claude Sonnet 5 — RelayModels" }
      ]
    }
  }
}
JSON
chmod 600 ~/.pi/agent/models.json

Key ကို shell ထဲ ခဏထည့်ပြီး test လုပ်ရန်

secret ကို screen မပေါ်စေသော prompt
read -rsp "RelayModels API key: " RELAYMODELS_API_KEY; echo
export RELAYMODELS_API_KEY
pi --provider relaymodels --model claude-sonnet-5 \
  --no-session -p "Reply exactly: PI_READY"
unset RELAYMODELS_API_KEY

PI_READY ပြန်လာရင် model ချိတ်ပြီးပါပြီ။ Key ကို command-line argument မပေးထားတာကြောင့် shell history ထဲ key မကျန်ဘူး။

04 CREATE TELEGRAM BOT

Private bot token နဲ့ owner ID ယူပါ

  1. Telegram မှာ official @BotFather ကိုဖွင့်ပါ။
  2. /newbot ပို့ပြီး bot name နဲ့ bot နဲ့ဆုံးတဲ့ username ရွေးပါ။
  3. BotFather ပေးတဲ့ token ကို မည်သူ့ကိုမှ မပို့ပါနဲ့။ မင်း bot အသစ်ကိုဖွင့်ပြီး /start တစ်ခါပို့ပါ။

မင်းရဲ့ numeric Telegram ID ကို ရယူရန်

Bot ကို message ပို့ပြီးမှ အောက် command ကို Cloud Shell မှာ run ပါ။ Token ကို hidden input နဲ့ပဲ ယူမယ်။

getUpdates · owner ID finder
read -rsp "Telegram bot token: " BOT_TOKEN; echo
curl -fsS "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates" \
| python3 -c 'import sys,json; d=json.load(sys.stdin); print(*sorted({str(x["message"]["from"]["id"]) for x in d.get("result",[]) if "message" in x}), sep="\n")'

Output ထဲက မင်း ID ကို အပေါ်က Telegram numeric ID field မှာထည့်ပါ။ ဘာမှမပေါ်ရင် bot ကို message အသစ်တစ်ခါပို့ပြီး command ပြန်runပါ။

05 INSTALL BRIDGE

Owner-only Telegram → Pi bridge ကို တင်ပါ

ဒီ bridge က long polling သုံးလို့ public port၊ domain၊ webhook မလိုဘူး။ Normal message တွေကို plan-only အဖြစ်ပို့ပြီး /run နဲ့စတဲ့ message သာ Cloud Shell ထဲက test directory မှာ Pi ကို tool သုံးခွင့်ပေးမယ်။

A. Folder နဲ့ package ဖန်တီးရန်

cloud-shell · bash
mkdir -p ~/pi-telegram-bridge ~/pi-remote-agent
cd ~/pi-telegram-bridge
npm init -y
npm install --ignore-scripts node-telegram-bot-api

B. Pi ကို isolated Docker sandbox ထဲတွင် ပြင်ဆင်ရန်

Telegram ကနေခေါ်တဲ့ Pi ကို Cloud Shell account နဲ့ secret ဖိုင်တွေ မမြင်နိုင်အောင် container ထဲမှာ သီးခြား run မယ်။ Container က test workspace နဲ့ model config ဖိုင်ကိုပဲ ရမယ်။

Dockerfile.pi · isolated worker
cat > ~/pi-telegram-bridge/Dockerfile.pi <<'DOCKER'
FROM node:24-bookworm-slim
RUN apt-get update \
  && apt-get install -y --no-install-recommends bash ca-certificates git ripgrep \
  && npm install -g --ignore-scripts @earendil-works/pi-coding-agent \
  && rm -rf /var/lib/apt/lists/*
WORKDIR /workspace
ENTRYPOINT ["pi"]
DOCKER
cd ~/pi-telegram-bridge
docker build -t pi-telegram-sandbox -f Dockerfile.pi .

C. Pi အတွက် safety rules ထည့်ရန်

~/pi-remote-agent/AGENTS.md
cat > ~/pi-remote-agent/AGENTS.md <<'MD'
# Cloud Shell test workspace rules

- Stay inside this test workspace. Do not access remote servers or accounts.
- Never read, print, copy, or modify private keys, tokens, `.env` files, or credentials.
- Before any change: inspect current state, explain the smallest safe action, then act.
- Never delete user data or files outside this workspace.
- Never install system-wide software, change authentication, or alter Cloud Shell settings.
- Prefer backups, reversible edits, and syntax checks.
- Report every command run, changed file, verification result, and rollback path.
MD

D. Bridge code ဖန်တီးရန်

~/pi-telegram-bridge/bot.cjs
cat > ~/pi-telegram-bridge/bot.cjs <<'JS'
'use strict';

const TelegramBot = require('node-telegram-bot-api');
const { spawn } = require('node:child_process');

const required = ['BOT_TOKEN', 'TELEGRAM_USER_ID', 'RELAYMODELS_API_KEY'];
for (const name of required) {
  if (!process.env[name]) throw new Error(`Missing ${name} in .env`);
}

const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true });
const ownerId = String(process.env.TELEGRAM_USER_ID);
const workDir = process.env.WORK_DIR || `${process.env.HOME}/pi-remote-agent`;
const modelConfig = `${process.env.HOME}/.pi/agent/models.json`;
const piImage = process.env.PI_IMAGE || 'pi-telegram-sandbox';
const provider = process.env.PI_PROVIDER || 'relaymodels';
const model = process.env.PI_MODEL || 'claude-sonnet-5';
let busy = false;

function splitText(text, max = 3800) {
  const parts = [];
  let rest = text || '(Pi returned no text)';
  while (rest.length > max) {
    let cut = rest.lastIndexOf('\n', max);
    if (cut < max * 0.5) cut = max;
    parts.push(rest.slice(0, cut));
    rest = rest.slice(cut).replace(/^\n/, '');
  }
  parts.push(rest);
  return parts;
}

function run(cmd, args, options = {}) {
  return new Promise((resolve) => {
    const child = spawn(cmd, args, {
      cwd: options.cwd || workDir,
      env: options.env || process.env,
      stdio: ['ignore', 'pipe', 'pipe']
    });
    let stdout = '';
    let stderr = '';
    const cap = 120000;
    child.stdout.on('data', d => { stdout = (stdout + d).slice(-cap); });
    child.stderr.on('data', d => { stderr = (stderr + d).slice(-20000); });
    const timer = setTimeout(() => child.kill('SIGTERM'), options.timeout || 600000);
    child.on('error', err => {
      clearTimeout(timer);
      resolve({ code: -1, stdout, stderr: err.message });
    });
    child.on('close', code => {
      clearTimeout(timer);
      resolve({ code, stdout: stdout.trim(), stderr: stderr.trim() });
    });
  });
}

async function sendLong(chatId, text) {
  for (const part of splitText(text)) await bot.sendMessage(chatId, part);
}

bot.on('message', async (msg) => {
  const chatId = msg.chat.id;
  if (String(msg.from?.id) !== ownerId) return;
  const text = (msg.text || '').trim();
  if (!text) return bot.sendMessage(chatId, 'Text message ပဲ အရင်စမ်းပါ။');

  if (text === '/start' || text === '/help') {
    return bot.sendMessage(chatId,
      'Normal message = plan / answer only\n' +
      '/status = Cloud Shell read-only health check\n' +
      '/run <task> = test workspace ထဲမှာ Pi ကို လုပ်ခိုင်းမယ်\n\n' +
      'Sensitive ဖိုင်တွေ၊ remote server တွေကို မထိပါနဲ့။'
    );
  }

  if (text === '/status') {
    const r = await run('bash', ['-lc',
      'hostname; uptime; printf "\\nDISK\\n"; df -h "$HOME"; printf "\\nMEMORY\\n"; free -h'
    ], { timeout: 30000 });
    return sendLong(chatId, r.code === 0 ? r.stdout : `Status error (${r.code})\n${r.stderr}`);
  }

  if (busy) return bot.sendMessage(chatId, 'Pi က အလုပ်လုပ်နေတယ်။ ပြီးမှ နောက်တစ်ခု ပို့ပါ။');
  busy = true;
  await bot.sendChatAction(chatId, 'typing');

  const execute = text.startsWith('/run ');
  const task = execute ? text.slice(5).trim() : text;
  const prefix = execute
    ? 'EXECUTION MODE. Work only inside the current Cloud Shell test workspace. Follow AGENTS.md. ' +
      'Do not access remote servers. Inspect first, make the smallest reversible change, verify it, and report exact results. '
    : 'PLAN-ONLY MODE. Answer or create a plan. Do not change files, do not run shell commands, ' +
      'and do not claim that any action was completed. ';

  const piArgs = ['--provider', provider, '--model', model, '--no-session'];
  if (!execute) piArgs.push('--tools', 'read,grep,find,ls');
  piArgs.push('-p', `${prefix}\n\nUser request:\n${task}`);

  const dockerArgs = [
    'run', '--rm', '--read-only', '--network', 'bridge',
    '--cap-drop=ALL', '--security-opt', 'no-new-privileges',
    '--pids-limit', '256', '--memory', '1g', '--cpus', '1',
    '--tmpfs', '/tmp:rw,noexec,nosuid,size=64m',
    '-e', 'RELAYMODELS_API_KEY',
    '-v', `${workDir}:/workspace:rw`,
    '-v', `${modelConfig}:/root/.pi/agent/models.json:ro`,
    '-w', '/workspace', piImage,
    ...piArgs
  ];
  const safeEnv = {
    PATH: process.env.PATH,
    HOME: process.env.HOME,
    RELAYMODELS_API_KEY: process.env.RELAYMODELS_API_KEY
  };
  const result = await run('docker', dockerArgs, { timeout: 600000, env: safeEnv });
  busy = false;

  if (result.code === 0) return sendLong(chatId, result.stdout);
  return sendLong(chatId, `Pi error (${result.code})\n${result.stderr || result.stdout}`);
});

bot.on('polling_error', err => console.error('polling_error:', err.message));
console.log('Pi Telegram bridge is running for owner', ownerId);
JS

E. Secrets ကို permission 600 ဖြင့် သိမ်းရန်

အောက် command ကို run လုပ်တဲ့အခါ token နဲ့ key က screen ပေါ်မပေါ်ဘူး။ Telegram ID ကို အပေါ်က field ကနေ အလိုအလျောက်ထည့်ပေးထားတယ်။

.env · never commit
cd ~/pi-telegram-bridge
umask 077
read -rsp "Telegram bot token: " BOT_TOKEN; echo
read -rsp "RelayModels API key: " RELAYMODELS_API_KEY; echo
cat > .env <<EOF
BOT_TOKEN=$BOT_TOKEN
TELEGRAM_USER_ID=YOUR_TELEGRAM_ID
RELAYMODELS_API_KEY=$RELAYMODELS_API_KEY
PI_PROVIDER=relaymodels
PI_MODEL=claude-sonnet-5
WORK_DIR=$HOME/pi-remote-agent
EOF
chmod 600 .env
unset BOT_TOKEN RELAYMODELS_API_KEY
ls -l .env
06 RUN & TEST

Bot ကို run ပြီး အဆင့်လိုက်စမ်းပါ

Bridge ကို Cloud Shell terminal ရဲ့ foreground မှာ run ပြီး Telegram ကနေ အဆင့်လိုက် စမ်းပါ။

cloud-shell · terminal 1
cd ~/pi-telegram-bridge
node --env-file=.env bot.cjs

Pi Telegram bridge is running ပေါ်ရင် Telegram ကနေ ဒီ order အတိုင်း စမ်းပါ။

/help

Bot command နဲ့ mode အဓိပ္ပာယ်တွေ ပြမယ်။

/status

LLM မသုံးဘဲ Cloud Shell hostname, uptime, disk, memory ကို read-only စစ်မယ်။

ဒီ task အတွက် plan တစ်ခုရေး

Normal message က plan-only ဖြစ်ပြီး command မလုပ်ဘူး။

/run sample.txt ဖိုင်တစ်ခု ဖန်တီး

Execution mode ဝင်ပြီး test workspace ထဲမှာ Pi ကို စမ်းမယ်။

ပထမဆုံး safe test

/run sample.txt ထဲ PI_READY လို့ရေးပြီး ပြန်ဖတ်ပြ။ တခြားဖိုင်မပြင်နဲ့ လို့ ပို့ပါ။ ပြန်လာတဲ့ command နဲ့ output ကို Cloud Shell terminal မှာ cat ~/pi-remote-agent/sample.txt နဲ့ တိုက်စစ်ပါ။

Terminal ပိတ်မိသေးပေမယ့် ခဏဆက် run ချင်ရင်

tmux · optional
tmux new -s pi-bot
cd ~/pi-telegram-bridge
node --env-file=.env bot.cjs

# Detach: Ctrl+B, ပြီးရင် D
# ပြန်ဝင်ရန်:
tmux attach -t pi-bot
tmux က 24/7 မဖြစ်စေပါ

Cloud Shell VM ကို Google ကပိတ်လိုက်ရင် tmux နဲ့ bot နှစ်ခုလုံးပိတ်မယ်။ ဒီအဆင့်က setup စမ်းဖို့ပဲ။

07 TROUBLESHOOTING

မဖြစ်ရင် ဒီနေရာက စစ်ပါ

pi: command not found
Terminal tab အသစ်ဖွင့်ပါ။ မရသေးရင် find "$HOME" -type f -name pi 2>/dev/null | head နဲ့ path ရှာပြီး installer ပြန်runပါ။
RelayModels model မပေါ် / 401 error
set -a; source ~/pi-telegram-bridge/.env; set +a ပြီး pi --list-models relaymodels စစ်ပါ။ ~/.pi/agent/models.json မှာ provider name နဲ့ environment variable စာလုံးပေါင်းကို စစ်ပါ။
Telegram 409 conflict / bot reply မပြန်
Bot token တစ်ခုကို polling process တစ်ခုတည်း run ရမယ်။ အရင် process ရှိမရှိ pgrep -af 'bot.cjs' စစ်ပါ။ Webhook ထားဖူးရင် Telegram Bot API ရဲ့ deleteWebhook ကို terminal ကနေ ဖျက်ပြီး ပြန်စပါ။
Bot က နာရီဝက်ကျော်ပြီး ရပ်သွား
ဒါက Cloud Shell limitation ဖြစ်နိုင်တယ်။ Session အသစ်ဖွင့်ပြီး bridge ကို ပြန်runပါ။ Cloud Shell မှာ 24/7 ဆက်မ run နိုင်ပါ။
Bot token သို့ API key ပေါက်သွားပြီ
BotFather မှာ token ကို revoke/regenerate လုပ်ပါ။ RelayModels key ကို provider ဘက်မှာ revoke လုပ်ပြီး key အသစ်ထုတ်ပါ။ Production secret တွေကို Pi chat ထဲ မကူးပါနဲ့။

အတည်ပြုထားသော ရင်းမြစ်များ