Skip to content

Latest commit

 

History

36 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Herdr 에이전트 텔레그램 리모컨

English | 한국어

Herdr를 처음 본다면: Herdr는 여러 터미널과 코딩 에이전트를 pane(분할 작업창) 단위로 실행·유지하는 에이전트 중심 터미널 멀티플렉서다. 이 프로젝트는 그 pane을 Telegram과 연결한다.

외출 중에도 스마트폰 텔레그램에서 Herdr에 열린 Codex·Claude Code pane을 직접 제어하는 경량 봇.

Beta: 현재 봇 UI는 한국어 우선이다. Codex와 Claude Code를 모두 지원하며 tmux는 지원하지 않는다.

  • 슬래시 명령(/ship, /compact, /cost 등) 네이티브 주입
  • 화면 캡처 텍스트 + PNG 전송 (/screen, /tail N, /screenshot)
  • 권한 프롬프트 원격 응답 (/yes, /no, /1, /2, ...)
  • 스마트 프롬프트 알림 — 프롬프트 떠도 CLI에서 화살표로 옵션 옮기면 알림 안 옴, 가만히 두면(=원격) 15초 후 알림 (상세)
  • 위험 명령(/clear, /kill, /quit)은 60초 TTL 확인 토큰으로 보호
  • 설치된 모든 스킬(플러그인 포함 /superpowers:write-plan 같은 형식도) 자동 지원
  • 열린 pane 전체 조회·선택 (/panes, /use, /at) — 포커스 변경과 무관하게 명시적 pane만 제어

AI에게 설치 맡기기 (추천)

Codex 또는 Claude Code에 이 저장소 주소와 아래 프롬프트를 붙여넣으면, 에이전트가 현재 환경을 확인하고 자동화할 수 있는 설치를 진행한다. BotFather, Telegram 토픽, 토큰 입력처럼 사람이 직접 해야 하는 단계에서는 한 단계씩 안내하고 기다린다.

아래 GitHub 저장소를 읽고 Herdr Telegram Remote를 설치해줘.

https://github.com/etinpres/herdr-telegram-remote

현재 운영체제와 Herdr 설치 상태부터 확인해. Herdr가 없다면 공식 설치법으로
설치하고, Herdr 안에서 Codex 또는 Claude Code를 다시 실행해야 하는 시점에
멈춰서 알려줘. 자동으로 가능한 저장소 clone, installer 실행, integration,
백그라운드 서비스, doctor 검증은 직접 진행해줘.

BotFather 봇 생성, 비공개 forum group의 Topics와 Manage Topics 설정처럼 내가
Telegram 앱에서 해야 하는 작업은 한 단계씩 안내하고 내 확인을 기다려줘.
개인 봇 채팅의 Threaded Mode는 대안으로 설명하되, 기본은 비공개 forum
supergroup을 추천해줘.

봇 토큰이나 chat/user ID를 이 대화에 붙여넣게 하지 마. 토큰은 로컬 .env에
직접 입력하도록 정확한 파일 경로와 편집 방법만 알려주고, .env의 내용이나
토큰을 읽거나 출력하지 마. 내가 저장했다고 확인하면 discover_chat.py로 ID를
찾고 나머지 설정을 계속해줘.

설치가 끝나면 doctor.py를 실행하고 Telegram의 /help, /panes, 실제 메시지
왕복까지 검증해줘. 실패하면 추측하지 말고 현재 출력과 README의
트러블슈팅을 근거로 원인을 확인해줘.

사람이 직접 해야 하는 것: Telegram에서 봇·비공개 그룹을 만들고 Topics 및 봇의 Manage Topics 권한을 켠 뒤, 토큰을 로컬 .env에 입력한다. 토큰은 에이전트 대화, GitHub issue, 화면 녹화에 붙여넣지 않는다.

Herdr가 이미 설치되어 있다면 Herdr pane에서 codex 또는 claude를 실행한 뒤 위 프롬프트를 보내는 흐름이 가장 간단하다. 모든 명령을 직접 실행하려면 수동 설치로 이동한다.


요구사항

  • macOS (launchd) 또는 Linux with systemd
  • Windows: 네이티브 미지원. WSL2 안에서 Linux 경로로 사용
  • Python 3.10+, curl, Herdr 0.7.4+ (필수)
  • 텔레그램 계정

봇은 Herdr의 CLI/socket API로 pane을 조회·읽기·제어한다. UI에서 포커스된 pane은 절대 자동 대상으로 쓰지 않으며, 저장된 pane이 닫히면 fail-closed로 다시 선택을 요구한다.


Windows (WSL2) 안내

이 저장소의 서비스 설치기는 네이티브 Windows를 지원하지 않는다. 대신 WSL2(Windows Subsystem for Linux 2) 안에서 리눅스용 설치 경로를 그대로 따라가면 됨.

WSL2 = 뭐?

Microsoft 공식 기능. Windows 안에서 진짜 리눅스(기본 Ubuntu)를 돌리는 가상 환경. 설치 한 줄, 무료.

WSL2 설치 (PowerShell 관리자 권한)

wsl --install
  • Windows 10 (빌드 19041+) 또는 Windows 11 필요
  • 재부팅 한 번 후 Ubuntu 터미널 자동 실행 → 사용자명/비밀번호 설정
  • 이후 시작 메뉴에서 "Ubuntu" 실행하면 리눅스 셸 진입

WSL2 안에서 우리 리모컨 설치

Ubuntu 터미널 안에서 리눅스 경로 그대로 실행:

sudo apt update && sudo apt install -y python3 curl git
curl -fsSL https://herdr.dev/install.sh | sh
git clone https://github.com/etinpres/herdr-telegram-remote.git \
  ~/.local/share/herdr-telegram-remote
cd ~/.local/share/herdr-telegram-remote
./install.sh

install.sh가 자동으로 systemd --user 서비스로 등록함.

Herdr도 WSL2 안에서 실행

Ubuntu 터미널에서 Herdr를 열고 그 안의 pane에서 Codex 또는 Claude Code를 실행한다.

herdr
# Herdr pane 안에서 codex 또는 claude

주의사항

  • WSL2는 기본적으로 Windows 로그아웃하면 꺼짐. loginctl enable-linger로 유지 가능(install.sh가 시도하지만 WSL2에선 효과 제한적) — 사실상 Windows 로그인 유지 + Ubuntu 터미널 하나 띄워놓는 게 가장 확실.
  • /screenshot은 WSL2에선 Linux 도구(grim 등) 설치해도 WSL2엔 디스플레이 서버가 없어서 캡처 불가. /screen//tail(텍스트)은 정상 작동.
  • 성능 팁: 코드 저장소는 WSL2 파일시스템(~/)에 두고 작업. Windows 드라이브(/mnt/c/...)는 I/O 느림.

Herdr 설치 + pane 세팅

Herdr 설치

OS 명령
macOS (Homebrew) brew install herdr
Linux / WSL2 curl -fsSL https://herdr.dev/install.sh | sh

설치 확인: herdr --version.

에이전트를 Herdr 안에서 실행

Herdr를 열고 원하는 만큼 pane을 만든 뒤 각 pane에서 codex 또는 claude를 실행:

herdr
# 각 pane에서 codex 또는 claude

pane 선택

모든 열린 pane은 Telegram에서 조회할 수 있다:

/panes
/use w1:p4
/where
/at w1:p2 이 pane에서 현재 작업을 요약해줘

/use는 기본 대상을 바꾸고 /at은 기본 대상을 바꾸지 않는 일회성 전송이다. pane ID는 Herdr가 반환한 값을 그대로 사용한다. pane 이동·닫힘으로 ID가 사라지면 다른 pane으로 자동 전환하지 않는다.

/panes 응답에는 각 pane의 선택 버튼도 함께 표시된다. 버튼을 누르면 해당 pane이 기본 대상으로 바뀌고 이후 평문 메시지가 그 pane으로 전달된다. 닫힌 pane의 오래된 버튼은 다른 pane으로 대체하지 않고 오류로 끝난다.


