cyclecad 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/API-BUILD-MANIFEST.txt +339 -0
  2. package/API-SERVER.md +535 -0
  3. package/Architecture-Deck.pptx +0 -0
  4. package/CLAUDE.md +172 -11
  5. package/CLI-BUILD-SUMMARY.md +504 -0
  6. package/CLI-INDEX.md +356 -0
  7. package/CLI-README.md +466 -0
  8. package/COLLABORATION-INTEGRATION-GUIDE.md +325 -0
  9. package/CONNECTED_FABS_GUIDE.md +612 -0
  10. package/CONNECTED_FABS_README.md +310 -0
  11. package/DELIVERABLES.md +343 -0
  12. package/DFM-ANALYZER-INTEGRATION.md +368 -0
  13. package/DFM-QUICK-START.js +253 -0
  14. package/Dockerfile +69 -0
  15. package/IMPLEMENTATION.md +327 -0
  16. package/LICENSE +31 -0
  17. package/MARKETPLACE_QUICK_REFERENCE.txt +294 -0
  18. package/MCP-INDEX.md +264 -0
  19. package/QUICKSTART-API.md +388 -0
  20. package/QUICKSTART-CLI.md +211 -0
  21. package/QUICKSTART-MCP.md +196 -0
  22. package/README-MCP.md +208 -0
  23. package/TEST-TOKEN-ENGINE.md +319 -0
  24. package/TOKEN-ENGINE-SUMMARY.md +266 -0
  25. package/TOKENS-README.md +263 -0
  26. package/TOOLS-REFERENCE.md +254 -0
  27. package/app/index.html +168 -3
  28. package/app/js/TOKEN-INTEGRATION.md +391 -0
  29. package/app/js/agent-api.js +3 -3
  30. package/app/js/ai-copilot.js +1435 -0
  31. package/app/js/cam-pipeline.js +840 -0
  32. package/app/js/collaboration-ui.js +995 -0
  33. package/app/js/collaboration.js +1116 -0
  34. package/app/js/connected-fabs-example.js +404 -0
  35. package/app/js/connected-fabs.js +1449 -0
  36. package/app/js/dfm-analyzer.js +1760 -0
  37. package/app/js/marketplace.js +1994 -0
  38. package/app/js/material-library.js +2115 -0
  39. package/app/js/token-dashboard.js +563 -0
  40. package/app/js/token-engine.js +743 -0
  41. package/app/test-agent.html +1801 -0
  42. package/bin/cyclecad-cli.js +662 -0
  43. package/bin/cyclecad-mcp +2 -0
  44. package/bin/server.js +242 -0
  45. package/cycleCAD-Architecture.pptx +0 -0
  46. package/cycleCAD-Investor-Deck.pptx +0 -0
  47. package/demo-mcp.sh +60 -0
  48. package/docs/API-SERVER-SUMMARY.md +375 -0
  49. package/docs/API-SERVER.md +667 -0
  50. package/docs/CAM-EXAMPLES.md +344 -0
  51. package/docs/CAM-INTEGRATION.md +612 -0
  52. package/docs/CAM-QUICK-REFERENCE.md +199 -0
  53. package/docs/CLI-INTEGRATION.md +510 -0
  54. package/docs/CLI.md +872 -0
  55. package/docs/MARKETPLACE-API-SCHEMA.json +564 -0
  56. package/docs/MARKETPLACE-INTEGRATION.md +467 -0
  57. package/docs/MARKETPLACE-SETUP.html +439 -0
  58. package/docs/MCP-SERVER.md +403 -0
  59. package/examples/api-client-example.js +488 -0
  60. package/examples/api-client-example.py +359 -0
  61. package/examples/batch-manufacturing.txt +28 -0
  62. package/examples/batch-simple.txt +26 -0
  63. package/model-marketplace.html +1273 -0
  64. package/package.json +14 -3
  65. package/server/api-server.js +1120 -0
  66. package/server/mcp-server.js +1161 -0
  67. package/test-api-server.js +432 -0
  68. package/test-mcp.js +198 -0
  69. package/~$cycleCAD-Investor-Deck.pptx +0 -0
