# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview WebSSH is a web-based SSH client. A Tornado async server handles HTTP/WebSocket connections and tunnels terminal I/O to remote SSH servers via Paramiko. The browser renders the terminal using xterm.js. ## Development Commands ```bash # Install pip install -r requirements.txt pip install -e . # editable install (provides `wssh` CLI entry point) # Run python run.py # starts on default port 8888 python run.py --port=8888 --debug=True --data-dir=./data # Lint ruff check . # or: flake8 . (max-line-length=79, see setup.cfg) # Test pytest # all tests pytest --cov=webssh # with coverage pytest tests/test_app.py # single file ``` ## Architecture ``` Browser (xterm.js + WebSocket) <--> Tornado (WsockHandler) <--> Paramiko SSH channel <--> Remote SSH server ``` **Backend (`webssh/`)** - `main.py` — entry point; wires routes, parses CLI options, starts Tornado IOLoop. - `handler.py` — all Tornado request handlers. `MixinHandler` is the base mixin providing IP filtering, XSRF, origin checks, and session auth. Key handlers: `IndexHandler` (serves UI on GET, initiates SSH on POST), `WsockHandler` (WebSocket relay), `LoginHandler`/`LogoutHandler`, `ConnectionsHandler`/`ConnectionHandler`. - `worker.py` — `Worker` class manages the Paramiko SSH channel lifecycle and registers its socket fd on Tornado's IOLoop for async read/write. - `settings.py` — CLI option definitions (Tornado `define()`), host key loading, SSL context setup, font defaults. - `auth.py` — admin user setup and password verification using PBKDF2-SHA256. - `storage.py` — persistent saved-connections store (`connections.json`) with file locking. - `policy.py` — thread-safe `AutoAddPolicy` wrapper for Paramiko host key validation. - `utils.py` — input parsing/validation helpers (`to_str`, `to_bytes`, `to_int`, `to_ip_address`, hostname/port validators). **Frontend (`webssh/static/js/main.js`, `webssh/templates/`)** - jQuery 3 + Bootstrap 4 UI, xterm.js terminal, WebSocket bridge. - `index.html` — terminal page; `login.html` — auth page. **Data directory** (`~/.webssh` or `--data-dir`): stores `auth.json`, `connections.json`, cookie secret. ## Key Design Constraints - **Async safety**: Paramiko SSH connections are blocking. Always run them via `IndexHandler.executor` (ThreadPoolExecutor) to avoid blocking the Tornado IOLoop. - **Thread safety**: File writes to `auth.json`/`connections.json` and Paramiko host-key mutations must use `threading.Lock`. - **New endpoints**: Subclass `MixinHandler`. Use `@tornado.web.authenticated` for protected routes. - **Python 3.10+** required (see setup.py classifiers). - **File permissions**: Database files (`auth.json`, `connections.json`) are created with mode `0o600`. ## Testing Tests use pytest. `tests/sshserver.py` spins up a local mock SSH server (Paramiko-based) for integration testing of handler connections, password auth, key auth, and 2FA.