Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kakaoterm

일할 때 코딩하는 척하면서 몰래 카톡하려고 만들었습니다.

kakaoterm은 카카오톡 mac 앱을 macOS 접근성(Accessibility) API로 읽고 써서, 브라우저 탭 하나를 Claude Code 터미널 세션처럼 보이게 하는 로컬 클라이언트입니다. 카카오톡 창은 화면 밖으로 밀어 숨겨둔 채로 동작하니, 옆에서 보면 그냥 터미널에서 코드 작업 중인 화면입니다.

kakaoterm 실행 화면

╭──────────────────────────────────────────────╮
│ ✻ Welcome to Claude Code!                    │
│   /help for help, /status for your current   │
╰──────────────────────────────────────────────╯

  ⎿  Resumed session team-2

⏺ dev-1
  내일 회의 자료 공유 부탁드려요

> 네, 오후에 올릴게요

✻ Pondering… (esc to interrupt) · 3s

> Try "fix lint errors"
? for shortcuts · team-2          ⚒ 2 background tasks   ⏵⏵ accept edits on

카카오톡 방 하나가 "세션", 상대방 메시지는 로 시작하는 어시스턴트 출력, 내가 보낸 메시지는 > 프롬프트처럼 그려집니다. 방 이름과 사람 이름은 설정 파일의 별칭(alias)으로 바꿔 표시할 수 있습니다.


목차

  1. 특징
  2. 동작 원리
  3. 구조도
  4. 파일 구성
  5. 요구 사항
  6. 설치
  7. 실행
  8. 사용법 (단축키 / 명령)
  9. 설정 (kaka.json)
  10. WebSocket 프로토콜
  11. 한계
  12. 문제 해결
  13. 개인정보와 보안

특징

  • 카카오톡 앱을 건드리지 않습니다. 리버스 엔지니어링, 로컬 DB 복호화, 네트워크 가로채기 없이 macOS가 공식 제공하는 접근성 API만 씁니다.
  • 카카오톡을 숨긴 채로 읽고 보냅니다. 창을 주 화면 오른쪽 아래 구석 밖으로 밀어두고(주차) hide 상태를 유지합니다. 메시지 전송처럼 창이 잠깐 보여야 하는 순간에도 앞으로 가져오지 않습니다.
  • 브라우저 UI는 Claude Code 터미널을 그대로 흉내냅니다. 환영 배너, 출력, 생각 중 스피너, 슬래시 명령 팔레트, 상태 표시줄까지.
  • 가만히 두면 코드 작업 중인 것처럼 보입니다. 30초 동안 아무 일이 없으면 Read, Grep, Bash, Update 같은 가짜 도구 호출 줄이 4~9초 간격으로 흘러갑니다. 키 입력이나 새 메시지가 오면 즉시 멈춥니다.
  • 사진 메시지도 펼쳐볼 수 있습니다. 카카오톡 창을 화면 캡처해서 썸네일을 가져옵니다(화면 기록 권한 필요).
  • 터미널 버전도 있습니다. 같은 kakao_ax.py 계층 위에서 prompt_toolkit으로 도는 kaka.py.

동작 원리

1. 왜 접근성 API인가

macOS의 모든 네이티브 앱은 시각 장애인용 보조 기술(VoiceOver 등)을 위해 자기 화면을 접근성 트리(AX tree) 로 노출합니다. 창 → 테이블 → 행 → 셀 → 텍스트 같은 계층 구조이고, 각 요소는 AXRole(역할), AXValue(값), AXPosition(위치), AXIdentifier(식별자) 같은 속성을 가집니다.

카카오톡 mac 앱도 예외가 아니라서, 손쉬운 사용 권한만 있으면 다른 프로세스에서 이 트리를 읽고(메시지 읽기), 속성을 바꾸고(입력창에 글 넣기), 동작을 실행(버튼 누르기)할 수 있습니다. kakao_ax.py가 이 일을 전담하며, pyobjc를 통해 ApplicationServicesQuartz 프레임워크를 직접 호출합니다.

