Skip to main content
How-To Guides Last updated: 8 October 2026

Inline settings menu

Nathan Schram
By Founder, Little Bear Apps

Adjust Untether’s behaviour without editing config files or restarting — tap buttons right in Telegram. The /config command opens an interactive settings menu with inline keyboard buttons, similar to BotFather’s settings style. Navigate sub-pages, toggle settings, and return to the overview, all within a single message that edits in place.

Open the menu

Send /config in any chat:

/config

The home page shows current values grouped under Agent controls, Display and Routing, with buttons arranged in pairs (max 2 per row) for comfortable mobile tap targets:

🐕 Untether settings

Agent controls (Claude Code)
Permission mode: on  · approve the plan first
Ask mode: on  · interactive questions
Diff preview: off  · buttons only

Display
Cost & usage: cost on, sub off
Verbose: off  · compact progress
Resume line: on

Routing
Engine: claude (default)
Model: default  · from CLI settings
Listen: all  · respond to everything
Follow-up: queue  · wait for the run
⏰ Triggers: active                    ← only when triggers are configured
Effort: default  · high

[📋 Permission mode]  [❓ Ask mode]
[📝 Diff preview]  [🔍 Verbose]
[💰 Cost & usage]  [↩️ Resume line]
[📡 Listen]        [🔁 Loop mode]
[🧠 Reasoning]     [⚙️ Engine & model]
[↪️ Follow-up]     [ℹ️ About]
[⏰ Triggers]      [⏸ Pause triggers]   ← only when [triggers] is enabled

📖 Help guides · 🐛 Report a bug

Engine-specific controls

The home page adapts to the current engine. Claude Code shows Permission mode, Ask mode, and Diff preview under “Agent controls”. Codex CLI shows Approval policy (full auto / safe = read-only sandbox). Gemini CLI (deprecated) shows Approval mode (read-only / edit files / full access). Engines without interactive controls (OpenCode, Pi, Amp) skip the agent controls section entirely.

Tap any button to open that setting’s page. Each sub-page shows:

  • A description of the setting
  • The current effective value (resolved from override or default — never shows a bare “default” label)
  • Buttons to change the value
  • A Clear override button to revert to the global/engine default
  • A ← Back button to return to the home page
  • A 📖 Learn more link to the matching page of the help centre (littlebearapps.com/help/untether/…)

Toggle behaviour

Most settings use a two-button selection pattern: [On] [Off] [Clear] with a ✓ on the active option. Tap either button to set the value. Tapping Clear removes the per-chat override and falls back to the global setting.

When you tap a setting button:

  1. Confirmation toast — a brief popup appears confirming the change (e.g. “Permission mode: off (acceptEdits)”, “Verbose: on”). This uses the same toast mechanism as Claude Code approval buttons.
  2. Auto-return — the menu automatically navigates back to the home page, showing the updated value across all settings. No need to tap “Back” manually.

Multi-state settings

Some settings have more than two states and use a different layout:

  • Permission mode (Claude Code) — four options shown in a 2+2+1 split: [Off] [On] on the first row, [Plan-auto] [Auto] on the second, [Clear override] on the third
  • Approval mode (Gemini, deprecated) — three options (read-only / edit files / full access)
  • Effort (Claude Code) — low / medium / high / xhigh / max
  • Reasoning (Codex) — low / medium / high / xhigh

The active option is marked with a ✓ prefix. Tap a different option to switch.

Engine-aware visibility

