feat(ops): Telegram <-> Claude Code bridge daemon (autonomous response loop) #20

Merged
navigator merged 1 commit from feature/telegram-claude-bridge into main 2026-05-24 13:21:32 -03:00
Owner

Closes the inbound side of the Telegram channel.

Outbound was notify-telegram.sh (PR #19); this adds the daemon that polls Telegram getUpdates, runs each message through claude -p (using user's logged-in CLI session), and sends the response back to the authorized chat. Result: navigator can command the loop from any phone with Telegram, autonomously.

Files:

  • infra/ops/telegram-claude-bridge.sh (AGPL v3): polling daemon. Offset persistence in ~/.local/state/, chat-id filter (authorized only), --resume session continuity across messages, 4000-char chunking for long responses.
  • infra/ops/telegram-claude-bridge.service: systemd user unit (no root). Restart=always, EnvironmentFile loads settings.env.
  • infra/ops/INSTALL-bridge.md: pre-reqs + install commands + verify + tune + state file paths + security note.

Pre-req for deploy: claude login on agent host (interactive one-time, device flow). Bridge daemon does not handle auth itself.

Architecture: outbound + inbound + persistent session = autonomous bidirectional channel. Combines with PR #19 notify-telegram.sh (proactive pings) and ADR-016 GitOps loop (autonomous PR merging).

Tests: shell only. shell-lint validates the daemon and service. Auto-merge via auto-merge.sh once CI green.

Closes the inbound side of the Telegram channel. Outbound was notify-telegram.sh (PR #19); this adds the daemon that polls Telegram getUpdates, runs each message through `claude -p` (using user's logged-in CLI session), and sends the response back to the authorized chat. Result: navigator can command the loop from any phone with Telegram, autonomously. Files: - infra/ops/telegram-claude-bridge.sh (AGPL v3): polling daemon. Offset persistence in ~/.local/state/, chat-id filter (authorized only), --resume session continuity across messages, 4000-char chunking for long responses. - infra/ops/telegram-claude-bridge.service: systemd user unit (no root). Restart=always, EnvironmentFile loads settings.env. - infra/ops/INSTALL-bridge.md: pre-reqs + install commands + verify + tune + state file paths + security note. Pre-req for deploy: `claude login` on agent host (interactive one-time, device flow). Bridge daemon does not handle auth itself. Architecture: outbound + inbound + persistent session = autonomous bidirectional channel. Combines with PR #19 notify-telegram.sh (proactive pings) and ADR-016 GitOps loop (autonomous PR merging). Tests: shell only. shell-lint validates the daemon and service. Auto-merge via auto-merge.sh once CI green.
feat(ops): Telegram <-> Claude Code bridge daemon (autonomous response loop)
All checks were successful
build / scalafmt-check (push) Successful in 4s
build / sbt-compile (push) Successful in 4s
build / shell-lint (push) Successful in 18s
build / scalafmt-check (pull_request) Successful in 4s
build / sbt-compile (pull_request) Successful in 4s
build / shell-lint (pull_request) Successful in 12s
34cb0ca895
Closes the inbound channel from navigator to the autonomous loop.
Outbound was notify-telegram.sh (PR #19); this PR adds the inbound
side so navigator can issue commands via Telegram from anywhere and
get Claude responses back on the same chat.

- infra/ops/telegram-claude-bridge.sh (AGPL v3): bash daemon. Long-polls
  /getUpdates with offset persistence in ~/.local/state/, filters by
  authorized chat (TELEGRAM_CHAT_ID), runs each message through
  claude -p with --permission-mode acceptEdits (loop can write +
  execute inside the repo), persists --resume session id across
  invocations for conversation continuity, chunks responses into
  4000-char Telegram pieces, full log to ~/.local/state/bridge.log.
  Timeouts tunable via env (POLL_TIMEOUT, CLAUDE_TIMEOUT).

- infra/ops/telegram-claude-bridge.service: systemd user unit. No root
  required. Restart=always with 15s backoff. EnvironmentFile loads
  settings.env. Install via 'systemctl --user enable --now' +
  'loginctl enable-linger' for persistence after logout.

- infra/ops/INSTALL-bridge.md: pre-req checklist (claude logged in,
  settings.env, jq+curl), install commands, verify, tune, stop/restart,
  state file locations, security note on permission-mode.

Pre-req for deploy: claude login on agent host (interactive one-time;
device flow generates ~/.claude/.credentials.json that the bridge
inherits). Bridge daemon does not handle login itself.
fluidpop-bot left a comment
Collaborator

CI green (head 34cb0ca895), auto-approving

CI green (head 34cb0ca8951e6872506b1110f87786ce73e106f2), auto-approving
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Fluid/fluidpop-v1!20
No description provided.