step-classify

A reference table for assigning each Untether issue—the project’s agent and messaging system—to the main area where its root cause belongs.

In plain words
What is it for?
Use it to classify issues involving subprocesses, Telegram messaging, control channels, and other documented system areas.
Why use it?
It makes investigations consistent and points developers toward the right logs, checks, and project rules.

Command for Claude Code

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 commands/littlebearapps/untether/step-classify
Clone the repo
git clone --depth 1 https://github.com/littlebearapps/untether

Made for: Claude Code.

Per session 0 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 1,939 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 1 finding. 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.00000 $0.01939
Opus 5 $0.00000 $0.00970
Sonnet 5 $0.00000 $0.00388
Haiku 4.5 $0.00000 $0.00194

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

Security

Grade A, and why

step-classify scanned grade A with 1 finding 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 2d 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.

Runs shell commandslowCapability

Expected in a hook, worth knowing in a rule or an instructions file.

| **runner-subprocess** | `subprocess.create.failed`, `subprocess.died_without_completion`, `runner_failed`, signal exits (rc=143/137), JSONL parse errors, EventFactory misuse | grep `engine=<X>` `event=session.summary`;
.claude/commands/debug/step-classify.md · 63 lines

How it starts

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

Step 1 — Classify

This is the canonical Untether issue-class table. Pick exactly one primary class per issue (the area where the root cause lives). If behaviour crosses boundaries, note a secondary class.

For each row: the column "diagnostic hints" lists grep targets and the canonical rule file that owns the area. Match aggressively — over-classifying is far less costly than under-classifying.

The 15 classes

Class Indicators in logs / chat Diagnostic hints Canonical rule
runner-subprocess subprocess.create.failed, subprocess.died_without_completion, runner_failed, signal exits (rc=143/137), JSONL parse errors, EventFactory misuse grep engine=<X> event=session.summary; check 3-event contract; verify proc_returncode and last_event_type runner-development.md
telegram-transport Outbox stuck, rate-limit 429, callback_data overflow, message-too-long, voice transcription failures, file upload denied, media-group dedup grep outbox, file_transfer, voice_transcription, rate_limit, 429; check TelegramOutbox invariants; verify callback_data ≤ 64 bytes telegram-transport.md
control-channel Approval buttons missing / stuck, PTY FD leak, ask-question crash, plan-mode cooldown abuse, ExitPlanMode loop, AskUserQuestion stuck-sequential grep control_request, control_response, _DISCUSS_COOLDOWN, _PENDING_ASK_REQUESTS; check PTY finally cleanup; check session-registry cleanup control-channel.md
trigger-cron-webhook Cron fired wrong time / wrong tz, webhook 401/403/429/503, SSRF block, fetch-cron parse failure, hot-reload didn't apply, run_once re-fired grep trigger.fired, cron, webhook, ssrf, triggers paused, config.reload; check timezone string in cron config; verify HMAC signature (none — see src/untether/triggers/)
session-resume-lock Wrong session resumed, stale resume token, session lock leak, registry not cleaned, /continue failures grep SessionLockMixin, lock_for, session_id, resume; check WeakValueDictionary cleanup; verify lock acquired before subprocess spawn runner-development.md
stall-liveness-watchdog subprocess.liveness_stall, subprocess.liveness_kill, stall_warning, peak_idle excessive, repeat stall_warnings on cron sessions grep liveness, stall, proc_diag, cpu_active; check tool_timeout vs mcp_tool_timeout; see systemic-patterns.md for by-design cases (cron + plan-mode) (none — see src/untether/utils/proc_diag.py)
auto-continue Auto-continue loops (death spiral), missing auto-continue (Claude exit with last_event_type=user), retry exhaustion, signal-death suppression bypass grep auto_continue, last_event_type, proc_returncode; check signal-death suppression (rc=143/137); verify [auto_continue].max_retries runner-development.md
config-hot-reload Restart-required key edited mid-run, hot-reload race, update_from() field copy missed, TelegramBridgeConfig corruption grep config.reload, restart_required, RESTART_REQUIRED_FIELDS; check update_from() field coverage; verify slot preservation; see feedback_agent_self_restart_pattern in MEMORY.md telegram-transport.md §TelegramBridgeConfig hot-reload
fleet-rollout fleet-rollout.sh failure, attestation marker missing, version mismatch across hosts, partial-rollback state check ~/.untether-dev/integration-test-pass-${VERSION}.json exists; check pipx list on each host; verify integration-test gate not bypassed release-discipline.md §Fleet rollout
outbox-delivery Files not delivered, deny-glob false-positive, size-limit hit, file-count cap, auto-cleanup didn't fire grep outbox, deny_glob, file_transfer; check .untether-outbox/ dir in project; verify [transports.telegram.files] config telegram-transport.md §Outbox file delivery
cost-budget Per-run budget exceeded silently, daily budget reset wrong, alert level skipped, auto-cancel didn't trigger grep cost_budget, budget.alert, auto_cancel; check cost_tracker.py; verify daily reset timezone (none — see src/untether/cost_tracker.py)
at-scheduler-cancel-restart /at delay lost on restart, /cancel didn't drop pending delay, /new orphan tasks, /restart drain timeout grep at_scheduler, cancel.requested, shutdown.drain, _cancel_chat_tasks; verify drain integration via at_scheduler.active_count() (none — see src/untether/telegram/at_scheduler.py, commands/topics.py)
help-faq-release-guard FAQ deleted/moved (hook block), guard-script edit blocked, force-push to master blocked, PR merge to master blocked, MCP write to master blocked check .claude/hooks.json enforcement; verify help-faq-protect.sh, release-guard.sh, release-guard-protect.sh, release-guard-mcp.sh; check docs/faq/faq.md exists and has ≥7 question-shaped H2s help-faq.md, release-discipline.md §Release guard
auto-error-watcher Watcher daemon stopped, false-positive filings, duplicate issues, wrong host tag, signature dedup miss check systemctl --user status untether-issue-watcher on each host; inspect ~/.local/state/untether-issue-watcher/seen.json; verify HOST env var (none — see MEMORY.md untether-issue-watcher section)
ci-pipeline-release-guard CI job failure (format/ruff/ty/pytest/build/lockfile/install-test/pip-audit/bandit/codeql/docs), validate_release.py reject, auto-tag-on-master skip on stable bump, OIDC publish failure check .github/workflows/; verify pyproject.toml version matches CHANGELOG.md heading; verify all changelog entries have [#N] links; check uv lock --check clean release-discipline.md, context-quality.md

Read the full file on GitHub · 63 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. 2d ago First seen · 63 lines · 0 tokens per session scan A 757b2656ba40

Subscribe to this mod's changes

step-classify is a command published in the GitHub repository littlebearapps/untether (66 stars, last pushed 3d ago), licensed MIT. It costs nothing until one of its globs matches a file; then it loads 1,939 tokens. A static security scan graded it A with 1 finding (runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.