설치 (3분)

1. Telegram 봇 생성

  1. 텔레그램에서 @BotFather와 대화 시작
  2. /newbot → 이름/username 입력 → 봇 토큰 받기
  3. 생성된 봇에게 아무 메시지나 먼저 전송 (안 하면 봇이 답장 못 함)

2. Chat ID 확인

개인 봇 채팅은 @userinfobotId: 123456789가 chat ID이자 user ID다. pane별 토픽은 봇과 본인만 있는 비공개 forum supergroup을 권장한다. 그룹에서 메시지를 한 번 보낸 뒤 .env에 토큰만 넣고, 본문을 출력하지 않는 ID 발견 도구를 실행한다:

./discover_chat.py

출력의 음수 chat_idTELEGRAM_CHAT_ID에, 본인의 양수 sender_user_idALLOWED_USER_IDS에 넣는다.

3. 저장소 클론 + 설치

git clone https://github.com/etinpres/herdr-telegram-remote.git \
  ~/.local/share/herdr-telegram-remote
cd ~/.local/share/herdr-telegram-remote
./install.sh

첫 실행에서 .env 템플릿이 생성되고 스크립트가 멈춤. .env를 열어서:

TELEGRAM_BOT_TOKEN=<BOT_TOKEN>               # 1번에서 받은 토큰
TELEGRAM_CHAT_ID=123456789                    # 2번에서 확인한 숫자
TOPIC_MODE=auto                               # 토픽 지원 시만 자동 활성화
HERDR_SESSION=default                         # Herdr named session
HERDR_DEFAULT_PANE=                           # 선택 사항; Telegram /use로 지정 가능
COMPLETION_NOTIFY_MIN_S=300                   # 이 시간 이상 작업 완료 알림
BRIEFING_FALLBACK_DELAY_S=30                  # 브리핑 누락 시에만 작업 시작 확인
STORE_INBOX=0                                 # Telegram 원문 로컬 저장(기본 꺼짐)
LOG_MESSAGE_PREVIEW=0                         # 로그에 메시지 앞부분 저장(기본 꺼짐)
PHOTO_MAX_BYTES=20971520                      # 이미지 한 개의 로컬 저장 상한(20 MiB)
ALLOWED_USER_IDS=123456789                    # 본인 user ID (콤마로 여러 명)

첫 기동 후 Telegram에서 /panes/use <pane-id>로 기본 대상을 선택한다.

forum group에서 pane별 대화를 분리하려면 Topics를 켜고 봇에 Manage Topics 관리자 권한을 준다. poller가 열린 Herdr pane마다 토픽을 자동으로 만든다. 개인 봇 Threaded Mode도 사용할 수 있지만 클라이언트별 General/알림 표시 차이가 있어 forum group이 더 일관된다.

다시 ./install.sh를 실행하면 Codex·Claude Code Herdr integration, managed 응답 규칙, 백그라운드 서비스를 설치한다. 한 에이전트만 쓰면 --agents codex 또는 --agents claude를 추가한다.

./doctor.py

doctor.py는 Herdr 버전·서버·integration, managed 규칙, .env 권한, Telegram API를 읽기 전용으로 검사한다. 설치기는 기존 ~/.codex/AGENTS.md~/.claude/CLAUDE.md를 보존하고 식별 마커 사이 managed block만 추가한다.

4. 동작 확인

텔레그램에서 본인 봇에게 /help 전송. 명령어 목록이 답장으로 오면 성공.


주요 명령어

