Skip to content

Instantly share code, notes, and snippets.

@possibilities
Created February 2, 2026 19:22
Show Gist options
  • Select an option

  • Save possibilities/1b62302850d46b41270ee2e453d01c55 to your computer and use it in GitHub Desktop.

Select an option

Save possibilities/1b62302850d46b41270ee2e453d01c55 to your computer and use it in GitHub Desktop.
Refactor: Bot Operations into internalctl Subcommands

Refactor: Bot Operations into internalctl Subcommands

Overview

This refactor decouples core task pipeline logic from the Telegram transport layer, making bot operations independently testable and enabling future transport adapters (Slack, web UI, etc.).

Architecture

Hooks (share-plan.py)
        │
        v
internalctl (core logic)
  create-task, advance-task, list-tasks, show-task, delete-task, accept-task-plan
        │
        v (optional)
telegramctl (transport adapter)
  notify-task, await-callbacks

New internalctl Subcommands

Command Description
create-task Create a task with --url, --title, --project, --session-id, --cwd
list-tasks List tasks, optionally filtered by --stage
show-task <id> Show full task details
advance-task <id> Move task to next stage with --target and --user-name
delete-task <id> Remove a task
accept-task-plan Auto-accept plan in Claude via tmux (--session-id, --cwd)

State Management (Split Files)

Core state in ~/.local/share/internalctl/tasks/{task_id}.yaml:

id: 42
stage: "1 → Plan"
url: "https://telegra.ph/..."
title: "Feature X"
project: myproject
metadata:
  session_id: abc123
  cwd: /Users/mike/code/project
history:
  - stage: "1 → Plan"
    timestamp: "2026-02-02T..."
created_at: "2026-02-02T..."

Telegram state in ~/.local/share/telegramctl/tasks/{message_id}.yaml:

task_id: 42
message_id: 12345
topic_id: 48
topic_name: "1 → Plan"
callback_data: "move:12345:2 → Work"
sent_at: "2026-02-02T..."

Files Created/Modified

New files in scripts/bin/commands/internalctl/:

  • task_helpers.py - Core task state management
  • run_create_task.py - Create task
  • run_list_tasks.py - List tasks
  • run_show_task.py - Show task details
  • run_advance_task.py - Advance task stage
  • run_delete_task.py - Delete task
  • run_accept_task_plan.py - Auto-accept in Claude

New files in scripts/bin/commands/telegramctl/:

  • tg_task_helpers.py - Telegram-specific state management
  • run_notify_task.py - Send notification for internalctl task

Modified:

  • scripts/bin/commands/internalctl/cli.py - Added task subcommands
  • scripts/bin/commands/telegramctl/cli.py - Added notify-task, removed send-question
  • scripts/bin/commands/telegramctl/run_await_callbacks.py - Uses split state, calls internalctl
  • scripts/bin/commands/telegramctl/helpers.py - Removed question functions
  • marketplace/plugins/claude/hooks/share-plan.py - Uses internalctl create-task + notify-task

Deleted:

  • marketplace/plugins/claude/hooks/share-question.py - Questions no longer supported
  • scripts/bin/commands/telegramctl/run_send_question.py - Questions no longer supported

Migration

A one-time migration script is available at /tmp/migrate-legacy-tasks.py:

uv run /tmp/migrate-legacy-tasks.py

This will:

  1. Backup ~/.local/share/telegramctl/ to ~/Desktop/telegramctl-backup-{timestamp}/
  2. Migrate pending files to the new split state format
  3. Remove old pending/ directory

CLI-Only Workflow (No Telegram)

# List tasks in Plan stage
internalctl list-tasks --stage "1 → Plan"

# Review a task
internalctl show-task 42

# Approve it (auto-accepts in Claude if session active)
internalctl advance-task 42 --target "2 → Work" --user-name "CLI User"

Benefits

  1. Testable - Each internalctl command can be unit tested without Telegram
  2. Composable - Other tools can use the task state
  3. Extensible - Easy to add Slack, Discord, or web UI adapters
  4. Debuggable - Can inspect and manipulate state via CLI
  5. Offline-capable - Core workflow works without network
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment