# macOS Docker Client Design

## Goal

Add a simple macOS-friendly Docker client that behaves like the previous local proxy product: the user runs one container, opens a web UI, loads a subscription, chooses a server, and points macOS apps at `127.0.0.1:8080`.

## Product Shape

The client is not a transparent gateway. It must not require router changes, host networking, `NET_ADMIN`, iptables, ipset, or TProxy. The first-screen UI should explain the current proxy state, active server, and exact local proxy addresses. Gateway-only controls remain available only when the app runs in gateway mode.

## Runtime Architecture

`APP_MODE=client` switches the config generator to proxy-only sing-box config:

- one `mixed` inbound on `PROXY_PORT`;
- no `tproxy` inbound;
- custom routing rules still apply before fallback;
- `proxyDefaultMode` controls the mixed proxy fallback and defaults to VPN;
- generated configs still pass `sing-box check` before restart.

The client Docker image builds the React frontend inside Docker so macOS installation does not require local Node.js. Docker publishes only loopback ports:

- `127.0.0.1:3456` for the UI;
- `127.0.0.1:8080` for HTTP/SOCKS proxy.

## Installer

The macOS installer is a curl-friendly shell script. It checks macOS, Docker, Docker Compose, and Git, clones or updates the repository under `~/.vpn-proxy-client`, then runs the client compose file with `--build`. It prints the UI URL, proxy URLs, and optional `networksetup` commands, but does not change system proxy settings automatically.

## UI

Client mode gets a user-facing overview based on the old workflow:

- status: ready, stopped, not configured, applying, error;
- active server and traffic quota;
- copyable HTTP and SOCKS5 proxy URLs;
- short macOS setup commands;
- primary actions: load subscription, choose server, restart, stop.

Gateway terminology such as TProxy, devices, router, transparent fallback, and direct bypass cache is hidden in client mode.

## Verification

Use `node:test` for server config behavior, then run:

- `npm test`;
- `npm run build`;
- `docker compose -f docker-compose.client.yml config`.