명령 설명
/help 명령어 목록
/panes 현재 열린 모든 Herdr pane 목록과 선택 버튼
/use <pane-id 또는 라벨> 기본 제어 pane 선택
/where 현재 선택한 pane 확인
/at <pane-id> <메시지> 선택을 바꾸지 않고 특정 pane에 일회성 전송
/screen, /tail N 선택한 Herdr pane 화면을 텍스트로 전송
/screenshot 화면을 PNG로 전송 (플랫폼별 지원 범위 ↓)
/cancel, /esc, /enter 키 이벤트 주입
/yes, /no, /1~/9 옵션 프롬프트 응답
/compact, /cost, /agents, /model <n> 선택한 에이전트가 지원하는 네이티브 슬래시
/ship, /review, /assemble 사용자 스킬 슬래시 (자동 인식)
/clear, /kill, /quit 위험 — /confirm <token>으로 60초 내 승인 필요
/restart [claude|codex|x] 종료된 pane에서 에이전트 재기동 (x = Claude bypass)
그 외 /... 선택한 에이전트 TUI로 그대로 전달

/usage, /fast, /cost, /agents, /config, /status, /model처럼 메뉴나 즉시 상태 화면을 여는 대화형 명령은 주입 약 0.8초 뒤 같은 Telegram 토픽으로 짧은 결과를 자동 회신한다. /usage는 연간 활동 그래프와 TUI 상태줄을 버리고 Lifetime·Peak·Streak·Longest task만 담은 전용 요약 카드로 보낸다. 첫 메뉴는 사용량 보기, 리셋 메뉴 Telegram 버튼으로 바꾸며 버튼 선택 결과도 자동 요약한다. /status는 버전·모델·스레드·작업 폴더·권한· 컨텍스트·주간 한도와 초기화 시각만 담고 계정·세션 ID·TUI 테두리는 버린다. 다른 대화형 명령은 명령 전후에 새로 바뀐 내용만 최대 12줄·1200자로 보낸다. 모든 카드에는 전체 화면 보기 버튼이 있다. /up, /down, /tab과 장기 실행 스킬은 알림 폭주·브리핑 중복을 막기 위해 자동 회신에서 제외한다.


pane별 Telegram 토픽

Threaded Mode가 켜진 개인 봇 또는 Topics가 켜진 비공개 포럼 그룹에서는 열린 Herdr pane마다 w1:p1 · herdr 같은 전용 토픽을 자동 생성한다. TELEGRAM_CHAT_ID로 지정한 채팅만 수신하므로 이전 1:1 채팅이나 다른 그룹의 메시지는 Herdr에 주입되지 않는다.

  • 토픽 안의 평문·사진·명령은 전역 /use 선택과 관계없이 해당 pane으로만 전달된다.
  • 브리핑, 중간 오류 알림, 프롬프트, 완료 알림과 최종 답장도 같은 pane 토픽으로 돌아온다.
  • pane 라벨이 바뀌면 최대 15초 안에 토픽 이름도 바뀐다.
  • pane이 닫혀도 토픽과 대화 기록은 보존하며 다른 pane으로 재지정하지 않는다.
  • 개인 봇에서는 General이 전체 관리와 기존 단일 채팅 fallback으로 남는다. 포럼 그룹에서는 봇에 토픽 관리 권한을 준 뒤 General을 숨기고 pane 토픽만 유지할 수 있다.
  • 매핑은 본문이나 토큰 없이 topics.json에 pane ID, thread ID, 라벨만 저장하며 mode 600으로 보호한다.

토픽 안에서는 대상이 이미 정해져 있어 pane 선택 버튼을 붙이지 않는다. 기존 세션 재시작은 필요 없고, 중앙 poller와 tg_notify.sh가 라우팅을 담당한다.


작업 전 브리핑

Telegram 요청이 도구 호출, 파일 수정, 조사, 빌드처럼 실제 작업을 시작해야 하는 내용이면 대상 에이전트가 첫 도구 호출 전에 평소 CLI commentary와 같은 짧은 브리핑을 Telegram으로 보낸다.

  • 브리핑에는 에이전트가 이해한 내용과 바로 확인·수정할 일을 1~3문장으로 적는다.
  • 브리핑은 문장별로 빈 줄을 넣고 pane 버튼 없이 가볍게 표시한다.
  • 단순 대화나 즉시 끝나는 답변에는 별도 브리핑을 보내지 않는다.
  • 브리핑은 tg_notify.sh --briefing으로 전송되어 완료 답장으로 기록되지 않는다.
  • 성공한 브리핑은 별도 briefings.jsonl 표식을 남긴다. 본문은 저장하지 않는다.
  • 작업 종료 후에는 같은 pane 토픽으로 최종 답장을 별도로 보낸다. General fallback에서는 기존 pane 버튼을 유지한다.
  • 최종 답장이 오지 않으면 기존 5분 완료 watcher가 fallback 알림을 보낼 수 있다.

