ep.1에서 텔레그램 봇을 만들었고, ep.2에서 사진 분류를 자동화했다. 그런데 여기까지는 전부 “폰 → PC” 단방향이다. 사진을 보내는 건 되는데, PC한테 뭔가를 시키는 건 안 된다.
이번에 만든 건 방향을 뒤집는 거다. 폰에서 텔레그램으로 작업을 지시하면, AI가 알아서 분석하고 실행하고 결과를 보고한다. 커밋, 푸시 같은 git 명령도 폰에서 한 줄이면 된다.
전체 구조
폰 (텔레그램)
↓ /작업 블로그 글 아이디어 3개 뽑아줘
텔레그램 봇 (Node.js)
↓ Claude Code CLI 호출
AI PM 에이전트
↓ 작업 분석 → 계획 수립 → 실행
텔레그램 봇
↓ 결과 보고
폰 (텔레그램)
핵심은 텔레그램 봇이 Claude Code CLI를 호출하는 거다. Claude Code는 터미널에서 AI 에이전트를 돌릴 수 있는 도구인데, -p 플래그로 비대화형 실행이 가능하다. 봇이 이걸 Node.js의 exec()로 호출하면, 텔레그램 메시지 한 줄이 AI 에이전트 실행으로 이어지는 파이프라인이 완성된다.
/작업 명령의 흐름
/작업 명령을 보내면 3단계로 진행된다.
1단계: 즉시 응답 — 봇이 “작업 분석 중…”이라는 메시지를 바로 보내준다. AI가 생각하는 동안 폰에서 멍때리는 게 아니라, 접수됐다는 걸 바로 확인할 수 있다.
2단계: 계획 수립 + 확인 — AI PM이 작업을 분석하고 계획을 세운다. 이 계획이 텔레그램으로 날아오는데, 여기에 [실행]과 [취소] 인라인 버튼이 붙는다. 계획을 읽어보고 괜찮으면 실행 버튼을 탭, 아니면 취소.
3단계: 실행 + 완료 보고 — 실행 버튼을 누르면 AI PM이 실제로 작업을 수행한다. 파일을 만들거나, 코드를 수정하거나, 다른 에이전트에게 작업을 분배하거나. 끝나면 결과가 새 메시지로 온다. 계획 메시지는 그대로 남아 있어서 나중에 뭘 했는지 확인할 수 있다.
나: /작업 playbook에 test.md 파일 추가해줘
봇: 🔄 작업 분석 중...
↓
봇: 📋 계획 수립 완료
- playbook 루트에 test.md 생성
- 내용: helloworld
[✅ 실행] [❌ 취소]
↓ (실행 탭)
봇: ✅ 작업 완료
test.md 파일을 생성했습니다.
확인 단계가 있는 이유는 간단하다. AI가 엉뚱한 걸 하기 전에 한 번 검토할 수 있어야 한다. 계획을 보고 “아 이거 아닌데” 하면 취소하면 된다. 폰에서 버튼 한 번 탭하는 거니까 부담도 없다.
Git도 폰에서 된다
개발하다 보면 커밋이나 푸시 같은 git 작업이 수시로 필요하다. 이것도 텔레그램에서 바로 된다.
| 명령어 | 동작 | 예시 |
/커밋 |
git add + commit | /커밋 tb "버그 수정" |
/푸시 |
git push | /푸시 playbook |
/병합 |
git merge | /병합 blog feature/seo |
프로젝트 이름은 별칭도 지원한다. telegram-bridge를 매번 치기 귀찮으니까 tb로 줄여 쓸 수 있다. 모든 명령어는 한글로도 된다. /commit 대신 /커밋, /push 대신 /푸시.
git 명령은 AI를 거치지 않고 직접 실행한다. exec()로 쉘에서 바로 git push를 돌리는 거라 빠르고 안정적이다. AI가 끼어들 필요가 없는 단순 작업은 단순하게 처리하는 게 맞다.
삽질: Claude Code를 서브프로세스로 돌리기
이 기능을 만들면서 가장 시간을 잡아먹은 건 Claude Code CLI를 Node.js 서브프로세스로 돌리는 부분이었다.
문제 1: 중첩 세션 차단 — Claude Code는 이미 실행 중인 세션 안에서 또 다른 Claude Code를 실행하면 막아버린다. 환경변수 CLAUDECODE가 설정되어 있으면 중첩으로 판단하는 건데, 봇이 Claude Code 세션 안에서 시작됐기 때문에 이 변수가 상속된다. 단순히 undefined로 설정하는 건 Node.js에서 제대로 안 먹혀서, 쉘 명령어에 직접 unset을 넣어야 했다.
문제 2: SSE 포트 충돌 — CLAUDECODE만 지워서는 부족했다. CLAUDE_CODE_SSE_PORT라는 환경변수가 남아 있으면, 새로 뜨는 Claude 프로세스가 부모 세션의 SSE 포트에 연결하려다 영원히 대기 상태에 빠진다. 이것도 같이 unset해야 했다.
문제 3: 권한 승인 프롬프트 — Claude Code는 파일 수정 같은 작업을 하기 전에 사용자 승인을 기다린다. 대화형에서는 괜찮은데, -p 모드(비대화형)에서는 승인해줄 사람이 없으니 무한 대기한다. --dangerously-skip-permissions 플래그로 해결.
const command = `cd '${projectDir}' && ` +
`unset CLAUDECODE CLAUDE_CODE_SSE_PORT CLAUDE_CODE_ENTRYPOINT && ` +
`claude -p '${prompt}' --output-format json ` +
`--dangerously-skip-permissions < /dev/null`;
이 한 줄에 도달하기까지 꽤 돌아왔다. 프로세스가 멈추는데 에러 메시지는 안 나오고, 환경변수 하나씩 빼면서 원인을 찾아야 했다. 자동화의 즐거움이란 이런 삽질을 포함하는 거다.
보안과 워크로그
보안은 오너 Chat ID로 처리한다. 봇 설정에 내 텔레그램 Chat ID를 등록해두면, 다른 사람이 명령을 보내도 무시한다. Chat ID 미설정 시에는 요청자의 ID를 알려줘서 바로 등록할 수 있게 했다.
워크로그는 이중으로 기록한다. AI PM에게 “작업 끝나면 워크로그 써”라고 프롬프트에 포함시키고, 혹시 PM이 빼먹을 경우를 대비해서 봇이 직접 worklog/ 폴더에 최소한의 기록을 남긴다. AI한테 100% 맡기면 가끔 빼먹으니까, 코드로 보험을 걸어두는 거다.
지금까지 만든 것
ep.1부터 ep.3까지의 결과를 정리하면 이렇다.
| 기능 | 명령 | 설명 |
| 사진 전송 | 사진 보내기 | 폰 → PC 자동 저장 |
| 자동 분류 | #밥로그, #dev 등 | 해시태그로 폴더 분류 |
| AI 작업 | /작업 | AI PM이 분석 → 실행 → 보고 |
| Git | /커밋, /푸시, /병합 | 원격 git 명령 |
텔레그램 봇 하나가 파일 전송 도구에서 AI 기반 원격 개발 환경으로 진화했다. 폰에서 사진을 보내는 것도, 작업을 지시하는 것도, 코드를 커밋하는 것도 전부 텔레그램 채팅방 하나에서 된다.
다음 에피소드에서는 이 파이프라인을 더 확장할 예정이다. 배포 자동화, 빌드 알림, 혹은 블로그 발행까지 폰에서 처리하는 것. 1인 개발팀의 자동화는 아직 끝나지 않았다.