@ai-cortex/daemon 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,64 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: Cortex
6
+ Licensed Work: Cortex Daemon 0.1.0
7
+ The Licensed Work is (c) 2026 Cortex.
8
+ Additional Use Grant: You may make use of the Licensed Work, provided that
9
+ you may not use the Licensed Work for a Service that
10
+ competes with the Licensed Work. A "Service" is a
11
+ commercial offering that provides substantially the
12
+ same functionality as the Licensed Work to third
13
+ parties as a managed service, hosted solution, or
14
+ distributed product.
15
+ Change Date: 2030-03-21
16
+ Change License: Apache License, Version 2.0
17
+
18
+ For information about alternative licensing arrangements for the Licensed Work,
19
+ please contact the Licensor.
20
+
21
+ Notice
22
+
23
+ Business Source License 1.1
24
+
25
+ Terms
26
+
27
+ The Licensor hereby grants you the right to copy, modify, create derivative
28
+ works, redistribute, and make non-production use of the Licensed Work. The
29
+ Licensor may make an Additional Use Grant, above, permitting limited production
30
+ use.
31
+
32
+ Effective on the Change Date, or the fourth anniversary of the first publicly
33
+ available distribution of a specific version of the Licensed Work under this
34
+ License, whichever comes first, the Licensor hereby grants you rights under the
35
+ terms of the Change License, and the rights granted in the paragraph above
36
+ terminate.
37
+
38
+ If your use of the Licensed Work does not comply with the requirements currently
39
+ in effect as described in this License, you must purchase a commercial license
40
+ from the Licensor, its affiliated entities, or authorized resellers, or you must
41
+ refrain from using the Licensed Work.
42
+
43
+ All copies of the original and modified Licensed Work, and derivative works of
44
+ the Licensed Work, are subject to this License. This License applies separately
45
+ for each version of the Licensed Work and the Change Date may vary for each
46
+ version of the Licensed Work released by Licensor.
47
+
48
+ You must conspicuously display this License on each original or modified copy of
49
+ the Licensed Work. If you receive the Licensed Work in original or modified form
50
+ from a third party, the terms and conditions set forth in this License apply to
51
+ your use of that work.
52
+
53
+ Any use of the Licensed Work in violation of this License will automatically
54
+ terminate your rights under this License for the current and all other versions
55
+ of the Licensed Work.
56
+
57
+ This License does not grant you any right in any trademark or logo of Licensor
58
+ or its affiliates (provided that you may use a trademark or logo of Licensor as
59
+ expressly required by this License).
60
+
61
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN
62
+ "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS
63
+ OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY,
64
+ FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # Cortex
2
+
3
+ A transparent API proxy daemon that makes LLM coding agents smarter. Set one environment variable and Cortex sits between your coding agent and the LLM provider — observing conversations, fingerprinting tasks, injecting relevant knowledge from a local brain directory, and tracking multi-agent sessions in real time.
4
+
5
+ ## How It Works
6
+
7
+ ```
8
+ Claude Code / Cursor / Aider
9
+
10
+
11
+ localhost:9090 ◄── Cortex daemon
12
+
13
+ │ 1. Detect & classify agent (main, subagent, teammate)
14
+ │ 2. Parse messages
15
+ │ 3. Prune verbose tool outputs (day-1 value)
16
+ │ 4. Fingerprint conversation (rules + semantic embedding)
17
+ │ 5. Match against brain directory (RRF fusion)
18
+ │ 6. Inject best match if confident
19
+
20
+
21
+ api.anthropic.com
22
+ ```
23
+
24
+ Cortex never modifies responses — only request bodies. SSE streaming passes through raw and unmodified.
25
+
26
+ ## Quick Start
27
+
28
+ ```bash
29
+ # Install dependencies
30
+ npm install
31
+
32
+ # Run the interactive setup wizard
33
+ npm run setup
34
+
35
+ # Start the daemon
36
+ npm run dev
37
+
38
+ # In another terminal, point your agent at Cortex
39
+ export ANTHROPIC_BASE_URL=http://localhost:9090
40
+
41
+ # Use your agent normally — Cortex works transparently
42
+ claude
43
+ ```
44
+
45
+ ## Day-1 Value
46
+
47
+ With zero configuration and an empty brain, Cortex provides **always-on pruning** of verbose tool outputs. Tool results over 500 tokens are automatically summarized (keeping the first and last 50 tokens with a summary line), reducing context bloat on every request.
48
+
49
+ ## Brain Directory
50
+
51
+ The brain is a collection of Markdown files with YAML frontmatter in `brain/entries/`. Each entry is a solution, pattern, or fix that Cortex can inject when it detects a matching situation.
52
+
53
+ ```yaml
54
+ ---
55
+ id: node-esm-import
56
+ title: "Node.js ESM import resolution"
57
+ language: javascript
58
+ error_types: [ERR_MODULE_NOT_FOUND, "Cannot find module"]
59
+ tags: [debugging, imports, node, esm]
60
+ ---
61
+
62
+ When you see ERR_MODULE_NOT_FOUND in an ESM project...
63
+ ```
64
+
65
+ Cortex ships with 13 seed entries covering common issues (ESM imports, Python venvs, CORS, merge conflicts, etc.). Add your own by dropping `.md` files into `brain/entries/`.
66
+
67
+ ### Multi-Source Brain
68
+
69
+ Brain entries can come from multiple sources beyond local files:
70
+ - **local** — Markdown+YAML files from registered directories
71
+ - **cheat.sh** — Community-driven cheat sheets (1 req/sec throttle)
72
+ - **tldr** — Simplified man pages from GitHub
73
+ - **devdocs** — DevDocs API adapter
74
+
75
+ Manage sources with `cortex brain sources`.
76
+
77
+ ## Intelligence Pipeline
78
+
79
+ 1. **Fingerprinter** — Extracts features from the conversation: programming languages, error types, file types, conversation phase, and a 384-dim semantic embedding via BGE-small (local ONNX model).
80
+
81
+ 2. **Matcher** — Two retrieval channels fused via Reciprocal Rank Fusion:
82
+ - CH1: Weighted Jaccard similarity on rule features (language, error types, tags)
83
+ - CH2: Cosine similarity on semantic embeddings
84
+
85
+ 3. **Injector** — If the top match exceeds the confidence threshold (0.9), injects the brain entry content into the last user message wrapped in `<cortex_context>` tags. Max 16K chars (~4000 tokens).
86
+
87
+ ## Agent Tracking
88
+
89
+ Cortex automatically detects and classifies agents passing through the proxy:
90
+
91
+ - **Main sessions** — Full Claude Code sessions with CLAUDE.md context and Agent tool
92
+ - **Subagents** — Specialized agents spawned by main sessions (shorter TTL)
93
+ - **Teammates** — Agents that are part of a Claude Code team
94
+
95
+ Agent classification uses heuristics (system prompt markers, tool count, model tier) and links children to parents via temporal ordering, team config, or content matching. View the live topology:
96
+
97
+ ```bash
98
+ cortex agents topology
99
+ ```
100
+
101
+ ## Claude Code Statusline
102
+
103
+ Cortex includes a statusline script for Claude Code that shows real-time pipeline status with gradient colors:
104
+
105
+ ```
106
+ ◆ Cortex ── Snagged a request ── [████████░░] 72% ── 12.4K saved ── 3 injections
107
+ ```
108
+
109
+ The statusline shows pipeline phase, context bar, tokens saved, and agent info. Enable it through `cortex setup` or configure manually in `~/.claude/settings.json`.
110
+
111
+ ## Dashboard & Management API
112
+
113
+ Cortex runs a management API on port 9091 (configurable) with a built-in HTML dashboard:
114
+
115
+ ```bash
116
+ # Open dashboard
117
+ open http://localhost:9091
118
+
119
+ # API endpoints
120
+ curl http://localhost:9091/api/status
121
+ curl http://localhost:9091/api/brain/summary
122
+ curl http://localhost:9091/api/agents
123
+ curl http://localhost:9091/api/agents/topology
124
+ curl http://localhost:9091/api/statusline
125
+ ```
126
+
127
+ SSE streams available at `/api/logs/stream` and `/api/pipeline/live`.
128
+
129
+ ## CLI
130
+
131
+ ```bash
132
+ cortex start [-d] [--port N] # Start daemon (foreground or detached)
133
+ cortex stop # Graceful shutdown
134
+ cortex status # Query running daemon or show config
135
+ cortex setup # Interactive config wizard (TUI)
136
+ cortex brain <subcommand> # list | search | stats | import | sources
137
+ cortex features <subcommand> # list | enable | disable
138
+ cortex logs [-n N] [--follow] # View or stream JSONL logs
139
+ cortex config <subcommand> # show | path | set (dotted key syntax)
140
+ cortex agents <subcommand> # list | topology | history | detail <id>
141
+ ```
142
+
143
+ ## Configuration
144
+
145
+ Cortex reads from `~/.cortex/config.yaml` with sensible defaults:
146
+
147
+ ```yaml
148
+ proxyPort: 9090
149
+ targetBaseUrl: "https://api.anthropic.com"
150
+ dashboardPort: 9091
151
+ brainDir: "./brain/entries"
152
+ dataDir: "~/.cortex"
153
+ pruneThresholdTokens: 500
154
+ injectionConfidenceThreshold: 0.9
155
+ rrfWeights:
156
+ featureOverlap: 0.5
157
+ semantic: 0.5
158
+ agentTracking:
159
+ maxActive: 1000
160
+ maxHistory: 100
161
+ subagentTtlMs: 300000 # 5 min
162
+ mainTtlMs: 3600000 # 1 hr
163
+ teammateTtlMs: 3600000 # 1 hr
164
+ ```
165
+
166
+ Environment overrides: `CORTEX_PORT`, `CORTEX_TARGET_URL`, `CORTEX_DASHBOARD_PORT`.
167
+
168
+ ## Session Logs
169
+
170
+ Every request is logged as JSONL to `~/.cortex/logs/session-{date}.jsonl` with fingerprint data, match scores, injection decisions, agent classification, and processing time.
171
+
172
+ ## Development
173
+
174
+ ```bash
175
+ npm run dev # Start with tsx
176
+ npm run build # TypeScript compile
177
+ npm test # Run vitest (41 test files)
178
+ npx tsc --noEmit # Type-check
179
+ ```
180
+
181
+ **Note:** Embedding tests require single-fork mode due to ONNX model file locks:
182
+ ```bash
183
+ npx vitest run --pool=forks --poolOptions.forks.singleFork
184
+ ```
185
+
186
+ ## Requirements
187
+
188
+ - Node.js 20+
189
+ - `better-sqlite3` requires native compilation (VS C++ build tools on Windows)
190
+ - First run downloads BGE-small ONNX model (~130MB) to `~/.cortex/models/`
191
+
192
+ ## Project Structure
193
+
194
+ ```
195
+ src/
196
+ ├── proxy/ HTTP server, body buffering, HTTPS forwarding, SSE passthrough, token cache
197
+ ├── context/ Message parser, token estimator, pruner, injector
198
+ ├── fingerprint/ Rule extraction, BGE-small embedder, composite fingerprint
199
+ ├── matcher/ Feature overlap, cosine similarity, RRF fusion
200
+ ├── brain/ SQLite store, Markdown+YAML loader, multi-source adapters
201
+ ├── agents/ Agent detection, classification, parent linking, team reader, state registry
202
+ ├── core/ CortexCore orchestrator, event emitter, feature manager, accumulator, logger
203
+ ├── cli/ Router, commands, console renderer, wizard, Claude settings bridge
204
+ ├── api/ Management REST API + SSE streams
205
+ ├── dashboard/ Static HTML dashboard
206
+ ├── tui/ Interactive config screen (panels, fields, renderer)
207
+ ├── statusline/ Pipeline phase phrases and gradient colors
208
+ └── types/ Shared type contracts (Anthropic API, Fingerprint, Brain, Agents, Events)
209
+
210
+ bin/cortex-statusline Node.js statusline script for Claude Code
211
+ brain/entries/ 13 seed brain entries (Markdown + YAML frontmatter)
212
+ tests/ Unit + integration tests (41 test files)
213
+ ```
214
+
215
+ ## License
216
+
217
+ MIT
@@ -0,0 +1,3 @@
1
+ name: "cortex-default"
2
+ version: "0.1.0"
3
+ description: "Default brain directory shipped with Cortex"
@@ -0,0 +1,100 @@
1
+ ---
2
+ id: bash-permission-denied
3
+ title: "Bash permission denied errors"
4
+ language: bash
5
+ error_types: ["Permission denied", "EACCES"]
6
+ tags: [debugging, bash, permissions, linux]
7
+ ---
8
+
9
+ ## Problem
10
+
11
+ Running a script or accessing a file fails with `Permission denied` or `EACCES`.
12
+
13
+ ## Common Causes & Fixes
14
+
15
+ ### 1. Script not executable
16
+
17
+ ```bash
18
+ ls -la script.sh
19
+ # -rw-r--r-- (no x bit)
20
+
21
+ chmod +x script.sh
22
+ ./script.sh # Now works
23
+ ```
24
+
25
+ ### 2. Missing shebang
26
+
27
+ Even with the execute bit, the script needs a shebang line:
28
+
29
+ ```bash
30
+ #!/usr/bin/env bash
31
+ echo "Hello"
32
+ ```
33
+
34
+ Without it, the OS does not know which interpreter to use. You can also run it explicitly:
35
+
36
+ ```bash
37
+ bash script.sh
38
+ ```
39
+
40
+ ### 3. Wrong ownership
41
+
42
+ ```bash
43
+ ls -la /path/to/file
44
+ # Shows owner:group
45
+
46
+ # Change ownership
47
+ sudo chown $USER:$USER /path/to/file
48
+
49
+ # Or change just for the directory
50
+ sudo chown -R $USER:$USER /path/to/directory
51
+ ```
52
+
53
+ ### 4. File in a restricted directory
54
+
55
+ Directories need the execute bit (`x`) for traversal:
56
+
57
+ ```bash
58
+ chmod +x /path/to/directory
59
+ ```
60
+
61
+ ### 5. npm global install fails with EACCES
62
+
63
+ Do not use `sudo npm install -g`. Fix the npm prefix instead:
64
+
65
+ ```bash
66
+ mkdir -p ~/.npm-global
67
+ npm config set prefix '~/.npm-global'
68
+ # Add to ~/.bashrc or ~/.zshrc:
69
+ export PATH=~/.npm-global/bin:$PATH
70
+ ```
71
+
72
+ Or use `npx` to avoid global installs entirely.
73
+
74
+ ### 6. Docker volume permission mismatch
75
+
76
+ Files created inside a container may have root ownership on the host:
77
+
78
+ ```bash
79
+ sudo chown -R $USER:$USER ./data
80
+ ```
81
+
82
+ Or run the container with your UID:
83
+
84
+ ```bash
85
+ docker run --user $(id -u):$(id -g) myimage
86
+ ```
87
+
88
+ ## `sudo` vs `chown`
89
+
90
+ - **`sudo`** runs a single command as root — use for one-off admin tasks
91
+ - **`chown`** changes file ownership permanently — use when your user should own the file
92
+ - Prefer `chown` over repeatedly using `sudo` for files in your project
93
+
94
+ ### Quick Checklist
95
+
96
+ - `ls -la` to check permissions and ownership
97
+ - `chmod +x` to add execute permission
98
+ - `chown $USER` to fix ownership
99
+ - Add shebang (`#!/usr/bin/env bash`) to scripts
100
+ - Never `sudo npm install -g` — fix npm prefix instead
@@ -0,0 +1,98 @@
1
+ ---
2
+ id: cors-preflight
3
+ title: "CORS preflight errors"
4
+ language: javascript
5
+ error_types: ["CORS", "Access-Control-Allow-Origin", "preflight", "blocked by CORS policy"]
6
+ tags: [debugging, cors, http, api, express]
7
+ ---
8
+
9
+ ## Problem
10
+
11
+ Browser blocks a request with `blocked by CORS policy`. The server does not include the correct `Access-Control-Allow-Origin` header, or the preflight OPTIONS request fails.
12
+
13
+ ## What Is CORS
14
+
15
+ Cross-Origin Resource Sharing is a browser security feature. When JavaScript on `http://localhost:3000` calls an API on `http://localhost:8080`, the browser enforces CORS because the origins differ (different port = different origin).
16
+
17
+ The browser sends a **preflight** OPTIONS request first for non-simple requests (custom headers, PUT/DELETE, JSON content-type). The server must respond with the correct CORS headers.
18
+
19
+ ## Fix: Express cors Middleware
20
+
21
+ ```bash
22
+ npm install cors
23
+ ```
24
+
25
+ ```javascript
26
+ import cors from 'cors';
27
+ import express from 'express';
28
+
29
+ const app = express();
30
+
31
+ // Allow all origins (development only)
32
+ app.use(cors());
33
+
34
+ // Or restrict to specific origins (production)
35
+ app.use(cors({
36
+ origin: ['http://localhost:3000', 'https://myapp.com'],
37
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
38
+ allowedHeaders: ['Content-Type', 'Authorization'],
39
+ credentials: true,
40
+ }));
41
+ ```
42
+
43
+ ## Fix: Manual Headers
44
+
45
+ If you cannot use the middleware:
46
+
47
+ ```javascript
48
+ app.use((req, res, next) => {
49
+ res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
50
+ res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
51
+ res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
52
+ res.header('Access-Control-Allow-Credentials', 'true');
53
+ if (req.method === 'OPTIONS') {
54
+ return res.sendStatus(204);
55
+ }
56
+ next();
57
+ });
58
+ ```
59
+
60
+ The key: you must handle the OPTIONS method and return the headers.
61
+
62
+ ## Fix: Dev Proxy (Avoids CORS Entirely)
63
+
64
+ Use your frontend dev server to proxy API requests — same origin, no CORS:
65
+
66
+ **Vite:**
67
+
68
+ ```javascript
69
+ // vite.config.js
70
+ export default {
71
+ server: {
72
+ proxy: {
73
+ '/api': 'http://localhost:8080',
74
+ },
75
+ },
76
+ };
77
+ ```
78
+
79
+ **Create React App:**
80
+
81
+ ```json
82
+ {
83
+ "proxy": "http://localhost:8080"
84
+ }
85
+ ```
86
+
87
+ ## Common Gotchas
88
+
89
+ - `credentials: true` requires a specific origin — `*` is not allowed with credentials
90
+ - The `Origin` header is set by the browser and cannot be overridden by JavaScript
91
+ - CORS errors in the console mean the server is wrong, not the client
92
+
93
+ ### Quick Checklist
94
+
95
+ - Install and configure `cors` middleware
96
+ - Handle OPTIONS preflight requests
97
+ - Use a dev proxy to avoid CORS during development
98
+ - Set specific origins (not `*`) when using credentials
@@ -0,0 +1,99 @@
1
+ ---
2
+ id: docker-port-conflict
3
+ title: "Docker and system port conflicts"
4
+ language: general
5
+ error_types: ["address already in use", "port is already allocated", "EADDRINUSE"]
6
+ tags: [debugging, docker, networking, ports]
7
+ ---
8
+
9
+ ## Problem
10
+
11
+ Starting a server or container fails with `address already in use`, `port is already allocated`, or `EADDRINUSE`. Another process is already listening on that port.
12
+
13
+ ## Find What Is Using the Port
14
+
15
+ ### Linux / macOS
16
+
17
+ ```bash
18
+ lsof -i :3000
19
+ # or
20
+ ss -tlnp | grep 3000
21
+ ```
22
+
23
+ ### Windows
24
+
25
+ ```powershell
26
+ netstat -ano | findstr :3000
27
+ ```
28
+
29
+ ### Docker specifically
30
+
31
+ ```bash
32
+ docker ps --format "table {{.Names}}\t{{.Ports}}"
33
+ ```
34
+
35
+ ## Kill the Process
36
+
37
+ ```bash
38
+ # Using the PID from lsof output
39
+ kill -9 <PID>
40
+ ```
41
+
42
+ Or stop a Docker container:
43
+
44
+ ```bash
45
+ docker stop <container-name>
46
+ ```
47
+
48
+ ## Fix Docker Port Mapping
49
+
50
+ If two containers or a container and a host process collide, change the host port mapping:
51
+
52
+ ```yaml
53
+ # docker-compose.yml
54
+ services:
55
+ web:
56
+ ports:
57
+ - "3001:3000" # Changed host port from 3000 to 3001
58
+ ```
59
+
60
+ Or on the command line:
61
+
62
+ ```bash
63
+ docker run -p 3001:3000 myimage
64
+ ```
65
+
66
+ The format is `HOST:CONTAINER` — change the left side to an available port.
67
+
68
+ ## Prevent Recurring Conflicts
69
+
70
+ 1. **Use `.env` for port config** so different developers can use different ports:
71
+
72
+ ```env
73
+ PORT=3000
74
+ ```
75
+
76
+ ```yaml
77
+ ports:
78
+ - "${PORT}:3000"
79
+ ```
80
+
81
+ 2. **Stop old containers** before starting new ones:
82
+
83
+ ```bash
84
+ docker compose down
85
+ docker compose up -d
86
+ ```
87
+
88
+ 3. **Check before starting:**
89
+
90
+ ```bash
91
+ lsof -i :3000 || echo "Port 3000 is free"
92
+ ```
93
+
94
+ ### Quick Checklist
95
+
96
+ - `lsof -i :PORT` to find the conflicting process
97
+ - `kill -9 <PID>` or `docker stop` to free the port
98
+ - Change the host port mapping if both services need to run
99
+ - `docker compose down` before `up` to avoid stale containers
@@ -0,0 +1,107 @@
1
+ ---
2
+ id: env-vars-missing
3
+ title: "Environment variables not loading"
4
+ language: general
5
+ error_types: ["undefined", "env var not set", "missing environment variable", "ENOENT .env"]
6
+ tags: [debugging, env, dotenv, configuration]
7
+ ---
8
+
9
+ ## Problem
10
+
11
+ Application reads `undefined` for environment variables that should be set. The `.env` file exists but values are not reaching the process.
12
+
13
+ ## Fix by Runtime
14
+
15
+ ### Node.js (dotenv)
16
+
17
+ ```bash
18
+ npm install dotenv
19
+ ```
20
+
21
+ ```javascript
22
+ // At the very top of your entry point
23
+ import 'dotenv/config';
24
+
25
+ console.log(process.env.DATABASE_URL);
26
+ ```
27
+
28
+ Or with Node 20.6+, use the built-in flag:
29
+
30
+ ```bash
31
+ node --env-file=.env src/index.js
32
+ ```
33
+
34
+ ### Python
35
+
36
+ ```bash
37
+ pip install python-dotenv
38
+ ```
39
+
40
+ ```python
41
+ from dotenv import load_dotenv
42
+ import os
43
+
44
+ load_dotenv() # Reads .env from current directory
45
+
46
+ db_url = os.environ["DATABASE_URL"]
47
+ # or with a default:
48
+ db_url = os.environ.get("DATABASE_URL", "sqlite:///local.db")
49
+ ```
50
+
51
+ ### Shell
52
+
53
+ Variables in `.env` are not automatically exported. Source the file:
54
+
55
+ ```bash
56
+ export $(grep -v '^#' .env | xargs)
57
+ ```
58
+
59
+ Or set inline:
60
+
61
+ ```bash
62
+ export DATABASE_URL=postgres://localhost:5432/mydb
63
+ ```
64
+
65
+ Add to `~/.bashrc` or `~/.zshrc` for persistence across sessions.
66
+
67
+ ### Docker
68
+
69
+ ```bash
70
+ docker run --env-file .env myimage
71
+ ```
72
+
73
+ ```yaml
74
+ # docker-compose.yml
75
+ services:
76
+ app:
77
+ env_file:
78
+ - .env
79
+ ```
80
+
81
+ ## `.env` File Format
82
+
83
+ ```env
84
+ # Comments start with #
85
+ DATABASE_URL=postgres://localhost:5432/mydb
86
+ API_KEY=sk-abc123
87
+ NODE_ENV=development
88
+ ```
89
+
90
+ Rules:
91
+ - No spaces around `=`
92
+ - No quotes needed (unless value contains spaces)
93
+ - One variable per line
94
+ - Lines starting with `#` are comments
95
+
96
+ ## Common Gotchas
97
+
98
+ - `.env` is not committed to git — make sure it exists locally (use `.env.example` as a template)
99
+ - `dotenv` must be imported before any code that reads `process.env`
100
+ - Docker Compose interpolates `${VAR}` in `docker-compose.yml` from the host `.env`, not the container's
101
+
102
+ ### Quick Checklist
103
+
104
+ - Verify `.env` file exists and has correct format
105
+ - Load dotenv at the top of entry point
106
+ - Use `--env-file` for Docker
107
+ - `export` for shell — variables are not exported by default