Termote

Release CI License GHCR Docker Pulls

Go React TypeScript PWA

Termote - Launched on J2TEAM Launch   Termote trên Unikorn.vn

모바일/데스크톱에서 PWA를 통해 CLI 도구(Claude Code, GitHub Copilot, 모든 터미널)를 원격 제어. > **Termote** = Terminal + Remote > > 🇬🇧 [English](README.md) | 🇻🇳 [Tiếng Việt](README.vi.md) | 🇨🇳 [简体中文](README.zh-CN.md) | 🇯🇵 [日本語](README.ja.md) | 🇪🇸 [Español](README.es.md) | 🇧🇷 [Português (BR)](README.pt-BR.md) | 🇫🇷 [Français](README.fr.md) | 🇩🇪 [Deutsch](README.de.md) | 🇷🇺 [Русский](README.ru.md) | 🇮🇩 [Bahasa Indonesia](README.id.md) ## 기능 - **세션 전환**: 생성/편집/삭제가 가능한 여러 tmux 세션 - **세션 탭**: 빠른 창 전환을 위한 가로 탭 바 - **모바일 친화적**: 가상 키보드 툴바 (Tab/Ctrl/Shift/방향키, 확장 가능) - **제스처 지원**: 스와이프로 Ctrl+C, Tab, 히스토리 탐색 - **명령 히스토리**: 검색 기능으로 이전에 전송한 명령 재호출 - **빠른 작업**: 자주 쓰는 작업(clear, cancel, exit)을 위한 플로팅 메뉴 - **연결 표시기**: 실시간 서버 상태 및 연결 끊김 자동 감지 - **업데이트 확인**: GitHub releases에서 새 버전 자동 알림 - **PWA**: 홈 화면에 설치 가능, 오프라인 지원 - **영구 세션**: tmux가 세션을 유지 - **접을 수 있는 사이드바**: 토글 가능한 세션 사이드바가 있는 데스크톱 UI - **전체 화면 모드**: 몰입형 터미널 경험 - **설정 저장**: AES-256 암호화 비밀번호로 설치 설정 자동 저장 ## 스크린샷

모바일 터미널    세션 사이드바