2. 읽기: 채팅 목록과 방 메시지

채팅 목록 (Kakao.chat_list)

  • 제목이 KakaoTalk(한국어 앱은 카카오톡)인 메인 창에서 AXTable을 찾고, 각 행의 첫 셀 안 요소들을 훑습니다.

  • 카카오톡이 붙여둔 식별자로 필드를 구분합니다.

    AXIdentifier 의미
    _NS:40 방 이름
    _NS:69 마지막 메시지 시각
    Count Label 안 읽은 개수
    _NS:87 마지막 메시지 미리보기
    AXImage + 설명에 notioff 알림 꺼진 방
  • 속성 여러 개를 IPC 한 번에 가져오는 AXUIElementCopyMultipleAttributeValues를 써서 호출 수를 줄입니다. 그래도 전체 목록은 수 초가 걸리므로 10초마다 별도 스레드에서 읽습니다.

방 메시지 (Kakao.read_room)

  • 카카오톡에서 "창으로 연" 방만 별도 윈도우로 존재하고, 그 창 안의 AXTable 행이 메시지 하나입니다.
  • 행 안의 AXTextArea가 본문, AXStaticText가 이름 또는 시각(AM/PM/오전/오후 포함 여부로 구분), 높이 40px 이상인 AXImage가 사진입니다.
  • 누가 보냈는지는 좌표로 판단합니다. 말풍선의 오른쪽 끝이 창 오른쪽 가장자리 근처(창 너비 - 40px)보다 오른쪽이면 me, 아니면 them.
  • 같은 사람이 연속으로 보내면 이름이 생략되므로, 직전 발신자 이름을 이어받습니다.
  • "여기까지 읽으셨습니다" 구분선(_NS:30)은 건너뜁니다.
  • 처음 한 번은 전체(약 70행)를 읽어 히스토리로 보내고, 그 뒤로는 1초마다 마지막 12행만 읽어 새 메시지만 찾습니다.

변화분 찾기 (diff)

메시지에 고유 ID가 없으므로 (발신 방향, 종류, 본문) 튜플을 키로 씁니다. 이전에 본 키 목록의 꼬리(최대 6개) 를 이번 목록에서 찾고, 그 뒤에 붙은 것만 새 메시지로 봅니다. 꼬리를 못 찾으면(스크롤이 크게 바뀐 경우) 최근 3개만 새것으로 간주합니다.

3. 쓰기: 방 열기와 메시지 전송

접근성 API로 "값을 넣는" 것은 되지만, 카카오톡의 전송 버튼 AXPress는 먹지 않습니다. 그래서 키 이벤트를 직접 만듭니다.

  • CGEventPostToPid카카오톡 프로세스에만 Return 키를 보냅니다. 전역 키 입력이 아니라서 다른 앱에 영향이 없고, 카카오톡을 최전면으로 가져올 필요도 없습니다.
  • 단, 앱이 hide 상태이면 키가 무시됩니다. 그래서 전송 직전에 잠깐 unhide하고, 끝나면 다시 hide합니다. 이때 창이 화면 구석 밖에 주차되어 있어 사실상 보이지 않습니다.

메시지 전송 (Kakao.send)

  1. 방 창에서 설명이 Enter a message(한국어 앱은 메시지 입력)인 AXTextArea(입력창)를 찾습니다.
  2. AXValue에 본문을 넣습니다.
  3. unhide → 방 창을 AXRaise + AXMain + AXFocused로 앱 안의 키 윈도우로 만듭니다(앞으로 가져오지는 않음).
  4. 입력창에 포커스를 주고 Return을 보냅니다.
  5. 입력창 값이 바뀌었는지(비워졌는지)로 성공을 판단합니다. 1초 안에 안 바뀌면 폴백으로 앱을 앞으로 가져와 Return을 한 번 더 보내고, 화면에 activate fallback을 표시합니다.
  6. 남은 글자가 있으면 지우고, 다시 hide합니다.

방 열기 (Kakao.open_room)

  1. 채팅 목록에서 이름이 일치(없으면 부분 일치)하는 행을 찾습니다.
  2. AXSelectedRows로 행을 선택하고 Return을 보냅니다.
  3. 1초 뒤 새 창이 생겼는지 확인합니다. 안 생겼으면 폴백으로 앱을 앞으로 가져와 행 좌표에 더블클릭 이벤트를 보냅니다.
  4. 새 창이 생기면 즉시 주차(구석 밖으로 이동)하고 다시 숨깁니다.

4. 숨김과 주차

  • 숨김 여부 판단: NSRunningApplication.isHidden은 갱신이 늦어 믿을 수 없습니다. 대신 CGWindowListCopyWindowInfo로 "화면에 보이는 이 프로세스의 일반 창 개수"를 세어 0이면 숨김으로 봅니다.
  • 주차(park_windows): 모든 카카오톡 창의 AXPosition을 주 화면 오른쪽 아래 (너비 - 12, 높이 - 12) 로 옮깁니다. macOS가 창을 완전히 화면 밖으로는 못 보내게 하므로 12px만 남깁니다.
  • 복귀(unpark_windows): 창들을 화면 안으로 계단식으로 되돌립니다. 카카오톡을 직접 써야 할 때 /unpark.
  • 서버가 뜨면 자동으로 주차 + 숨김, 서버가 꺼지면 자동으로 복귀 + 표시.

5. 사진 펼치기

  • 방을 읽을 때 사진 행의 화면 좌표(frame)를 기억해둡니다.
  • 사용자가 o를 누르면 먼저 그 행이 창 안에 보이도록 스크롤 영역의 AXMakeScreenRectVisible을 설정하고(창 밖으로 스크롤된 행은 캡처에 안 담깁니다), 좌표를 다시 읽은 뒤 CGWindowListCreateImage해당 창만 그 영역을 캡처해 PNG로 보냅니다.
  • 숨긴 앱의 창은 캡처되지 않으므로, 숨긴 상태라면 주차한 채로 잠깐 숨김을 풀었다가 되돌립니다. 이때 macOS가 창을 화면 안으로 되돌리기도 해서 좌표는 숨김을 푼 뒤에 읽고, 막 보이게 된 창은 그려질 때까지 투명한 빈 이미지가 잡히므로 잠시 재시도합니다. 화면 기록 권한이 필요하고, 채팅에 보이는 썸네일 크기까지만 가져옵니다.

6. 서버와 브라우저

  • server.pyaiohttp127.0.0.1:8765에 정적 파일과 WebSocket(/ws)을 제공합니다.
  • 스레드 구성
    • 방 폴링 스레드: 1초마다 열린 방 창을 읽어 새 메시지를 브로드캐스트.
    • 목록 폴링 스레드: 10초마다 채팅 목록을 읽어 바뀌었을 때만 브로드캐스트.
    • 명령 실행: 브라우저가 보낸 open/send/close/image/hide/park/unpark를 executor 스레드에서 처리.
    • AX 호출은 ax_lock으로 직렬화합니다(목록 읽기는 읽기 전용이라 락 없이 돕니다).
  • 에코 억제: 내가 보낸 글은 브라우저에 즉시 그려지므로, 15초 안에 카카오톡에서 같은 본문이 me로 읽혀도 다시 그리지 않습니다.
  • 창 닫힘 판정: AX 창 목록이 순간적으로 비는 경우가 있어, 3회 연속 안 보일 때만 닫힌 것으로 봅니다.
  • 브라우저가 새로 붙으면 서버가 가진 채팅 목록과 열린 방 히스토리를 통째로 내려줍니다. 연결이 끊기면 1.5초 뒤 자동 재접속합니다.

구조도

더 자세한 그림은 docs/architecture.html 을 브라우저에서 열어보세요. (GitHub에서는 HTML을 직접 렌더링하지 않으므로 클론 후 로컬에서 열거나, GitHub Pages를 켜면 됩니다.)

계층 구조

flowchart TB
    subgraph browser["브라우저 (web/)"]
        UI["index.html + style.css<br/>Claude Code 터미널 모양"]
        JS["app.js<br/>상태 관리 · 팔레트 · 단축키 · 가짜 작업 로그"]
    end

    subgraph server["server.py (aiohttp, 127.0.0.1:8765)"]
        WS["/ws WebSocket 핸들러"]
        ST["State<br/>seen · msgs · rooms_payload · recent_sent"]
        P1["방 폴링 스레드 (1초)"]
        P2["목록 폴링 스레드 (10초)"]
        CMD["명령 executor<br/>open / send / close / image / hide / park / unpark"]
    end

    subgraph ax["kakao_ax.py"]
        K["class Kakao<br/>chat_list · read_room · open_room · send<br/>hide · park_windows · capture_image"]
    end

    subgraph macos["macOS 프레임워크 (pyobjc)"]
        AXAPI["ApplicationServices<br/>AXUIElement* (읽기/속성 설정/동작)"]
        QZ["Quartz<br/>CGEventPostToPid · CGWindowList* · CGDisplayBounds"]
        AK["AppKit<br/>NSRunningApplication hide/unhide/activate"]
    end

    KT["KakaoTalk.app<br/>(숨김 + 화면 구석 밖 주차)"]

    UI --- JS
    JS <-- "JSON 메시지" --> WS
    WS --- ST
    P1 --> ST
    P2 --> ST
    WS --> CMD
    P1 & P2 & CMD --> K
    K --> AXAPI & QZ & AK
    AXAPI & QZ & AK --> KT
Loading

메시지 전송 흐름

sequenceDiagram
    participant B as 브라우저
    participant S as server.py
    participant K as kakao_ax.Kakao
    participant T as KakaoTalk

    B->>B: 내 줄(">") 즉시 그리기 + 스피너 시작
    B->>S: {"type":"send","room":"…","text":"…"}
    S->>S: recent_sent에 기록 (에코 억제용)
    S->>K: send(win, text)
    K->>T: 입력창 AXValue = text
    K->>T: unhide (앞으로 가져오지 않음)
    K->>T: 창 AXRaise/AXMain/AXFocused
    K->>T: CGEventPostToPid(Return)
    K->>T: 입력창이 비었는지 1초 대기
    alt 비워지지 않음
        K->>T: activate + Return (폴백)
    end
    K->>T: hide
    K-->>S: (ok, note)
    S-->>B: {"type":"sent","ok":true}
    Note over S,T: 다음 폴링에서 같은 본문이 me로 읽히면 무시
Loading

새 메시지 수신 흐름

sequenceDiagram
    participant T as KakaoTalk
    participant K as kakao_ax.Kakao
    participant S as server.py (방 폴링, 1초)
    participant B as 브라우저

    loop 1초마다
        S->>K: room_windows()
        K->>T: AXWindows 조회
        S->>K: read_room(win, tail=12)
        K->>T: 마지막 12행의 AX 속성 읽기
        K-->>S: [Msg, …]
        S->>S: diff(이전 키열, 이번 키열)
        alt 새 메시지 있음
            S-->>B: {"type":"new","room":"…","msgs":[…]}
            B->>B: "⏺ 이름" 줄로 그리기, 스피너 종료
        end
    end
Loading

파일 구성

kakaoterm/
├── kakao_ax.py        카카오톡 접근성 계층. 읽기/쓰기/숨김/주차/캡처 전부 여기
├── server.py          aiohttp 서버. 폴링 스레드 + WebSocket + 명령 처리
├── kaka.py            터미널 버전 클라이언트 (prompt_toolkit)
├── kaka.json          별칭 설정 (git에 올리지 않음)
├── kaka.example.json  별칭 설정 예시
├── requirements.txt
├── web/
│   ├── index.html     Claude Code 모양 화면 뼈대
│   ├── style.css      터미널 색상/타이포
│   └── app.js         WebSocket 클라이언트, 팔레트, 단축키, 가짜 작업 로그
└── docs/
    └── architecture.html  구조도 (브라우저에서 열기)

요구 사항

항목 내용
OS macOS (Apple Silicon / Intel 무관). macOS 26에서 확인
Python 3.10 이상 권장. 3.13에서 확인
카카오톡 Mac App Store 버전 KakaoTalk mac 앱, 로그인된 상태. 26.7.0에서 확인
권한 시스템 설정 > 개인정보 보호 및 보안 > 손쉬운 사용 (필수) / 화면 기록 (사진 펼치기용, 선택)

주의: 접근성 식별자(_NS:40 등)는 카카오톡 앱 빌드에 따라 바뀔 수 있습니다. 카카오톡이 업데이트된 뒤 목록이나 메시지가 안 읽히면 문제 해결의 식별자 항목을 보세요.


설치

git clone https://github.com/MangoEric/kakaoterm.git
cd kakaoterm
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp kaka.example.json kaka.json   # 별칭은 나중에 편집

권한 설정

서버를 어느 터미널 앱에서 실행하느냐에 따라 그 앱에 권한을 줘야 합니다. (Terminal.app, iTerm2, VS Code 내장 터미널 등)

  1. 시스템 설정 → 개인정보 보호 및 보안 → 손쉬운 사용에서 터미널 앱을 켭니다. 없으면 +로 추가.
  2. 사진까지 보려면 같은 곳의 화면 기록에도 터미널 앱을 켭니다.
  3. 권한을 바꾼 뒤에는 터미널 앱을 완전히 종료했다 다시 여는 것이 안전합니다.

카카오톡 준비

  1. 카카오톡 mac 앱을 실행하고 로그인합니다.
  2. 카카오톡 설정에서 알림 배너를 끕니다. (숨겨도 배너는 뜹니다.)
  3. 실시간으로 읽고 싶은 방은 카카오톡에서 미리 더블클릭해 별도 창으로 열어두면 서버가 뜨자마자 잡힙니다. 서버가 뜬 뒤 브라우저 팔레트에서 열어도 됩니다.

실행

브라우저 버전 (권장)

.venv/bin/python server.py

open http://127.0.0.1:8765 가 출력되면 브라우저에서 그 주소를 엽니다. 서버가 뜨는 순간 카카오톡 창을 주차하고 숨깁니다. Ctrl+C로 끄면 창을 되돌리고 다시 보이게 합니다.

터미널 버전

.venv/bin/python kaka.py
명령 동작
/rooms 채팅 목록과 안 읽은 개수
/open <이름> 방을 창으로 연다
/use <이름> 열린 창 중 보낼 대상 선택
/windows 열린 방 창 목록
/close [이름] 방 창 닫기 (기본: 현재 방)
/history [n] 현재 방의 최근 n개 (기본 20)
/quit 종료
그 외 입력 현재 방으로 전송

목록만 빠르게 볼 때: .venv/bin/python kaka.py --rooms


사용법

브라우저 화면은 키보드만으로 조작합니다.

단축키

동작
/ 또는 Ctrl+K 방/명령 팔레트 열기. 타이핑으로 필터, / 이동, Enter 실행, Esc 닫기
Enter 전송 (Shift+Enter 줄바꿈)
Tab / Shift+Tab 열린 방 순환
Ctrl+W 현재 방 창 닫기
Ctrl+L 화면 비우기
Ctrl+H 카카오톡 즉시 주차 + 숨김
(프롬프트가 비었을 때) 메시지 탐색 모드 진입
탐색 모드에서 / 또는 k/j 메시지 이동 (시각이 함께 표시됨)
탐색 모드에서 o 또는 Enter 사진 펼치기/접기
탐색 모드에서 Esc 프롬프트로 복귀
Esc (일반) 스피너 중단, 입력 비우기

사진 메시지는 로 탐색 모드에 들어가 그 줄로 이동한 뒤 o를 누르면 펼쳐집니다.

방을 열고 사진을 펼치는 과정

슬래시 명령

팔레트에는 채팅방이 /별칭 형태의 명령으로 나열되고, 그 아래에 고정 명령이 있습니다.

방 목록 팔레트

명령 동작
/<방 별칭> 그 방을 연다 (이미 열려 있으면 전환)
/close 현재 방 창 닫기
/hide 카카오톡 주차 + 숨김
/park 카카오톡 창을 화면 구석 밖으로 밀기
/unpark 창을 화면 안으로 되돌리기 (카카오톡을 직접 쓸 때)
/clear 화면 비우기

팔레트 항목 오른쪽의 노란 숫자는 안 읽은 개수, 초록 는 이미 창으로 열린 방입니다. 상태 표시줄의 ⚒ N background tasks는 알림이 켜진 방들의 안 읽은 메시지 합계입니다.

화면 읽는 법

표시 의미
⏺ 이름 다음 줄 상대방 메시지. 같은 사람이 연속이면 이름 생략
> 본문 (회색) 내가 보낸 메시지
> 본문 (노란 취소선) 전송 실패
⎿ Read image (o to expand) 사진 메시지. 탐색 모드에서 o
✻ Pondering… 전송 후 답을 기다리는 중. 상대 메시지가 오거나 60초가 지나면 사라짐
⏺ Read (src/…) 30초 이상 조용할 때 나오는 가짜 작업 로그. 실제 동작 아님
session resumed / connection lost WebSocket 연결 상태
opened (activate fallback) 숨긴 채로는 실패해서 카카오톡을 잠깐 앞으로 가져왔음

설정 (kaka.json)

{
  "aliases": {
    "프로젝트 A 단톡": "team-a",
    "홍길동": "dev-1"
  }
}
  • aliases의 키는 방 이름 또는 사람 이름의 일부입니다. 부분 일치하면 값으로 바꿔 표시합니다.
  • 팔레트의 명령 이름(/team-a)도 별칭을 따릅니다.
  • 별칭은 표시에만 쓰이고, 서버 내부와 카카오톡에는 원래 이름이 그대로 갑니다.
  • 이 파일은 개인 정보를 담게 되므로 .gitignore에 들어 있습니다. kaka.example.json을 복사해서 만드세요.

WebSocket 프로토콜 (개발자용)

브라우저와 서버는 ws://127.0.0.1:8765/ws에서 JSON 한 줄씩 주고받습니다.

서버 → 브라우저

type 내용
rooms 채팅 목록 전체. {name, alias, unread, time, preview, open, muted}[]
history 방이 처음 잡혔거나 재접속했을 때 그 방의 전체 메시지
new 새 메시지 목록
closed 방 창이 닫힘
opened / sent 명령 결과. ok, note(폴백/잔여 문자 등)
image 사진 PNG(base64). 실패하면 note에 사유
hidden / parked / unparked 명령 결과
error 폴링/명령 오류 메시지

브라우저 → 서버

type 필드
open room (원래 이름)
send room, text
close room
image room, index (메시지 행 순번)
hide / park / unpark 없음

메시지 객체: {side: "me"|"them", name, time, text, kind: "text"|"image", index}


한계

  • 실시간으로 읽히는 건 카카오톡에서 창으로 연 방뿐입니다. 나머지 방은 채팅 목록의 안 읽은 개수와 미리보기만 보입니다.
  • 방 하나당 카카오톡이 창에 로드한 최근 약 70개 메시지만 읽힙니다. 위로 스크롤한 과거는 안 가져옵니다.
  • 사진은 창 캡처 방식이라 채팅에 보이는 썸네일 크기까지만입니다. 원본은 로컬 캐시가 암호화되어 있어 접근하지 않습니다.
  • 이모티콘, 파일, 링크 미리보기, 답장/멘션 같은 특수 메시지는 본문 텍스트가 있으면 텍스트로, 없으면 건너뜁니다.
  • 메시지에 고유 ID가 없어 (방향, 종류, 본문)으로 구분합니다. 같은 사람이 같은 글을 연달아 보내면 한 번으로 합쳐질 수 있습니다.
  • Dock 뱃지는 남습니다. Dock 자동 숨김을 켜면 가려집니다.
  • 카카오톡을 앞으로 가져와야 하는 폴백이 발생하면 그 0.5초 남짓 동안 카카오톡이 화면에 나타날 수 있습니다.
  • 카카오톡 앱 업데이트로 접근성 식별자나 창 구조가 바뀌면 동작이 깨질 수 있습니다.

문제 해결

error: KakaoTalk이 실행 중이 아닙니다 카카오톡 mac 앱이 실행 중이어야 합니다. 프로세스 이름 KakaoTalkpgrep으로 찾습니다.

서버는 뜨는데 채팅 목록이 비어 있음 / 방을 열어도 메시지가 안 보임

  • 손쉬운 사용 권한이 서버를 실행한 터미널 앱에 있는지 확인하세요. 권한을 준 뒤 터미널을 재시작하세요.
  • 카카오톡 메인 창이 닫혀 메뉴바만 남은 상태면 open -g -a KakaoTalk으로 다시 띄웁니다(자동으로 시도합니다).
  • 카카오톡 업데이트로 식별자가 바뀌었을 수 있습니다. kakao_ax.py 상단의 BOOKMARK_ID, chat_list_NS:40/_NS:69/_NS:87, INPUT_DESCS를 확인하세요. Xcode의 Accessibility Inspector로 카카오톡 창을 찍어보면 현재 식별자를 볼 수 있습니다.

opened (activate fallback) / sent (activate fallback) 가 자주 뜸 숨긴 채로 Return이 안 먹어 카카오톡을 앞으로 가져온 경우입니다. 다른 카카오톡 창(설정 창 등)이 열려 있거나, 카카오톡이 막 실행된 직후에 잘 생깁니다. 카카오톡 창을 방 창과 메인 창만 남기고 정리하면 줄어듭니다.

사진이 capture unavailable (screen recording permission?) 화면 기록 권한이 터미널 앱에 없습니다. 권한을 준 뒤 터미널을 재시작하세요.

카카오톡을 직접 쓰고 싶은데 창이 안 보임 브라우저에서 /unpark를 실행하면 창을 화면 안으로 되돌립니다. 서버를 끄면(Ctrl+C) 자동으로 되돌립니다. 서버가 비정상 종료돼 창이 구석에 박혀 있으면, 카카오톡을 완전히 종료했다 다시 실행하세요.

한글 입력 중 Enter를 치면 마지막 글자가 두 번 들어감 브라우저 IME 조합 중 이벤트는 무시하도록 처리되어 있습니다. 그래도 문제가 있으면 브라우저 종류를 알려주세요.

포트 8765가 이미 사용 중 server.py 상단의 PORT를 바꾸세요.


개인정보와 보안

  • 서버는 127.0.0.1에만 바인딩됩니다. 같은 컴퓨터의 브라우저 외에는 접근할 수 없습니다.
  • 메시지는 메모리에만 있고 파일이나 외부 서버로 보내지 않습니다. 서버를 끄면 사라집니다.
  • kaka.json에는 방 이름과 사람 이름이 들어가므로 저장소에 올리지 마세요(.gitignore 처리됨).
  • web/index.html의 배너에 있는 cwd: 경로는 화면 장식용 문자열입니다. 원하는 값으로 바꾸세요.
  • 이 도구는 본인 계정의 카카오톡을 본인이 조작하는 용도입니다. 타인의 기기나 계정에 쓰지 마세요.

About

카카오톡 mac 앱을 macOS 접근성 API로 읽고 써서 브라우저 탭을 Claude Code 터미널처럼 보이게 하는 로컬 클라이언트

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages