OpenCode Remote is currently a Telegram gateway for OpenCode with text, image, sticker, and opt-in voice support.
- Telegram private-chat and configured group gateway using grammY long polling.
- Optional authorized Telegram users for private-chat access configured in
.opencode-remote/config.json. - Optional allowed Telegram group chat IDs that authorize every sender in those groups, including other bots.
- Local or remote OpenCode server connection configured with
opencode.apiUrl. - Optional local OpenCode startup with
opencode.autoStart=true. - OpenCode session creation, listing, switching, prompt sending, and stop requests.
- OpenCode permission requests surfaced in Telegram with inline approve/deny buttons.
- Long-running OpenCode prompts use a configurable
opencode.promptTimeoutMstimeout, defaulting to 35 minutes. - Editable Telegram activity messages showing OpenCode tool and skill usage during prompts.
- Telegram-safe response chunking for long assistant replies.
- Published npm CLI package with the
opencode-remotebin built todist/withtsdown. - Background gateway lifecycle commands:
opencode-remote start,opencode-remote stop, andopencode-remote status. - User-level login startup commands:
opencode-remote startup enable,opencode-remote startup disable, andopencode-remote startup status. - Interactive JSON config setup with project-local and global config discovery, selected-scope current defaults, highlighted arrow-key lists, and
ffmpeginstall/retry handling for voice setup. - SQLite app-state persistence for selected OpenCode sessions and progress preferences, scoped by OpenCode project identity.
- Optional Telegram voice mode using Groq Whisper transcription, Edge TTS speech generation, and
ffmpegOGG Opus conversion. - Telegram sticker understanding with static WebP sticker attachments, generated or fallback visual context for non-static stickers, saved sticker packs, and sticker replies.
- CLI config updates with
opencode-remote config setand voice cache clearing withopencode-remote cache clear.
/statusshows whether the gateway is running and which OpenCode session is active./newcreates and selects a new OpenCode session./sessionslists recent OpenCode sessions and lets the user switch with inline buttons./stoprequests abort for the active OpenCode session./progressopens a private-chat prompt activity visibility menu and still accepts directoff,new,all, orverbosemodes./voiceopens a voice settings menu with mode, captions, paginated country selection, paginated clickable voice selection, and test voice actions. It still accepts direct commands to show status, set mode, toggle captions, list voices by required short country/locale filter, set the active Edge TTS voice, and send a test voice note./stickersopens a saved-pack menu and still accepts direct commands to save, list, and forget sticker packs for future sticker replies./skillslists local OpenCode skills from default skill folders, configuredskills.paths, compatible Claude/Agents skill folders, OpenCode Remote generated skills, and sanitized bundled skills shipped with the npm package./skills create, theNew skillmenu button, or private chat requests such as "please create a skill" create project-local generated skills under.opencode/skills/opencode-remote-generated/after preview and confirmation. Gateway startup and/skillsrefresh install or update bundled skills under the first project-local configuredskills.pathsdirectory, falling back to.opencode/skills, and clean up the legacy experimental meme agent.- Telegram command menu buttons perform real actions, open submenus, or start guided text input instead of only returning slash-command usage text.
/groupopens a private-chat grouped management menu for known allowed groups. In groups,/groupreplies with a short DM-only notice.- Per-group custom trigger phrases are managed from the DM
/groupmenu. /helpshows the available bot commands.- The Telegram slash-command menu is refreshed on gateway startup.
- Non-command text from an authorized private user is sent to OpenCode as a prompt. In allowed groups, text, photo, voice, and sticker messages are sent to OpenCode only when group routing settings identify them as addressed to the bot.
- Custom group trigger phrases are plain text, case-insensitive, and match as bounded words or phrases anywhere in text, captions, and voice transcripts.
- Allowed groups keep bounded in-memory recent context while the gateway is running. Routed group prompts include capped recent context, but passive messages are not sent to OpenCode by themselves.
- Telegram text, photo, album, voice, and sticker prompts include safe author context, including forwarded original authors and messages sent by anonymous admins or on behalf of chats/channels when Telegram provides usable names.
- The bot shows Telegram typing activity while a prompt is running.
- In private chats, the bot can show an editable
Activitymessage with OpenCode tools and skills used during a prompt. Group chats always suppress this activity message. - OpenCode permission requests, including child subagent session permission requests, are sent as text with
Allow once,Always allow, andDenybuttons, even when voice replies are enabled. - Incoming text prompts get a temporary eye reaction while processing.
- OpenCode can request one Telegram emoji reaction by returning a hidden
[telegram_reaction: ...]marker, which is removed before the user sees the reply. - When saved sticker packs are available, eligible hidden reaction markers may be answered with a saved sticker reply instead of an emoji reaction.
- When saved sticker packs are available, explicit user requests for a sticker can be answered with a saved sticker reply through a hidden gateway marker.
- User emoji reactions to recent bot messages are sent back to OpenCode as feedback prompts.
- Telegram voice messages are transcribed and sent to OpenCode when voice mode is enabled.
- Voice replies replace text replies after voice prompts in
/voice onmode and after text, photo, and voice prompts in/voice allmode, with optional text captions and text fallback if speech generation or sending fails. - When the bundled meme-generation skill is installed, OpenCode can create local meme files from the active session; generated meme files are delivered back through Telegram through validated
MEDIA:output.
- If no active session is selected, the gateway creates one before sending a prompt.
- New sessions receive hidden gateway context with no assistant reply so OpenCode understands messenger, voice, activity, and permission behavior without showing a setup response to the user.
- Prompt sends are serialized through the active session so complex OpenCode runs are not overlapped accidentally.
- Child subagent session tool and permission events are associated with the active gateway prompt while it is running.
- Selected session state is stored in
opencode-remote.dbunder the platform app-data directory and scoped by project identity. - Stopping a task uses OpenCode's session abort API for the active session.
- Session state is messenger-neutral in the gateway core, so future adapters can reuse it.
- Telegram photo messages are downloaded temporarily and sent to OpenCode as file prompt parts.
- Telegram photo albums with a shared
media_group_idare grouped into one OpenCode prompt. - Album captions become the prompt text when present.
- Photos without captions use a default short reaction prompt.
- Temporary downloaded photo files are cleaned up after handling.
- Telegram sticker messages are sent to OpenCode with visual attachment context and safe sticker metadata.
- Static stickers use direct WebP image attachments. Video stickers use sampled preview sheets. Animated
.tgsstickers uselottie_convert.pywhen available, with source-file fallback. - Sticker visuals are cached under app-data cache storage and validated with
file_unique_id, kind, dimensions, file size, and converter version. - Cached sticker visuals can be summarized into short safe descriptions for the saved-sticker catalog used by future sticker replies.
- Generated media delivery is limited to gateway-controlled generated-media cache files and validated local files.
- Voice replies are disabled by default, so Telegram replies are text-only until enabled.
- Voice captions are disabled by default and can be enabled with
/voice captions on. - Groq Whisper uses
whisper-large-v3-turboby default for transcription. /voice list <countryCode|locale> [page]pages Edge TTS voices for a required country code such asuaorus, or a full locale such asuk-UA.- Edge TTS voice short names such as
en-US-AndrewNeuralanduk-UA-OstapNeuralcan be selected with/voice set. ffmpegis required only when voice mode is enabled.- Generated MP3/OGG files are treated as disposable app-data cache.
- The bot ignores private Telegram users outside the configured user allowlist.
- The bot ignores group chats outside the configured chat allowlist. Allowed groups authorize all senders in that group, so configure only groups whose members and admins you trust.
- Group conversation memory is ephemeral, bounded, and cleared on gateway restart or OpenCode session changes. Persistent group state stores settings and known group metadata, not message text.
- Secrets are configured through private
.opencode-remote/config.jsonfiles, not persisted settings. - Bundled OpenCode Remote runtime assets are enabled project-locally under
.opencode/; global OpenCode config is not modified by default. - Generated media delivery is constrained to generated-media cache files and validated local files.
- The selected active session is persisted as non-secret JSON state.
- Saved sticker packs persist only non-secret sticker identifiers and metadata.
- Telegram reaction API failures are best-effort warnings and do not block prompt delivery.
- Default tests mock Telegram and OpenCode; no live services are required for normal verification.
- OpenCode model switching from Telegram.
- Signal or other messenger adapters.
See TODO.md for the current development roadmap.