## 아키텍처 ```mermaid flowchart TB subgraph Client["클라이언트 (모바일/데스크톱)"] PWA["PWA - React + TypeScript"] Gestures["제스처 컨트롤"] Keyboard["가상 키보드"] end subgraph Server["tmux-api 서버 :7680"] Static["정적 파일"] Proxy["WebSocket 프록시"] API["REST API /api/tmux/*"] Auth["Basic Auth"] end subgraph Backend["백엔드 서비스"] ttyd["ttyd :7681"] tmux["tmux"] Shell["Shell"] Tools["CLI 도구"] end Gestures --> PWA Keyboard --> PWA PWA --> Static PWA <--> Proxy PWA --> API Auth -.-> Static & Proxy & API Proxy <--> ttyd API --> tmux ttyd --> tmux --> Shell --> Tools ``` ## 빠른 시작 > 📖 **Termote가 처음이신가요?** 예제와 함께하는 완전한 안내는 [시작 가이드](docs/getting-started.md)를 확인하세요. ```bash ./scripts/termote.sh # 대화형 메뉴 ./scripts/termote.sh install container # 컨테이너 모드 (docker/podman) ./scripts/termote.sh install native # 네이티브 모드 (호스트 도구) ./scripts/termote.sh link # 'termote' 글로벌 명령 생성 make test # 테스트 실행 ``` > `link` 이후 어디서든 `termote` 사용 가능: `termote health`, `termote install native --lan` > > **팁**: 향상된 대화형 메뉴를 위해 [gum](https://github.com/charmbracelet/gum) 설치 (선택 사항, bash 폴백 가능) ## 설치 ### 한 줄 명령 (권장) **macOS/Linux:** ```bash # 다운로드 후 설치 전 확인 (기본값: native 모드) curl -fsSL https://raw.githubusercontent.com/lamngockhuong/termote/main/scripts/get.sh | bash # 확인 없이 자동 설치 curl -fsSL .../get.sh | bash -s -- --yes # 다운로드만 (설치 안 함) curl -fsSL .../get.sh | bash -s -- --download-only # 저장된 설정으로 자동 업데이트 curl -fsSL .../get.sh | bash -s -- --update # 특정 버전 설치 curl -fsSL .../get.sh | bash -s -- --version 0.0.4 # 모드와 옵션을 명시적으로 지정 curl -fsSL .../get.sh | bash -s -- --yes --container --lan curl -fsSL .../get.sh | bash -s -- --yes --native --tailscale myhost # 새 비밀번호 강제 입력 (저장된 설정 무시) curl -fsSL .../get.sh | bash -s -- --yes --container --fresh ``` **Windows (PowerShell):** > **참고:** 시스템에서 스크립트 실행이 비활성화된 경우, 먼저 이 명령을 실행하세요: > > ```powershell > Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned > ``` ```powershell # 다운로드 후 설치 전 확인 (기본값: native 모드) irm https://raw.githubusercontent.com/lamngockhuong/termote/main/scripts/get.ps1 | iex # 확인 없이 자동 설치 $env:TERMOTE_AUTO_YES = "true"; irm .../get.ps1 | iex # 모드를 명시적으로 지정 $env:TERMOTE_MODE = "container"; irm .../get.ps1 | iex # 저장된 설정으로 자동 업데이트 $env:TERMOTE_UPDATE = "true"; irm .../get.ps1 | iex ``` ### Docker ```bash # 올인원 (자격 증명 자동 생성, 로그 확인: docker logs termote) docker run -d --name termote -p 7680:7680 ghcr.io/lamngockhuong/termote:latest # 사용자 지정 자격 증명 docker run -d --name termote -p 7680:7680 \ -e TERMOTE_USER=admin -e TERMOTE_PASS=secret \ ghcr.io/lamngockhuong/termote:latest # 인증 없음 (로컬 개발 전용) docker run -d --name termote -p 7680:7680 \ -e NO_AUTH=true \ ghcr.io/lamngockhuong/termote:latest # 영구 저장을 위한 볼륨 사용 docker run -d --name termote -p 7680:7680 \ -v termote-data:/home/termote \ ghcr.io/lamngockhuong/termote:latest # 사용자 지정 workspace 디렉토리 마운트 docker run -d --name termote -p 7680:7680 \ -v ~/projects:/workspace \ ghcr.io/lamngockhuong/termote:latest # Tailscale HTTPS 사용 (호스트에 Tailscale 필요) docker run -d --name termote -p 7680:7680 \ -e TERMOTE_USER=admin -e TERMOTE_PASS=secret \ ghcr.io/lamngockhuong/termote:latest sudo tailscale serve --bg --https=443 http://127.0.0.1:7680 # 접속: https://your-hostname.tailnet-name.ts.net ``` ### Release에서 설치 ```bash # 최신 릴리스 다운로드 VERSION=$(curl -s https://api.github.com/repos/lamngockhuong/termote/releases/latest | grep tag_name | cut -d '"' -f4) wget https://github.com/lamngockhuong/termote/releases/download/${VERSION}/termote-${VERSION}.tar.gz tar xzf termote-${VERSION}.tar.gz cd termote-${VERSION#v} # 설치 (대화형 메뉴 또는 모드 지정) ./scripts/termote.sh install ./scripts/termote.sh install container ``` ### 소스에서 설치 ```bash git clone https://github.com/lamngockhuong/termote.git cd termote ./scripts/termote.sh install container ``` > **참고**: `termote.sh`는 `install` (소스에서 빌드, 가능한 경우 사전 빌드된 아티팩트 사용), `uninstall`, `health` 명령을 지원하는 통합 CLI입니다. ## 배포 모드 ```mermaid flowchart LR subgraph Container["컨테이너 모드"] direction TB C1["Docker/Podman"] --> C2["tmux-api :7680"] --> C3["ttyd :7681"] --> C4["tmux"] end subgraph Native["네이티브 모드"] direction TB N1["호스트 시스템"] --> N2["tmux-api :7680"] --> N3["ttyd :7681"] --> N4["tmux + 호스트 도구"] end User["사용자"] --> Container & Native ``` | 모드 | 설명 | 사용 사례 | 플랫폼 | | ------------- | ------------- | ----------------------------- | ------------ | | `--container` | 컨테이너 모드 | 간단한 배포, 격리된 환경 | macOS, Linux | | `--native` | 전체 네이티브 | 호스트 도구 접근 (claude, gh) | macOS, Linux | ### 옵션 | 플래그 | 설명 | | --------------------------- | ------------------------------------------ | | `--lan` | LAN에 노출 (기본값: localhost만) | | `--tailscale ` | Tailscale HTTPS 활성화 | | `--no-auth` | 기본 인증 비활성화 | | `--port ` | 호스트 포트 (기본값: 7680, Windows: 7690) | | `--fresh` | 새 비밀번호 강제 입력 (저장된 설정 무시) | | `--update` | 저장된 설정으로 자동 업데이트 | | `--version ` | 특정 버전 설치 (`v` 포함/미포함 모두 가능) | | 환경 변수 | 설명 | | -------------- | ------------------------------------------------ | | `WORKSPACE` | 마운트할 호스트 디렉토리 (기본값: `./workspace`) | | `TERMOTE_USER` | Basic auth 사용자 이름 (기본값: 자동 생성) | | `TERMOTE_PASS` | Basic auth 비밀번호 (기본값: 자동 생성) | | `NO_AUTH` | `true`로 설정하여 인증 비활성화 | ### 컨테이너 모드 (간편한 사용을 위해 권장) 스크립트가 `podman` 또는 `docker`를 자동 감지합니다 -- 둘 다 동일하게 작동합니다. ```bash ./scripts/termote.sh install container # localhost + basic auth ./scripts/termote.sh install container --no-auth # localhost + 인증 없음 ./scripts/termote.sh install container --lan # LAN 접근 가능 # 접속: http://localhost:7680 # 사용자 지정 workspace 디렉토리 (컨테이너 내 /workspace에 마운트) WORKSPACE=~/projects ./scripts/termote.sh install container WORKSPACE=/path/to/code make install-container ``` > **보안 참고**: `$HOME`을 직접 마운트하지 마세요 -- `.ssh`, `.gnupg` 같은 민감한 디렉토리가 컨테이너에서 접근 가능해집니다. 대신 특정 프로젝트 디렉토리를 마운트하세요. ### 네이티브 (호스트 바이너리 접근을 위해 권장) 호스트 바이너리(claude, git 등)에 접근이 필요할 때 사용: ```bash # Linux sudo apt install ttyd tmux # 또는: sudo snap install ttyd ./scripts/termote.sh install native # macOS brew install ttyd tmux go ./scripts/termote.sh install native # 접속: http://localhost:7680 ``` ### Tailscale HTTPS 사용 (모든 모드) 자동 HTTPS를 위해 `tailscale serve`를 사용합니다 (수동 인증서 관리 불필요): ```bash # Tailscale만 (기본 포트 443) ./scripts/termote.sh install container --tailscale myhost.ts.net # 사용자 지정 포트 ./scripts/termote.sh install native --tailscale myhost.ts.net:8765 # Tailscale + LAN 접근 가능 ./scripts/termote.sh install container --tailscale myhost.ts.net --lan # 접속: https://myhost.ts.net (또는 사용자 지정 포트의 경우 :8765) ``` ### 제거 ```bash ./scripts/termote.sh uninstall container # 컨테이너 모드 ./scripts/termote.sh uninstall native # 네이티브 모드 ./scripts/termote.sh uninstall all # 전체 ``` ### 업데이트 ```bash # 방법 1: 저장된 설정으로 자동 업데이트 curl -fsSL .../get.sh | bash -s -- --update # 방법 2: 한 줄 명령 재실행 (버전 비교, 설치 전 확인) curl -fsSL .../get.sh | bash # 방법 3: 수동 업데이트 ./scripts/termote.sh uninstall [container|native] git pull origin main # 소스에서 설치한 경우 ./scripts/termote.sh install [container|native] [--lan] [--tailscale ...] ``` ## 플랫폼 지원 | 플랫폼 | 컨테이너 | 네이티브 | CLI 스크립트 | | ------- | ---------- | ---------- | ------------ | | Linux | ✓ | ✓ | termote.sh | | macOS | ✓ | ✓ | termote.sh | | Windows | ⚠️ (실험적) | ⚠️ (실험적) | termote.ps1 | > **⚠️ Windows 지원 (실험적)**: Windows 지원은 현재 초기 단계이며 추가 테스트가 필요합니다. 컨테이너 모드는 Docker Desktop이 필요하고, 네이티브 모드는 psmux가 필요합니다. GitHub에서 이슈를 보고해 주세요. ### Windows 네이티브 모드 Windows 네이티브 모드는 [psmux](https://github.com/psmux/psmux) (Windows용 tmux 호환 터미널 멀티플렉서)를 사용합니다: ```powershell # psmux 설치 winget install psmux # Termote 실행 .\scripts\termote.ps1 install native .\scripts\termote.ps1 install container # 또는 Docker Desktop으로 컨테이너 모드 ``` > 기본적으로 `install native`는 [fork/MSVC ttyd 빌드](https://github.com/lamngockhuong/ttyd/releases)를 다운로드합니다 (최신 Windows에서 작동). `-Ttyd official`을 사용하면 업스트림 tsl0922/ttyd 빌드로 전환합니다. ## 모바일 사용법 | 동작 | 제스처 | | --------------- | ---------------------- | | 취소/중단 | 왼쪽 스와이프 (Ctrl+C) | | Tab 자동 완성 | 오른쪽 스와이프 | | 히스토리 위로 | 위로 스와이프 | | 히스토리 아래로 | 아래로 스와이프 | | 붙여넣기 | 길게 누르기 | | 글꼴 크기 | 핀치 인/아웃 | 가상 툴바 제공: Tab, Esc, Ctrl, Shift, 방향키 및 일반 키 조합. Ctrl+Shift 조합(붙여넣기, 복사) 지원. 추가 키(Home, End, Delete 등)를 위해 최소 모드와 확장 모드 간 전환 가능. ## 프로젝트 구조 ``` termote/ ├── Makefile # 빌드/테스트/배포 명령 ├── Dockerfile # Docker 모드 (tmux-api + ttyd) ├── docker-compose.yml ├── entrypoint.sh # Docker 엔트리포인트 ├── docs/ # 문서 │ └── images/screenshots/ # 앱 스크린샷 ├── pwa/ # React PWA │ └── src/ │ ├── components/ │ ├── contexts/ │ ├── hooks/ │ ├── types/ │ └── utils/ ├── tmux-api/ # Go 서버 │ ├── main.go # 엔트리 포인트 │ ├── serve.go # 서버 (PWA, 프록시, 인증) │ └── tmux.go # tmux API 핸들러 ├── scripts/ │ ├── termote.sh # Unix CLI (install/uninstall/health) │ ├── termote.ps1 # Windows PowerShell CLI │ ├── get.sh # Unix 온라인 설치기 (curl | bash) │ └── get.ps1 # Windows 온라인 설치기 (irm | iex) ├── tests/ # 테스트 모음 │ ├── test-termote.sh │ ├── test-termote.ps1 # Windows 테스트 │ ├── test-get.sh │ └── test-entrypoints.sh └── website/ # Astro Starlight 문서 사이트 └── src/content/docs/ # MDX 문서 ``` ## 개발 ```bash make build # PWA와 tmux-api 빌드 make test # 모든 테스트 실행 make health # 서비스 상태 확인 make clean # 컨테이너 중지 # E2E 테스트 (실행 중인 서버 필요) ./scripts/termote.sh install container # 먼저 서버 시작 pnpm --filter termote test:e2e # Playwright 테스트 실행 pnpm --filter termote test:e2e:ui # UI 디버거로 실행 ``` **수동 테스트:** [자체 테스트 체크리스트](docs/self-test-checklist.md) 참조 ## 문제 해결 ### 세션이 유지되지 않음 - tmux 확인: `tmux ls` - ttyd가 `-A` 플래그(attach-or-create)를 사용하는지 확인 ### WebSocket 오류 - tmux-api 로그 확인: `docker logs termote` - ttyd가 포트 7681에서 실행 중인지 확인 ### 모바일 키보드 문제 - viewport meta 태그가 있는지 확인 - 에뮬레이터가 아닌 실제 기기에서 테스트 ### 네이티브 모드: 프로세스가 시작되지 않음 ```bash ps aux | grep ttyd # ttyd 실행 중인지 확인 ps aux | grep tmux-api # tmux-api 실행 중인지 확인 lsof -i :7680 # 포트 사용 중인지 확인 ``` ## 보안 참고 - **기본값: localhost만** - `--lan` 플래그를 사용하지 않으면 LAN에 노출되지 않음 - **기본 인증 기본 활성화** - 로컬 개발 시 `--no-auth`로 비활성화 - **내장 무차별 대입 방지** - 속도 제한 (IP당 5회 시도/분) - 프로덕션에는 HTTPS(Tailscale) 사용 - 신뢰할 수 있는 네트워크/VPN으로 제한 ## 다른 프로젝트 | 프로젝트 | 설명 | | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | [GitHub Flex](https://github.com/lamngockhuong/github-flex) | GitHub 인터페이스를 생산성 기능으로 향상시키는 크로스 브라우저 확장 프로그램 (Chrome & Firefox) | | [TabRest](https://github.com/lamngockhuong/tabrest) | 비활성 탭을 자동으로 언로드하여 메모리를 확보하는 Chrome 확장 프로그램 | | [Specpin](https://github.com/lamngockhuong/specpin) | 실행 중인 웹 UI 요소에 Git으로 버전 관리되는 살아있는 비즈니스 명세를 고정 (브라우저 확장 프로그램 + Go sidecar) | ## 라이선스 MIT