이 방식은 고정 시간 뒤 일반적인 접수 문구를 보내는 대신, 실제 에이전트가 이해한 작업 방향을 즉시 보여준다.

메시지 유형 헤더

pane에서 오는 주요 작업 메시지는 pane ID 바로 옆에 유형을 표시한다.

  • [w1:p1 · 브리핑 · herdr] — 작업 시작 전 이해 내용과 진행 방향
  • [w1:p1 · 중간 · herdr] — 중대한 오류, 안전 게이트 또는 계획 변경
  • [w1:p1 · 완료 · herdr] — 에이전트 최종 답장 또는 긴 작업 완료 watcher

tg_notify.sh--briefing, --progress, Herdr agent 환경, 중앙 watcher의 --completion을 기준으로 헤더를 자동 보정한다. 따라서 기존 pane 세션을 재시작하지 않아도 Telegram에 표시되는 유형은 즉시 적용된다. 프롬프트 응답 대기, /screen, /panes 같은 봇 기능 메시지는 완료로 오인하지 않도록 유형을 자동 부여하지 않는다.

중대한 오류·계획 변경 중간 알림

Telegram에서 시작된 작업 도중 중대한 오류나 예외로 작업 방향, 결과 또는 예상 소요시간이 실질적으로 달라지면 대상 에이전트가 최종 답변 전에 중간 알림을 보낸다.

  • 외부 쓰기·배포가 안전 게이트에 막힌 경우
  • 승인·입력 내용과 현재 상태가 불일치하는 경우
  • 우회, 복구 또는 계획 변경이 필요한 경우
  • 사용자 판단 없이는 작업을 계속할 수 없는 경우

예상된 테스트 실패, 즉시 재시도로 해결된 일시적 오류, 결과에 영향 없는 경고와 일반 진행 상황은 보내지 않는다. 같은 사건은 한 번만 알리고, 영향이나 다음 행동이 다시 실질적으로 바뀐 경우에만 추가로 알린다.

중간 알림은 tg_notify.sh --progress로 전송한다. pane 표시, ⚠️ 중간 알림, 발견 내용, 현재 안전 상태, 계속/중단 여부, 다음 행동을 짧은 문단으로 담는다. --progress는 pane 버튼, 완료 답장 표식, 브리핑 표식을 만들지 않으며 CLI commentary와 중복되는 최종답변 블록도 출력하지 않는다. 따라서 기존 브리핑 누락 안전망과 5분 완료 watcher를 방해하지 않고, 작업 종료 후 최종 답장은 그대로 별도 전송된다.

에이전트가 규칙을 한 번 놓치는 경우를 위해 중앙 poller도 안전망을 둔다. Telegram에서 idle/done pane으로 전달한 작업이 실제 working 상태에 들어간 뒤 기본 30초 동안 브리핑 표식이나 최종 답장 표식이 없을 때만, 버튼 없는 작업 시작 확인을 한 번 보낸다. 정상 브리핑, 빠른 최종 답장, 30초 안에 끝난 짧은 작업, 이미 작업 중인 pane의 추가 입력에는 fallback이 생기지 않는다. 지연 시간은 BRIEFING_FALLBACK_DELAY_S로 조정한다.

브리핑 전송 여부는 Codex/Claude가 시작할 때 읽은 전역 지침에 의해 결정된다. 지침 추가 전에 이미 실행 중이던 세션은 한 번 종료 후 resume 또는 재시작해야 이 동작을 읽는다. formatter와 버튼 처리처럼 중앙 전송 스크립트가 담당하는 변경은 재시작 없이 즉시 적용된다.

