Sign inSign up

mguptahub/plane-telegram

By mguptahub

•Updated 7 months ago

Personal AI bot connecting Plane.so to Telegram via AI + MCP

Buildkit cache
Image
0

2.5K

mguptahub/plane-telegram repository overview

⁠Plane Telegram AI Bot

A self-hosted Docker service that connects Plane.so⁠ to Telegram via AI. Ask questions about your projects, issues, cycles, and more — right from Telegram.

Supports two deployment modes:

  • Personal mode (default) — one workspace, one user, zero setup friction
  • Multi-user mode — any Telegram user can /login with their own Plane credentials; ideal for shared team bots or public deployments

⁠Architecture

Telegram → Bot (python-telegram-bot) → AI (Claude/GPT) + Plane Tools → Plane.so

The AI uses Plane tools to query and interact with your workspace. It decides which tools to call based on your natural language questions. Tools are built on the official plane-sdk with lean schemas to minimise token usage, backed by an SQLite cache for workspace data.

⁠Prerequisites

  1. Plane PAT (API Key) — Generate from your Plane workspace settings → API Tokens
  2. Telegram Bot Token — Create a bot via @BotFather⁠ on Telegram
  3. AI API Key — From Anthropic⁠ or OpenAI⁠
  4. Docker — Installed on your server

⁠Setup Telegram Bot

  1. Open Telegram and search for @BotFather⁠
  2. Send /newbot and follow the prompts:
    • Bot name: Choose a display name (e.g., "Plane AI Assistant")
    • Bot username: Must end in "bot" (e.g., "my_plane_ai_bot")
  3. BotFather will give you a bot token — save it for TELEGRAM_BOT_TOKEN

Note: No need to set bot commands in BotFather. The bot registers all commands with Telegram automatically on startup.

Optional extras via BotFather:

  • /setdescription — Description shown in the chat header
  • /setabouttext — Text shown in the bot's profile
  • /setuserpic — Profile picture

⁠Quick Start

⁠Personal Mode (single user)

Run the pre-built Docker image:

docker run -d \
  --name plane-telegram \
  -v $(pwd)/data:/app/data \
  -e PLANE_PAT=your_plane_api_key \
  -e PLANE_WORKSPACE_SLUG=your-workspace-slug \
  -e TELEGRAM_BOT_TOKEN=your_telegram_bot_token \
  -e AI_PROVIDER=anthropic \
  -e AI_API_KEY=your_ai_api_key \
  --restart unless-stopped \
  mguptahub/plane-telegram:latest

That's it! Replace the values with your credentials, find your bot on Telegram, and send /start.

⁠Multi-User Mode (shared / team bot)

Add MULTI_USER=true and omit PLANE_PAT / PLANE_WORKSPACE_SLUG:

docker run -d \
  --name plane-telegram \
  -v $(pwd)/data:/app/data \
  -e MULTI_USER=true \
  -e TELEGRAM_BOT_TOKEN=your_telegram_bot_token \
  -e AI_PROVIDER=anthropic \
  -e AI_API_KEY=your_ai_api_key \
  --restart unless-stopped \
  mguptahub/plane-telegram:latest

Each user (or group chat) runs /login to connect their own Plane account. See Multi-User Mode⁠ for details.

⁠Additional Configuration (Optional)
docker run -d \
  --name plane-telegram \
  -v $(pwd)/data:/app/data \
  -e PLANE_PAT=your_plane_api_key \
  -e PLANE_WORKSPACE_SLUG=your-workspace-slug \
  -e TELEGRAM_BOT_TOKEN=your_telegram_bot_token \
  -e AI_PROVIDER=openai \
  -e AI_API_KEY=your_ai_api_key \
  -e AI_MODEL=gpt-4o \
  -e AI_BASE_URL=https://api.openai.com/v1 \
  -e MAX_HISTORY_MESSAGES=15 \
  -e SESSION_TIMEOUT_MINUTES=60 \
  -e DEBUG_LOGGING=false \
  --restart unless-stopped \
  mguptahub/plane-telegram:latest

⁠Environment Variables