Settings are engine-specific and only appear when relevant:

  • Permission mode — Claude Code only. Codex and Gemini have their own pre-run policies instead.
  • Approval policy — Codex CLI only. Toggle between “full auto” (default, Codex’s own sandbox setting) and “safe” (read-only sandbox via --sandbox read-only; tests, builds and cache//tmp writes fail too). This is a pre-run policy — not interactive mid-run approval.
  • Approval mode — Gemini CLI only (deprecated). Toggle between “read-only”, “edit files” (file reads/writes OK, shell commands blocked via --approval-mode auto_edit), and “full access” (all tools approved via --approval-mode yolo). This is a pre-run policy. Despite its label, “read-only” (also what an unset chat shows) runs Gemini with --approval-mode yolo, i.e. full access — see Interactive approval.
  • Ask mode and Diff preview — Claude Code only. Hidden for other engines.
  • Follow-up — Claude Code only (#775). queue (default) or steer for messages sent while a run is working; see steer follow-ups. Hidden on the home page for other engines; if you reach the page anyway it says that other engines always queue.
  • Reasoning — Claude Code and Codex only. Hidden for OpenCode, Pi, Gemini, and Amp.
  • Engine & model — always visible. Engine and model are merged into a single page. Shows the current engine and model override; to set a model, use /model set <name>.

When you switch engines via the Engine & model page, the home page automatically shows or hides the relevant controls.

Available settings

SettingOptionsPersisted
Permission modeoff, on, plan-auto, autoYes (chat prefs)
Approval policyfull auto, safe (read-only sandbox)Yes (chat prefs)
Approval moderead-only, edit files, full accessYes (chat prefs)
Ask modeoff, onYes (chat prefs)
Verboseoff, onNo (in memory, cleared on restart)
Diff previewoff, onYes (chat prefs)
Engine & modelany configured engine + modelYes (chat prefs)
Effort / ReasoningClaude: low, medium, high, xhigh, max; Codex: low, medium, high, xhighYes (chat prefs)
Cost & usageAPI cost, subscription usage, budget, stop at limitYes (chat prefs)
Resume lineoff, onYes (chat prefs)
Listenall, mentionsYes (chat prefs)
Follow-upqueue, steerYes (chat prefs)
Budgetoff, onYes (chat prefs)
Stop at limitoff, onYes (chat prefs)

Approval policy appears instead of Permission mode when the engine is Codex CLI. Approval mode appears instead of Permission mode when the engine is Gemini CLI.

Triggers page

When [triggers] is enabled, the home page gains a bottom row with a ⏰ Triggers button that opens the Triggers page (config:tg), even when nothing is configured yet (the page then explains how to add one). When at least one cron or webhook is configured, the same row also carries the one-tap ⏸ Pause triggers / ▶️ Resume triggers toggle (#296) (#271 Tier 2 + #294).

The Triggers page shows:

  • State and counts — running / paused, plus per-chat cron and webhook totals.
  • Master pause/resume toggle — tap Pause to suspend all cron firing and webhook dispatch globally without editing config; tap Resume to clear it. While paused, webhooks return 503 triggers paused (with Retry-After: 60), the webhook server’s HTTP /health endpoint reports paused: true, and /ping shows ⏸ triggers paused: … (suspended). Pause is in-memory only — restart auto-resumes (the safe default).
  • Per-chat cron list — each line shows the cron id, human-readable schedule via describe_cron(schedule, timezone), project, engine, the cron’s own model= / effort= when it sets one (#743), and last-fired relative time.
  • Per-chat webhook list — each line shows the webhook id, path, auth scheme, project, engine, and last-fired.

Lists are scoped to the current chat (crons_for_chat() / webhooks_for_chat() with the bridge default_chat_id fallback), capped at 10 entries with a …and N more (see untether.toml) overflow marker. The pause/resume controls remain visible even when the chat has no triggers configured. 📡 is Listen only; Triggers always use ⏰, matching /ping and the run footer.

See Schedule tasks for the pause flow end-to-end.

Loop mode page

When the active engine is Claude Code, the home page gains a 🔁 Loop mode button that opens the Loop sub-page (#289). Loop mode is off by default — turning it on lets Claude schedule repeated runs: Untether declines Claude Code’s own CronCreate and runs the schedule itself, with the [loop] caps, firing each iteration with claude --resume whether or not the session is still open (#925). With it off, Claude can’t schedule recurring or timed tasks and points you here, or to /at for a one-off. Self-paced wake-ups (ScheduleWakeup) work in both modes, up to max_iterations in a row.

The page shows:

  • State — Currently: On (global) / Off (global) (no per-chat override, so the [loop] enabled default applies) or On (per-chat) / Off (per-chat).
  • Cost + quota warning — explicit reminder before turning ON: every loop fire counts against [cost_budget], so set a budget first.
  • 💰 Set a budget — deep-link to the Cost & Usage page (config:cu) for one-tap budget setup.
  • Buttons — [On] [Off] with ✓ on the active per-chat choice, then [Clear override] [💰 Set a budget] and [← Back].

/cancel and /new both drop pending loop iterations for the current chat (or forum topic); the next message resumes the session without the cancelled loop, and new loops in that session run normally (#926). /continue is unaffected (it doesn’t trigger loop replay).

Loop mode is Claude-only (LOOP_SUPPORTED_ENGINES = frozenset({"claude"})); the button is hidden for other engines. See Schedule tasks → Loop mode for the full architecture and cost guidance.

Cost & Usage page

The Cost & Usage sub-page merges cost display and budget controls into a unified page with toggle rows:

  • API cost — per-run cost in the message footer (requires engine cost reporting)
  • Subscription usage — 5h/weekly subscription usage in the footer (Claude Code only)
  • Budget — turn budget tracking on or off for this chat (overrides global [cost_budget] setting)
  • Stop at limit — per-chat override of [cost_budget] auto_cancel. Stops new runs once the daily budget is reached and ends a session after the reply that passes the per-run budget. It can’t interrupt a reply in progress (see Cost budgets)

Each toggle uses the [✓ Label: on] [Label: off] [Clear] compact pattern (labels distinguish the four toggles). Clear removes the per-chat override and falls back to the global config.

For historical cost data across sessions, use the /stats command.

About page

ℹ️ About shows the Untether version and a py X.Y.Z · <engine> X.Y.Z · … line with the version of each available engine CLI (in alphabetical order) that answers --version (Pi included), plus GitHub, bug-report and feature-request links. The engine CLIs are checked side by side in the background, so the page opens in a few seconds without holding up the bot, and the versions are reused for 5 minutes (#951).

Callbacks vs commands

  • Text command (/config): sends a new message with the menu.
  • Button tap: edits the existing message in place — no message spam.

All button interactions use early callback answering for instant feedback.

Was this helpful?

Related Articles