76 lines
3.9 KiB
Markdown
76 lines
3.9 KiB
Markdown
|
|
# CLAUDE.md
|
|||
|
|
|
|||
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|||
|
|
|
|||
|
|
## Commands
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Build
|
|||
|
|
go build .
|
|||
|
|
|
|||
|
|
# Build with injected encryption key (production)
|
|||
|
|
go build -ldflags "-X gotermix/internals.fileEncKeyHex=$(openssl rand -hex 32)" .
|
|||
|
|
|
|||
|
|
# Build with env-var key
|
|||
|
|
export GOTERMINAL_ENC="your64hexchars"
|
|||
|
|
go build -ldflags "-X gotermix/internals.fileEncKeyHex=${GOTERMINAL_ENC}" .
|
|||
|
|
|
|||
|
|
# Run (dev)
|
|||
|
|
./gotermix
|
|||
|
|
./gotermix -addr 0.0.0.0:8443 -nopw
|
|||
|
|
|
|||
|
|
# Change credentials (app must restart to pick up)
|
|||
|
|
./gotermix -setlogin newuser newpassword
|
|||
|
|
|
|||
|
|
# Store custom TLS cert (validates before storing, exits after)
|
|||
|
|
./gotermix -cert /etc/ssl/my.crt -certkey /etc/ssl/my.key
|
|||
|
|
./gotermix -certreset
|
|||
|
|
|
|||
|
|
# Tests — none exist yet
|
|||
|
|
go vet ./...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Architecture
|
|||
|
|
|
|||
|
|
Entry point: `main.go` (5 lines). All logic in `internals/` package. Web assets in `internals/web/` (embedded via `//go:embed`).
|
|||
|
|
|
|||
|
|
### Session model
|
|||
|
|
`/` always creates a new PTY-backed shell session (hex ID 32 chars). `/s/<id>` reconnects to existing session. Multiple browser tabs can share one session — all see the same PTY output via broadcast. The session ID is embedded in the served HTML via `strings.NewReplacer` replacing `[[SESSION_ID]]` and `[[AUTHED]]` literals in the `shellPageHTML` const. Sessions are reaped after 24h idle (10-min ticker). Rolling 1MB replay buffer lets new tab connections catch up on history.
|
|||
|
|
|
|||
|
|
### Transport
|
|||
|
|
HTTPS only. Self-signed cert auto-generated in memory on startup unless custom cert paths are stored (encrypted) in `gws-creds.json`. TLS handshake errors from browsers rejecting self-signed certs are suppressed via `tlsHandshakeFilter`. WebSocket (`/ws/<id>`) carries raw PTY bytes as binary frames; resize events as JSON text frames.
|
|||
|
|
|
|||
|
|
### Auth flow
|
|||
|
|
1. Browser POSTs credentials to `/auth`
|
|||
|
|
2. Server checks against `storedCreds` (SHA-256 × 50,000 rounds + salt, constant-time compare)
|
|||
|
|
3. On success: sets `gws_auth` cookie (HttpOnly, Secure, SameSite=Lax, 12h) containing HMAC-SHA256 timestamp token
|
|||
|
|
4. All subsequent routes (`/ws/`, `/upload`, `/download`) call `isAuthed()` which validates the token
|
|||
|
|
5. `-nopw` flag bypasses all auth checks (`nopwMode = true`)
|
|||
|
|
|
|||
|
|
### Credential & key storage
|
|||
|
|
- `gws-creds.json` (next to binary): AES-256-GCM encrypted JSON with username, salt, hash, optional cert paths
|
|||
|
|
- Encryption key priority: (1) build-time `-ldflags "-X gotermix/internals.fileEncKeyHex=..."`, (2) `gws.key` file next to binary, (3) auto-generated and written to `gws.key`
|
|||
|
|
- Default creds if file missing or unreadable: user `ivor` / `Silv3rSw0rd!`
|
|||
|
|
|
|||
|
|
### File transfer
|
|||
|
|
- **Upload**: browser POSTs multipart to `/upload` with `sid` field. Server writes to OS temp file, then injects `mv <tmp> <dest>` directly into the PTY shell — file lands with the shell's effective user permissions.
|
|||
|
|
- **Download**: GET `/download?path=...` → `http.ServeFile` after `filepath.Clean`. Absolute paths used directly; relative paths anchored to `initialCwd` (cwd at startup).
|
|||
|
|
|
|||
|
|
### Frontend
|
|||
|
|
UI lives in `internals/web/shell.html` (~670 lines, embedded at build time). Favicon in `internals/web/favicon.svg`. Uses xterm.js + FitAddon from CDN. Keyboard handling: capture-phase listener blocks all Ctrl+key browser shortcuts; xterm's `attachCustomKeyEventHandler` handles Ctrl+Shift+C (copy), Ctrl+V (paste via Clipboard API). `[[SESSION_ID]]` and `[[AUTHED]]` placeholders replaced by `serveTerminalPage` via `strings.NewReplacer`.
|
|||
|
|
|
|||
|
|
### External dependencies
|
|||
|
|
- `github.com/creack/pty` — PTY allocation and resize (`pty.Start`, `pty.Setsize`)
|
|||
|
|
- `github.com/gorilla/websocket` — WebSocket upgrader and framing
|
|||
|
|
|
|||
|
|
### Routes
|
|||
|
|
| Path | Handler |
|
|||
|
|
|------|---------|
|
|||
|
|
| `/` | New session, serve terminal page |
|
|||
|
|
| `/s/<32-hex-id>` | Reconnect to specific session |
|
|||
|
|
| `/ws/<32-hex-id>` | WebSocket: PTY I/O + resize |
|
|||
|
|
| `/auth` | POST: credential check, set cookie |
|
|||
|
|
| `/upload` | POST multipart: inject mv into PTY |
|
|||
|
|
| `/download` | GET `?path=`: ServeFile |
|
|||
|
|
| `/favicon.svg` | Inline SVG terminal icon |
|