VariableRequiredDefaultDescription
MULTI_USERNofalseEnable multi-user mode — each Telegram chat registers its own Plane account
PLANE_PATYes*—Plane API key / Personal Access Token (*not required when MULTI_USER=true)
PLANE_WORKSPACE_SLUGYes*—Default workspace slug (*not required when MULTI_USER=true)
PLANE_BASE_URLIf self-hostedhttps://app.plane.soYour self-hosted Plane URL
TELEGRAM_BOT_TOKENYes—Telegram bot token from BotFather
AI_PROVIDERYes—anthropic or openai (any OpenAI-compatible)
AI_API_KEYYes—API key for your AI provider
AI_MODELNoAutoModel name (defaults to claude-sonnet-4-20250514 or gpt-4o)
AI_BASE_URLNoProvider defaultOptional base URL override
AI_APP_REFERERNo—HTTP-Referer header (used by OpenRouter for attribution)
AI_APP_TITLENoPlane Telegram AIX-Title header (used by OpenRouter for attribution)
MAX_HISTORY_MESSAGESNo15Number of messages to include as context
SESSION_TIMEOUT_MINUTESNo60Auto-expire old messages from context
LOG_LEVELNoINFOLogging level
DEBUG_LOGGINGNofalseWrite per-request debug logs to data/debug_logs/
⁠AI_BASE_URL Examples
ProviderAI_PROVIDERAI_BASE_URL
Anthropic (default)anthropic—
OpenAI (default)openai—
Groqopenaihttps://api.groq.com/openai/v1
OpenRouteropenaihttps://openrouter.ai/api/v1
Together AIopenaihttps://api.together.xyz/v1
LiteLLM proxyopenaihttp://localhost:4000/v1
Azure OpenAIopenaihttps://your-resource.openai.azure.com/

⁠Available Tools

ToolDescription
get_meGet current user info
get_workspace_membersList all workspace members
list_projectsList all projects
get_projectGet a project by UUID
get_project_membersList members of a project
list_statesList workflow states for a project
list_labelsList labels for a project
list_work_itemsList work items (filterable by state, priority, assignee, label)
get_work_itemGet a work item by UUID or identifier (e.g. PROJ-42)
create_work_itemCreate a new work item
update_work_itemUpdate an existing work item
list_initiativesList workspace initiatives

⁠Bot Commands

The bot registers all commands with Telegram automatically — they appear in the / menu.

⁠Account (multi-user mode only)
CommandDescription
/loginConnect your Plane account (PAT + workspace slug)
/logoutRemove your credentials and clear all chat data
/statusShow connection status, cache state, and active project
⁠General
CommandDescription
/startShow welcome message
/helpShow help and command reference
/resetClear conversation history and start fresh
/toolsList all available Plane tools
/statusShow connection status and active context
⁠Workspace
CommandDescription
/workspaceShow the currently active workspace and project
/workspace showSame as above
/workspace <slug>Switch workspace, rebuild cache, and clear active project

Examples:

/workspace
/workspace my-company
/workspace show

Each chat session has its own active workspace. The default is set by PLANE_WORKSPACE_SLUG. Switching workspace rebuilds the cache and resets the active project (projects are workspace-scoped).

⁠Project Context

Set an active project once so you don't need to type the identifier on every /workitems call.

CommandDescription
/projectShow the currently active project
/project showSame as above
/project <IDENTIFIER>Set the active project (validated against cache)

Examples:

/project
/project BACK
/project INVESTOS

The active project is cleared automatically when you switch workspace.

⁠Quick Lists

Explicit mode — project identifier always required, ignores active project context. Useful for one-off lookups across projects.

CommandDescription
/list projectsList all projects in the active workspace
/list workitems <PROJ> [query]List work items for a project
/list states <PROJ>List workflow states for a project
/list labels <PROJ>List labels for a project
/list members <PROJ>List members of a project

Context mode — uses the active project set by /project. Set it once, then query freely.

CommandDescription
/workitems [query]List work items using the active project context
/statesList workflow states for the active project
/labelsList labels for the active project
/membersList members of the active project

<PROJ> is the project identifier (e.g. BACK, INVESTOS). The optional [query] for work items is plain English — the AI resolves it into filters (state, priority, assignee, label). Only one filter value is supported per field.

Examples:

/list projects

# Explicit — project always required
/list workitems BACK
/list workitems BACK todo
/list workitems BACK high priority
/list workitems BACK assigned to me
/list workitems BACK labeled as James
/list states BACK
/list labels BACK
/list members BACK

# Context — /project BACK must be set first
/workitems
/workitems todo
/workitems in progress
/workitems urgent
/workitems assigned to me
/workitems labeled as James
/states
/labels
/members
⁠Cache Management

The bot caches workspace data (user info, projects, states, labels, members) in SQLite to reduce API calls and speed up responses.

CommandDescription
/cacheShow all cache entries (same as show)
/cache showList cache entries with size and age
/cache updateRefresh all cached data (top-level + existing project data)
/cache cleanDelete project-level caches, refresh top-level only

