-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathllms-full.txt
More file actions
11370 lines (7743 loc) · 372 KB
/
llms-full.txt
File metadata and controls
11370 lines (7743 loc) · 372 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Untether
> Telegram bridge for AI coding agents. Send tasks by voice or text, stream progress live, and approve changes — from your phone, anywhere. Works with Claude Code, Codex, OpenCode, Pi, Gemini CLI, and Amp.
---
# Conversation modes
Untether can handle follow-up messages in two ways: **chat mode** (auto-resume) or **stateless** (reply-to-continue). Both work across all your devices — start a conversation on your phone, continue it from your laptop, or check in from [Telegram Web](https://web.telegram.org).
During [onboarding](install.md), you chose a **workflow** (assistant, workspace, or handoff) that automatically configured this for you:
| Workflow | Session mode | Topics | Resume lines |
|----------|--------------|--------|--------------|
| **assistant** | chat | off | hidden |
| **workspace** | chat | on | hidden |
| **handoff** | stateless | off | shown |
This page explains what those settings mean and how to change them.
## Chat mode (auto-resume)
<!-- SCREENSHOT: Telegram showing chat mode — user sends follow-up without replying, bot auto-resumes -->
**What it feels like:** a normal chat assistant.
!!! user "You"
explain what this repo does
!!! untether "Untether"
done · codex · 8s
...
!!! user "You"
now add tests
Untether treats the second message as a continuation. If you want a clean slate, use:
!!! user "You"
/new
To pin a project or branch for the chat, use:
!!! user "You"
/ctx set <project> [@branch]
`/new` clears the session but keeps the bound context.
Tip: set a default engine for this chat with `/agent set claude`.
## Stateless (reply-to-continue)
<!-- SCREENSHOT: Telegram showing stateless mode — user replying to a message with resume line -->
**What it feels like:** every message is independent until you reply.
!!! user "You"
explain what this repo does
!!! untether "Untether"
done · codex · 8s
...
codex resume abc123
To continue the same session, **reply** to a message with a resume line:
!!! untether "Untether"
done · codex · 8s
!!! user "You"
now add tests
## Changing your settings
You can manually change these settings in your config file:
=== "untether config"
```sh
untether config set transports.telegram.session_mode "chat"
untether config set transports.telegram.show_resume_line false
```
=== "toml"
```toml
[transports.telegram]
session_mode = "chat" # "chat" or "stateless"
show_resume_line = false # true or false
```
Or re-run onboarding to pick a different workflow:
```sh
untether --onboard
```
## Resume lines in chat mode
If you enable chat mode (or topics), Untether can auto-resume, so you can hide resume lines for a cleaner chat.
Disable them if you want a fully clean footer, or enable `show_resume_line` to keep reply-branching visible.
If you prefer always-visible resume lines, set:
=== "untether config"
```sh
untether config set transports.telegram.show_resume_line true
```
=== "toml"
```toml
[transports.telegram]
show_resume_line = true
```
## Reply-to-continue still works
Even in chat mode, replying to a message with a resume line takes precedence and branches from that point.
## Related
- [Routing and sessions](../explanation/routing-and-sessions.md)
- [Chat sessions](../how-to/chat-sessions.md)
- [Forum topics](../how-to/topics.md)
- [Commands & directives](../reference/commands-and-directives.md)
## Next
Now that you know which mode you want, move on to your first run:
[First run →](first-run.md)
---
# First run
This tutorial walks you through sending your first task, watching it execute, and learning the core interaction patterns. Your agent runs on your machine; you control it from [Telegram](https://telegram.org) on whatever device is in your hand.
**What you'll learn:** How Untether streams progress, how to continue conversations, and how to cancel a run.
## 1. Start Untether in a repo
Untether runs agent CLIs in your current directory. Navigate to a repo you want to work in:
```sh
cd ~/dev/your-project
untether
```
Untether keeps running in your terminal. In Telegram, your bot will post a startup message like:
!!! untether "Untether"
🐕 untether v0.23.0 is ready
engine: `codex` · projects: `3`<br>
working in: /Users/you/dev/your-project
The message is compact by default — diagnostic lines only appear when they carry signal (e.g. `mode: chat` when in chat mode, or engine issues). This tells you:
- Which engine is the default and how many projects are registered
- Which directory Untether will run in
- Any engine issues (missing, misconfigured) when relevant
!!! note "Untether runs where you start it"
The agent will see files in your current directory. If you want to work on a different repo, stop Untether (`Ctrl+C`) and restart it in that directory—or set up [projects](projects-and-branches.md) to switch repos from chat.
## 2. Send a task
Open Telegram and send a message to your bot:
!!! user "You"
explain what this repo does
## 3. Watch progress stream
Untether immediately posts a progress message and updates it as the agent works:
!!! untether "Untether"
starting · codex · 0s
<!-- SCREENSHOT: progress message in Telegram showing "working · codex · 12s · step 3" with action list -->
As the agent calls tools and makes progress, you'll see updates like:
!!! untether "Untether"
working · codex · 12s · step 3
✓ tool: read: readme.md<br>
✓ tool: read: docs/index.md<br>
✓ tool: read: src/untether/runner.py
The progress message is edited in-place.
## 4. See the final answer
<!-- SCREENSHOT: final answer message in Telegram with model/cost footer and resume line -->
When the agent finishes, Untether sends a new message and replaces the progress message, so you get a notification.
!!! untether "Untether"
done · codex · 11s · step 5
Untether is a Telegram bridge for AI coding agents (Codex, Claude Code, OpenCode, Pi). It lets you run agents from chat, manage multiple projects and git worktrees, stream progress (commands, file changes, elapsed time), and resume sessions from either chat or terminal. It also supports file transfer, group topics mapped to repo/branch contexts, and multiple engines via chat commands, with a plugin system for engines/transports/commands.
codex resume 019bb89b-1b0b-7e90-96e4-c33181b49714
That last line is the **resume line**—it's how Untether knows which conversation to continue.
## 5. Continue the conversation
How you continue depends on your mode.
**If you're in chat mode:** just send another message (no reply needed).
!!! user "You"
now add tests for the API
Use `/new` any time you want a fresh thread.
**If you're in stateless mode:** **reply** to a message that has a resume line.
!!! untether "Untether"
done · codex · 11s · step 5
!!! user "You"
what command line arguments does it support?
Untether extracts the resume token from the message you replied to and continues the same agent session.
!!! tip "Reply-to-continue still works in chat mode"
If resume lines are visible, replying to any older message branches the conversation from that point.
Use `show_resume_line = true` if you want this behavior all the time.
!!! tip "Reset with /new"
`/new` clears stored sessions for the current chat or topic.
## 6. Cancel a run
Sometimes you want to stop a run in progress—maybe you realize you asked the wrong question, or it's taking too long.
While the progress message is showing, tap the **cancel** button or reply to it with:
!!! untether "Untether"
working · codex · 12s · step 3
!!! user "You"
/cancel
<!-- SCREENSHOT: cancel button on progress message and the resulting "cancelled" status -->
Untether sends `SIGTERM` to the agent process and posts a cancelled status:
!!! failure ""
cancelled · codex · 12s
codex resume 019bb89b-1b0b-7e90-96e4-c33181b49714
If a resume token was already issued (and resume lines are enabled), it will still be included so you can continue from where it stopped.
!!! note "Cancel only works on progress messages"
If the run already finished, there's nothing to cancel. Just send a new message or reply to continue.
## 7. Try a different engine
Want to use a different engine for one message? Prefix your message with `/<engine>`:
!!! user "You"
/claude explain the error handling in this codebase
This uses Claude Code for just this message. The resume line will show `claude --resume ...`, and replies will automatically use Claude.
Available prefixes depend on what you have installed: `/codex`, `/claude`, `/opencode`, `/pi`.
!!! tip "Set a default engine"
Use `/agent set claude` to make this chat (or topic) use Claude by default. Run `/agent` to see what's set.
## What just happened
Key points:
- Untether spawns the agent CLI as a subprocess
- The agent streams JSONL events (tool calls, progress, answer)
- Untether renders these as an editable progress message
- When done, the progress message is replaced with the final answer
- Chat mode auto-resumes; resume lines let you reply to branch
## Troubleshooting
**Progress message stuck on "starting" (or not updating)**
The agent might be doing something slow (large repo scan, network call). Wait a bit, or `/cancel` and try a more specific prompt.
**Agent CLI not found**
The agent CLI isn't on your PATH. Install the CLI for the engine you're using (e.g., `npm install -g @openai/codex`) and make sure the install location is in your PATH.
**Bot doesn't respond at all**
Check that Untether is still running in your terminal. You should also see a startup message ("untether is ready") from the bot in Telegram. If not, restart it.
**Resume doesn't work (starts a new conversation)**
Make sure you're **replying** to a message that contains a resume line. If you hid resume lines (`show_resume_line = false`), turn them on or use chat mode to continue by sending another message.
## Next
You've mastered the basics. Next, learn how to control Claude Code's actions in real time with Telegram buttons.
[Interactive control →](interactive-control.md)
---
# Tutorials
1. [Install](install.md)
2. [First run](first-run.md)
3. [Interactive control](interactive-control.md)
4. [Projects & branches](projects-and-branches.md)
5. [Multi-engine](multi-engine.md)
See also: [Conversation modes](conversation-modes.md)
---
# Install and onboard
This tutorial walks you through installing Untether, creating a Telegram bot, and generating your config file. Once set up, you can send coding tasks from your phone while you're out, review results on your tablet, or keep working from your laptop — anywhere [Telegram](https://telegram.org) runs.
**What you'll have at the end:** A working `~/.untether/untether.toml` with your bot token, chat ID, workflow settings, and default engine.
## 1. Install Python 3.14 and uv
Install `uv`, the modern Python [package manager](https://docs.astral.sh/uv/):
```sh
curl -LsSf https://astral.sh/uv/install.sh | sh
```
Install Python 3.14 with uv:
```sh
uv python install 3.14
```
## 2. Install Untether
```sh
uv tool install -U untether
```
Verify it's installed:
```sh
untether --version
```
You should see something like `0.31.0`.
## 3. Install agent CLIs
Untether shells out to agent CLIs. Install the ones you plan to use (or install them all now):
### Codex
```sh
npm install -g @openai/codex
```
Untether uses the official Codex CLI, so your existing ChatGPT subscription applies. Run `codex` and sign in with your ChatGPT account.
### Claude Code
```sh
npm install -g @anthropic-ai/claude-code
```
Untether uses the official Claude CLI, so your existing Claude subscription applies. Run `claude` and log in with your Claude account. Untether defaults to subscription billing unless you opt into API billing in config.
!!! note "macOS credentials"
On macOS, Claude Code stores OAuth credentials in macOS Keychain rather than a plain-text file. Untether handles both automatically — just make sure you've run `claude login` at least once before starting Untether.
### OpenCode
```sh
npm install -g opencode-ai@latest
```
OpenCode supports logging in with Anthropic for your Claude subscription or with OpenAI for your ChatGPT subscription, and it can connect to 75+ providers via Models.dev (including local models).
### Pi
```sh
npm install -g @mariozechner/pi-coding-agent
```
Pi can authenticate via a provider login or use API billing. You can log in with Anthropic (Claude subscription), OpenAI (ChatGPT subscription), GitHub Copilot, Google Cloud Code Assist (Gemini CLI), or Antigravity (Gemini 3, Claude, GPT-OSS), or choose API billing instead.
## 4. Run onboarding
Start Untether without a config file. It will detect this and launch the setup wizard:
```sh
untether
```
You'll see:
```
step 1: bot token
? do you already have a bot token from @BotFather? (yes/no)
```
If you don't have a bot token yet, answer **n** and Untether will show you the steps.
## 5. Create a Telegram bot
If you answered **n**, follow these steps (or skip to step 6 if you already have a token):
1. Open Telegram and message [@BotFather](https://t.me/BotFather)
2. Send `/newbot` or use the mini app
3. Choose a display name (the obvious choice is "untether")
4. Choose a username ending in `bot` (e.g., `my_untether_bot`)
<!-- SCREENSHOT: BotFather conversation showing /newbot flow and the generated token -->
BotFather will congratulate you on your new bot and will reply with your token:
```
Done! Congratulations on your new bot. You will find it at
t.me/my_untether_bot. You can now add a description, about
section and profile picture for your bot, see /help for a
list of commands.
Use this token to access the HTTP API:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz
Keep your token secure and store it safely, it can be used
by anyone to control your bot.
```
Copy the token (the `123456789:ABC...` part).
!!! warning "Keep your token secret"
Anyone with your bot token can control your bot. Don't commit it to git or share it publicly.
## 6. Enter your bot token
Paste your token when prompted:
```
? paste your bot token: ****
validating...
connected to @my_untether_bot
```
Untether validates the token by calling the Telegram API. If it fails, double-check you copied the full token.
## 7. Pick your workflow
<!-- SCREENSHOT: onboarding wizard in terminal showing the workflow selection step -->
Untether shows three workflow previews:
=== "assistant"
ongoing chat
<div class="workflow-preview">
<div class="msg msg-you">make happy wings fit</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 8s · step 3</div><div class="clearfix"></div>
<div class="msg msg-you">carry heavy creatures</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 12s · step 5</div><div class="clearfix"></div>
<div class="msg msg-you"><span class="cmd">/new</span></div><div class="clearfix"></div>
<div class="msg msg-you">add flower pin</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 6s · step 2</div><div class="clearfix"></div>
</div>
=== "workspace"
topics per branch
<div class="workflow-preview">
<div class="topic-bar"><span class="topic-active">happian @memory-box</span><span class="topic">untether @master</span></div>
<div class="msg msg-you">store artifacts forever</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 10s · step 4</div><div class="clearfix"></div>
<div class="msg msg-you">also freeze them</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 6s · step 2</div><div class="clearfix"></div>
</div>
=== "handoff"
reply to continue
<div class="workflow-preview">
<div class="msg msg-you">make it go back in time</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 8s · step 3<br><span class="resume">codex resume <span class="id-1">abc123</span></span></div><div class="clearfix"></div>
<div class="msg msg-you">add reconciliation ribbon</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 3s · step 1<br><span class="resume">codex resume <span class="id-2">def456</span></span></div><div class="clearfix"></div>
<div class="msg msg-you"><div class="reply-quote">done · codex · 8s · step 3</div>more than once</div><div class="clearfix"></div>
<div class="msg msg-bot">done · codex · 8s · step 5<br><span class="resume">codex resume <span class="id-1">abc123</span></span></div><div class="clearfix"></div>
</div>
```
? how will you use untether?
❯ assistant (ongoing chat, /new to reset)
workspace (projects + branches, i'll set those up)
handoff (reply to continue, terminal resume)
```
Each choice automatically configures conversation mode, topics, and resume lines:
| Workflow | Best for | What it does |
|----------|----------|--------------|
| **assistant** | Single developer, private chat | Chat mode (auto-resume), topics off, resume lines hidden. Use `/new` to start fresh. |
| **workspace** | Teams, multiple projects/branches | Chat mode, topics on, resume lines hidden. Each topic binds to a repo/branch. |
| **handoff** | Terminal-based workflow | Stateless (reply-to-continue), resume lines always shown. Copy resume line to terminal. |
!!! tip "Not sure which to pick?"
Start with **assistant** (recommended). You can always change settings later in your config file.
## 8. Connect your chat
Depending on your workflow choice, Untether shows different instructions:
**For assistant or handoff:**
```
step 3: connect chat
1. open a chat with @my_untether_bot
2. send /start
waiting for message...
```
**For workspace:**
```
step 3: connect chat
set up a topics group:
1. create a group and enable topics (settings → topics)
2. add @my_untether_bot as admin with "manage topics"
3. send any message in the group
waiting for message...
```
Once Untether receives your message:
```
got chat_id 123456789 for @yourusername (private chat)
```
!!! warning "Workspace requires a forum group"
If you chose workspace and the chat isn't a forum-enabled supergroup with proper bot permissions, Untether will warn you and offer to switch to assistant mode instead.
## 9. Choose your default engine
Untether scans your PATH for installed agent CLIs:
```
step 4: default engine
untether runs these engines on your computer. switch anytime with /agent.
engine status install command
───────────────────────────────────────────
codex ✓ installed
claude ✓ installed
opencode ✗ not found npm install -g opencode-ai@latest
pi ✗ not found npm install -g @mariozechner/pi-coding-agent
? choose default engine:
❯ codex
claude
```
Pick whichever you prefer. You can always switch engines per-message with `/codex`, `/claude`, etc.
## 10. Save your config
```
step 5: save config
? save config to ~/.untether/untether.toml? (yes/no)
```
Press **y** or **Enter** to save. You'll see:
```
✓ setup complete. starting untether...
```
Untether is now running and listening for messages!
<!-- SCREENSHOT: Telegram startup message from the bot showing version and engine info -->
## What just happened
Your config file lives at `~/.untether/untether.toml`. The exact contents depend on your workflow choice:
=== "assistant"
=== "untether config"
```sh
untether config set default_engine "codex"
untether config set transport "telegram"
untether config set transports.telegram.bot_token "..."
untether config set transports.telegram.chat_id 123456789
untether config set transports.telegram.session_mode "chat"
untether config set transports.telegram.show_resume_line false
untether config set transports.telegram.topics.enabled false
untether config set transports.telegram.topics.scope "auto"
```
=== "toml"
```toml title="~/.untether/untether.toml"
default_engine = "codex"
transport = "telegram"
[transports.telegram]
bot_token = "..."
chat_id = 123456789
session_mode = "chat" # auto-resume
show_resume_line = false # cleaner chat
[transports.telegram.topics]
enabled = false
scope = "auto"
```
=== "workspace"
=== "untether config"
```sh
untether config set default_engine "codex"
untether config set transport "telegram"
untether config set transports.telegram.bot_token "..."
untether config set transports.telegram.chat_id -1001234567890
untether config set transports.telegram.session_mode "chat"
untether config set transports.telegram.show_resume_line false
untether config set transports.telegram.topics.enabled true
untether config set transports.telegram.topics.scope "auto"
```
=== "toml"
```toml title="~/.untether/untether.toml"
default_engine = "codex"
transport = "telegram"
[transports.telegram]
bot_token = "..."
chat_id = -1001234567890 # forum group
session_mode = "chat"
show_resume_line = false
[transports.telegram.topics]
enabled = true # topics on
scope = "auto"
```
=== "handoff"
=== "untether config"
```sh
untether config set default_engine "codex"
untether config set transport "telegram"
untether config set transports.telegram.bot_token "..."
untether config set transports.telegram.chat_id 123456789
untether config set transports.telegram.session_mode "stateless"
untether config set transports.telegram.show_resume_line true
untether config set transports.telegram.topics.enabled false
untether config set transports.telegram.topics.scope "auto"
```
=== "toml"
```toml title="~/.untether/untether.toml"
default_engine = "codex"
transport = "telegram"
[transports.telegram]
bot_token = "..."
chat_id = 123456789
session_mode = "stateless" # reply-to-continue
show_resume_line = true # always show resume lines
[transports.telegram.topics]
enabled = false
scope = "auto"
```
This config file controls all of Untether's behavior. You can edit it directly to change settings or add advanced features.
[Full config reference →](../reference/config.md)
## Re-running onboarding
If you ever need to reconfigure:
```sh
untether --onboard
```
This will prompt you to update your existing config (it won't overwrite without asking).
## Troubleshooting
**"error: missing untether config"**
Run `untether` in a terminal with a TTY. The setup wizard only runs interactively.
**"failed to connect, check the token and try again"**
Make sure you copied the full token from BotFather, including the numbers before the colon.
**Bot doesn't respond to /start**
If you're still in onboarding, your terminal should show "waiting...". If you accidentally closed it, run `untether` again and restart the setup.
**"error: already running"**
You can only run one Untether instance per bot token. Find and stop the other process, or remove the stale lock file at `~/.untether/untether.lock`.
## Next
Learn more about conversation modes and how your workflow choice affects follow-ups.
[Conversation modes →](conversation-modes.md)
---
# Interactive control
This tutorial walks you through Untether's interactive permission system — approving, denying, and shaping agent actions from [Telegram](https://telegram.org) on whatever device is in your hand. Stay in control while you're away from the terminal.
**What you'll learn:** How to control Claude Code's actions in real time with Telegram buttons, how to request and review a plan before execution, and how to answer agent questions from anywhere.
!!! note "Claude Code only"
Interactive approval is a Claude Code feature. Other engines (Codex, OpenCode, Pi) run non-interactively — they don't prompt for approval.
## 1. Understand permission modes
Untether offers three permission modes that control how much oversight you have:
| Mode | Command | What happens |
|------|---------|-------------|
| **Plan** | `/planmode on` | Every tool call shows Approve / Deny buttons. Full control. |
| **Auto** | `/planmode auto` | Tools are auto-approved. Plan transitions are also auto-approved. Hands-off. |
| **Accept edits** | `/planmode off` | No approval buttons at all. Claude runs autonomously. |
For this tutorial, we'll use **Plan** mode so you can see every interaction.
## 2. Enable plan mode
Open your Telegram chat with the bot and send:
```
/planmode on
```
<!-- SCREENSHOT: /planmode on response showing "plan mode: on" confirmation -->
The bot confirms that plan mode is now active. This setting is stored per chat and persists across sessions.
## 3. Send a task
Send Claude a task that will require file changes:
```
add a comment to the top of README.md explaining what this project does
```
<!-- SCREENSHOT: user sending a task message to the bot -->
Claude starts working and you'll see a progress message stream in.
## 4. See approval buttons
When Claude wants to modify a file, Untether intercepts the tool call and shows you what's about to happen. You'll see a message like:
<!-- SCREENSHOT: approval buttons showing Edit tool with diff preview — Approve / Deny / Pause & Outline Plan -->
The message includes:
- **Tool name** (e.g. Edit, Write, Bash)
- **Diff preview** — removed lines (`- old`) and added lines (`+ new`) so you can see what will change
- **Three buttons**: Approve, Deny, and Pause & Outline Plan
Your phone will also buzz with a push notification so you don't miss it.
## 5. Approve a tool call
Tap **Approve** to let Claude proceed with the action. The button clears instantly — no spinner, no waiting. Claude continues with its work.
<!-- SCREENSHOT: progress message after approving, showing the action completed -->
You may see several approval requests in a row as Claude works through multiple steps.
## 6. Deny a tool call
If something doesn't look right, tap **Deny** instead. Claude receives a denial message explaining that you've blocked the action and asking it to communicate via visible text instead.
<!-- SCREENSHOT: deny response — Claude acknowledging the denial and explaining its intent -->
This is useful when you want Claude to explain its reasoning before making changes. After denying, Claude will typically describe what it was trying to do and ask for guidance.
## 7. Use "Pause & Outline Plan"
The third button — **Pause & Outline Plan** — is the most powerful. It appears when Claude tries to exit plan mode (transition from planning to execution).
Tap it to require Claude to write a comprehensive plan as a visible message before doing anything. The plan must include:
1. Every file to be created or modified (full paths)
2. What changes will be made in each file
3. The execution order and phases
4. Key decisions and trade-offs
5. The expected end result
<!-- SCREENSHOT: Claude's written outline/plan appearing as visible text in the chat -->
After Claude writes the outline, **Approve Plan** and **Deny** buttons appear automatically — no need to type "approved":
<!-- SCREENSHOT: post-outline Approve Plan / Deny buttons in Telegram -->
- Tap **Approve Plan** to let Claude proceed with implementation
- Tap **Deny** to stop Claude and provide different direction
!!! tip "Progressive cooldown"
After tapping "Pause & Outline Plan", a cooldown prevents Claude from immediately retrying. The cooldown starts at 30 seconds and escalates up to 120 seconds if Claude keeps retrying. This ensures the agent pauses long enough for you to read the outline.
## 8. Answer a question
Sometimes Claude needs to ask you something — like which approach to take or what naming convention to use. When Claude calls `AskUserQuestion`, you'll see the question in the chat with a ❓ prefix and **option buttons** for each choice:
<!-- SCREENSHOT: AskUserQuestion message showing the question text with option buttons -->
**Tap an option button** to select your answer. Claude receives your choice and continues immediately.
For multi-question flows (1 of N, 2 of N), each question appears in sequence after you answer the previous one.
If none of the options fit, tap **Other (type reply)** and type a custom answer as text. Untether routes your reply back to Claude, which reads it and continues.
```
You: Use snake_case for all variable names
```
<!-- SCREENSHOT: user replying with text to an AskUserQuestion, Claude continuing -->
You can also tap **Deny** to dismiss the question if it's not relevant.
!!! tip "Ask mode toggle"
Control whether Claude asks interactive questions via `/config` → **Ask mode**. When off, Claude proceeds with reasonable defaults instead of asking.
## 9. Switch to auto mode
Once you're comfortable with how Claude works, you might want less interruption. Switch to auto mode:
```
/planmode auto
```
<!-- SCREENSHOT: /planmode auto confirmation -->
In auto mode, tool calls (Edit, Write, Bash) are still auto-approved — Claude works without interruption. Plan transitions are also auto-approved, so you won't see ExitPlanMode buttons. The agent preamble still requests summaries and structured output.
## 10. Return to default
To turn off plan mode entirely:
```
/planmode off
```
This sets Claude to `acceptEdits` mode — no approval buttons at all. Claude runs autonomously, which is the fastest option for trusted tasks.
To check your current mode at any time:
```
/planmode show
```
<!-- SCREENSHOT: /planmode show output showing current mode and source -->
## What just happened
Key concepts:
- **Permission modes** control the level of oversight: plan (full control), auto (hands-off with plans), off (fully autonomous)
- **Approval buttons** appear inline in Telegram when Claude needs permission — Approve, Deny, or Pause & Outline Plan
- **Diff previews** show you exactly what will change before you approve
- **"Pause & Outline Plan"** forces Claude to write a visible plan before executing
- **AskUserQuestion** lets you answer Claude's questions with option buttons or a text reply
- **Push notifications** ensure you don't miss approval requests, even from another app
- **Ephemeral cleanup** automatically removes button messages when the run finishes
## Troubleshooting
**Approval buttons don't appear**
Check that you're using Claude Code (`/claude` prefix or `/agent set claude`) and that plan mode is on (`/planmode show`). Other engines don't support interactive approval.
**Buttons appear but nothing happens when I tap them**
Check your internet connection. If the tap doesn't register, try again — Untether answers callbacks immediately so there should be no delay.
**Claude keeps retrying after I tap "Pause & Outline Plan"**
This is the progressive cooldown at work. Claude may retry ExitPlanMode during the cooldown window, but each retry is auto-denied. Wait for Claude to write the outline, then use the Approve Plan / Deny buttons that appear.
**I don't get push notifications for approval requests**
Make sure Telegram notifications are enabled for this chat. Untether sends a separate notification message when buttons appear, but Telegram's notification settings control whether you see it.
## Next
Now that you can control your agent interactively, learn how to target specific repos and branches.
[Projects and branches →](projects-and-branches.md)
---
# Multi-engine workflows
This tutorial shows you how to use different engines for different tasks and set up defaults so you don't have to think about it. Swap between Claude Code, Codex, OpenCode, Pi, Gemini CLI, and Amp with a single prefix — from your phone, laptop, or any device with [Telegram](https://telegram.org).
**What you'll learn:** Engine directives, persistent defaults, and when to use which engine.
## Why multiple engines?
Different engines have different strengths:
| Engine | Good at | Unique features |
|-------|---------|----------------|
| **Claude Code** | Complex refactors, architecture, long context | Interactive permissions, plan mode, ask mode, diff preview |
| **Codex** | Fast edits, shell commands, quick fixes | Reasoning levels, device re-auth (`/auth`) |
| **OpenCode** | 75+ providers via Models.dev, local models | Broadest provider support |
| **Pi** | Multi-provider auth, conversational | Context compaction |
See the [engine compatibility matrix](https://github.com/littlebearapps/untether#engine-compatibility) in the README for a full feature-by-feature breakdown.
You might want Codex for quick tasks and Claude for deep work—without manually specifying every time.
## 1. One-off engine selection
Prefix any message with `/<engine>`:
!!! user "You"
/claude refactor this module to use dependency injection
!!! user "You"
/codex add a --verbose flag to the CLI
!!! user "You"
/pi explain how the event loop works in this codebase
The engine only applies to that message. The response will have a resume line for that engine:
!!! untether "Untether"
done · claude · 8s<br>
claude --resume abc123
When you reply, Untether sees `claude --resume` and automatically uses Claude—you don't need to repeat `/claude`.
## 2. Engine + project + branch
Directives combine. Order doesn't matter:
!!! user "You"
/claude /happy-gadgets @feat/di refactor to use dependency injection
Or:
!!! user "You"
/happy-gadgets @feat/di /claude refactor to use dependency injection
Both do the same thing: run Claude in the `happy-gadgets` project on the `feat/di` branch.
!!! note "Directives are only parsed at the start"
Everything after the first non-directive word is the prompt. `/claude fix /this/path` uses Claude with prompt "fix /this/path"—it doesn't try to parse `/this` as a directive.
## 3. Set a default engine for a chat
Use `/agent set` to change the default for the current scope:
!!! user "You"
/agent set claude
Response: