pytmux
명령어를 외우지 않아도 흐름이 끊기지 않는 터미널 — 마우스와 메뉴를 1급 시민으로 되돌린 개발 도구
배경과 목표
tmux는 강력하지만, 원격 Windows 환경에서 설치·설정이 번거롭고 무엇보다 모든 조작을 단축키로 외워야 합니다. pytmux는 이 마찰을 걷어내기 위해 시작한 개인 프로젝트입니다. 목표는 분명했습니다. 처음 실행하면 그냥 평소 쓰던 셸이 전체 화면으로 뜨고(학습 비용 0에서 출발), 앱이나 상위 터미널을 닫아도 셸 세션은 살아 있으며, 조작은 키보드·마우스·메뉴 어느 쪽으로도 가능해야 한다는 것이었습니다. “명령을 다 외우지 못하는 사람”과 “마우스를 더 쓰고 싶은 사람”을 명시적 사용자로 두었다는 점이 이 도구의 성격을 규정합니다.
디자인 축
저는 이 프로젝트를 기능 목록이 아니라 사용자 경험의 세 가지 축으로 설계했습니다. 첫째, 마우스 우선입니다. 경계선을 드래그해 패널 크기를 바꾸고, 클릭으로 포커스를 옮기고, 우클릭으로 메뉴를 열고, 휠로 지난 출력을 봅니다 — 터미널에서 당연히 기대하지만 대개 없는 상호작용을 1급으로 끌어올렸습니다. 둘째, 명령 암기 불필요입니다. 거의 모든 동작을 TUI 메뉴(prefix Enter·우클릭)와 검색형 명령 프롬프트(prefix : + 고스트 자동완성)로 발견할 수 있게 하여, 단축키를 몰라도 기능에 도달합니다. 셋째, 인지 부하 감소와 흐름 유지입니다. 활성 패널은 파란 테두리로 즉시 구분되고, 스크롤백은 copy-mode 진입 없이 휠만으로 열리며, 새 출력이 와도 보고 있던 화면은 고정됩니다. 조작 방식이 달라도 결국 하나의 명령(named command) 으로 수렴하도록 설계해, 마우스·키보드·메뉴가 서로 다른 세계가 되지 않게 했습니다.
핵심 시스템과 설계 결정
가장 중요한 설계 결정은 클라이언트/서버 분리였습니다. 셸의 수명을 화면을 그리는 앱의 수명에서 떼어내야 “닫아도 살아남는” 경험이 성립하기에, 셸 PTY를 백그라운드 데몬이 소유하고 Textual 클라이언트는 서버가 보낸 좌표대로 렌더만 합니다(레이아웃의 단일 진실 소스는 서버). 그 위에서 발견 가능성을 높이는 표면들을 얹었습니다. 상단 노트북형 탭바([+]/[x], 드래그 재정렬), 패널·레이아웃·탭을 서브메뉴로 정리한 화면 메뉴가 그 예입니다. 개발 도구로서 가장 공들인 부분은 Claude Code 통합입니다. 실행 중인 패널의 상태를 아이콘(대기·처리중·한도정지)으로 알리고, 토큰·컨텍스트 사용량을 상태줄에 표시하며 클릭하면 기간·세션·한도별 팝업으로 펼칩니다. 사용량 한도에 걸려 멈추면 출력에서 해제 시각을 읽어 그때 자동 재개하고, 컨텍스트가 꽉 차면 /compact로 스스로 복구합니다. 다만 여기서도 원칙을 지켰습니다 — pytmux는 화면 스크랩과 키 주입만으로 행동하므로, 실측 /usage 값을 추정치보다 우선하고 추정에는 항상 물결표를 붙여 가진 것 이상을 주장하지 않도록 정직하게 표기했습니다.
기술 하이라이트
서버는 단일 스레드 asyncio 루프, 패널마다 pyte(및 자작 VT 파서) 가상 스크린을 두고 변경 행만 diff로 보냅니다. Windows는 fork/AF_UNIX가 없어 ConPTY·TCP 루프백·리더 스레드로 네이티브 포팅했습니다. 선택 기능은 전부 delete-to-disable 플러그인으로, 디렉토리를 지우면 명령·렌더 어디에도 흔적 없이 사라집니다.
현황
tmux 대비 기능이 모두 구현되었고 헤드리스 테스트 800여 개가 전부 통과합니다. Windows 네이티브 백엔드까지 실기 검증을 마쳤으며, 저는 이 도구로 pytmux 자체를 개발하는 자기호스팅 상태로 매일 사용하고 있습니다.