Local Dev Setup

Write a local development environment setup guide for a service or project — covering prerequisites, repository setup, environment variables, local service dependencies, database seeding, running the service, running tests, common gotchas, IDE recommendations, and first-contribution checklist. Use when asked to write a dev setup guide, create onboarding documentation for engineers, document local environment setup, or write a getting-started guide for a codebase. Produces a complete setup guide that a new engineer can follow from zero to running tests in under 30 minutes, with a troubleshooting section for the most common setup failures.

Published by @Mohit Aggarwal·0 agent reads / 30d·0 saves·

Local Dev Setup Skill

Produce a complete local development environment setup guide for a service or project — walking a new engineer from zero (a clean laptop) to a working local environment with passing tests in under 30 minutes. A good setup guide reduces onboarding time, prevents the "it works on my machine" problem, and lets engineers make their first contribution with confidence. Write every step as a concrete command or action — not a description of what needs to happen.

Required Inputs

Ask for these if not already provided:

  • Service name and what it does
  • Tech stack — language, framework, database, cache, message queue, and any external services
  • Dependencies — databases, caches, message queues, and external services (mocked or real)
  • Test framework — how tests are run and what the test suite covers
  • CI/CD platform — GitHub Actions, CircleCI, Jenkins, etc. (for context on what "passing CI" means locally)

Output Format


Local Development Setup: [Service Name]

