Magic Comments
Section titled “Magic Comments”Configure script behavior with special comments at the top of your file. No code changes, no config files, no environment variables. Change a comment, behavior changes instantly.
// @mode worker// @cors reflective// @timeout 5000// @log-level standard// @ai true
// Your code starts here...return { hello: 'world' };How Magic Comments Work
Section titled “How Magic Comments Work”Magic comments are parsed at script load time. They must be placed at the very top of your file, before any code.
Rules:
- Start with
//followed by a space and@ - Must be at the top of the file — before any code, imports, or expressions
- One comment per line
- Validated via the validation API
- Take precedence over default values
- Case-sensitive for comment names
Validation example:
# Validate magic comments in a scripthoody exec validate magic-comments \ --code "// @mode worker\n// @cors reflective\n// @timeout 5000\nreturn {};"const containerClient = await client.withContainer({ id: CONTAINER_ID, project_id: PROJECT_ID, server: SERVER});const result = await containerClient.exec.validate.validateMagicComments({ code: '// @mode worker\n// @cors reflective\n// @timeout 5000\nreturn {};'});console.log(result.data); // { magicComments: { ... }, returnType: { ... }, message: "Magic comments parsed successfully" }curl -s -X POST "https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/v1/exec/validate/magic-comments" \ -H "Content-Type: application/json" \ -d '{ "code": "// @mode worker\n// @cors reflective\n// @timeout 5000\nreturn {};" }'Execution & Performance
Section titled “Execution & Performance”| Comment | Values | Default | Description |
|---|---|---|---|
@mode | worker | serverless | serverless | Choose execution mode — Worker for stateful persistent VM, Serverless for isolated fresh VM per request |
@enabled | true | false | true | Enable or disable script execution — a disabled script does not run |
@timeout | ms | 90s/5m/2h | 0 | unlimited | 3600000 | Soft request timeout (default 1 hour). Bare number = ms; unit suffixes (s/m/h/d) accepted. Past the deadline an un-started response gets 504; an already-streaming response is not interrupted and in-flight VM work is not killed. 0/unlimited = no timeout |
@await-promises | true | false | true | Auto-await returned promises before sending response |
@concurrent | number | true | false | true | Max concurrent executions (applies in both worker and serverless mode, and to cron). true = unlimited, false = single serial execution, N = at most N in parallel |
@schedule | cron expression | — | Run the script on a cron schedule (e.g., 0 9 * * *). See Scheduling |
Examples:
// @mode worker // Persistent VM, shared state// @timeout 60000 // 60 second timeout// @concurrent false // Serverless: process one at a time// @timeout 0 // No timeout (use carefully!)// @timeout unlimited // Same as @timeout 0CORS Configuration
Section titled “CORS Configuration”| Comment | Values | Default | Description |
|---|---|---|---|
@cors | reflective | * | URL | none | reflective | Origin policy for the actual response. Omitting @cors keeps the server’s global reflective CORS; none strips CORS headers; reflective/*/URL set the allowed origin |
@cors-credentials | true | false | false | Allow credentials (cookies, auth headers). Never combined with @cors * |
@cors-methods | GET,POST,... | (server default) | Access-Control-Allow-Methods is preflight-only — the browser reads it from the OPTIONS response, which is answered globally, so the per-script value is not applied (server default is used) |
@cors-headers | Authorization,... | (server default) | Access-Control-Allow-Headers is preflight-only (server-answered, not applied per-script); the per-script value drives Access-Control-Expose-Headers on the actual response |
@cors-max-age | number (seconds) | (server default) | Preflight cache hint. Not applied per-script — the OPTIONS preflight is answered globally by the server |
Examples:
// @cors reflective // Mirror request origin (development)// @cors * // Allow any origin (testing)// @cors https://app.example.com // Specific origin (production)// @cors none // No CORS headers// @cors-credentials true // Allow cookies// @cors-methods GET,POST // Only allow GET and POSTLogging & Debug
Section titled “Logging & Debug”| Comment | Values | Default | Description |
|---|---|---|---|
@log-level | none | minimal | standard | full | debug | standard | Logging verbosity |
@debug | true | false | false | Shortcut for @log-level debug |
@log-request-body | full | redacted | off | true | false | full | Log incoming request bodies |
@log-response-body | full | redacted | off | true | false | full | Log response bodies |
@log-max-body-size | bytes | 512kb/1mb | 1048576 | Max body size to log. Bare number = bytes; unit suffixes (kb/mb/gb) accepted |
@log-exclude-headers | header names | authorization cookie x-token | Headers to exclude from logs (e.g., authorization cookie) |
@log-retention-days | 0–3650 | 14 | Days to keep log files (values above the 3650-day cap are clamped) |
@debug-instrument | true | false | false | Enable code instrumentation for detailed tracing |
Examples:
// @log-level full // Maximum logging// @log-request-body true // Log request payloads// @log-response-body true // Log response payloads// @log-exclude-headers authorization cookie // Hide sensitive headers// @log-retention-days 30 // Keep logs for 30 days// @debug-instrument true // Detailed code tracingLog levels explained:
none— No loggingminimal— Request line and final status/duration only (skips the detailed request/response logs)standard— Request metadata and headers (default)full— Standard plus request/response bodies (body capture still gated by@log-request-body/@log-response-body)debug— Full plus internal execution details (VM creation, module loading, etc.)
AI Integration
Section titled “AI Integration”| Comment | Values | Default | Description |
|---|---|---|---|
@ai | true | false | true | Enable AI helpers — injects model, openai, ai, generateText, streamText, generateObject |
@ai-model | model name | google/gemini-2.5-flash-lite | AI model to use — overrides the server default (e.g., anthropic/claude-sonnet-4.5) |
@ai-temperature | 0 - 2 | — | AI temperature parameter (provider default when unset) |
@ai-max-tokens | number | — | Max tokens for AI response (provider default when unset) |
@ai-key | string | server-configured | AI API key override (default uses the server’s --ai-key flag) |
Example:
// @mode serverless// @ai true// @ai-model anthropic/claude-sonnet-4.5// @ai-temperature 0.3
const { text } = await generateText({ model, prompt: `Summarize this: ${req.body.content}`});
return { summary: text };Authentication
Section titled “Authentication”| Comment | Values | Default | Description |
|---|---|---|---|
@token | string | — | Per-endpoint shared secret. Requests must provide the token via one of four methods |
Add @token to protect any endpoint — no middleware, no auth library, no config:
// @token my-secret-key-123// @cors reflective
return { data: 'only authenticated requests see this' };Clients authenticate using any of these methods (checked in priority order):
| Priority | Method | Example |
|---|---|---|
| 1a | Authorization: Bearer <token> | curl -H "Authorization: Bearer my-secret-key-123" ... |
| 1b | Authorization: Basic (password field) | curl -u user:my-secret-key-123 ... or curl -u :my-secret-key-123 ... |
| 2 | X-Token header | curl -H "X-Token: my-secret-key-123" ... |
| 3 | ?token= query parameter | curl "https://...?token=my-secret-key-123" |
Security details:
- Constant-time comparison (SHA-256 +
timingSafeEqual) — immune to timing attacks - Token is redacted in all API responses, logs, and access logs (
[REDACTED]) ?token=is stripped fromreq.urlandmetadata.parametersbefore your script runs- CORS preflight (
OPTIONS) returns204without requiring auth (spec-correct behavior) - WebSocket
upgraderequests are also gated — pass the token via header or?token= - Empty or whitespace-only values are ignored (endpoint stays public)
See Authentication for the complete guide with examples.
Advanced Features
Section titled “Advanced Features”| Comment | Values | Default | Description |
|---|---|---|---|
@websocket | (flag) | — | Requires worker mode — Enable WebSocket support |
@rawBody | (flag) | — | Skip the request-body auto-parser — req stays a raw Node Readable stream (for large uploads, streaming, or passthrough). Accepts @rawBody, @rawBody true, or @rawBody false |
@label | string | — | Script classification label for filtering and organization |
@return-type | TypeScript type | — | TypeScript type definition for the script’s return value |
@return-type-mode | strict | warn | dev | strict | Enforcement mode for @return-type validation. strict rejects on mismatch, warn logs only, dev enforces only outside production |
@description | text | — | API documentation description |
@tags | Tag1, Tag2 | — | Categorization tags for API documentation |
Examples:
// @mode worker// @websocket // Enable WebSocket handlers// @label user-api // Classify this script// @return-type { id: string, name: string, email: string }// @return-type-mode strict // Enforce return-type at runtime// @description User profile API// @tags Users, ProfileMagic Comments API
Section titled “Magic Comments API”Manage magic comments programmatically via API endpoints:
| Endpoint | Description |
|---|---|
GET /api/v1/exec/magic-comments/schema | Get the canonical schema of all supported magic comments |
GET /api/v1/exec/magic-comments/read | Read magic comments from a script |
PUT /api/v1/exec/magic-comments/update | Update magic comments on a script |
POST /api/v1/exec/magic-comments/bulk-update | Bulk update magic comments across multiple scripts |
# Read magic comments from a specific scripthoody exec magic-comments read --path "api/hello.ts"// Get the full magic comments schemaconst schema = await containerClient.exec.magic.getSchema();console.log(schema.data);
// Read magic comments from a specific scriptconst comments = await containerClient.exec.magic.read('api/hello.ts');console.log(comments.data); // { path: "api/hello.ts", comments: { mode: "serverless", cors: "reflective", ... } }# Get the full magic comments schemacurl "https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/v1/exec/magic-comments/schema"
# Read magic comments from a specific scriptcurl "https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/v1/exec/magic-comments/read?path=api/hello.ts"Quick Reference
Section titled “Quick Reference”All magic comments at a glance:
| Category | Comments |
|---|---|
| Execution | @mode, @enabled, @timeout, @await-promises, @concurrent, @schedule |
| Authentication | @token |
| CORS | @cors, @cors-credentials, @cors-methods, @cors-headers, @cors-max-age |
| Logging | @log-level, @debug, @log-request-body, @log-response-body, @log-max-body-size, @log-exclude-headers, @log-retention-days, @debug-instrument |
| AI | @ai, @ai-model, @ai-temperature, @ai-max-tokens, @ai-key |
| Advanced | @websocket, @rawBody, @label, @return-type, @return-type-mode, @description, @tags |
What’s Next
Section titled “What’s Next” Authentication Protect endpoints with @token — all credential methods, WebSocket auth, security details
AI-Powered Scripts Deep dive into AI integration with @ai comments
Execution Modes Understand how @mode affects everything
Writing Scripts Script format and available variables
Validation API Validate magic comments programmatically