Project states, labels, and members are lazily cached on first use and reused for subsequent calls. Use /cache clean after making structural changes in Plane (new states, members, etc.).

⁠Example Conversations

These are natural language queries you can send directly to the bot (no commands needed):

⁠General Questions
Who am I?
What workspace am I in?
⁠Projects
List all my projects
How many projects do I have?
Tell me about the Backend project
⁠Work Items
What are the open issues in project Backend?
Show me all urgent items in INVESTOS
What issues are assigned to me in BACK?
Get me issue BACK-42
What's the status of PROJ-7?
⁠Creating & Updating
Create an issue titled "Fix auth bug" with high priority in project Backend
Create a new todo in INVESTOS: "Update pricing page"
Update BACK-42 to Done
Change the priority of PROJ-7 to urgent
Assign BACK-15 to John
⁠Workspace & Members
Who are the members of the BACK project?
List all workspace members
What states does the INVESTOS project have?
What labels are available in BACK?

⁠Multi-User Mode

Set MULTI_USER=true to allow any Telegram user (or group chat) to connect their own Plane account. The bot stores credentials per-chat and isolates all data (cache, history, active workspace) between chats.

⁠Registration flow
User:  /login
Bot:   Step 1 — reply with your Plane API token
User:  plane_pat_abc123...          ← bot deletes this message for security
Bot:   ✅ Verified as John ([email protected])
       Step 2 — reply with your workspace slug
User:  my-company
Bot:   ✅ Registered! Found 5 projects in workspace my-company.
⁠Multi-user commands
CommandDescription
/loginConnect a Plane account (PAT + workspace slug)
/logoutRemove credentials and clear all chat data
⁠How it works
  • Each chat gets its own credential store and cache namespace in SQLite
  • PLANE_PAT and PLANE_WORKSPACE_SLUG environment variables are optional when MULTI_USER=true
  • In groups, the /login flow uses Telegram's ForceReply so the bot receives replies even with privacy mode enabled
  • /logout removes the registration, all conversation history, and all cache entries for that chat
⁠Per-chat workspace switching

In multi-user mode, each chat also has its own active workspace. The registered workspace is the default — users can switch with /workspace <slug> at any time. Each chat tracks its own:

  • Active workspace — default is the registered workspace slug
  • Active project — set with /project <IDENTIFIER>
  • Cache — scoped to the chat, rebuilt on /login and /cache clean

⁠Data & Privacy

  • Self-hosted: Your Plane PAT, AI keys, and conversation data never leave your infrastructure
  • SQLite: Chat history and cache are stored locally in ./data/chat_history.db (volume-mapped)
  • No telemetry: The bot doesn't phone home

⁠Updating

Pull the latest image and restart:

docker pull mguptahub/plane-telegram:latest
docker stop plane-telegram
docker rm plane-telegram
# Then run the docker run command from Quick Start

Your chat history and cache persist in the ./data volume.

⁠Troubleshooting

Bot not responding?

  • Check logs: docker logs -f plane-telegram
  • Verify your Telegram bot token is correct
  • Make sure the bot is not blocked or hasn't been stopped

Plane connection fails?

  • Verify your PLANE_PAT is valid and has the right permissions
  • Verify your PLANE_WORKSPACE_SLUG is correct (the slug, not the full URL)
  • For self-hosted: ensure PLANE_BASE_URL is reachable from inside the container
  • Check logs: docker logs -f plane-telegram

AI errors?

  • Verify your AI_API_KEY is valid and has credits
  • Check the model name in AI_MODEL is correct for your provider

Work item filters not working?

  • Run /cache clean to ensure states and members are freshly cached
  • Try /cache show to inspect what's cached
  • Note: each filter (state, priority, assignee, label) accepts only one value at a time

Commands not showing in Telegram?

  • Send /help to force re-registration of commands
  • Force-close and reopen Telegram (the commands menu is cached client-side)

⁠Development

⁠Clone and Setup
git clone https://github.com/mguptahub/plane-telegram-ai
cd plane-telegram-ai
cp .env.example .env
# Edit .env with your credentials
⁠Build and Run with Docker Compose
docker compose up -d --build

Check logs:

docker compose logs -f
⁠Debug Logging

Set DEBUG_LOGGING=true to write per-request JSON logs to data/debug_logs/. Each file captures the full AI exchange including tool calls, token usage, and cache hits.

⁠License

MIT

Tag summary

Content type

Image

Digest

sha256:01fe1635d…

Size

53.5 MB

Last updated

7 months ago

docker pull mguptahub/plane-telegram