Monorepo for Aesthetic.Computer aesthetic.computer
README.md

Personal Aesel relay #

help.aesthetic.computer/api/aesel runs the same ClaudeServer and AppServer adapters as Aesel. The verified ADMIN_SUB alone can connect, using their AC access token. Provider credentials stay on the server. Existing help routes continue on port 3004; Caddy routes /api/aesel/* to loopback port 3006.

From the terminal, with ac login already complete:

aes --backend relay --model claude-sonnet-4-6
# Once Codex is authenticated on the VPS:
AESEL_RELAY_PROVIDER=codex aes --backend relay --model gpt-6-astra

Work runs in a separate directory on the VPS, not the client's local checkout. Tool approvals return to the terminal. Closing the client detaches without cancelling the turn. --resume <relay-session-uuid> reconnects; the relay replays its saved events and only unresolved approvals. No filesystem synchronization or phone integration is implicit in this backend.

Protocol #

Every private request needs Authorization: Bearer <AC access token>.

  • POST /api/aesel/sessions: {provider:"claude"|"codex", model?, effort?, instructions?}.
  • POST /api/aesel/sessions/:id/turn: {requestId:<UUID>, text, images?:[{mimeType,data:<base64>}]}.
  • GET /api/aesel/sessions/:id?after=<sequence>: events (up to 500), pending approvals, request statuses.
  • POST /api/aesel/sessions/:id/respond: {id, result} matching an outstanding engine request.
  • POST /api/aesel/sessions/:id/interrupt: {}.

Submit each attempt with a stable request UUID. Retries with the same UUID return its status without executing again. The full input, including image bytes, is written before acknowledgement. Events are appended as they arrive; a service restart marks unfinished attempts interrupted and preserves input. A new request UUID is an explicit retry. State lives under /var/lib/aesel-relay/sessions, private to the service account. Nothing deletes saved drawings automatically. This does not save an unsent phone draft.

Host setup #

Use a dedicated aesel system account with home /var/lib/aesel-relay. Install provider CLIs under /opt/aesel-relay/runtime (verified versions: Claude Code 2.1.289 and Codex 0.160.0). The relay unit runs as that account, with a read-only system and private temporary directory.

Root-owned /etc/aesel-relay.env (0600) supplies ADMIN_SUB, AUTH0_DOMAIN and CLAUDE_CODE_OAUTH_TOKEN. claude setup-token supplies Claude's credential; do not put it in source, a client bundle, logs or chat. The existing help subscription token can be reused. API-key environment variables are removed before starting adapters, preventing implicit API billing fallback.

Codex uses its own login in the service account's home:

sudo -u aesel HOME=/var/lib/aesel-relay \
  /opt/aesel-relay/runtime/node_modules/.bin/codex login --device-auth

After login, set CODEX_ENABLED=1 in the private environment file and restart the relay. Do not copy credentials from a live prompt's process. Subscription limits still apply. Claude's costUSD with costBasis:"list" is a list-price usage estimate, not proof of an extra charge to the subscription.

help/relay/deploy.sh installs the source and systemd unit. Set HELP_SSH_KEY when deploying from an isolated checkout. Caddy configuration:

handle /api/aesel/* {
    reverse_proxy 127.0.0.1:3006
}
handle {
    reverse_proxy localhost:3004
}

Validate with node --test help/relay/service.test.mjs and the existing Aesel provider adapter tests. Production checks must include unauthorized rejection and a real authenticated model turn. Whistlegraph still uses the messages API; it needs a client adapter for this session protocol before switching traffic.