@@ -0,0 +1,667 @@
1
+ # cycleCAD REST API Server
2
+
3
+ A Node.js HTTP server that exposes the cycleCAD Agent API via REST endpoints, enabling any language or platform to drive cycleCAD through JSON-RPC style commands.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Install dependencies (zero external deps, uses Node.js built-ins)
9
+ npm install
10
+
11
+ # Start server (default: localhost:3000)
12
+ npm run server
13
+
14
+ # Start with development mode logging
15
+ npm run server:dev
16
+
17
+ # Start with API key authentication
18
+ npm run server:auth
19
+ ```
20
+
21
+ Server will output:
22
+ ```
23
+ ╔═══════════════════════════════════════════════════════════╗
24
+ ║ cycleCAD API Server v0.2.0 ║
25
+ ║ ║
26
+ ║ HTTP: http://localhost:3000 ║
27
+ ║ API: POST /api/execute ║
28
+ ║ Batch: POST /api/batch ║
29
+ ║ Schema: GET /api/schema ║
30
+ ║ Health: GET /api/health ║
31
+ ║ History: GET /api/history ║
32
+ ║ Models: GET /api/models ║
33
+ ║ WebSocket: ws://localhost:3000/api/ws ║
34
+ ╚═══════════════════════════════════════════════════════════╝
35
+ ```
36
+
37
+ ## Configuration
38
+
39
+ Environment variables:
40
+ - `PORT` — Server port (default: 3000)
41
+ - `HOST` — Server host (default: 0.0.0.0)
42
+ - `CYCLECAD_API_KEY` — Optional API key for authentication
43
+ - `STATIC_DIR` — Directory to serve static files (default: ../app)
44
+ - `ENABLE_HTTPS` — Enable HTTPS (default: false)
45
+ - `CERT_FILE` — Path to HTTPS certificate
46
+ - `KEY_FILE` — Path to HTTPS key
47
+
48
+ ## API Endpoints
49
+
50
+ ### 1. Execute Single Command
51
+ **POST /api/execute**
52
+
53
+ Execute a single Agent API command.
54
+
55
+ Request:
56
+ ```json
57
+ {
58
+ "method": "ops.extrude",
59
+ "params": {
60
+ "height": 80,
61
+ "symmetric": false,
62
+ "material": "steel"
63
+ }
64
+ }
65
+ ```
66
+
67
+ Response (success):
68
+ ```json
69
+ {
70
+ "ok": true,
71
+ "result": {
72
+ "featureId": "extrude_1711425600000",
73
+ "type": "extrude",
74
+ "height": 80,
75
+ "symmetric": false,
76
+ "material": "steel",
77
+ "volume": 8000
78
+ },
79
+ "elapsed": 12,
80
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000"
81
+ }
82
+ ```
83
+
84
+ Response (error):
85
+ ```json
86
+ {
87
+ "ok": false,
88
+ "error": "Unknown method: ops.extrudee. Did you mean: ops.extrude?",
89
+ "elapsed": 2,
90
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000"
91
+ }
92
+ ```
93
+
94
+ ### 2. Execute Batch Commands
95
+ **POST /api/batch**
96
+
97
+ Execute multiple commands sequentially. Stops on first error unless `continueOnError` is set.
98
+
99
+ Request:
100
+ ```json
101
+ {
102
+ "commands": [
103
+ { "method": "sketch.start", "params": { "plane": "XY" } },
104
+ { "method": "sketch.circle", "params": { "cx": 0, "cy": 0, "radius": 25 } },
105
+ { "method": "sketch.end", "params": {} },
106
+ { "method": "ops.extrude", "params": { "height": 50 } }
107
+ ],
108
+ "continueOnError": false
109
+ }
110
+ ```
111
+
112
+ Response:
113
+ ```json
114
+ {
115
+ "ok": true,
116
+ "results": [
117
+ { "ok": true, "result": { "sketchId": "sketch_1711425600000", ... }, "elapsed": 5 },
118
+ { "ok": true, "result": { "entityId": "circle_1711425600001", ... }, "elapsed": 3 },
119
+ { "ok": true, "result": { "status": "complete", ... }, "elapsed": 2 },
120
+ { "ok": true, "result": { "featureId": "extrude_1711425600002", ... }, "elapsed": 8 }
121
+ ],
122
+ "errors": [],
123
+ "executed": 4,
124
+ "total": 4,
125
+ "elapsed": 18,
126
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000"
127
+ }
128
+ ```
129
+
130
+ ### 3. Get API Schema
131
+ **GET /api/schema**
132
+
133
+ Retrieve the complete API schema with all available commands, parameters, and descriptions.
134
+
135
+ Response:
136
+ ```json
137
+ {
138
+ "version": "0.2.0",
139
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000",
140
+ "namespaces": {
141
+ "sketch": {
142
+ "description": "Create 2D sketches on planes",
143
+ "commands": {
144
+ "start": {
145
+ "method": "sketch.start",
146
+ "description": "Start a 2D sketch on a plane",
147
+ "params": { "plane": "string (XY|XZ|YZ)" },
148
+ "returns": { "sketchId": "string", "plane": "string", "status": "string" }
149
+ },
150
+ "circle": { ... },
151
+ "line": { ... }
152
+ }
153
+ },
154
+ "ops": { ... },
155
+ "view": { ... },
156
+ "export": { ... },
157
+ "query": { ... },
158
+ "validate": { ... },
159
+ "assembly": { ... },
160
+ "meta": { ... }
161
+ },
162
+ "totalCommands": 55
163
+ }
164
+ ```
165
+
166
+ ### 4. Health Check
167
+ **GET /api/health**
168
+
169
+ Check server status and metrics.
170
+
171
+ Response:
172
+ ```json
173
+ {
174
+ "status": "ok",
175
+ "version": "0.2.0",
176
+ "uptime": 3600,
177
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000",
178
+ "commands": 55,
179
+ "commandsExecuted": 127,
180
+ "features": 3,
181
+ "models": 5,
182
+ "wsClients": 2,
183
+ "timestamp": "2024-03-26T15:30:00Z"
184
+ }
185
+ ```
186
+
187
+ ### 5. Get Command History
188
+ **GET /api/history?count=20**
189
+
190
+ Retrieve recent command execution history.
191
+
192
+ Query params:
193
+ - `count` — Number of recent commands to return (default: 20, max: 1000)
194
+
195
+ Response:
196
+ ```json
197
+ {
198
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000",
199
+ "total": 127,
200
+ "recent": [
201
+ {
202
+ "id": "cmd_123",
203
+ "method": "ops.extrude",
204
+ "params": { "height": 50, "material": "steel" },
205
+ "elapsed": 8,
206
+ "ok": true,
207
+ "timestamp": "2024-03-26T15:30:00Z",
208
+ "result": ["featureId", "type", "height"]
209
+ },
210
+ { ... }
211
+ ],
212
+ "timestamp": "2024-03-26T15:30:15Z"
213
+ }
214
+ ```
215
+
216
+ ### 6. List Models
217
+ **GET /api/models**
218
+
219
+ List all models/components in the scene.
220
+
221
+ Response:
222
+ ```json
223
+ {
224
+ "ok": true,
225
+ "models": [
226
+ { "id": "comp_1711425600000", "name": "Bracket", "position": [0, 0, 0] },
227
+ { "id": "comp_1711425600001", "name": "Shaft", "position": [50, 0, 0] }
228
+ ],
229
+ "count": 2
230
+ }
231
+ ```
232
+
233
+ ### 7. Get Model Details
234
+ **GET /api/models/:id**
235
+
236
+ Get details of a specific model.
237
+
238
+ Response:
239
+ ```json
240
+ {
241
+ "ok": true,
242
+ "model": {
243
+ "id": "comp_1711425600000",
244
+ "name": "Bracket",
245
+ "position": [0, 0, 0]
246
+ }
247
+ }
248
+ ```
249
+
250
+ ### 8. Delete Model
251
+ **DELETE /api/models/:id**
252
+
253
+ Remove a model from the scene.
254
+
255
+ Response:
256
+ ```json
257
+ {
258
+ "ok": true,
259
+ "message": "Model comp_1711425600000 deleted",
260
+ "remaining": 1
261
+ }
262
+ ```
263
+
264
+ ### 9. WebSocket Connection
265
+ **WebSocket /api/ws**
266
+
267
+ Establish a real-time bidirectional connection for continuous interaction.
268
+
269
+ Connection flow:
270
+ ```
271
+ Client connects → Server sends welcome message → Client sends commands → Server responds in real-time
272
+ ```
273
+
274
+ Welcome message:
275
+ ```json
276
+ {
277
+ "type": "welcome",
278
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000",
279
+ "message": "Connected to cycleCAD API Server"
280
+ }
281
+ ```
282
+
283
+ Client sends command (same format as POST /api/execute):
284
+ ```json
285
+ {
286
+ "method": "sketch.circle",
287
+ "params": { "cx": 0, "cy": 0, "radius": 25 }
288
+ }
289
+ ```
290
+
291
+ Server sends response:
292
+ ```json
293
+ {
294
+ "ok": true,
295
+ "result": { "entityId": "circle_...", ... },
296
+ "elapsed": 5,
297
+ "sessionId": "..."
298
+ }
299
+ ```
300
+
301
+ Server sends ping every 30s:
302
+ ```json
303
+ {
304
+ "type": "ping",
305
+ "timestamp": 1711425600000
306
+ }
307
+ ```
308
+
309
+ ## Command Namespaces
310
+
311
+ ### sketch — 2D Drawing
312
+ - `sketch.start` — Start sketch on a plane (XY/XZ/YZ)
313
+ - `sketch.line` — Draw line segment
314
+ - `sketch.circle` — Draw circle
315
+ - `sketch.rect` — Draw rectangle
316
+ - `sketch.arc` — Draw arc
317
+ - `sketch.end` — End sketch and extrude
318
+
319
+ ### ops — 3D Operations
320
+ - `ops.extrude` — Extrude sketch into 3D
321
+ - `ops.fillet` — Round edges
322
+ - `ops.chamfer` — Chamfer edges
323
+ - `ops.hole` — Create holes
324
+ - `ops.pattern` — Rectangular or circular pattern
325
+
326
+ ### view — Viewport Control
327
+ - `view.set` — Set view (isometric, top, front, right, bottom, back, left)
328
+ - `view.grid` — Toggle grid
329
+ - `view.wireframe` — Toggle wireframe mode
330
+
331
+ ### export — File Export
332
+ - `export.stl` — Export to STL (ASCII or binary)
333
+ - `export.obj` — Export to OBJ
334
+ - `export.gltf` — Export to glTF 2.0
335
+
336
+ ### query — Model Inspection
337
+ - `query.features` — List all features
338
+ - `query.bbox` — Get bounding box
339
+ - `query.materials` — List available materials
340
+
341
+ ### validate — Analysis & Validation
342
+ - `validate.dimensions` — Check dimensions
343
+ - `validate.cost` — Estimate manufacturing cost
344
+ - `validate.mass` — Calculate weight
345
+
346
+ ### assembly — Multi-Component Models
347
+ - `assembly.addComponent` — Add component
348
+ - `assembly.list` — List components
349
+
350
+ ### meta — Server Information
351
+ - `meta.ping` — Ping server
352
+ - `meta.version` — Get version info
353
+ - `meta.schema` — Get API schema
354
+
355
+ ## Authentication
356
+
357
+ ### Optional API Key
358
+
359
+ Enable API key authentication:
360
+ ```bash
361
+ CYCLECAD_API_KEY=your-secret-key npm run server
362
+ ```
363
+
364
+ Two ways to provide the key in requests:
365
+
366
+ 1. **Header**:
367
+ ```bash
368
+ curl -H "X-API-Key: your-secret-key" http://localhost:3000/api/health
369
+ ```
370
+
371
+ 2. **Query parameter**:
372
+ ```bash
373
+ curl http://localhost:3000/api/health?api_key=your-secret-key
374
+ ```
375
+
376
+ Without a valid key, all requests return:
377
+ ```json
378
+ {
379
+ "ok": false,
380
+ "error": "Unauthorized - invalid or missing API key"
381
+ }
382
+ ```
383
+
384
+ ## Rate Limiting
385
+
386
+ The server enforces rate limiting: **100 requests per minute per IP**.
387
+
388
+ Response headers:
389
+ ```
390
+ RateLimit-Limit: 100
391
+ RateLimit-Remaining: 95
392
+ RateLimit-Reset: 1711425660
393
+ ```
394
+
395
+ When limit is exceeded:
396
+ ```json
397
+ {
398
+ "ok": false,
399
+ "error": "Too many requests",
400
+ "retryAfter": 60
401
+ }
402
+ ```
403
+
404
+ ## CORS Headers
405
+
406
+ All responses include CORS headers for browser access:
407
+ ```
408
+ Access-Control-Allow-Origin: *
409
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE, PUT
410
+ Access-Control-Allow-Headers: Content-Type, X-API-Key, Authorization
411
+ ```
412
+
413
+ ## Static File Serving
414
+
415
+ The server serves the cycleCAD web app from `../app/`:
416
+ - `/` → `app/index.html`
417
+ - `/app/` → `app/index.html`
418
+ - `/app/mobile.html` → `app/mobile.html`
419
+ - `/app/js/*.js` → Static JS files
420
+ - `/app/css/*.css` → Static CSS files
421
+
422
+ ## Error Handling
423
+
424
+ All errors follow a consistent format:
425
+
426
+ ```json
427
+ {
428
+ "ok": false,
429
+ "error": "Human-readable error message",
430
+ "elapsed": 5,
431
+ "sessionId": "550e8400-e29b-41d4-a716-446655440000"
432
+ }
433
+ ```
434
+
435
+ Common error codes (HTTP status):
436
+ - `400 Bad Request` — Invalid JSON, missing required params
437
+ - `401 Unauthorized` — Invalid/missing API key
438
+ - `404 Not Found` — Unknown endpoint or resource
439
+ - `429 Too Many Requests` — Rate limit exceeded
440
+ - `500 Internal Server Error` — Server error
441
+
442
+ ## Examples
443
+
444
+ ### Python Client
445
+
446
+ ```python
447
+ import requests
448
+ import json
449
+
450
+ BASE_URL = 'http://localhost:3000'
451
+ API_KEY = 'your-api-key' # Optional
452
+
453
+ def execute_command(method, params=None):
454
+ headers = {'X-API-Key': API_KEY} if API_KEY else {}
455
+ response = requests.post(
456
+ f'{BASE_URL}/api/execute',
457
+ json={'method': method, 'params': params or {}},
458
+ headers=headers
459
+ )
460
+ return response.json()
461
+
462
+ def execute_batch(commands):
463
+ headers = {'X-API-Key': API_KEY} if API_KEY else {}
464
+ response = requests.post(
465
+ f'{BASE_URL}/api/batch',
466
+ json={'commands': commands},
467
+ headers=headers
468
+ )
469
+ return response.json()
470
+
471
+ # Example: Create a simple part
472
+ result = execute_command('sketch.start', {'plane': 'XY'})
473
+ print('Sketch started:', result['result']['sketchId'])
474
+
475
+ result = execute_command('sketch.circle', {
476
+ 'cx': 0, 'cy': 0, 'radius': 25
477
+ })
478
+ print('Circle created:', result['result']['entityId'])
479
+
480
+ result = execute_command('sketch.end')
481
+ result = execute_command('ops.extrude', {'height': 50, 'material': 'steel'})
482
+ print('Extrude complete:', result['result']['featureId'])
483
+ ```
484
+
485
+ ### JavaScript Client
486
+
487
+ ```javascript
488
+ const BASE_URL = 'http://localhost:3000';
489
+ const API_KEY = 'your-api-key'; // Optional
490
+
491
+ async function executeCommand(method, params = {}) {
492
+ const response = await fetch(`${BASE_URL}/api/execute`, {
493
+ method: 'POST',
494
+ headers: {
495
+ 'Content-Type': 'application/json',
496
+ ...(API_KEY && { 'X-API-Key': API_KEY })
497
+ },
498
+ body: JSON.stringify({ method, params })
499
+ });
500
+ return response.json();
501
+ }
502
+
503
+ async function executeBatch(commands) {
504
+ const response = await fetch(`${BASE_URL}/api/batch`, {
505
+ method: 'POST',
506
+ headers: {
507
+ 'Content-Type': 'application/json',
508
+ ...(API_KEY && { 'X-API-Key': API_KEY })
509
+ },
510
+ body: JSON.stringify({ commands })
511
+ });
512
+ return response.json();
513
+ }
514
+
515
+ // Example: WebSocket connection
516
+ const ws = new WebSocket('ws://localhost:3000/api/ws');
517
+
518
+ ws.onopen = () => {
519
+ console.log('Connected to cycleCAD');
520
+
521
+ // Send command
522
+ ws.send(JSON.stringify({
523
+ method: 'sketch.start',
524
+ params: { plane: 'XY' }
525
+ }));
526
+ };
527
+
528
+ ws.onmessage = (event) => {
529
+ const message = JSON.parse(event.data);
530
+ console.log('Response:', message);
531
+ };
532
+ ```
533
+
534
+ ### cURL Examples
535
+
536
+ Get schema:
537
+ ```bash
538
+ curl http://localhost:3000/api/schema | jq
539
+ ```
540
+
541
+ Check health:
542
+ ```bash
543
+ curl http://localhost:3000/api/health | jq
544
+ ```
545
+
546
+ Execute command:
547
+ ```bash
548
+ curl -X POST http://localhost:3000/api/execute \
549
+ -H 'Content-Type: application/json' \
550
+ -d '{
551
+ "method": "sketch.circle",
552
+ "params": {"cx": 0, "cy": 0, "radius": 25}
553
+ }' | jq
554
+ ```
555
+
556
+ Execute batch:
557
+ ```bash
558
+ curl -X POST http://localhost:3000/api/batch \
559
+ -H 'Content-Type: application/json' \
560
+ -d '{
561
+ "commands": [
562
+ {"method": "sketch.start", "params": {"plane": "XY"}},
563
+ {"method": "sketch.circle", "params": {"cx": 0, "cy": 0, "radius": 25}},
564
+ {"method": "sketch.end", "params": {}},
565
+ {"method": "ops.extrude", "params": {"height": 50}}
566
+ ]
567
+ }' | jq
568
+ ```
569
+
570
+ ## Development
571
+
572
+ ### Enable debug logging:
573
+ ```bash
574
+ npm run server:dev
575
+ ```
576
+
577
+ ### Test endpoints:
578
+ ```bash
579
+ # Terminal 1: Start server
580
+ npm run server:dev
581
+
582
+ # Terminal 2: Test in another terminal
583
+ curl http://localhost:3000/api/health | jq
584
+
585
+ # Test with API key
586
+ CYCLECAD_API_KEY=test123 npm run server
587
+ curl -H "X-API-Key: test123" http://localhost:3000/api/health | jq
588
+ ```
589
+
590
+ ### Monitor WebSocket connections:
591
+ ```bash
592
+ npm run server:dev
593
+ # Connect with: websocat ws://localhost:3000/api/ws
594
+ ```
595
+
596
+ ## Deployment
597
+
598
+ ### Docker
599
+
600
+ ```dockerfile
601
+ FROM node:18-alpine
602
+
603
+ WORKDIR /app
604
+ COPY . .
605
+
606
+ EXPOSE 3000
607
+ ENV PORT=3000 HOST=0.0.0.0
608
+
609
+ CMD ["npm", "run", "server"]
610
+ ```
611
+
612
+ ### Docker Compose
613
+
614
+ ```yaml
615
+ services:
616
+ api-server:
617
+ build:
618
+ context: .
619
+ dockerfile: Dockerfile
620
+ ports:
621
+ - "3000:3000"
622
+ environment:
623
+ PORT: 3000
624
+ HOST: 0.0.0.0
625
+ CYCLECAD_API_KEY: ${API_KEY}
626
+ volumes:
627
+ - ./app:/app/app:ro
628
+ ```
629
+
630
+ ## Troubleshooting
631
+
632
+ ### Port already in use
633
+ ```bash
634
+ # Find and kill process using port 3000
635
+ lsof -i :3000
636
+ kill -9 <PID>
637
+
638
+ # Or use a different port
639
+ PORT=3001 npm run server
640
+ ```
641
+
642
+ ### WebSocket connection refused
643
+ - Ensure server is running
644
+ - Check firewall rules
645
+ - Use `ws://` not `wss://` for local connections
646
+ - For HTTPS, must use `wss://` and provide valid certificates
647
+
648
+ ### Rate limit errors
649
+ - Space out requests: add delays between API calls
650
+ - Use batch endpoint for multiple operations
651
+ - Increase rate limit by modifying `RateLimiter` in code
652
+
653
+ ### Static files not serving
654
+ - Check `STATIC_DIR` path
655
+ - Verify files exist: `ls -la app/`
656
+ - Check permissions: `chmod 755 app/`
657
+
658
+ ## Performance
659
+
660
+ - **Latency**: < 10ms per command (local)
661
+ - **Throughput**: ~10,000 commands/second (batch operations)
662
+ - **Connections**: Supports unlimited concurrent WebSocket connections
663
+ - **Memory**: Base ~20MB + command history
664
+
665
+ ## License
666
+
667
+ MIT — See LICENSE file in repository root