Claude Code for Developer Experience: Local Dev Setup, Onboarding, and Tooling — Claude Skills 360 Blog
Blog / Productivity / Claude Code for Developer Experience: Local Dev Setup, Onboarding, and Tooling
Productivity

Claude Code for Developer Experience: Local Dev Setup, Onboarding, and Tooling

Published: August 26, 2026
Read time: 8 min read
By: Claude Skills 360

Developer experience (DX) determines how fast new engineers become productive and how much friction the existing team encounters daily. Claude Code dramatically improves DX tasks: generating Docker Compose setups that work first-time, writing onboarding scripts that handle OS differences, and creating CLAUDE.md files that give every team member the same AI context.

This guide covers developer experience improvements with Claude Code: local setup automation, dev containers, onboarding scripts, and team tooling.

One-Command Local Setup

Create a docker-compose.yml for local development.
Services: PostgreSQL, Redis, the Node API, and a React frontend.
It should work on both Mac and Linux without modification.
# docker-compose.yml
name: myapp

services:
  postgres:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: localpassword
      POSTGRES_DB: appdb
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./scripts/db/init:/docker-entrypoint-initdb.d  # Run SQL on first startup
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    command: redis-server --save 60 1  # Persist to disk every 60s
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      retries: 5

  api:
    build:
      context: ./api
      dockerfile: Dockerfile.dev
    ports:
      - "8080:8080"
    volumes:
      - ./api:/app
      - /app/node_modules  # Don't overwrite node_modules from host
    environment:
      NODE_ENV: development
      DATABASE_URL: postgresql://appuser:localpassword@postgres:5432/appdb
      REDIS_URL: redis://redis:6379
      JWT_SECRET: local-dev-secret-change-in-production
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    command: npm run dev  # Should use --watch / nodemon

  web:
    build:
      context: ./web
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ./web:/app
      - /app/node_modules
    environment:
      VITE_API_URL: http://localhost:8080
    depends_on:
      - api

  # Optional: DB UI for local debugging
  pgadmin:
    image: dpage/pgadmin4:latest
    profiles: ["tools"]  # Only starts with: docker compose --profile tools up
    ports:
      - "5050:80"
    environment:
      PGADMIN_DEFAULT_EMAIL: [email protected]
      PGADMIN_DEFAULT_PASSWORD: admin
    depends_on:
      - postgres

volumes:
  postgres_data:
  redis_data:
# scripts/setup.sh — one-command setup
#!/bin/bash
set -e

echo "Setting up development environment..."

# Check dependencies
command -v docker >/dev/null 2>&1 || { echo "Docker required. Install: https://docs.docker.com/get-docker/"; exit 1; }
command -v node >/dev/null 2>&1 || { echo "Node.js 20+ required"; exit 1; }

# Copy .env if it doesn't exist
[ -f .env ] || cp .env.example .env

# Install dependencies
npm install --prefix api
npm install --prefix web

# Start services
docker compose up -d postgres redis

# Wait for postgres
echo "Waiting for PostgreSQL..."
until docker compose exec postgres pg_isready -U appuser -q; do
  sleep 1
done

# Run migrations
npm run --prefix api migrate

# Seed dev data
npm run --prefix api db:seed

echo "✓ Setup complete. Run: docker compose up"

Dev Containers

Create a .devcontainer setup so any team member gets the
same environment in VS Code or GitHub Codespaces.
// .devcontainer/devcontainer.json
{
  "name": "MyApp Dev",
  "dockerComposeFile": ["../docker-compose.yml", "docker-compose.devcontainer.yml"],
  "service": "devcontainer",
  "workspaceFolder": "/workspace",

  "features": {
    "ghcr.io/devcontainers/features/node:1": { "version": "20" },
    "ghcr.io/devcontainers/features/github-cli:1": {}
  },

  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "Prisma.prisma",
        "bradlc.vscode-tailwindcss",
        "ms-azuretools.vscode-docker",
        "humao.rest-client",
        "mtxr.sqltools",
        "mtxr.sqltools-driver-pg"
      ],
      "settings": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.codeActionsOnSave": {
          "source.fixAll.eslint": "explicit"
        }
      }
    }
  },

  "forwardPorts": [3000, 8080, 5432],
  "portsAttributes": {
    "3000": { "label": "Frontend" },
    "8080": { "label": "API" },
    "5432": { "label": "PostgreSQL" }
  },

  "postCreateCommand": "bash .devcontainer/setup.sh",
  "remoteUser": "node"
}
# .devcontainer/docker-compose.devcontainer.yml
services:
  devcontainer:
    image: mcr.microsoft.com/devcontainers/base:ubuntu
    volumes:
      - ../:/workspace:cached
    command: sleep infinity
    depends_on:
      - postgres
      - redis
    networks:
      - default

Pre-Commit Hooks

Set up pre-commit hooks that:
1. Run prettier formatting
2. Run ESLint (only on staged files)
3. Run type checking
4. Prevent commits with console.log in API code
// package.json (root)
{
  "scripts": {
    "prepare": "husky"
  },
  "lint-staged": {
    "*.{ts,tsx}": [
      "prettier --write",
      "eslint --fix --max-warnings=0"
    ],
    "*.{json,md,yml,yaml}": [
      "prettier --write"
    ]
  }
}
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# Run lint-staged on staged files only (fast)
npx lint-staged

# Type check (only if TS files changed)
CHANGED_TS=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(ts|tsx)$' | head -1)
if [ -n "$CHANGED_TS" ]; then
  echo "Type checking..."
  npm run type-check 2>&1 | tail -20
  if [ $? -ne 0 ]; then
    echo "❌ Type check failed. Run: npm run type-check"
    exit 1
  fi
fi

# Block console.log in API code
API_LOGS=$(git diff --cached -- 'api/src/**/*.ts' | grep '^+' | grep 'console\.log')
if [ -n "$API_LOGS" ]; then
  echo "❌ Found console.log in API code (use logger instead):"
  echo "$API_LOGS"
  exit 1
fi

Team CLAUDE.md Template

Create a CLAUDE.md that every engineer on the team uses,
covering architecture decisions, coding conventions, and local workflow.
# MyApp

## Architecture
- **API**: Node.js 20, Express 4, TypeScript strict mode
- **Database**: PostgreSQL 16, Drizzle ORM for type-safe queries
- **Cache**: Redis 7 (sessions + hot data)
- **Frontend**: React 18, Vite, TanStack Query for server state
- **Auth**: JWT access tokens (15min) + refresh tokens (7d, httpOnly cookie)

## Local Development
```sh
# First time:
./scripts/setup.sh

# Daily:
docker compose up          # Starts postgres + redis
npm run dev --prefix api   # API on :8080 with hot reload
npm run dev --prefix web   # Frontend on :3000 with HMR

Key Decisions (ask before changing)

  • No ORMs for complex queries — use Drizzle’s sql“ tag or raw SQL
  • Service objects for business logic (src/services/) — not in controllers
  • No try/catch in controllers — use express-async-errors + global error handler
  • No any types — if you need escape hatch, use unknown + type assertion

Testing

npm test              # Unit tests (vitest)
npm run test:e2e      # E2E with Playwright (requires running app)
npm run test:ci       # Both, no watch mode

PR Process

  1. Branch from main: git checkout -b feat/your-feature
  2. Run tests before push: npm test
  3. PRs require 1 approval; don’t merge your own
  4. Squash merge to main — no individual commits on main

Common Commands

npm run migrate           # Run pending migrations
npm run migrate:create    # Create new migration file
npm run db:reset          # Drop + recreate (dev only)
npm run typecheck         # TypeScript without emitting
npm run lint              # ESLint check
npm run format            # Prettier fix

Environment Variables

See .env.example — all required vars documented there. Never commit .env files. Use 1Password for sharing secrets locally.


For the CLAUDE.md patterns that make AI coding more effective for your whole team, see the [CLAUDE.md guide](/blog/claude-md-guide/). For automating repetitive development tasks with Claude Code hooks, see the [hooks guide](/blog/claude-code-hooks-guide/). The [Claude Skills 360 bundle](https://claudeskills360.com) includes developer tooling skill sets for onboarding automation, local setup, and team process improvement. Start with the [free tier](/free/) to try developer experience code generation.

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free