15 KiB
Takopi User Guide
Takopi is a command-line tool that lets you control coding agents—like Codex, Claude, and others—through Telegram. Send a message, and takopi runs the agent in your repo, streaming progress back to your chat. It supports multi-repo workflows, git worktrees, and per-project routing.
This guide starts simple and layers on features as you go. Jump to any section or read straight through.
Prerequisites
Before you begin, make sure you have:
- A Telegram account
- Python 3.14+ and
uvinstalled - At least one supported agent CLI installed and on your
PATH(codex, claude, opencode, pi) - Basic familiarity with git (especially if you plan to use worktrees)
Key concepts
A few terms you'll see throughout:
| Term | Meaning |
|---|---|
| Engine | A coding agent backend (Codex, Claude, opencode, pi) |
| Project | A repo/workdir alias used for routing (can set default engine, worktrees, chat ID) |
| Worktree | A git feature that lets you check out multiple branches simultaneously in separate directories |
| Topic | A Telegram forum thread bound to a project/branch; stores per-topic resume tokens |
| Resume token | State that allows an engine to continue from where it left off |
How conversations work
Takopi is stateless by default. Each message starts a new engine session unless a resume token is present.
To continue a session:
- Reply to a bot message. Takopi reads the resume token from the footer and resumes that session.
- Forum topics (optional) store resume tokens per topic and auto-resume for new messages in that topic.
Reset with
/new. - Chat sessions (optional) store one resume token per chat (per sender in groups) so new messages
auto-resume without replying. Enable with
session_mode = "chat"and reset with/new. State is stored intelegram_chat_sessions_state.json. You can hide resume lines by setting[transports.telegram].show_resume_line = falsewhen auto-resume is available and a project context is resolved.
Reply-to-continue always works, even if chat sessions or topics are enabled.
1. Installation and setup
Install takopi with:
uv tool install -U takopi
Run it once to start the onboarding wizard:
takopi
The wizard walks you through:
- Creating a Telegram bot token via @BotFather
- Capturing your
chat_id(the wizard listens for a message from you) - Choosing a default engine
To re-run onboarding later, use takopi --onboard.
Your configuration is stored at ~/.takopi/takopi.toml.
Minimal configuration
After onboarding, your config looks something like this:
default_engine = "codex"
transport = "telegram"
[transports.telegram]
bot_token = "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
chat_id = 123456789
Optional: split long final responses instead of trimming them:
[transports.telegram]
message_overflow = "split" # trim | split
2. Your first handoff
The simplest workflow:
cdinto any git repository- Run
takopi - Send a message to your bot
Takopi streams progress in the chat and sends a final response when the agent finishes.
Basic controls
- Reply to a bot message to continue the session (takopi reads the resume token in the footer)
- Cancel a run by clicking the cancel button or replying to the progress message with
/cancel
3. Switching engines
Prefix your message with an engine directive to override the default:
/codex hard reset the timeline
/claude shrink and store artifacts forever
/opencode hide their paper until they reply
/pi render a diorama of this timeline
Directives are only parsed at the start of the first non-empty line.
Default agent per chat or topic
Use /agent to view or set a persistent default for the current scope:
/agent
/agent set claude
/agent clear
- Inside a forum topic,
/agent setaffects that topic. - In normal chats, it affects the whole chat.
- In group chats, only admins can change defaults.
Precedence (highest to lowest): resume token → /engine directive → topic default → chat default → project default → global default.
Setting up engines
Takopi shells out to the agent CLIs. Install them and make sure they're on your PATH
(codex, claude, opencode, pi). Authentication is handled by each CLI (login,
config files, or environment variables).
4. Projects
For repos you work with often, register them as projects:
cd ~/dev/happy-gadgets
takopi init happy-gadgets
This adds a project entry to your config (for example):
[projects.happy-gadgets]
path = "~/dev/happy-gadgets"
Now you can target it from anywhere using the /project directive:
/happy-gadgets pinky-link two threads
If you expect to add or edit projects while takopi is running, enable config watching so changes are picked up automatically:
watch_config = true
Project-specific settings
Projects can override global defaults:
[projects.happy-gadgets]
path = "~/dev/happy-gadgets"
default_engine = "claude"
worktrees_dir = ".worktrees"
worktree_base = "master"
Setting a default project
If you mostly work in one repo:
default_project = "happy-gadgets"
5. Worktrees
Worktrees let you work on multiple branches without switching back and forth. Use @branch to run a task in a dedicated worktree:
/happy-gadgets @feat/memory-box freeze artifacts forever
Takopi creates (or reuses) a worktree at:
<worktrees_root>/<branch>
worktrees_root is <project.path>/<worktrees_dir> unless worktrees_dir is an
absolute path. If the branch matches the repo's current branch, Takopi runs in the
main repo instead of creating a new worktree.
Worktree configuration
[projects.happy-gadgets]
path = "~/dev/happy-gadgets"
worktrees_dir = ".worktrees" # relative to project path
worktree_base = "master" # base branch for new worktrees
To avoid .worktrees/ showing up as untracked, add it to your global gitignore:
git config --global core.excludesfile ~/.config/git/ignore
echo ".worktrees/" >> ~/.config/git/ignore
Context persistence
Takopi adds a ctx: footer to messages with project and branch info. When you reply, this context carries forward—no need to repeat /project @branch each time.
6. Per-project chat routing
Give each project its own Telegram chat:
takopi chat-id --project happy-gadgets
Send any message in the target chat. Takopi captures the chat_id and updates your config:
[projects.happy-gadgets]
path = "~/dev/happy-gadgets"
chat_id = -1001234567890
Messages from that chat automatically route to the project.
Rules for chat IDs
- Each
projects.*.chat_idmust be unique - Project chat IDs must not match
transports.telegram.chat_id - Telegram uses positive IDs for private chats and negative IDs for groups/supergroups
Capture a chat ID without saving
To see a chat ID without writing to config:
takopi chat-id
7. Topics
Topics bind Telegram forum threads to specific project/branch contexts. They also preserve resume tokens and can store a default agent per topic.
Enabling topics
[transports.telegram.topics]
enabled = true
Your bot needs Manage Topics permission in the group.
If any projects.<alias>.chat_id are configured, topics are managed in those
project chats; otherwise topics are managed in the main chat.
Topic behavior
┌────────────────────────────┐
│ takopi projects │
├────────────────────────────┤
│ takopi @master │
│ takopi @feat/topics │
│ happy-gadgets @master │
│ happy-gadgets @feat/camera │
└────────────────────────────┘
Each project can have its own forum-enabled supergroup. Topics still
include the project name for consistency, but the project is inferred from the
chat. Regular messages in that chat also infer the project, so /project is
usually optional.
┌────────────────────────────────┐ ┌───────────────────────────────────┐
│ takopi │ │ happy-gadgets │
├────────────────────────────────┤ ├───────────────────────────────────┤
│ takopi @master │ │ happy-gadgets @master │
│ takopi @feat/topics │ │ happy-gadgets @feat/happy-camera │
│ takopi @feat/voice │ │ happy-gadgets @feat/memory-box │
└────────────────────────────────┘ └───────────────────────────────────┘
Topic commands
Run these inside a topic thread:
| Command | Description |
|---|---|
/topic <project> @branch |
Create a new topic bound to context |
/ctx |
Show the current binding |
/ctx set <project> @branch |
Update the binding |
/ctx clear |
Remove the binding |
/new |
Clear resume tokens for this topic |
In project chats, omit the project: /topic @branch or /ctx set @branch.
Configuration examples
Main chat only:
[transports.telegram]
chat_id = -1001234567890
# show_resume_line = false
[transports.telegram.topics]
enabled = true
Project chats:
[transports.telegram]
chat_id = 123456789 # main chat (private, for non-project messages)
# show_resume_line = false
[transports.telegram.topics]
enabled = true
[projects.takopi]
path = "~/dev/takopi"
chat_id = -1001111111111 # forum-enabled group
Topic state is stored in telegram_topics_state.json next to your config file. Chat defaults live in telegram_chat_prefs_state.json.
8. Voice notes
Dictate tasks instead of typing:
[transports.telegram]
voice_transcription = true
voice_transcription_model = "gpt-4o-mini-transcribe" # optional
Set OPENAI_API_KEY in your environment (uses OpenAI's transcription API with the
gpt-4o-mini-transcribe model by default). To use a local OpenAI-compatible
Whisper server, also set OPENAI_BASE_URL (for example, http://localhost:8000/v1)
and a dummy OPENAI_API_KEY if your server ignores it. If your server requires a
specific model name, set voice_transcription_model accordingly (for example,
whisper-1).
When you send a voice note, takopi transcribes it and runs the result as a normal text message. If transcription fails, you'll get an error message and the run is skipped.
9. File transfer
Upload files into the active repo/worktree or fetch files back into Telegram.
Upload a file
Send a document with a caption:
/file put <path>
Examples:
/file put docs/spec.pdf
/file put /happy-gadgets @feat/camera assets/logo.png
If you send a file without a caption, takopi saves it to:
incoming/<original_filename>
If you set auto_put_mode = "prompt", a caption/question will start a run
immediately after upload, with the prompt annotated with the uploaded path.
Use --force to overwrite an existing file:
/file put --force docs/spec.pdf
Fetch a file
Send:
/file get <path>
Directories are zipped automatically.
File transfer config
[transports.telegram.files]
enabled = true
auto_put = true
auto_put_mode = "upload"
uploads_dir = "incoming"
allowed_user_ids = [123456789]
deny_globs = [".git/**", ".env", ".envrc", "**/*.pem", "**/.ssh/**"]
Notes:
- File transfer is disabled by default.
- If
allowed_user_idsis empty, private chats are allowed and group usage requires admin privileges.
10. Configuration reference
Full example with all options:
# Global defaults
default_engine = "codex"
default_project = "takopi"
transport = "telegram"
watch_config = true # hot-reload on config changes (except transport)
[transports.telegram]
bot_token = "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
chat_id = 123456789
voice_transcription = true
voice_transcription_model = "gpt-4o-mini-transcribe"
session_mode = "stateless" # or "chat" for auto-resume per chat
show_resume_line = true
[transports.telegram.files]
enabled = true
auto_put = true
auto_put_mode = "upload"
uploads_dir = "incoming"
allowed_user_ids = [123456789]
deny_globs = [".git/**", ".env", ".envrc", "**/*.pem", "**/.ssh/**"]
[transports.telegram.topics]
enabled = true
scope = "auto"
# Project definitions
[projects.takopi]
path = "~/dev/takopi"
default_engine = "codex"
worktrees_dir = ".worktrees"
worktree_base = "master"
# chat_id = -1001234567890 # optional: dedicated chat
[projects.happy-planet]
path = "~/dev/happy-planet"
default_engine = "claude"
worktrees_dir = "~/.takopi/worktrees/happy-planet"
worktree_base = "develop"
11. Command cheatsheet
Message directives
| Directive | Example | Description |
|---|---|---|
/engine |
/codex make threads resolve their differences |
Use a specific engine |
/project |
/happy-gadgets add escape-pod |
Target a project |
@branch |
@feat/happy-camera rewind to checkpoint |
Run in a worktree |
| Combined | /happy-gadgets @feat/flower-pin observe unseen |
Project + branch |
In-chat commands
| Command | Description |
|---|---|
/cancel |
Reply to the progress message to stop the current run |
/file put <path> |
Upload a document into the repo/worktree |
/file get <path> |
Fetch a file (directories are zipped) |
/agent |
Show/set the default agent for the current scope |
/topic <project> @branch |
Create/bind a topic |
/ctx |
Show current context |
/ctx set <project> @branch |
Update context binding |
/ctx clear |
Remove context binding |
/new |
Clear stored resume tokens (topic or chat session) |
CLI commands
| Command | Description |
|---|---|
takopi |
Start the bot (runs onboarding if first time) |
takopi --onboard |
Re-run onboarding wizard |
takopi init <alias> |
Register current directory as a project |
takopi chat-id |
Capture a chat ID |
takopi chat-id --project <alias> |
Set a project's chat ID |
takopi --debug |
Write debug logs to debug.log |
12. Tips
Schedule tasks with Telegram
Telegram has a native message scheduling feature that works seamlessly with takopi. Long-press the send button and choose "Schedule Message" to run tasks at a specific time. You can also set up recurring schedules (daily, weekly, etc.) for automated workflows.
13. Troubleshooting
If something isn't working, rerun with takopi --debug and check debug.log
for errors. Include it when reporting issues.