{"id":47614978,"url":"https://github.com/lamngockhuong/termote","last_synced_at":"2026-04-11T04:03:19.993Z","repository":{"id":345635433,"uuid":"1186760949","full_name":"lamngockhuong/termote","owner":"lamngockhuong","description":"Remote control CLI tools (Claude Code, GitHub Copilot, any terminal) from mobile/desktop via PWA","archived":false,"fork":false,"pushed_at":"2026-03-28T05:18:52.000Z","size":959,"stargazers_count":23,"open_issues_count":1,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-28T08:32:13.909Z","etag":null,"topics":["cli","remote-control","terminal","tmux","ttyd"],"latest_commit_sha":null,"homepage":"https://termote.khuong.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lamngockhuong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-20T00:51:25.000Z","updated_at":"2026-03-28T05:18:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lamngockhuong/termote","commit_stats":null,"previous_names":["lamngockhuong/termote"],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/lamngockhuong/termote","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamngockhuong%2Ftermote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamngockhuong%2Ftermote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamngockhuong%2Ftermote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamngockhuong%2Ftermote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lamngockhuong","download_url":"https://codeload.github.com/lamngockhuong/termote/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamngockhuong%2Ftermote/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292104,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","remote-control","terminal","tmux","ttyd"],"created_at":"2026-04-01T21:16:08.939Z","updated_at":"2026-04-11T04:03:19.978Z","avatar_url":"https://github.com/lamngockhuong.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"pwa/public/banner-readme.svg\" alt=\"Termote\" width=\"600\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/lamngockhuong/termote/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/lamngockhuong/termote?style=flat-square\u0026color=blue\" alt=\"Release\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/lamngockhuong/termote/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/lamngockhuong/termote/ci.yml?branch=main\u0026style=flat-square\u0026label=CI\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/lamngockhuong/termote/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/lamngockhuong/termote?style=flat-square\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://ghcr.io/lamngockhuong/termote\"\u003e\u003cimg src=\"https://img.shields.io/badge/GHCR-termote-blue?style=flat-square\u0026logo=github\" alt=\"GHCR\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/lamngockhuong/termote\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/lamngockhuong/termote?style=flat-square\u0026logo=docker\" alt=\"Docker Pulls\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Go-1.21-00ADD8?style=flat-square\u0026logo=go\u0026logoColor=white\" alt=\"Go\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/React-19-61DAFB?style=flat-square\u0026logo=react\u0026logoColor=black\" alt=\"React\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/TypeScript-5.9-3178C6?style=flat-square\u0026logo=typescript\u0026logoColor=white\" alt=\"TypeScript\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/PWA-ready-5A0FC8?style=flat-square\u0026logo=pwa\u0026logoColor=white\" alt=\"PWA\" /\u003e\n\u003c/p\u003e\n\nRemote control CLI tools (Claude Code, GitHub Copilot, any terminal) from mobile/desktop via PWA.\n\n\u003e **Termote** = Terminal + Remote\n\u003e\n\u003e [Tiếng Việt](README.vi.md)\n\n## Features\n\n- **Session switching**: Multiple tmux sessions with create/edit/delete\n- **Mobile-friendly**: Virtual keyboard toolbar (Tab/Ctrl/Shift/arrows, expandable)\n- **Gesture support**: Swipe for Ctrl+C, Tab, history navigation\n- **PWA**: Installable to homescreen, offline-capable\n- **Persistent sessions**: tmux keeps sessions alive\n- **Collapsible sidebar**: Desktop UI with toggleable session sidebar\n- **Fullscreen mode**: Immersive terminal experience\n- **Config persistence**: Auto-save installation settings with AES-256 encrypted password\n\n## Screenshots\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/images/screenshots/mobile-terminal.png\" alt=\"Mobile Terminal\" width=\"280\" /\u003e\n  \u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"docs/images/screenshots/mobile-sidebar.png\" alt=\"Session Sidebar\" width=\"280\" /\u003e\n\u003c/p\u003e\n\n## Architecture\n\n```mermaid\nflowchart TB\n    subgraph Client[\"Client (Mobile/Desktop)\"]\n        PWA[\"PWA - React + TypeScript\"]\n        Gestures[\"Gesture Controls\"]\n        Keyboard[\"Virtual Keyboard\"]\n    end\n\n    subgraph Server[\"tmux-api Server :7680\"]\n        Static[\"Static Files\"]\n        Proxy[\"WebSocket Proxy\"]\n        API[\"REST API /api/tmux/*\"]\n        Auth[\"Basic Auth\"]\n    end\n\n    subgraph Backend[\"Backend Services\"]\n        ttyd[\"ttyd :7681\"]\n        tmux[\"tmux\"]\n        Shell[\"Shell\"]\n        Tools[\"CLI Tools\"]\n    end\n\n    Gestures --\u003e PWA\n    Keyboard --\u003e PWA\n    PWA --\u003e Static\n    PWA \u003c--\u003e Proxy\n    PWA --\u003e API\n    Auth -.-\u003e Static \u0026 Proxy \u0026 API\n    Proxy \u003c--\u003e ttyd\n    API --\u003e tmux\n    ttyd --\u003e tmux --\u003e Shell --\u003e Tools\n```\n\n## Quick Start\n\n\u003e 📖 **New to Termote?** Check out the [Getting Started Guide](docs/getting-started.md) for a complete walkthrough with examples.\n\n```bash\n./scripts/termote.sh                   # Interactive menu\n./scripts/termote.sh install container # Container mode (docker/podman)\n./scripts/termote.sh install native    # Native mode (host tools)\n./scripts/termote.sh link              # Create 'termote' global command\nmake test                              # Run tests\n```\n\n\u003e After `link`, use `termote` from anywhere: `termote health`, `termote install native --lan`\n\n\u003e **Tip**: Install [gum](https://github.com/charmbracelet/gum) for enhanced interactive menus (optional, bash fallback available)\n\n## Installation\n\n### One-liner (recommended)\n\n**macOS/Linux:**\n\n```bash\n# Download and prompt before install (defaults to native mode)\ncurl -fsSL https://raw.githubusercontent.com/lamngockhuong/termote/main/scripts/get.sh | bash\n\n# Auto-install without prompt\ncurl -fsSL .../get.sh | bash -s -- --yes\n\n# Download only (no install)\ncurl -fsSL .../get.sh | bash -s -- --download-only\n\n# Auto-update with saved config\ncurl -fsSL .../get.sh | bash -s -- --update\n\n# Install specific version\ncurl -fsSL .../get.sh | bash -s -- --version 0.0.4\n\n# With explicit mode and options\ncurl -fsSL .../get.sh | bash -s -- --yes --container --lan\ncurl -fsSL .../get.sh | bash -s -- --yes --native --tailscale myhost\n\n# Force new password (ignore saved config)\ncurl -fsSL .../get.sh | bash -s -- --yes --container --fresh\n```\n\n**Windows (PowerShell):**\n\n\u003e **Note:** If script execution is disabled on your system, run this first:\n\u003e\n\u003e ```powershell\n\u003e Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned\n\u003e ```\n\n```powershell\n# Download and prompt before install (defaults to native mode)\nirm https://raw.githubusercontent.com/lamngockhuong/termote/main/scripts/get.ps1 | iex\n\n# Auto-install without prompt\n$env:TERMOTE_AUTO_YES = \"true\"; irm .../get.ps1 | iex\n\n# With explicit mode\n$env:TERMOTE_MODE = \"container\"; irm .../get.ps1 | iex\n\n# Auto-update with saved config\n$env:TERMOTE_UPDATE = \"true\"; irm .../get.ps1 | iex\n```\n\n### Docker\n\n```bash\n# All-in-one (auto-generates credentials, check logs: docker logs termote)\ndocker run -d --name termote -p 7680:7680 ghcr.io/lamngockhuong/termote:latest\n\n# With custom credentials\ndocker run -d --name termote -p 7680:7680 \\\n  -e TERMOTE_USER=admin -e TERMOTE_PASS=secret \\\n  ghcr.io/lamngockhuong/termote:latest\n\n# Without auth (local dev only)\ndocker run -d --name termote -p 7680:7680 \\\n  -e NO_AUTH=true \\\n  ghcr.io/lamngockhuong/termote:latest\n\n# With volume for persistence\ndocker run -d --name termote -p 7680:7680 \\\n  -v termote-data:/home/termote \\\n  ghcr.io/lamngockhuong/termote:latest\n\n# Mount custom workspace directory\ndocker run -d --name termote -p 7680:7680 \\\n  -v ~/projects:/workspace \\\n  ghcr.io/lamngockhuong/termote:latest\n\n# With Tailscale HTTPS (requires Tailscale on host)\ndocker run -d --name termote -p 7680:7680 \\\n  -e TERMOTE_USER=admin -e TERMOTE_PASS=secret \\\n  ghcr.io/lamngockhuong/termote:latest\nsudo tailscale serve --bg --https=443 http://127.0.0.1:7680\n# Access at: https://your-hostname.tailnet-name.ts.net\n```\n\n### From Release\n\n```bash\n# Download latest release\nVERSION=$(curl -s https://api.github.com/repos/lamngockhuong/termote/releases/latest | grep tag_name | cut -d '\"' -f4)\nwget https://github.com/lamngockhuong/termote/releases/download/${VERSION}/termote-${VERSION}.tar.gz\ntar xzf termote-${VERSION}.tar.gz\ncd termote-${VERSION#v}\n\n# Install (interactive menu or with mode)\n./scripts/termote.sh install\n./scripts/termote.sh install container\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/lamngockhuong/termote.git\ncd termote\n./scripts/termote.sh install container\n```\n\n\u003e **Note**: `termote.sh` is the unified CLI supporting `install` (builds from source, uses pre-built artifacts when available), `uninstall`, and `health` commands.\n\n## Deployment Modes\n\n```mermaid\nflowchart LR\n    subgraph Container[\"Container Mode\"]\n        direction TB\n        C1[\"Docker/Podman\"] --\u003e C2[\"tmux-api :7680\"] --\u003e C3[\"ttyd :7681\"] --\u003e C4[\"tmux\"]\n    end\n\n    subgraph Native[\"Native Mode\"]\n        direction TB\n        N1[\"Host System\"] --\u003e N2[\"tmux-api :7680\"] --\u003e N3[\"ttyd :7681\"] --\u003e N4[\"tmux + Host Tools\"]\n    end\n\n    User[\"User\"] --\u003e Container \u0026 Native\n```\n\n| Mode          | Description    | Use Case                        | Platform     |\n| ------------- | -------------- | ------------------------------- | ------------ |\n| `--container` | Container mode | Simple deployment, isolated env | macOS, Linux |\n| `--native`    | All native     | Host tool access (claude, gh)   | macOS, Linux |\n\n### Options\n\n| Flag                        | Description                                     |\n| --------------------------- | ----------------------------------------------- |\n| `--lan`                     | Expose to LAN (default: localhost only)         |\n| `--tailscale \u003chost[:port]\u003e` | Enable Tailscale HTTPS                          |\n| `--no-auth`                 | Disable basic authentication                    |\n| `--port \u003cport\u003e`             | Host port (default: 7680, Windows: 7690)        |\n| `--fresh`                   | Force new password prompt (ignore saved config) |\n| `--update`                  | Auto-update with saved config                   |\n| `--version \u003cver\u003e`           | Install specific version (with or without `v`)  |\n\n| Environment Variable | Description                                      |\n| -------------------- | ------------------------------------------------ |\n| `WORKSPACE`          | Host directory to mount (default: `./workspace`) |\n| `TERMOTE_USER`       | Basic auth username (default: auto-generated)    |\n| `TERMOTE_PASS`       | Basic auth password (default: auto-generated)    |\n| `NO_AUTH`            | Set to `true` to disable authentication          |\n\n### Container Mode (recommended for simplicity)\n\nScripts auto-detect `podman` or `docker` — both work identically.\n\n```bash\n./scripts/termote.sh install container             # localhost with basic auth\n./scripts/termote.sh install container --no-auth   # localhost without auth\n./scripts/termote.sh install container --lan       # LAN accessible\n# Access: http://localhost:7680\n\n# Custom workspace directory (mounted to /workspace in container)\nWORKSPACE=~/projects ./scripts/termote.sh install container\nWORKSPACE=/path/to/code make install-container\n```\n\n\u003e **Security note**: Avoid mounting `$HOME` directly — sensitive directories like `.ssh`, `.gnupg` will be accessible in container. Mount specific project directories instead.\n\n### Native (recommended for host binary access)\n\nUse when you need access to host binaries (claude, git, etc):\n\n```bash\n# Linux\nsudo apt install ttyd tmux\n# Or: sudo snap install ttyd\n./scripts/termote.sh install native\n\n# macOS\nbrew install ttyd tmux go\n./scripts/termote.sh install native\n# Access: http://localhost:7680\n```\n\n### With Tailscale HTTPS (all modes)\n\nUses `tailscale serve` for automatic HTTPS (no manual cert management):\n\n```bash\n# Tailscale only (default port 443)\n./scripts/termote.sh install container --tailscale myhost.ts.net\n\n# Custom port\n./scripts/termote.sh install native --tailscale myhost.ts.net:8765\n\n# Tailscale + LAN accessible\n./scripts/termote.sh install container --tailscale myhost.ts.net --lan\n\n# Access: https://myhost.ts.net (or :8765 for custom port)\n```\n\n### Uninstall\n\n```bash\n./scripts/termote.sh uninstall container   # Container mode\n./scripts/termote.sh uninstall native      # Native mode\n./scripts/termote.sh uninstall all         # Everything\n```\n\n### Updating\n\n```bash\n# Option 1: Auto-update with saved config\ncurl -fsSL .../get.sh | bash -s -- --update\n\n# Option 2: Re-run one-liner (compares versions, prompts before install)\ncurl -fsSL .../get.sh | bash\n\n# Option 3: Manual update\n./scripts/termote.sh uninstall [container|native]\ngit pull origin main                    # If installed from source\n./scripts/termote.sh install [container|native] [--lan] [--tailscale ...]\n```\n\n## Platform Support\n\n| Platform | Container        | Native           | CLI Script  |\n| -------- | ---------------- | ---------------- | ----------- |\n| Linux    | ✓                | ✓                | termote.sh  |\n| macOS    | ✓                | ✓                | termote.sh  |\n| Windows  | ⚠️ (experimental) | ⚠️ (experimental) | termote.ps1 |\n\n\u003e **⚠️ Windows Support (Experimental)**: Windows support is currently in early stages and needs more testing. Container mode requires Docker Desktop, native mode requires psmux. Please report issues on GitHub.\n\n### Windows Native Mode\n\nWindows native mode uses [psmux](https://github.com/psmux/psmux) (tmux-compatible terminal multiplexer for Windows):\n\n```powershell\n# Install psmux\nwinget install psmux\n\n# Run Termote\n.\\scripts\\termote.ps1 install native\n.\\scripts\\termote.ps1 install container  # Or container mode with Docker Desktop\n```\n\n## Mobile Usage\n\n| Action           | Gesture             |\n| ---------------- | ------------------- |\n| Cancel/interrupt | Swipe left (Ctrl+C) |\n| Tab completion   | Swipe right         |\n| History up       | Swipe up            |\n| History down     | Swipe down          |\n| Paste            | Long press          |\n| Font size        | Pinch in/out        |\n\nVirtual toolbar provides: Tab, Esc, Ctrl, Shift, Arrow keys, and common key combos. Supports Ctrl+Shift combinations (paste, copy). Toggle between minimal and expanded mode for additional keys (Home, End, Delete, etc.).\n\n## Project Structure\n\n```\ntermote/\n├── Makefile                # Build/test/deploy commands\n├── Dockerfile              # Docker mode (tmux-api + ttyd)\n├── docker-compose.yml\n├── entrypoint.sh           # Docker entrypoint\n├── docs/                   # Documentation\n│   └── images/screenshots/ # App screenshots\n├── pwa/                    # React PWA\n│   └── src/\n│       ├── components/\n│       ├── contexts/\n│       ├── hooks/\n│       ├── types/\n│       └── utils/\n├── tmux-api/               # Go server\n│   ├── main.go             # Entry point\n│   ├── serve.go            # Server (PWA, proxy, auth)\n│   └── tmux.go             # tmux API handlers\n├── scripts/\n│   ├── termote.sh          # Unix CLI (install/uninstall/health)\n│   ├── termote.ps1         # Windows PowerShell CLI\n│   ├── get.sh              # Unix online installer (curl | bash)\n│   └── get.ps1             # Windows online installer (irm | iex)\n├── tests/                  # Test suite\n│   ├── test-termote.sh\n│   ├── test-termote.ps1    # Windows tests\n│   ├── test-get.sh\n│   └── test-entrypoints.sh\n└── website/                # Astro Starlight docs site\n    └── src/content/docs/   # MDX documentation\n```\n\n## Development\n\n```bash\nmake build          # Build PWA and tmux-api\nmake test           # Run all tests\nmake health         # Check service health\nmake clean          # Stop containers\n\n# E2E tests (requires running server)\n./scripts/termote.sh install container  # Start server first\ncd pwa \u0026\u0026 pnpm test:e2e       # Run Playwright tests\ncd pwa \u0026\u0026 pnpm test:e2e:ui    # Run with UI debugger\n```\n\n**Manual Testing:** See [Self-Test Checklist](docs/self-test-checklist.md)\n\n## Troubleshooting\n\n### Session not persisting\n\n- Check tmux: `tmux ls`\n- Verify ttyd uses `-A` flag (attach-or-create)\n\n### WebSocket errors\n\n- Check tmux-api logs: `docker logs termote`\n- Verify ttyd is running on port 7681\n\n### Mobile keyboard issues\n\n- Ensure viewport meta tag is present\n- Test on real device, not emulator\n\n### Native mode: processes not starting\n\n```bash\nps aux | grep ttyd         # Check if ttyd is running\nps aux | grep tmux-api     # Check if tmux-api is running\nlsof -i :7680              # Verify port is in use\n```\n\n## Security Notes\n\n- **Default: localhost only** - not exposed to LAN unless `--lan` flag used\n- **Basic auth enabled by default** - use `--no-auth` to disable for local dev\n- **Built-in brute-force protection** - rate limiting (5 attempts/min per IP)\n- Use HTTPS (Tailscale) for production\n- Restrict to trusted networks/VPN\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flamngockhuong%2Ftermote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flamngockhuong%2Ftermote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flamngockhuong%2Ftermote/lists"}