Tech stack: [Language + version] | [Framework] | [Database] | [Cache] Estimated setup time: [20–30 minutes] on a clean machine Last verified: [Date] on [macOS Ventura 13.x / Ubuntu 22.04] Questions? Ask in [Slack: #[team-channel]] or ping [@tech-lead-handle]

First contribution? Complete setup first (this doc), then read [CONTRIBUTING.md] for code standards and PR process.


Prerequisites

Install these tools before starting. The versions listed are the minimum required — newer patch versions are fine, newer major versions may have compatibility issues.

Required Tools

ToolRequired versionInstall
[Git]2.x+Pre-installed on most systems; or brew install git
[Language runtime — e.g. Go][1.22+][https://go.dev/dl/ or brew install go]
[Docker]24.x+[https://docs.docker.com/get-docker/]
[Docker Compose]2.x+Included with Docker Desktop; or brew install docker-compose
[Make]AnyPre-installed on macOS/Linux
[Tool — e.g. Node.js][20.x+][brew install node or https://nodejs.org]
[Tool — e.g. psql client][15+]brew install postgresql@15 (client only)

Optional but Recommended

ToolPurposeInstall
[direnv]Auto-load .envrc environment variablesbrew install direnv + setup instructions
[jq]Pretty-print JSON in terminalbrew install jq
[k9s]Kubernetes cluster UI (if using K8s locally)brew install k9s
[mkcert]Local HTTPS certificatesbrew install mkcert

Required Accounts and Access

Before starting, make sure you have:

  • GitHub access to [org/repo] — request via [access request process / Slack: #it-help]
  • [AWS / GCP / Azure] account with [dev environment] access — request via [process]
  • [Internal tool — e.g. 1Password] for retrieving development secrets — request via [process]
  • [VPN access] if required to reach internal services — request via [process]

1. Repository Setup

# Clone the repository
git clone [email protected]:[org]/[repo-name].git
cd [repo-name]

# Install git hooks (required — enforces commit message format and runs pre-commit checks)
make install-hooks
# Or manually:
# cp scripts/hooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit

# Verify your git setup
git config user.name   # should be your name
git config user.email  # should be your work email

If you see a permission denied error on clone: Your SSH key is not added to GitHub. Follow GitHub's SSH key guide or use HTTPS with a personal access token instead.


2. Environment Variables

The service requires environment variables for configuration. Never commit actual secrets to the repository.

Step 1 — Copy the example file

cp .env.example .env.local

Step 2 — Fill in the values

Open .env.local in your editor. Below is a description of every variable and where to get its value:

VariableDescriptionWhere to get itExample (not real)
APP_ENVEnvironment nameSet to developmentdevelopment
APP_PORTPort the service listens onSet to 8080 for local8080
DATABASE_URLPostgreSQL connection stringUse value from Docker Compose (Section 3)postgres://app:password@localhost:5432/[service]_dev
REDIS_URLRedis connection stringUse value from Docker Composeredis://localhost:6379
SECRET_KEYApplication secret keyGenerate with: openssl rand -hex 32[random 64-char hex]
[EXTERNAL_SERVICE]_API_KEYAPI key for [External Service]Retrieve from [1Password vault: "Dev API Keys"] or ask [name]
[EXTERNAL_SERVICE]_BASE_URLBase URL for [External Service]Use sandbox URL: https://sandbox.[external-service].comhttps://sandbox.stripe.com
LOG_LEVELLogging verbositySet to debug for local developmentdebug
[FEATURE_FLAG_SDK_KEY]Feature flag platform SDK keyRetrieve from [LaunchDarkly/Split dev project]

Using direnv (recommended): Rename .env.local to .envrc, add dotenv at the top, and run direnv allow. Variables will load automatically when you cd into the project.


3. Local Service Dependencies

All infrastructure dependencies run in Docker Compose. You do not need to install PostgreSQL, Redis, or Kafka locally.

# Start all dependencies (PostgreSQL, Redis, and any other services)
docker compose up -d

# Verify all containers are healthy
docker compose ps
# Expected output: all services show "healthy" status

# View logs if something is not healthy
docker compose logs [service-name]

What Docker Compose Starts

ServicePortPurposeHealth check
PostgreSQL [version]5432Primary databasepg_isready -U app
Redis [version]6379Cache and session storeredis-cli ping
[Kafka + Zookeeper]9092 / 2181Message queuekafka-topics.sh --list
[Mock server — e.g. WireMock]8089Mocks for external APIs in testscurl localhost:8089/__admin
[LocalStack]4566AWS service emulation (S3, SQS, etc.)aws --endpoint-url=http://localhost:4566 s3 ls

If a container exits immediately: See Troubleshooting section — common causes are port conflicts and Docker memory limits.

Stopping Dependencies

# Stop containers (preserves data volumes)
docker compose stop

# Stop and remove containers (clears data — use when you want a fresh start)
docker compose down -v

4. Install Dependencies and Build

# Install language dependencies
# Go:
go mod download

# Node.js:
npm install   # or: yarn install / pnpm install

# Python:
python -m venv .venv
source .venv/bin/activate   # On Windows: .venv\Scripts\activate
pip install -r requirements-dev.txt

# Verify build compiles cleanly
make build
# Expected: no errors; binary or compiled output in [./bin/ or ./dist/]

5. Database Setup and Seeding

# Run database migrations (creates tables and schema)
make db-migrate
# Or directly:
# [Migration command — e.g. "go run ./cmd/migrate up" or "alembic upgrade head" or "npm run db:migrate"]

# Verify migrations applied
# psql $DATABASE_URL -c "\dt"  # should list all tables

# Seed the database with development data
make db-seed
# Or directly:
# [Seed command — e.g. "go run ./cmd/seed" or "python scripts/seed.py" or "npm run db:seed"]

# Verify seed data is present
# psql $DATABASE_URL -c "SELECT COUNT(*) FROM [primary-table]"
# Expected: [N] rows

What the seed creates:

  • [N] test user accounts (credentials in [scripts/seed/README.md or .env.example])
  • [N] sample [resources] for development and testing
  • Admin account: [[email protected]] / password: see .env.example for dev password variable

To reset to a clean state:

docker compose down -v   # wipe database volume
docker compose up -d     # start fresh
make db-migrate
make db-seed

6. Running the Service

# Run the service locally
make run
# Or directly:
# [Run command — e.g. "go run ./cmd/server" or "python app.py" or "npm run dev"]

# Expected output:
# [Example of healthy startup log lines — e.g.:]
# {"level":"info","message":"Database connected","host":"localhost","port":5432}
# {"level":"info","message":"Redis connected","host":"localhost","port":6379}
# {"level":"info","message":"Server listening","port":8080}

Verify It's Working

# Health check
curl http://localhost:8080/health
# Expected: {"status":"ok","version":"[git-sha]"}

# Test a key endpoint (authenticated)
# First, get a dev token:
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[dev-user-from-seed]@example.com","password":"[dev-password-from-env]"}'
# Copy the token from the response, then:

curl http://localhost:8080/api/v1/[resource] \
  -H "Authorization: Bearer [token-from-above]"
# Expected: 200 with JSON response

Hot Reload (for Development)

# Run with hot reload — service restarts automatically on file changes
make run-dev
# Or:
# [Hot reload command — e.g. "air" for Go / "uvicorn --reload" for Python / "npm run dev" for Node]

7. Running Tests

# Run the full test suite
make test
# Or:
# [Test command — e.g. "go test ./..." or "pytest" or "npm test"]

# Run tests with coverage report
make test-coverage
# Coverage report: [./coverage.html or stdout]

# Run a specific test file or test case
# Go: go test ./pkg/[package]/... -run TestFunctionName
# Python: pytest tests/test_[module].py::TestClass::test_method -v
# Node: npm test -- --testPathPattern=[filename]

# Run only unit tests (fast — no external dependencies)
make test-unit

# Run only integration tests (requires Docker Compose dependencies running)
make test-integration

Expected test results:

  • Unit tests: [N] tests, all pass, [<30] seconds
  • Integration tests: [N] tests, all pass, [<2] minutes
  • Coverage: [≥80]% (enforced in CI — tests fail below this threshold)

Before pushing a PR, always run:

make lint      # code linting — must pass
make test      # full test suite — must pass
make build     # verify compilation — must pass

8. IDE Setup

VS Code (Recommended)

Install the recommended extensions (VS Code will prompt you automatically):

// .vscode/extensions.json — already in the repository
{
  "recommendations": [
    "[language-extension — e.g. golang.go]",
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "ms-azuretools.vscode-docker",
    "eamodio.gitlens"
  ]
}

Workspace settings are in .vscode/settings.json — format on save is enabled, linter is configured automatically.

[Language]-specific setup:

[e.g. Go: The gopls language server is installed automatically by the Go extension.
 Run "Go: Install/Update Tools" from the command palette after installing the extension.]

JetBrains (IntelliJ / GoLand / PyCharm / WebStorm)

  • Open the project root as the project directory
  • [Language SDK]: set to [version] — File → Project Structure → SDKs
  • Run configurations are checked into .idea/runConfigurations/ — they appear automatically
  • Enable "Run formatters on save" in Settings → Tools → Actions on Save

9. Common Gotchas and Troubleshooting

Docker container exits immediately on startup

Symptom: docker compose ps shows a container as Exited (1) seconds after starting.

# Check the container logs for the error
docker compose logs [container-name]

# Common causes:
# 1. Port already in use — find and kill the conflicting process:
lsof -ti tcp:[port] | xargs kill -9

# 2. Docker doesn't have enough memory — allocate at least 4GB in Docker Desktop:
# Docker Desktop → Settings → Resources → Memory → 4GB

# 3. M1/M2 Mac architecture mismatch — add platform directive to docker-compose.yml:
# platform: linux/amd64

Database connection refused

Symptom: Service fails to start with "connection refused" or "dial tcp localhost:5432: connect: connection refused"

# Is PostgreSQL actually running?
docker compose ps postgres
# If not running: docker compose up -d postgres

# Is it on the right port?
lsof -i :5432

# Can you connect manually?
psql postgres://app:password@localhost:5432/[service]_dev -c "SELECT 1"

# If using a custom DATABASE_URL, verify it matches the docker-compose.yml settings exactly

Migrations fail with "relation already exists"

Symptom: make db-migrate errors with "ERROR: relation [table] already exists"

# Check current migration state
[migration status command — e.g. "go run ./cmd/migrate status" or "alembic current"]

# The database may be in a partial state — reset it:
docker compose down -v
docker compose up -d
make db-migrate  # should now succeed on a clean database

Tests fail with "connection refused" or dependency errors

Symptom: Integration tests fail because they cannot connect to PostgreSQL or Redis.

# Integration tests need Docker Compose running
docker compose up -d

# Verify all containers are healthy before running tests
docker compose ps   # all should show "healthy"

# If containers are running but tests still fail, check environment variables:
make test-integration  # should pick up .env.local automatically
# If not: source .env.local && make test-integration

make lint fails on a fresh checkout

Symptom: Lint errors on files you have not modified.

# Formatting issue — auto-fix with:
# Go:
gofmt -w .
goimports -w .

# Python:
black .
isort .

# Node/TypeScript:
npm run lint:fix
# Or: npx eslint --fix . && npx prettier --write .

# Re-run lint to confirm
make lint

Environment variables not loading

Symptom: Service starts but immediately fails with "missing required environment variable: [VAR]"

# Verify .env.local exists and has all required variables
cat .env.local | grep "^[A-Z]" | awk -F= '{print $1}'

# Compare against required variables in .env.example
diff <(grep "^[A-Z_]*=" .env.example | cut -d= -f1 | sort) \
     <(grep "^[A-Z_]*=" .env.local | cut -d= -f1 | sort)

# Missing variables are shown in left column only (< prefix)

10. First Contribution Checklist

Before opening your first pull request, verify:

Setup complete:

  • make build passes with no errors
  • make test passes — all tests green
  • make lint passes — no lint errors
  • Service starts and health check returns 200
  • You can authenticate and call at least one API endpoint

Git and GitHub:

  • You have read [CONTRIBUTING.md] — code standards, commit message format, PR process
  • Your git user.name and user.email are set correctly
  • Pre-commit hooks are installed (ls .git/hooks/pre-commit should exist)
  • You have branched from main (not committing directly to main)

Development workflow:

  • You know how to run a specific test: [test command for single test]
  • You know how to reset the database: docker compose down -v && docker compose up -d && make db-migrate && make db-seed
  • You have joined [Slack: #[team-channel]] and [#[service-consumers-channel] if applicable]
  • You have read the [architecture overview doc / README] — you understand what this service does

First PR:

  • Changes are small and focused — one logical change per PR
  • Tests are added or updated for your change
  • make test && make lint && make build all pass locally before requesting review
  • PR description explains what changed and why (use the [pr-description-writer skill] if needed)

Quality Checks

  • A new engineer with no prior knowledge of the project can follow this guide from start to finish without asking anyone for help
  • Every command is tested on a clean environment — not written from memory and assumed to work
  • Environment variables table covers every variable in .env.example — no undocumented variables
  • The troubleshooting section covers the 5 most common real failures observed during onboarding — not theoretical issues
  • Docker Compose version and Docker Desktop memory requirements are stated explicitly
  • "Expected output" is shown for key commands so engineers know whether a step succeeded
  • Setup time estimate is honest — verified by timing a real onboarding session, not estimated

Anti-Patterns

  • Do not write setup steps from memory without testing them on a clean machine — steps that skip implicit knowledge break for new engineers
  • Do not leave environment variables undocumented — every variable in .env.example must appear in the Variables table with a description and source
  • Do not write troubleshooting entries for theoretical issues — only include problems that have actually occurred during real onboarding sessions
  • Do not assume Docker Desktop is configured correctly — memory limits and platform (M1/M2) compatibility must be explicitly called out
  • Do not omit expected output for key commands — without "expected output", engineers cannot tell whether a step succeeded or silently failed

Bundled with this artifact

1 file

Reference files that ship alongside this artifact. Agents pull these in only when the task needs them.

More on the bench

SKILL0

Ros And Ros2 Rules

ROS and ROS2 rules for packages, nodes, launch files, messages, services, actions, simulation, and testing

software-engineering+1
0
SKILL0

Embedded Mcu Stm32 And Hal Rules

Embedded C/C++ rules for MCU, STM32, HAL, interrupts, DMA, memory constraints, and hardware-focused testing

software-engineering+1
0
SKILL0

System Design

Design systems, services, and architectures. Trigger with "design a system for", "how should we architect", "system design for", "what's the right architecture for", or when the user needs help with API design, data modeling, or service boundaries.

software-engineering+2
0