CLI 최종 답변 기록

Herdr agent pane 안에서 tg_notify.sh로 최종 답장을 보내면, 전송 성공 뒤 assistant 최종 답변에도 Telegram 본문 전체를 요약하지 않고 그대로 출력한다. 따라서 tool output이 여러 줄이라 접히더라도 깨끗한 최종 답변 블록에서 전체 내용을 읽을 수 있다. helper도 같은 내용을 📨 Telegram으로 보낸 최종 답변 tool-output 블록에 남겨 전송 증거를 보존한다.

  • helper의 tool-output 기록은 현재 열린 pane에 재시작 없이 즉시 적용된다. 전체 본문을 assistant 최종 답변에 반복하는 규칙은 해당 pane이 갱신된 전역 지침을 로드해야 하므로, 기존 세션에서 계속 요약하면 한 번 종료 후 resume한다.
  • 작업 전 브리핑은 이미 CLI commentary로 보이므로 중복 출력하지 않는다.
  • 중앙 poller의 /panes, 완료 watcher 같은 자동 알림은 daemon 로그에 본문을 복제하지 않는다.
  • Telegram 전송 본문과 CLI 최종 답변은 같은 전체 내용을 사용하며 요약본으로 대체하지 않는다.

스마트 프롬프트 알림

봇은 모든 열린 Herdr 에이전트 pane의 번호형 권한/질문 프롬프트를 감지해 pane ID와 함께 텔레그램으로 알림을 보냄. 응답은 /at w1:p4 /1처럼 대상 pane을 명시할 수 있다.

  1. 프롬프트 감지 → 즉시 알림 안 보내고 기본 15초 대기
  2. 그 사이 화살표 키 등으로 커서가 다른 옵션으로 이동하면 → "사용자가 CLI에서 직접 응답 중"으로 판단 → 알림 취소
  3. 커서가 안 움직이고 프롬프트도 안 사라지면 → 외출 중으로 판단 → 알림 발송
  4. 같은 프롬프트는 한 번만 알림 (응답 후 새 프롬프트는 처음부터 다시 카운트)

설계 원칙: false negative(필요한데 안 옴) 절대 없음. 외출 시엔 키보드를 못 누르니 무조건 알림이 옴. 단점은 CLI에서 프롬프트 보고 15초 넘게 고민하면 알림이 한 번 오는 정도(긴 작업 걸어놓고 자리 비웠을 땐 오히려 알림이 도움됨).

지연 시간 조정은 .envPROMPT_NOTIFY_DELAY_S (기본 15, 단위 초). 변경 후 launchctl kickstart -k gui/$(id -u)/com.$(whoami).tg-poll (macOS) 또는 systemctl --user restart tg-poll (Linux).


긴 작업 완료 알림

봇은 모든 열린 Herdr 에이전트 pane의 작업 상태를 감시한다. 기본 5분(300초) 이상 진행된 작업이 안정적으로 종료되면 다음 내용을 Telegram으로 보낸다.

  • pane ID와 라벨
  • 대략적인 소요 시간
  • 최근 최종 답변 요약(최대 900자)
  • 바로 이어서 지시할 /at <pane-id> <메시지> 예시
  • 해당 pane을 기본 대상으로 선택하거나 화면을 확인하는 Telegram 버튼

Herdr가 agent_status=unknown을 보고하는 기존 Codex 세션도 화면 하단의 Working (...) 표시를 보조 감지한다. 권한/질문 프롬프트로 멈춘 상태는 완료로 오인하지 않고 기존 프롬프트 알림으로 안내한다. 해당 pane의 tg_notify.sh 직접 답장이 실제 Telegram에 성공한 경우에만 중복 완료 알림을 생략한다. 규칙을 아직 로드하지 않은 기존 세션이 답장을 보내지 않으면 완료 알림이 fallback으로 온다.

완료 알림과 [pane-id · label]로 시작하는 에이전트 최종 답장에는 같은 버튼이 붙는다. 작업 전 브리핑에는 버튼이 붙지 않는다. 이 pane 선택 버튼은 기본 대상을 바꾸고 채팅에 선택 결과를 남긴다. 화면 보기 버튼은 기본 대상을 바꾸지 않은 채 해당 pane의 최근 화면만 전송한다. 이 버튼 처리는 중앙 Telegram 폴러와 전송 스크립트가 담당하므로 기존 pane 세션을 재시작할 필요가 없다.

tg_notify.sh는 Telegram 답장의 가독성도 보정한다. pane 표시는 첫 줄에 따로 놓고, shell-safe 문자열의 \n을 실제 개행으로 바꾸며, 줄바꿈 없이 지나치게 길거나 3문장 이상 이어진 pane 답장은 문장 경계에서 보수적으로 문단을 나눈다. 문자 그대로 \n을 표시하려면 호출 문자열에 \\n을 사용한다. Codex·Claude 전역 규칙도 내용 전환 시 빈 줄과 항목별 줄바꿈을 요구한다.

Telegram API 길이 제한으로 메시지 전체가 실패하지 않도록 일반 본문은 UTF-16 기준 3900, 사진·문서 caption은 1000 단위로 안전 여유를 두고 제한한다. 초과분은 …(Telegram 길이 제한으로 잘림)으로 표시되므로 긴 로그·코드는 --doc 첨부를 사용한다.

짧은 작업도 알림받고 싶으면 .envCOMPLETION_NOTIFY_MIN_S를 낮추고, 알림을 줄이려면 높인다.


/screenshot 플랫폼별 지원

플랫폼 지원 범위 비고
macOS ✅ 풀 지원 창 단위 캡처 가능 (아래 macOS 설정 참고)
Linux 데스크탑 (X11/Wayland) ⚠️ 전체 화면만 grim·scrot·gnome-screenshot·maim 중 하나 필요
WSL2 ❌ 불가 디스플레이 서버 없음 — /screen·/tail로 대체
헤드리스 서버 ❌ 불가 같은 이유

Linux에서 도구 설치:

# Ubuntu/Debian (Wayland)
sudo apt install -y grim

# 또는 X11
sudo apt install -y scrot

봇이 자동으로 PATH에서 grim → gnome-screenshot → scrot → maim 순으로 찾음.


macOS 추가 설정

1. 화면 녹화 권한 (필수)

/screenshot이 동작하려면 launchd가 실행하는 python3 바이너리에 화면 녹화 권한이 있어야 함.

  1. 시스템 설정 → 개인정보 보호 및 보안 → 화면 녹화
  2. + 버튼 → /usr/bin/python3 추가 (또는 install.sh가 plist에 박은 파이썬 경로)
  3. 토글 ON
  4. 권한 부여 후 데몬 재기동:
    launchctl kickstart -k gui/$(id -u)/com.$(whoami).tg-poll

주의: /Library/Frameworks/Python.framework/Versions/3.x/bin/python3는 심볼릭 링크라 TCC가 인식 못 함. 실제 번들 경로(.../Resources/Python.app)를 추가해야 하는 경우가 있음. 가장 확실한 건 /usr/bin/python3 사용 (install.sh 기본값).

2. 창 단위 캡처용 pyobjc (선택)

.envTERMINAL_APP을 지정하면 그 앱의 창만 캡처함 (데스크탑 전체가 아니라). Quartz(CoreGraphics)로 창 ID를 찾는 과정에서 pyobjc가 필요:

pip3 install --user pyobjc-framework-Quartz

설치 안 돼 있으면 경고 없이 전체 화면 캡처로 폴백 — 선택 사항.

.env 예시:

TERMINAL_APP=Termius     # 또는 iTerm, Terminal, Warp, Ghostty, kitty, Alacritty, WezTerm

대소문자 무관, 부분 일치. 해당 앱의 가장 큰 on-screen 창 하나만 찍음.

