Zero to Productive in Minutes, Not Days
Environment setup should not be a rite of passage. Codev.md captures every runtime, service, credential path, and seed step in a structured file, turning a multi-day slog into a procedure that can be followed, verified, and repaired.
Pair the written steps with a devcontainer or an image so the description and the reality stay attached. A tool can then walk a new developer through setup, read the error output, and check the result against what the document says should have happened.
Every hour lost to a broken local environment is an hour nobody bills, demos, or remembers fondly. Write it down once and stop paying the same tax twice.
Environment Documentation Best Practices
Make a working environment reproducible by anyone, or anything, that reads the repository.
Pin Exact Versions
List every runtime, tool, and service with the precise version you support. Ranges look generous and cost hours. Specificity here prevents most first-day failures outright.
Give the Command, Not the Description
Each step should be something the reader can copy and run. Prose that describes a command is a translation task, and translation is exactly where mistakes get introduced.
Document How Secrets Are Obtained
Explain where each credential comes from, how to request access, and where it belongs locally. Never the value itself - but "ask the tech lead" is a bottleneck with a name on it, not documentation.
Write Down the Failures You Have Seen
Keep a section of real setup errors and their fixes, quoted in the exact wording the terminal produces so the text is searchable. Everyone hits the same wall. Only the first person should have to think about it.
Separate the Platforms
Give Windows, macOS, and Linux their own headings rather than parenthetical asides. Mixed instructions with footnotes are how people end up running the wrong command with complete confidence.
End Each Phase With a Check
Close every major stage with something that proves it worked: a health endpoint returning 200, a migration listed as applied, a seeded row you can query back. Silent success is how a broken setup survives to day three.
Make Data Reset One Command
Document how to seed the database, load fixtures, and return to a clean state. Data is the most fragile part of any local setup and the least likely to be written down. One reset command is worth a page of explanation.
Fix the Docs in the PR That Broke Them
Adding a service dependency and updating the setup file are one change, not two. Split them and the second one never happens, and after two or three misses nobody trusts the file enough to follow it.
Setup Time Is a Tax on Every Developer
Every hour spent debugging a local environment is an hour not spent building. Multiply that by each person who joins, each machine that gets replaced, each rebuild after a bad upgrade, and each container an agent spins up on demand. Codev.md treats setup documentation as high-return work: written once, collected repeatedly. Here is the bar worth holding yourself to. If a new developer cannot go from zero to running tests in under 30 minutes using only your documentation, your Codev.md needs work.
The Codev Template
# Codev.md - Development Environment Setup
<!-- Complete setup guide: prerequisites, installation, configuration, troubleshooting -->
<!-- Get a new developer from zero to running the application in under 30 minutes -->
<!-- Last updated: 2026-07-27 -->
## How to Use This Document
Three rules keep a setup document useful instead of decorative:
1. **The 30-minute bar is the success criterion.** Hand this file to someone who has never seen the repository and time them. If they are not running the application in 30 minutes, the document has a bug - fix the document, not the person.
2. **"Ask the tech lead for the API key" is a bottleneck, not documentation.** Every credential below names where it lives and who grants it. If a step still requires a conversation, that step is unfinished.
3. **Pin versions precisely, but never in prose.** A prerequisite of "Node.js" is meaningless and a major-version range is barely better - an exact version, pinned in a file that both humans and CI read, is a prerequisite. Pin it in `.nvmrc` and `package.json` `engines`, then have this document teach the reader how to *read* the pin. A version number typed into a paragraph is stale the first time you upgrade; a command that reads the pin never is.
## Prerequisites
### System Requirements
- **OS**: macOS 13+ (Ventura), Ubuntu 22.04+, or Windows 11 with WSL2
- **RAM**: 16GB minimum (services + IDE + browser consume ~10GB during development)
- **Disk**: 20GB free space (node_modules, Docker images, database data)
- **Network**: VPN access required for staging/production databases (request from IT)
### Required Software
Install these in order. Each step assumes the previous one is complete.
#### 1. Node.js (via a version manager)
The exact version this project requires is pinned in `.nvmrc`, and the acceptable range is enforced by `engines.node` in `package.json`. Do not install a version named in this paragraph - install the one the repository asks for.
```bash
# Install a Node version manager (nvm, fnm, asdf, or volta - pick one and stay on it).
# Follow the installer's own current instructions; do not copy a pinned installer URL
# into this file, because it will rot.
# From the repository root, let the repo choose the version:
nvm install # reads .nvmrc
nvm use # reads .nvmrc
nvm alias default "$(cat .nvmrc)"
# Verify against the pin rather than against a number written here:
cat .nvmrc # the version this repo requires
node --version # must match .nvmrc
node -p "require('./package.json').engines.node" # the range CI enforces
```
`.nvmrc` should track a Node release line that is still in active LTS support - check the Node.js release schedule when you bump it, rather than trusting whatever this document said the last time it was edited.
#### 2. Package Manager
The package manager and its version are pinned in the `packageManager` field of `package.json`. Corepack reads that field and activates the matching version, so there is no globally installed copy to drift out of sync.
```bash
corepack enable
corepack install # installs exactly the version named in package.json
# Verify against the pin:
node -p "require('./package.json').packageManager"
pnpm --version # must match the version above
```
#### 3. Docker and Docker Compose
```bash
# macOS: Install Docker Desktop from https://docker.com/products/docker-desktop
# Linux:
sudo apt-get update
sudo apt-get install docker.io docker-compose-v2
sudo usermod -aG docker $USER # Log out and back in after this
docker --version # any Docker Engine release still receiving security updates
docker compose version # must be Compose v2 - the `docker compose` subcommand,
# not the standalone `docker-compose` binary
```
#### 4. Git
```bash
git --version # any release still receiving security updates
# Configure git (use your work email)
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
git config --global pull.rebase true
git config --global init.defaultBranch main
```
#### 5. PostgreSQL Client (for debugging, not the server)
Match the client major version to the server major version pinned in `docker-compose.yml`. A client older than the server will fail on newer `pg_dump` formats.
```bash
# Read the server version the project actually runs:
grep -A1 'image: postgres' docker-compose.yml
# macOS:
brew install libpq
brew link --force libpq
# Ubuntu (substitute the major version you just read):
sudo apt-get install postgresql-client-<major>
psql --version # must match the server major version in docker-compose.yml
```
## Reproducible and Agent-Ready Environments
The numbered steps below install everything onto your own machine. That path works, but it is the slowest to reproduce and the easiest to get subtly wrong - and a coding agent cannot follow it at all without inheriting whatever drift already exists on the host.
Prefer a containerized environment. The goal is that a human and an agent get byte-identical toolchains, so "works on my machine" stops being a category of bug.
### Devcontainer (preferred path)
The repository ships `.devcontainer/devcontainer.json`, which pins the base image, the toolchain versions, the extensions, and the post-create commands. Anything that supports the devcontainer specification can open it - editors, CLIs, and hosted development environments alike.
```bash
# Build and enter the container (CLI path; your editor's "Reopen in Container" does the same)
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . -- pnpm test
```
What belongs in the devcontainer definition:
- The base image, pinned by digest, not by a floating tag
- Every tool the numbered setup steps install, so the container *is* the setup script
- The `postCreateCommand` that installs dependencies, runs migrations, and seeds data
- `forwardPorts` for every port listed in the Service Dependencies section
When the setup steps below and the devcontainer definition disagree, the devcontainer wins and the document is wrong. Fix the document.
### Remote Development Machines
Long-running or unattended agent work should not run on a laptop. Move it to a remote development machine - a cloud workspace or a dedicated VM that runs the same devcontainer image.
Why it matters beyond convenience:
- **Blast radius.** An agent that deletes a directory deletes it on a disposable machine, not on the host holding your SSH keys and your other clients' repositories.
- **Credential separation.** The remote machine holds only the scoped credentials this project needs. Your personal credentials never enter the environment an agent can read.
- **Auditability.** Shell history, network egress, and file changes on a shared remote machine can be logged centrally. The same activity on a laptop is invisible.
- **Continuity.** A task that takes an hour survives you closing your lid.
Document for your own project: how to request a machine, how long they live, and what gets wiped on teardown.
### Network Boundary and Egress Allowlist
The development environment should not be able to reach arbitrary hosts. Restrict outbound traffic to an allowlist, and treat any addition to it as a reviewed change.
| Destination | Why it is needed | Allowed from |
|-------------|------------------|--------------|
| Package registry | Dependency installation | All environments |
| Source host (git remote) | Clone, fetch, push | All environments |
| Model provider API | AI features and agent inference | All environments |
| Secrets manager | Credential retrieval at startup | All environments |
| Error and telemetry sink | Local debugging parity | Dev and staging |
| Payment provider sandbox | Billing flows against test keys | Dev and staging |
| Production database or API | - | **Never from a development environment** |
Two properties make an allowlist worth the effort. It stops a compromised or hallucinated dependency from exfiltrating your source tree or your `.env` file. And it turns "the agent tried to call something unexpected" from an invisible event into a logged, blocked one that a human reviews.
Keep the allowlist in version control next to the devcontainer definition so a diff shows exactly when a destination was added and by whom.
## Project Setup
### Step 1: Clone and Install
```bash
# Clone the repository
git clone [email protected]:acme-corp/atlas.git
cd atlas
# Install dependencies (pnpm, not npm)
pnpm install
# This also runs the postinstall script which:
# - Generates Prisma client
# - Sets up git hooks via Husky
# - Validates .nvmrc matches your Node version
```
### Step 2: Start Infrastructure Services
```bash
# Start PostgreSQL, Redis, and MinIO (S3-compatible storage) via Docker
docker compose up -d
# Verify all services are healthy
docker compose ps
# Should show 3 services with status "healthy"
# Expected ports:
# PostgreSQL: 5432
# Redis: 6379
# MinIO: 9000 (API) / 9001 (Console)
```
### Step 3: Configure Environment Variables
```bash
# Copy the example environment file
cp .env.example .env
```
Edit `.env` with the following values. Secrets marked with [1PASSWORD] should be retrieved from the "Atlas Dev" vault in 1Password.
```bash
# Database (Docker Compose defaults - no changes needed for local dev)
DATABASE_URL="postgresql://atlas:atlas_dev_password@localhost:5432/atlas_dev"
# Redis (Docker Compose defaults)
REDIS_URL="redis://localhost:6379"
# Object Storage (MinIO - Docker Compose defaults)
S3_ENDPOINT="http://localhost:9000"
S3_ACCESS_KEY="minioadmin"
S3_SECRET_KEY="minioadmin"
S3_BUCKET="atlas-uploads"
# Authentication
AUTH_SECRET="generate-locally-see-command-below"
GOOGLE_CLIENT_ID="[1PASSWORD: Atlas Dev > Google OAuth > Client ID]"
GOOGLE_CLIENT_SECRET="[1PASSWORD: Atlas Dev > Google OAuth > Client Secret]"
# Email (development uses local mailpit - no config needed)
SMTP_HOST="localhost"
SMTP_PORT="1025"
# External Services
STRIPE_SECRET_KEY="[1PASSWORD: Atlas Dev > Stripe > Test Secret Key]"
STRIPE_WEBHOOK_SECRET="[1PASSWORD: Atlas Dev > Stripe > Webhook Secret]"
AI_PROVIDER_API_KEY="[1PASSWORD: Atlas Dev > AI Provider > API Key]"
# Application
NODE_ENV="development"
PORT="3000"
LOG_LEVEL="debug"
```
```bash
# Generate the AUTH_SECRET value
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Paste the output as the AUTH_SECRET value in .env
```
### Step 4: Initialize the Database
```bash
# Run all migrations to create tables
pnpm db:migrate
# Seed development data (creates test users, sample data)
pnpm db:seed
# Verify the database is set up correctly
pnpm db:studio
# Opens Prisma Studio at http://localhost:5555
# You should see tables with seeded data
```
### Step 5: Start the Development Server
```bash
# Start the application in development mode (hot reload enabled)
pnpm dev
# Application: http://localhost:3000
# API docs: http://localhost:3000/api/docs
# Email inbox: http://localhost:8025 (Mailpit - catches all dev emails)
```
### Step 6: Verify Everything Works
```bash
# Run the test suite to confirm your setup is correct
pnpm test
# Expect: 0 failures and 0 skipped. The runner prints the total; if your total is
# lower than CI's on the same commit, tests are being skipped and your setup is
# incomplete - do not move on.
# Run a quick smoke test
pnpm test:smoke
# If all tests pass, your environment is ready
```
### Test Accounts (from seed data)
| Email | Password | Role |
|-------|----------|------|
| [email protected] | password123 | Admin |
| [email protected] | password123 | User |
| [email protected] | password123 | Viewer |
## Service Dependencies
### Service Architecture
```
+----------------+
| Next.js App |
| (port 3000) |
+-------+--------+
|
+-------------+-------------+
| | |
+-------v---+ +-----v-----+ +----v------+
| PostgreSQL | | Redis | | MinIO |
| (port 5432)| |(port 6379)| |(port 9000)|
+------------+ +-----------+ +-----------+
```
### PostgreSQL (Primary Database)
- **Purpose**: All application data - users, documents, teams, billing
- **Version**: pinned by the `postgres` image tag in `docker-compose.yml` - that file is the source of truth, not this line
- **Local access**: `psql postgresql://atlas:atlas_dev_password@localhost:5432/atlas_dev`
- **GUI**: Prisma Studio (`pnpm db:studio`) or pgAdmin/DBeaver
### Redis (Cache and Queues)
- **Purpose**: Session store, rate limiting, background job queue (BullMQ)
- **Version**: pinned by the `redis` image tag in `docker-compose.yml`
- **Local access**: `redis-cli` or RedisInsight
- **Note**: Flushing Redis in dev is safe - sessions will just expire and jobs will re-enqueue
### MinIO (Object Storage)
- **Purpose**: File uploads, document attachments, profile images
- **Console**: http://localhost:9001 (login: minioadmin/minioadmin)
- **Note**: S3-compatible API. Production uses AWS S3. Code is identical.
## MCP Servers This Repository Expects
Model Context Protocol (MCP) servers are how a coding agent reaches tools and live data - the database, the issue tracker, the error reporter. They are a service dependency like PostgreSQL or Redis, and they belong in this document for the same reason: an undocumented dependency is a setup failure waiting to happen, and an over-privileged one is an incident waiting to happen.
Configuration lives in the repository so every developer and every agent gets the same set. Credentials never do - they come from the environment or the secrets manager.
| Server | What the agent uses it for | Scope | Credential source |
|--------|---------------------------|-------|-------------------|
| Database (schema introspection) | Read table structure, indexes, and applied migrations | **Read-only**, dev database only | `MCP_DB_URL` from 1Password |
| Filesystem | Read and edit files inside the workspace | Read/write, workspace root only | None |
| Git / source host | Read diffs, open pull requests, comment | Read/write on branches; **never force-push to the default branch** | Fine-grained token, repo-scoped |
| Issue tracker | Read tickets, post status comments | Read/write on this project only | Project-scoped token |
| Error reporting | Read stack traces while debugging | **Read-only** | Read token |
| Documentation search | Look up internal architecture docs | **Read-only** | SSO |
### Rules for Adding a Server
1. **Default to read-only.** Grant write scope only where a workflow genuinely requires it, and name that workflow in the table above. Read-only is the difference between an agent that reports a problem and an agent that causes one.
2. **Scope to this project.** A token that can reach every repository in the organization is not a project dependency, it is an organizational risk.
3. **Never point a development-environment server at production data.** Use a seeded copy. This is the same rule as the egress allowlist, applied to tools instead of hosts.
4. **Pin the server version** the same way you pin every other dependency, and review upgrades. An MCP server is code you are handing your credentials to.
5. **Record what each one is for.** A server nobody can justify should be removed, not tolerated.
6. **Rotate on offboarding.** MCP credentials are credentials. They belong in the same rotation list as everything else in Secrets Management below.
## Common Development Commands
```bash
# Application
pnpm dev # Start dev server with hot reload
pnpm build # Production build
pnpm start # Start production build locally
pnpm lint # Run ESLint
pnpm type-check # TypeScript compiler check
# Database
pnpm db:migrate # Apply pending migrations
pnpm db:migrate:create # Create a new migration
pnpm db:seed # Seed development data
pnpm db:reset # Drop all tables, re-migrate, re-seed
pnpm db:studio # Open Prisma Studio GUI
# Testing
pnpm test # Run all unit tests
pnpm test:watch # Run tests in watch mode
pnpm test:integration # Integration tests (needs running services)
pnpm test:e2e # Playwright end-to-end tests
pnpm test:coverage # Generate coverage report
# Docker
docker compose up -d # Start all services
docker compose down # Stop all services
docker compose logs -f # Tail logs from all services
docker compose down -v # Stop and delete all data (fresh start)
# Code Generation
pnpm generate:component # Scaffold a new React component
pnpm generate:route # Scaffold a new API route
pnpm generate:migration # Create a new database migration
```
## What an Agent May Run Without Approval
Every command above falls into one of three tiers. Publishing the tiers is what makes unattended agent work safe: without them, a team either approves every command (and gets no benefit) or approves everything (and eventually loses data). Tier the risk once, write it down, and let the boundary do the work.
### Tier 1: Autonomous - no approval needed
Reversible, local, and cheap. An agent may run these unattended, in a loop, as often as it likes.
```bash
pnpm lint # Read-only analysis
pnpm type-check # Read-only analysis
pnpm test # Local, isolated, no external calls
pnpm test:watch
pnpm build # Writes only to the build output directory
pnpm dev # Local server
pnpm db:migrate # Local dev database only
pnpm db:seed # Local dev database only
pnpm db:reset # Destroys only local seeded data
docker compose up -d
docker compose logs -f
git add / git commit / git checkout -b # Local history, recoverable
```
The common thread: worst case, a human runs `pnpm db:reset` or deletes a branch and everything is back.
### Tier 2: Human approval required
Reversible only with effort, or visible to someone outside the loop.
- Pushing to a shared branch, or opening a pull request that triggers CI on shared runners
- Installing or upgrading a dependency (supply-chain surface, and it changes the lockfile everyone shares)
- Adding a destination to the egress allowlist, or adding an MCP server
- Editing CI configuration, deployment workflows, or anything under `.github/`
- Any command against staging
- Writing to a third-party sandbox that other developers share
- Deleting a file the agent did not create in this session
### Tier 3: Never - not with approval
An agent does not run these. If a task appears to require one, the task is wrong or the tooling is missing a safe equivalent.
- Anything touching production data: production `DATABASE_URL`, production API tokens, production object storage
- Any `DELETE`, `UPDATE`, `DROP`, or `TRUNCATE` outside a local dev database
- Anything that spends money: provisioning infrastructure, sending real email or SMS, charging a live payment key
- `git push --force` to a default or release branch, history rewrites, tag deletion
- Rotating, revoking, or printing production secrets
- Anything irreversible with no rollback path documented in this file
### Making the Boundary Enforceable
A list in a document is a convention. These make it a control:
- **Withhold the credentials.** A development environment that has no production connection string cannot touch production, whatever any prompt says. This is the strongest control available and it is free.
- **Keep the egress allowlist narrow** so Tier 3 destinations are unreachable, not merely discouraged.
- **Run deterministic scanners in CI** - secret scanning, dependency audit, license check, migration linting. A scanner rejects a bad change the same way every time; a reviewer does not.
- **Require review by risk tier, not by author.** A dependency bump and a migration deserve different scrutiny regardless of whether a human or an agent wrote them.
- **Ship an audit trail.** Log which commands ran, which MCP servers were called, and which egress attempts were blocked, then forward those events to wherever your organization already watches security logs. An agent action nobody can reconstruct is an agent action nobody can review.
- **Use specialized review agents as a pre-filter, not a gate.** They are good at catching the mechanical problems before a human looks. They do not replace the human on a Tier 2 change.
## IDE Setup
### VS Code (Recommended)
#### Required Extensions
Install via the Extensions panel or command line:
```bash
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension bradlc.vscode-tailwindcss
code --install-extension Prisma.prisma
code --install-extension usernamehw.errorlens
code --install-extension eamodio.gitlens
```
#### Workspace Settings
The project includes `.vscode/settings.json` with team-standard settings. Key settings:
```json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib",
"tailwindCSS.experimental.classRegex": [
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
]
}
```
#### Debugging Configuration
The project includes `.vscode/launch.json` with pre-configured debug profiles:
- **Next.js: Server** - Debug server-side code with breakpoints
- **Next.js: Client** - Debug client-side code in Chrome
- **Jest: Current File** - Debug the currently open test file
### JetBrains (WebStorm)
- Enable ESLint and Prettier integration in Preferences > Languages & Frameworks
- Set Node interpreter to the version-manager-managed Node
- Import the `.editorconfig` from the project root
### Agent Instructions (`AGENTS.md`)
Editor choice is personal; agent instructions are not. The repository root holds an `AGENTS.md` - plain Markdown, no frontmatter, no schema - that tells any coding agent how this project builds, tests, and formats itself. It is read natively by a wide range of agent CLIs and editor integrations, so one file covers the whole team instead of one config per tool.
Precedence is nearest-file-wins: an `AGENTS.md` inside `packages/api/` overrides the root file for work in that directory. Use that to keep the root file short and put package-specific rules where they apply.
What belongs in it, and what does not:
- **Belongs**: the exact build/test/lint commands, the version-pin locations described above, the risk tiers from the previous section, project conventions a newcomer would get wrong.
- **Does not belong**: anything secret, anything already enforced by a linter or CI (say it once, in the tool), and prose about why the architecture is good.
Update `AGENTS.md` in the same pull request that changes the commands it documents - the same rule this document lives under.
## Troubleshooting
### Port Conflicts
```bash
# Check what is using a port
# macOS/Linux:
lsof -i :3000
# Windows (PowerShell):
netstat -ano | findstr :3000
# Kill process on port
# macOS/Linux:
kill -9 $(lsof -t -i :3000)
# Windows:
taskkill /PID [PID] /F
# Or change the port in .env:
PORT=3001
```
### Docker Issues
```bash
# Services will not start
docker compose down -v # Remove volumes and try fresh
docker compose up -d
# Out of disk space
docker system prune -a # Remove unused images and containers
docker volume prune # Remove unused volumes
# Permission denied (Linux)
sudo usermod -aG docker $USER
# Log out and back in
```
### Database Issues
```bash
# Cannot connect to database
docker compose ps # Is postgres service running?
docker compose logs db # Check postgres logs for errors
# Migration fails
pnpm db:migrate:status # Check which migrations have been applied
pnpm db:reset # Nuclear option - drops everything and starts fresh
# Prisma client out of sync with schema
pnpm prisma generate # Regenerate the Prisma client
```
### Node/pnpm Issues
```bash
# Wrong Node version
nvm use # Reads .nvmrc and switches to correct version
# Dependency resolution errors
rm -rf node_modules
pnpm install --force # Force reinstall all dependencies
# pnpm lockfile conflicts after merge
git checkout --theirs pnpm-lock.yaml
pnpm install
git add pnpm-lock.yaml
```
## Environment Variables Reference
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `DATABASE_URL` | Yes | - | PostgreSQL connection string |
| `REDIS_URL` | Yes | - | Redis connection string |
| `S3_ENDPOINT` | Yes | - | S3/MinIO endpoint URL |
| `S3_ACCESS_KEY` | Yes | - | S3/MinIO access key |
| `S3_SECRET_KEY` | Yes | - | S3/MinIO secret key |
| `S3_BUCKET` | Yes | - | S3/MinIO bucket name |
| `AUTH_SECRET` | Yes | - | NextAuth session encryption secret |
| `GOOGLE_CLIENT_ID` | Yes | - | Google OAuth client ID |
| `GOOGLE_CLIENT_SECRET` | Yes | - | Google OAuth client secret |
| `STRIPE_SECRET_KEY` | No | - | Stripe API key (payments disabled without) |
| `AI_PROVIDER_API_KEY` | No | - | Model provider API key (AI features disabled without) |
| `MCP_DB_URL` | No | - | Read-only connection string for the schema-introspection MCP server |
| `PORT` | No | 3000 | Application port |
| `NODE_ENV` | No | development | Environment mode |
| `LOG_LEVEL` | No | info | Logging verbosity (debug/info/warn/error) |
## Secrets Management
### Development Secrets
- Store in `.env` (gitignored - never committed)
- Get values from 1Password vault "Atlas Dev"
- Never share secrets over Slack or email - use 1Password sharing
### Generating Local Secrets
```bash
# Generate a random secret key (for AUTH_SECRET, etc.)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Generate a UUID
node -e "console.log(require('crypto').randomUUID())"
```
### Production Secrets
- Managed via [AWS Systems Manager Parameter Store / Vault / etc.]
- Rotated quarterly by the platform team
- Access requests go through [process/tool]
- Never present in a development environment, a devcontainer, or any MCP server configuration - see the risk tiers above
## Keeping This Document Current
- **Update setup docs in the same pull request as the change.** A new service dependency, a changed port, a new required credential, a new MCP server, or an added egress destination all make this file wrong the moment they merge. Reviewers should block a PR that changes setup without changing this file.
- **Re-time the 30-minute bar** whenever someone new joins. It is the only claim here that can be measured, so measure it.
- **Never write a version number in prose.** Point at `.nvmrc`, `package.json`, or `docker-compose.yml` and show the command that reads it. Every literal version in a paragraph is a future support ticket.
- **Delete steps that no longer apply.** A setup document that has only ever grown is a setup document nobody finishes.
Why Markdown Matters for AI-Native Development
Environment Setup in One File
Getting a repository running should not require finding whoever set it up last time. Codev.md records the required runtimes and their exact versions, the services, the seed data, and where credentials come from - all of it in the repo itself, corrected by the same pull request that breaks it.
Devcontainers and Reproducible Machines
A documented setup is good. A setup that builds itself is better. Codev.md pairs the written procedure with the container or image definition that reproduces it, so a laptop, a CI runner, and a remote dev box all land on identical versions. The document then carries the choices an image cannot explain.
What an Agent May Run Unattended
An agent working in your environment will eventually reach for the network, the database, or a deploy command. Decide in advance which of those are allowed without a person watching, restrict outbound traffic to an allowlist, and put the boundary somewhere the agent reads. An undeclared boundary is not a boundary.
"Environment problems are never one big problem. They are forty small ones, each obvious to whoever solved it first and invisible to everybody afterward. Codev.md is where those forty go, so the fortieth new hire pays roughly the same cost as the first, which is nearly none."
Frequently Asked Questions
What is Codev.md?
Codev.md is a platform for documenting development environment setup in structured markdown. It captures every dependency, configuration step, and troubleshooting tip so new developers get productive in minutes instead of days.
How does Codev.md reduce onboarding time?
By providing copy-paste commands, verification steps, and a troubleshooting FAQ, Codev.md eliminates the guesswork from environment setup. AI assistants can walk developers through each step and debug issues in real time.
What should I document in a Codev.md file?
Document prerequisite tools with exact version numbers, setup commands, environment variables, secrets management procedures, database initialization, OS-specific steps, and solutions to the top 10 setup failures your team has encountered.
Can AI assistants use Codev.md to help with setup?
Yes. When your setup documentation is in structured markdown in the repository, AI assistants can reference it to guide developers through installation, diagnose configuration errors, and validate environment readiness.
Does Codev.md handle different operating systems?
Codev.md templates include separate sections for Windows, macOS, and Linux with platform-specific commands and paths. Clear OS headers prevent the confusion that mixed-platform instructions cause.
Is Codev.md free?
Yes, all Codev.md templates are free to copy or download. Customize the template for your project's specific toolchain and dependencies.
How do I keep my Codev.md file current?
Add "update setup docs" to your definition of done for any infrastructure change. If you add a service dependency or change a tool version, update Codev.md in the same pull request.
Explore More Templates
About Codev.md
Our Mission
Codev.md is maintained by RJL, and every section of it started life as a setup step somebody got wrong.
Version pinning is the highest-return habit in this whole area. "Node 20" and "Node 20.11.0" are different documents, and one of them fails on a Tuesday for reasons that take three hours to locate. Write the exact version, write why that version, and write what breaks when you move off it.
The newer half of the problem is that the environment now has a second class of occupant. Agents run commands, install packages, and reach outward, and they do it faster than anyone can watch. Treat the sandbox boundary - what is reachable, what is writable, what needs a person first - as part of the setup documentation rather than something bolted on afterward.
Why Markdown Matters
AI-Native
LLMs parse markdown better than any other format. Fewer tokens, cleaner structure, better results.
Version Control
Context evolves with code. Git tracks changes, PRs enable review, history preserves decisions.
Human Readable
No special tools needed. Plain text that works everywhere. Documentation humans actually read.
Stuck with a setup that only works on one machine? Send the symptoms and we will compare notes.