# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Repository layout (high level) - `mengyaconnect-backend/` — Go (Gin) HTTP + WebSocket server that: - exposes a WebSocket SSH “bridge” (`/api/ws/ssh`) backed by `golang.org/x/crypto/ssh` - persists SSH profiles / quick commands / scripts to the local filesystem under `data/` - `mengyaconnect-frontend/` — Vite + Vue 3 single-page UI using `xterm.js` to render terminals and talk to the backend WebSocket. There is no top-level build system; run commands inside each subproject directory. ## Common development commands ### Backend (Go) Run the server (default `:8080`): ```sh cd mengyaconnect-backend go run . ``` Build a local binary: ```sh cd mengyaconnect-backend go build -o mengyaconnect-backend ``` Basic checks (no dedicated lint/test tooling is configured beyond standard Go tools): ```sh cd mengyaconnect-backend go fmt ./... go test ./... # run a single Go test (if/when tests exist) go test -run TestName ./... ``` ### Frontend (Vite + Vue) Install deps (repo includes `package-lock.json`): ```sh cd mengyaconnect-frontend npm install ``` Run dev server (default `http://localhost:5173`): ```sh cd mengyaconnect-frontend npm run dev ``` Build + preview: ```sh cd mengyaconnect-frontend npm run build npm run preview ``` ## Backend architecture (mengyaconnect-backend) **Single-file server:** Almost all backend logic lives in `mengyaconnect-backend/main.go`. ### HTTP routes Defined in `main.go` near the top: - `GET /health` — basic health check. - `GET /api/ws/ssh` — WebSocket endpoint for interactive SSH. - SSH profile CRUD: - `GET /api/ssh` - `POST /api/ssh` - `PUT /api/ssh/:name` - `DELETE /api/ssh/:name` - Quick command CRUD (stored as an array; updates by index): - `GET /api/commands` - `POST /api/commands` - `PUT /api/commands/:index` - `DELETE /api/commands/:index` - Script CRUD (stored as files): - `GET /api/scripts` - `GET /api/scripts/:name` - `POST /api/scripts` - `PUT /api/scripts/:name` - `DELETE /api/scripts/:name` Response convention is typically `{ "data": ... }` on success and `{ "error": "..." }` on failure. ### Persistence model (filesystem) All persisted state is stored under a base directory: - base: `DATA_DIR` env var, default `data/` - SSH profiles: `data/ssh/*.json` - commands list: `data/command/command.json` - scripts: `data/script/` `sanitizeName()` is used for path-safety (prevents `../` traversal by forcing `filepath.Base`). Note: the repo currently contains example data files under `mengyaconnect-backend/data/` (including SSH profiles). Treat these as sensitive and rotate/remove before sharing the repository. ### WebSocket SSH bridge The backend upgrades `/api/ws/ssh` and uses a simple JSON message protocol (`wsMessage` in `main.go`). Client → server message types: - `connect`: `{ host, port, username, password? | privateKey? , passphrase?, cols, rows }` - `input`: `{ data }` (raw terminal input) - `resize`: `{ cols, rows }` - `ping` - `close` Server → client message types: - `status`: `{ status, message }` (e.g. connected/ready/closing/closed) - `output`: `{ data }` (stdout/stderr bytes as text) - `error`: `{ message }` - `pong` SSH implementation notes: - PTY is requested as `xterm-256color`. - Host key verification is currently disabled via `ssh.InsecureIgnoreHostKey()`. ### Backend configuration (env) - `PORT` (default `8080`) or `ADDR` (default `:`) - `DATA_DIR` (default `data`) - `GIN_MODE` (if set, passed to `gin.SetMode`) - `ALLOWED_ORIGINS` (comma-separated) is used by the WebSocket upgrader `CheckOrigin`. ## Frontend architecture (mengyaconnect-frontend) **Single-screen UI:** Most logic is in `mengyaconnect-frontend/src/App.vue`. - Uses `@xterm/xterm` + `@xterm/addon-fit`. - Supports multiple concurrent sessions via tabs (each tab owns its own `WebSocket` + `Terminal`). - Terminal input is forwarded to the backend as `{ type: "input", data }`. - Resize events are forwarded as `{ type: "resize", cols, rows }`. ### Frontend configuration (Vite env) `wsUrl` is computed in `App.vue`: - If `VITE_WS_URL` is set, it is used as the full WebSocket URL. - Otherwise it builds `${ws|wss}://${window.location.hostname}:${VITE_WS_PORT||8080}/api/ws/ssh`. In development, you’ll usually run: - backend on `localhost:8080` - frontend on `localhost:5173`