untether CLAUDE.md

untether CLAUDE.md is an instructions file for coding agents from littlebearapps/untether. It costs 10,500 tokens per session, scanned A, original, MIT.

A set of project instructions for Untether, a Telegram bridge that lets you control coding-agent command-line tools from your phone.

In plain words
What is it for?
Use it when changing Untether's Telegram controls, agent runners, configuration, or documentation.
Why use it?
It gives an agent clear guidance about Untether's design, files, features, and reference material when working on the project.

Instructions file

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add instructions/littlebearapps/untether/claude-md
Clone the repo
git clone --depth 1 https://github.com/littlebearapps/untether

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for untether CLAUDE.md

README.md
[![agentmods](https://agentmods.dev/badge/instructions/littlebearapps/untether/claude-md.svg)](https://agentmods.dev/instructions/littlebearapps/untether/claude-md)
Your own site
<a href="https://agentmods.dev/instructions/littlebearapps/untether/claude-md"><img src="https://agentmods.dev/badge/instructions/littlebearapps/untether/claude-md.svg" alt="Measured on agentmods" height="20"></a>
Per session 10,500 This file is loaded in full into every session.
When invoked 10,500 The same file — it is already loaded in full.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.10500 $0.10500
Opus 5 $0.05250 $0.05250
Sonnet 5 $0.02100 $0.02100
Haiku 4.5 $0.01050 $0.01050

Measured 3d ago against content hash 2ca3310b8386, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

untether CLAUDE.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 3d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

CLAUDE.md · 412 lines

How it starts

The opening of the file, as written. The whole thing — 412 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Untether

Telegram bridge for Claude Code, Codex, OpenCode, Pi, Gemini CLI, Amp, and other agent CLIs. Control your coding agents from anywhere — walking the dog, watching footy, at a friend's place.

Repo: littlebearapps/untether Based on: banteg/takopi (upstream)

Untether adds interactive permission control, plan mode support, and several UX improvements on top of upstream takopi. All interactive features are Claude Code-specific; Codex, OpenCode, and other engines use standard non-interactive mode.

Features (vs upstream takopi)

  • Interactive permission control — bidirectional Telegram buttons for tool approval, plan mode, and clarifying questions
  • Pause & Outline Plan — third button on plan approval; the outline (chat text, or the ExitPlanMode plan input on plan-file CLIs, #659) is posted with Approve/Deny/Let's discuss buttons (hold-open keeps session alive while user reads); the v2.1.72-74-era progressive cooldown was retired in #570 (upstream retry loop fixed, verified on CLI 2.1.215)
  • Agent context preamble — configurable prompt preamble tells agents they're on Telegram and requests structured end-of-task summaries; [preamble] config section
  • /planmode — toggle permission mode per chat (on/off/auto)
  • /listen — set listen mode (all / mentions) per chat or topic; controls when the bot responds in groups; renamed from /trigger in v0.35.3 (#297) to disambiguate from webhook/cron triggers — /trigger still works as a deprecated alias for one release cycle
  • Ask mode — interactive AskUserQuestion with option buttons, sequential multi-question flows, and /config toggle; Claude-only
  • Early callback answering — clears button spinners immediately instead of waiting for processing
  • Approval push notifications — separate notify message when approval buttons appear
  • Ephemeral message cleanup — approval-related messages auto-delete when run finishes
  • Bold formatting — command responses use HTML bold for key values
  • /usage — shows API usage and cost for the current session
  • /export — exports session transcript as markdown or JSON
  • /browse — navigate project files via inline keyboard buttons
  • Cost tracking and budget — per-run and daily cost limits with configurable alerts
  • Subscription usage footer — configurable [footer] to show 5h/weekly subscription usage instead of/alongside API costs
  • Graceful restart/restart command drains active runs before restarting; SIGTERM also triggers graceful drain
  • Compact startup message — version number, conditional diagnostics (only shows mode/topics/triggers/engines when they carry signal), project count instead of full list
  • Workflow mode indicator — startup message shows mode: assistant, mode: workspace, or mode: handoff; derived from session_mode + topics.enabled
  • Model/mode footer — final messages show model name + permission mode (e.g. 🏷 sonnet · plan) from StartedEvent.meta; all engines populate model info
  • /verbose — toggle verbose progress mode per chat; shows tool details (file paths, commands, patterns) in progress messages
  • /config — inline settings menu with navigable sub-pages; toggle plan mode, ask mode, verbose, engine, trigger via buttons
  • [progress] config — global verbosity and max_actions settings in untether.toml
  • Pi context compactionAutoCompactionStart/AutoCompactionEnd events rendered as progress actions
  • Stall diagnostics & liveness watchdog/proc process diagnostics (CPU, RSS, TCP, FDs), progressive stall warnings with Telegram notifications, liveness watchdog for alive-but-silent subprocesses, stall auto-cancel (dead process, no-PID zombie, absolute cap) with CPU-active suppression (sleeping-process aware — shows tool name when main process waiting on child), tool-active repeat suppression (first warning fires, repeats suppressed while child CPU-active), MCP tool-aware threshold (15 min for network-bound MCP calls vs 10 min for local tools) with contextual "MCP tool running: {server}" messaging, session.summary structured log; bare rate_limit_events latch a conservative 60s wait so throttled sessions aren't mistaken for hung ones (#657); [watchdog] config section with configurable tool_timeout, mcp_tool_timeout, and stream_idle_auto_retry/stream_idle_max_retries (#572 — bounded auto-resume of Type-A mid-generation API stalls, default off; Type-B never retries)
  • Auto-continue — detects Claude Code sessions that exit after receiving tool results without processing them (upstream bugs #34142, #30333) and auto-resumes; suppressed on signal deaths (rc=143/SIGTERM, rc=137/SIGKILL) to prevent death spirals under memory pressure; configurable via [auto_continue] with enabled (default true) and max_retries (default 1)
  • Empty-resume recovery (quarantine-and-fresh) (#631, #632) — a resume that returns 0 turns/$0 (upstream dangling-tool_use defect) quarantines the session in session_quarantine.json and auto-resends the message once on a fresh session; sessions SIGTERM'd after a result (forced_teardown_after_result) are quarantined proactively so the next message diverts to a fresh session before any empty result is seen; [auto_continue] flags empty_resume_fresh and quarantine_on_forced_teardown (both default true); structured events runner.empty_resultsession.quarantinedsession.auto_resend_fresh/session.resume_diverted_fresh; Claude runner only
  • MCP catalog observability + proactive refresh (#365) — catalog_staleness.detected structlog WARNING once per (session, server, status) tuple when Claude's system.init reports a non-connected MCP status (detect_catalog_staleness, default on); opt-in fire-and-forget mcp_status control_request after each tool_result to nudge Claude Code's catalog (notify_catalog_refresh, default off). Request IDs use the ut_catalog_refresh_<session_id>_<seq> namespace; drained via ClaudeRunner._drain_catalog_refresh. Logs catalog.refresh_sent INFO / catalog.refresh_failed WARN/ERROR. Claude runner only
  • File upload deduplication — auto-appends _1, _2, … when target file exists, instead of requiring --force; media groups without captions auto-save to incoming/
  • Agent-initiated file delivery (outbox) — agents write files to .untether-outbox/ during a run; Untether sends them as Telegram documents on completion with 📎 captions; deny-glob security, size limits, file count cap, auto-cleanup; [transports.telegram.files] config
  • Progress persistence — active progress messages persisted to active_progress.json; on restart, orphan messages edited to "⚠️ interrupted by restart" with keyboard removed
  • Resume line formatting — visual separation with blank line and ↩️ prefix in final message footer
  • /continue — cross-environment resume; pick up the most recent CLI session from Telegram using each engine's native continue flag (--continue, resume --last, --resume latest); supported for Claude, Codex, OpenCode, Pi, Gemini (not AMP)
  • Timezone-aware cron triggers — per-cron timezone or global default_timezone with IANA names (e.g. Australia/Melbourne); DST-aware via zoneinfo; invalid names rejected at config parse time
  • Hot-reload trigger configuration — editing untether.toml applies cron/webhook changes immediately without restart; TriggerManager holds mutable state that the cron scheduler and webhook server reference at runtime; handle_reload() re-parses [triggers] on config file change
  • Hot-reload Telegram bridge settingsvoice_transcription (incl. the #638 voice_transcription_language ISO-639-1 hint), file transfer, allowed_user_ids, timing, and show_resume_line settings reload without restart; TelegramBridgeConfig unfrozen (slots kept) with update_from() wired into handle_reload(); restart-only keys (bot_token, chat_id, session_mode, topics, message_overflow) still warn
  • /at command — one-shot delayed runs: /at 30m <prompt> schedules a prompt to run in 60s–24h; /cancel drops pending delays before firing; lost on restart (documented) with a per-chat cap of 20 pending delays; telegram/at_scheduler.py holds task-group + run_job refs
  • run_once cron flag[[triggers.crons]] entries can set run_once = true to fire once then auto-disable; cron stays in TOML and re-activates on config reload or restart
  • Trigger visibility (Tier 1)/ping shows per-chat trigger summary (⏰ triggers: 1 cron (id, 9:00 AM daily (Melbourne))); run footer shows ⏰ cron:<id> / ⚡ webhook:<id> for trigger-initiated runs; new describe_cron() utility renders common patterns in plain English
  • Graceful restart improvements (Tier 1) — persists Telegram update_id to last_update_id.json so restarts don't drop/duplicate messages; Type=notify systemd integration via stdlib sd_notify (READY=1 + STOPPING=1); RestartSec=2
  • diff_preview plan bypass (#283) — after user approves a plan outline via "Pause & Outline Plan", the _discuss_approved flag short-circuits diff preview for subsequent Edit/Write tools so no second approval is needed
  • User-extensible env allowlist (#409)[security] env_extra_allow and env_extra_prefix_allow (in untether.toml) extend the engine-subprocess env allowlist with per-deployment names so users can thread credential-manager tokens (1Password, Doppler, Vault, Infisical, …) without forking utils/env_policy.py. Names are validated against [A-Z_][A-Z0-9_]*. Honoured by the Claude and Pi runners and by the env_audit probe. BWS_ACCESS_TOKEN was promoted into the built-in defaults at the same time. One env_policy.user_extension INFO log per process
  • Master trigger pause toggle (#294)TriggerManager.pause() / resume() / is_paused gate cron firing and webhook dispatch globally; webhook server returns 503 triggers paused (with Retry-After: 60); /health endpoint reflects paused state. Wired into /config two ways: home-page button row (only when triggers configured) and a dedicated 📡 Triggers page (config:tg) showing counts + Pause/Resume button. /ping switches to ⏸ triggers paused: … (suspended) while paused. Pause is in-memory only — restart auto-resumes (safe default)

Read the full file on GitHub · 412 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 3d ago First seen · 412 lines · 10,500 tokens per session scan A 2ca3310b8386

Subscribe to this mod's changes

untether CLAUDE.md is an instructions file published in the GitHub repository littlebearapps/untether (66 stars, last pushed 4d ago), licensed MIT. It adds 10,500 tokens to every session, about $0.0525 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.