Monorepo for Aesthetic.Computer
aesthetic.computer
1# help.aesthetic.computer — AI Agent Service Plan
2
3## Overview
4
5A Claude-powered AI assistant service for the Aesthetic Computer community.
6Users with AC handles can bring their own Anthropic API key and get AI help
7with pieces, KidLisp, creative computing, and more.
8
9**Domain:** `help.aesthetic.computer`
10**IP:** `146.190.150.173`
11**Droplet:** `help-aesthetic-computer` (ID: 552385566)
12**Specs:** 2 vCPU, 4GB RAM, Ubuntu 24.04, SFO3 (~$24/mo)
13**Status:** Live — landing page + Auth0 sign-in deployed
14
15---
16
17## Architecture
18
19### No Container Isolation Needed
20
21Unlike NanoClaw (which runs Claude Code CLI with Bash/file access in containers),
22this service uses the Claude API with **server-controlled tools**. Users can't
23escape the defined tool set — no sandbox needed.
24
25### Stack
26
27- **Node.js 22 + Express** (same pattern as silo, oven)
28- **Caddy** (HTTPS reverse proxy, auto-certs)
29- **MongoDB** (via silo — user keys, conversation history, tool permissions)
30- **Systemd** (service management)
31- **Claude API** (`@anthropic-ai/sdk` npm package)
32
33### Auth Flow
34
351. User visits `help.aesthetic.computer`
362. Auth0 login (same as rest of AC)
373. User must have an `@handle` (registered AC user)
384. User provides their Anthropic API key in settings
395. Key stored encrypted in MongoDB
406. All Claude API calls use the user's own key
41
42### Landing Page
43
44The landing page explains:
45- What help.aesthetic.computer does
46- How to get an AC handle (if you don't have one)
47- How to get an Anthropic API key
48- How to connect your key
49- What tools/capabilities are available
50
51---
52
53## Tool Allow/Deny Lists (RBAC)
54
55Tools are defined server-side and passed to the Claude API per-request
56based on user role. Users never see tools they don't have access to.
57
58### @jeffrey (admin)
59
60```
61allow: [
62 create-piece, # Create new .mjs or .lisp pieces
63 edit-piece, # Modify existing pieces
64 search-codebase, # Search AC source code
65 explain-piece, # Explain how a piece works
66 run-kidlisp, # Execute KidLisp code
67 system-status, # Check oven/silo/session health
68 manage-users, # View/manage user permissions
69 deploy, # Trigger deployments
70 raw-chat, # Unconstrained Claude conversation
71 search-docs, # Search AC documentation
72]
73deny: []
74```
75
76### Registered User (@handle)
77
78```
79allow: [
80 create-kidlisp, # Create KidLisp pieces in own namespace
81 fork-piece, # Fork existing pieces
82 search-docs, # Search AC documentation
83 explain-piece, # Explain how a piece works
84 raw-chat, # Claude conversation (with AC context)
85 my-pieces, # List/manage own published pieces
86]
87deny: [
88 deploy,
89 system-status,
90 manage-users,
91 edit-piece (others'),
92 search-codebase,
93]
94```
95
96### Anonymous (no handle, no key)
97
98```
99allow: [
100 search-docs, # Read-only doc search
101 explain-piece, # Explain public pieces
102]
103deny: [everything else]
104```
105
106### Storage
107
108Tool permissions stored in MongoDB `help-permissions` collection.
109Editable from silo dashboard. Start with hardcoded defaults,
110make configurable later.
111
112---
113
114## API Endpoints
115
116### Public
117
118| Endpoint | Method | Purpose |
119|----------|--------|---------|
120| `/` | GET | Landing page (HTML) |
121| `/health` | GET | Health check |
122| `/auth/config` | GET | Auth0 config for frontend |
123
124### Authenticated
125
126| Endpoint | Method | Purpose |
127|----------|--------|---------|
128| `/auth/me` | GET | Current user info + role |
129| `/api/settings` | GET/PUT | API key management |
130| `/api/chat` | POST | Send message to Claude (SSE streaming) |
131| `/api/conversations` | GET | List conversation history |
132| `/api/conversations/:id` | GET/DELETE | Get/delete conversation |
133| `/ws` | WebSocket | Real-time streaming (alternative to SSE) |
134
135### Admin Only (@jeffrey)
136
137| Endpoint | Method | Purpose |
138|----------|--------|---------|
139| `/api/admin/users` | GET | List users + their roles |
140| `/api/admin/permissions` | GET/PUT | Edit tool permissions |
141| `/api/admin/stats` | GET | Usage stats |
142
143---
144
145## Claude API Integration
146
147### Per-Request Flow
148
149```javascript
150import Anthropic from '@anthropic-ai/sdk';
151
152async function handleChat(user, message, conversationHistory) {
153 // Get user's API key from MongoDB (decrypted)
154 const apiKey = await getUserApiKey(user.sub);
155
156 // Get user's allowed tools based on role
157 const tools = getToolsForRole(user.role);
158
159 // Create client with user's key
160 const client = new Anthropic({ apiKey });
161
162 // System prompt with AC context
163 const systemPrompt = buildSystemPrompt(user);
164
165 // Stream response
166 const stream = client.messages.stream({
167 model: 'claude-sonnet-4-5-20250929',
168 max_tokens: 4096,
169 system: systemPrompt,
170 messages: [...conversationHistory, { role: 'user', content: message }],
171 tools,
172 });
173
174 return stream;
175}
176```
177
178### System Prompt
179
180The system prompt includes:
181- AC documentation context (from CLAUDE.md, piece API docs)
182- KidLisp reference (118 built-in functions)
183- User's role and permissions
184- Conversation instructions (be helpful, AC-aware)
185
186### Tool Definitions
187
188Each tool is a Claude API tool definition + a server-side handler:
189
190```javascript
191const TOOLS = {
192 'search-docs': {
193 definition: {
194 name: 'search_docs',
195 description: 'Search AC documentation and piece source code',
196 input_schema: {
197 type: 'object',
198 properties: {
199 query: { type: 'string', description: 'Search query' }
200 },
201 required: ['query']
202 }
203 },
204 handler: async (input) => {
205 // Server-side: search docs, return results
206 // User can't escape this — it's just a search
207 }
208 },
209 // ... more tools
210};
211```
212
213---
214
215## Deployment
216
217### Provisioning Script
218
219Create `help/deploy.fish` following the judge/oven pattern:
220
2211. SSH into droplet (need to add SSH key first)
2222. Wipe judge files: `rm -rf /opt/judge`, stop ollama
2233. Install/update Node.js 22
2244. Create `/opt/help` directory
2255. Upload `server.mjs`, `dashboard.html`, `package.json`, `.env`
2266. Install npm dependencies
2277. Configure Caddy for `help.aesthetic.computer`
2288. Create systemd service `help`
2299. Start services
230
231### SSH Key
232
233The judge SSH key was generated on a different machine. Need to either:
234- Add the vault's `id_rsa.pub` to the droplet via DO API (console access)
235- Or destroy and recreate the droplet (fresh start, same IP not guaranteed)
236- Or use DO console to add a new key
237
238### Environment Variables
239
240```bash
241# MongoDB (via silo)
242MONGODB_CONNECTION_STRING=mongodb://aesthetic_app:...@silo.aesthetic.computer:27017/...
243MONGODB_NAME=aesthetic
244
245# Auth0
246AUTH0_DOMAIN=aesthetic.us.auth0.com
247AUTH0_CLIENT_ID=...
248AUTH0_CUSTOM_DOMAIN=hi.aesthetic.computer
249ADMIN_SUB=auth0|63effeeb2a7d55f8098d62f9
250
251# Encryption key for stored API keys
252ENCRYPTION_KEY=<generate new key>
253
254# Optional: fallback community API key
255ANTHROPIC_API_KEY=<for anonymous/shared use>
256```
257
258---
259
260## File Structure
261
262```
263help/
264├── server.mjs # Express API server
265├── dashboard.html # Landing page + chat UI
266├── tools/ # Tool definitions + handlers
267│ ├── search-docs.mjs
268│ ├── explain-piece.mjs
269│ ├── create-kidlisp.mjs
270│ ├── fork-piece.mjs
271│ └── system-status.mjs
272├── deploy.fish # Deployment script
273├── redeploy.fish # Quick update script
274├── package.json
275└── README.md
276```
277
278Vault:
279```
280aesthetic-computer-vault/help/
281├── deploy.env # DO + Cloudflare credentials
282└── .env # MongoDB, Auth0, encryption keys
283```
284
285---
286
287## Relationship to NanoClaw
288
289The `/nanoclaw` submodule remains as **reference code** for:
290- Claude Agent SDK patterns (session management, tool execution)
291- How to build async message streams
292- IPC patterns between host and agent
293- Memory/context management via CLAUDE.md files
294
295We don't run NanoClaw — we build our own simpler service.
296
297---
298
299## Infrastructure Summary
300
301| Service | Domain | IP | Purpose |
302|---------|--------|----|---------|
303| oven | oven.aesthetic.computer | 137.184.237.166 | Screenshot/video |
304| silo | silo.aesthetic.computer | 64.23.151.169 | DB dashboard |
305| session | session-server | 157.245.134.225 | Real-time multiplayer |
306| **help** | **help.aesthetic.computer** | **146.190.150.173** | **AI agent** |
307| system | aesthetic.computer | Netlify | Main site |
308
309---
310
311## Phase Plan
312
313### Phase 1: Foundation (DONE)
314- [x] Recreated droplet with SSH key (destroyed old judge, new ID 552385566)
315- [x] Installed Node.js 22 + Caddy 2.10
316- [x] Built minimal Express server with Caddy reverse proxy
317- [x] Auth0 integration (same client as silo)
318- [x] Landing page with sign-in + API key input
319
320### Phase 2: Core Chat
321- [ ] API key storage (encrypted in MongoDB)
322- [ ] Claude API integration with streaming
323- [ ] Basic chat UI
324- [ ] Conversation history
325
326### Phase 3: Tools
327- [ ] search-docs tool
328- [ ] explain-piece tool
329- [ ] create-kidlisp tool
330- [ ] Role-based tool filtering
331
332### Phase 4: Community
333- [ ] Public launch
334- [ ] Usage analytics
335- [ ] Rate limiting
336- [ ] Admin dashboard in silo