3. Homebrew python3 사용 시

install.sh가 command -v python3 결과를 plist에 박기 때문에 Homebrew 파이썬(/opt/homebrew/bin/python3)이 먼저 걸리면 그 경로로 등록됨. 이 경우:

  • 화면 녹화 권한은 Homebrew python3 경로에 추가해야 함
  • 또는 plist를 수정해서 /usr/bin/python3로 바꾸고 kickstart

권한은 plist가 실제로 실행하는 바이너리에 붙이는 게 원칙.


보안

  • TELEGRAM_CHAT_IDALLOWED_USER_IDS를 모두 검사하며 등록되지 않은 chat/sender는 무응답 fail-secure
  • .envchmod 600, git .gitignore에 포함
  • poller 시작 시 inbox.jsonl, state.json, outbound.jsonl, briefings.jsonl, topics.json, pending.json, 로그를 600, photos/700, 저장된 사진을 600으로 강제한다.
  • 위험 명령은 요청 Telegram 계정에 귀속된 UUID 토큰 + 60초 TTL로 실수 방지
  • 기본은 Telegram 원문·메시지 미리보기를 로컬에 저장하지 않음 (STORE_INBOX=0, LOG_MESSAGE_PREVIEW=0)
  • 원문·미리보기 보존을 켜도 chat/user 인증을 통과한 update만 기록하며, slash 인자는 항상 로그에서 숨김
  • Telegram 이미지 다운로드는 PHOTO_MAX_BYTES(기본 20 MiB)로 제한
  • accept-all은 ALLOW_ANY=1I_UNDERSTAND_ALLOW_ANY=1을 모두 써야만 작동하고, /restart x 권한 우회 재기동도 별도 확인을 요구함
  • macOS /screenshot은 화면 녹화 권한 필요 — macOS 추가 설정 참고

로컬·Telegram 저장 경계는 PRIVACY.md, 취약점 제보와 토큰 폐기 절차는 SECURITY.md를 본다.


트러블슈팅

증상 원인 해결
봇이 답장 안 함 ALLOWED_USER_IDS 누락 .env 확인 후 서비스 재기동
/screenshot 실패 스크린 녹화 권한 (macOS) / 도구 없음 (Linux) macOS 권한 부여 / sudo apt install grim
서비스 죽어있음 (macOS) launchd 기동 실패 launchctl kickstart -k gui/$(id -u)/com.$(whoami).tg-poll, 운영 로그는 poll.log
서비스 죽어있음 (Linux) systemd 기동 실패 systemctl --user status tg-poll, journalctl --user -u tg-poll
명령이 안 들어감 선택한 pane이 닫힘 또는 Herdr session 불일치 /panes/use <pane-id>, .envHERDR_SESSION 확인

제거

./install.sh --uninstall

managed Codex·Claude 규칙은 함께 제거한다. Herdr integration은 다른 Herdr 기능이 사용할 수 있어 보존하며, .env와 로그도 자동 삭제하지 않는다. 완전 삭제 전에 clone 폴더 경로를 직접 확인한다.


아키텍처

Telegram (long-polling)
    ↓
tg_poll.py (launchd/systemd 상주)
    ├── tg_commands.dispatch() → action 분류
    │    ├── RAW_SLASH / SKILL_SLASH (allowlist)
    │    ├── Pattern passthrough (모든 /well-formed 슬래시)
    │    ├── KEY_COMMANDS (ctrl-c, esc, enter, 숫자키 …)
    │    ├── DANGEROUS + /confirm (TTL 60s)
    │    └── fallback_prefix (평문 메시지)
    ↓
herdr_transport.py → Herdr CLI/socket API → 명시적 Codex/Claude pane

순수 함수 디스패치 + Herdr transport + 데몬 I/O 분리 구조다. 위험 명령 확인 토큰에는 승인 당시 pane ID가 함께 묶여 선택 변경으로 다른 pane에 실행되지 않는다.


라이선스

MIT

About

Control Codex and Claude Code panes in Herdr from Telegram

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages