.agents/skills/hot-reload-development/SKILL.md
# Skill: Hot-Reload Development **Description**: Guidance for agents configuring development containers with hot-reload capabilities, volume mounts, and watch mechanisms for rapid iteration. **When to use**: When creating development Containerfiles, configuring hot-reload for compiled or interpreted languages, or setting up volume mounts for source code changes. --- ## Quick Start ### I'm setting up hot-reload for a Go service 1. Read `.opencode/rules/patterns/development/hot-reload.md` —
npx skillsauth add em-jones/staccato-toolkit .agents/skills/hot-reload-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Description: Guidance for agents configuring development containers with hot-reload capabilities, volume mounts, and watch mechanisms for rapid iteration.
When to use: When creating development Containerfiles, configuring hot-reload for compiled or interpreted languages, or setting up volume mounts for source code changes.
.opencode/rules/patterns/development/hot-reload.md — Go services: Use file watcher for rebuild + restart.air.toml configFROM golang:1.23-alpine
RUN apk add --no-cache bash curl git && \
wget -qO- https://github.com/watchexec/watchexec/releases/download/v1.25.1/watchexec-1.25.1-x86_64-unknown-linux-musl.tar.xz | tar xJv && \
mv watchexec-1.25.1-x86_64-unknown-linux-musl/watchexec /usr/local/bin/
WORKDIR /workspace
EXPOSE 8080
CMD ["watchexec", "-r", "-e", "go", "--", "go", "run", "main.go"]
docker run -v $(pwd):/workspace -p 8080:8080 app:dev.opencode/rules/patterns/development/hot-reload.md — Node.js: Use built-in development serversFROM node:22
WORKDIR /workspace
EXPOSE 7007 3000
CMD ["yarn", "serve"]
docker run -v $(pwd):/workspace -p 7007:7007 -p 3000:3000 app:dev.opencode/rules/patterns/development/hot-reload.md — Go CLI: Interactive shell for manual iterationFROM golang:1.23-alpine
RUN apk add --no-cache bash curl git
WORKDIR /workspace
CMD ["/bin/sh"]
docker run -it -v $(pwd):/workspace app:devgo build -o cli . && ./cli health.opencode/rules/patterns/development/hot-reload.md — Volume mount pattern/workspace-v $(pwd):/workspacedocker inspect <container-id> | grep Mounts -A 10tmp/, vendor/, .git/node_modules/, dist/, .git/*.go*.js, *.ts, *.jsx, *.tsxwatchexec -r -e go -i tmp/ -i vendor/ -- go run main.goPurpose: Enable source code changes on host to be reflected inside the container.
Standard pattern:
FROM <base-image>
WORKDIR /workspace # ← Standard mount point
CMD [<hot-reload-command>]
Usage:
docker run -v $(pwd):/workspace -p <port>:<port> app:dev
Key principles:
/workspace as the standard mount point (consistent across all services)WORKDIR$(pwd)) for portability| Language | Mechanism | Tool | Restart Time | Configuration |
| ----------- | -------------------------------- | ----------------------- | ------------ | --------------------- |
| Go (server) | File watcher + rebuild + restart | watchexec or air | 1-3 seconds | Inline or .air.toml |
| Go (CLI) | Manual rebuild | Interactive shell | N/A (manual) | None |
| Node.js | Built-in HMR | yarn serve, npm run dev | <1 second | webpack/vite config |
| TypeScript | Built-in watch | tsc --watch | <1 second | tsconfig.json |
Option 1: watchexec (recommended)
Installation:
RUN wget -qO- https://github.com/watchexec/watchexec/releases/download/v1.25.1/watchexec-1.25.1-x86_64-unknown-linux-musl.tar.xz | tar xJv && \
mv watchexec-1.25.1-x86_64-unknown-linux-musl/watchexec /usr/local/bin/
Usage:
CMD ["watchexec", "-r", "-e", "go", "--", "go", "run", "main.go"]
Flags:
-r: Restart on file change-e go: Watch only *.go files--: Separator between watchexec flags and commandgo run main.go: Command to runExclude directories:
CMD ["watchexec", "-r", "-e", "go", "-i", "tmp/*", "-i", "vendor/*", "--", "go", "run", "main.go"]
Option 2: air
Installation:
RUN go install github.com/cosmtrek/air@latest
Configuration (.air.toml):
[build]
cmd = "go build -o ./tmp/main ."
bin = "tmp/main"
include_ext = ["go"]
exclude_dir = ["tmp", "vendor", ".git"]
delay = 1000 # ms
Usage:
CMD ["air"]
Key differences:
Purpose: Use framework-provided development servers with Hot Module Replacement.
Backstage:
FROM node:22
WORKDIR /workspace
EXPOSE 7007 3000
CMD ["yarn", "serve"]
Express/Custom:
FROM node:22
WORKDIR /workspace
EXPOSE 3000
CMD ["npm", "run", "dev"]
Key principles:
yarn serve, npm run dev)Ports:
Purpose: Provide manual control over rebuild timing for CLI tools.
Pattern:
FROM golang:1.23-alpine
RUN apk add --no-cache bash curl git
WORKDIR /workspace
CMD ["/bin/sh"]
Usage:
docker run -it -v $(pwd):/workspace app:dev
# Inside container:
go build -o cli .
./cli health
# Edit source, rebuild, test again
Key principles:
-it flag)Purpose: Expose all ports needed for development testing.
Go HTTP server:
EXPOSE 8080 # API server
Node.js backend (Backstage):
EXPOSE 7007 3000 # Backend API, Frontend dev server
Usage:
# Map all exposed ports
docker run -v $(pwd):/workspace -p 7007:7007 -p 3000:3000 app:dev
Key principles:
EXPOSEdocker run command (-p host:container)Purpose: Pass environment-specific configuration at runtime.
Pattern:
# ✓ Good: Pass env vars at runtime
docker run -v $(pwd):/workspace -p 8080:8080 \
-e DATABASE_URL=postgres://localhost/dev \
-e LOG_LEVEL=debug \
app:dev
Alternative: Use .env file:
docker run -v $(pwd):/workspace -p 8080:8080 \
--env-file .env \
app:dev
Key principles:
-e flag or --env-file.env file for multiple variablesPurpose: Include debugging tools not present in production images.
Pattern:
FROM golang:1.23-alpine
RUN apk add --no-cache bash curl git jq vim
WORKDIR /workspace
CMD ["watchexec", "-r", "-e", "go", "--", "go", "run", "main.go"]
Common tools:
bash: Interactive shellcurl: API testinggit: Version control operationsjq: JSON parsingvim or nano: Text editingKey principles:
Purpose: Minimize CPU usage and rebuild time for file watchers.
Exclude directories:
# watchexec
CMD ["watchexec", "-r", "-e", "go", "-i", "tmp/*", "-i", "vendor/*", "-i", ".git/*", "--", "go", "run", "main.go"]
# air (.air.toml)
[build]
exclude_dir = ["tmp", "vendor", "node_modules", ".git"]
Watch only source files:
# watchexec: Watch only *.go files
CMD ["watchexec", "-r", "-e", "go", "--", "go", "run", "main.go"]
Key principles:
Go services:
golang:1.23-alpinewatchexec or airbash, curl, gitWORKDIR /workspaceEXPOSE 8080)CMD ["watchexec", "-r", "-e", "go", "--", "go", "run", "main.go"]-v $(pwd):/workspaceNode.js services:
node:22WORKDIR /workspaceEXPOSE 7007 3000 (backend, frontend dev server)CMD ["yarn", "serve"]-v $(pwd):/workspaceCLI tools:
golang:1.23-alpinebash, curl, gitWORKDIR /workspaceCMD ["/bin/sh"]-v $(pwd):/workspaceGo services:
# Build and run
docker build -f Containerfile.dev -t app:dev .
docker run -v $(pwd):/workspace -p 8080:8080 app:dev
# Edit source file
echo "// test change" >> main.go
# Verify rebuild triggered (check logs)
docker logs <container-id>
# Expected: "watchexec: rebuilding..." or similar
# Test API
curl http://localhost:8080/healthz
Node.js services:
# Build and run
docker build -f Containerfile.dev -t app:dev .
docker run -v $(pwd):/workspace -p 7007:7007 -p 3000:3000 app:dev
# Edit source file
echo "// test change" >> src/index.ts
# Verify HMR triggered (check browser console or logs)
docker logs <container-id>
# Expected: "webpack compiled successfully" or similar
# Test API
curl http://localhost:7007/api/health
FROM golang:1.23-alpine
RUN apk add --no-cache bash curl git && \
wget -qO- https://github.com/watchexec/watchexec/releases/download/v1.25.1/watchexec-1.25.1-x86_64-unknown-linux-musl.tar.xz | tar xJv && \
mv watchexec-1.25.1-x86_64-unknown-linux-musl/watchexec /usr/local/bin/
WORKDIR /workspace
EXPOSE 8080
CMD ["watchexec", "-r", "-e", "go", "-i", "tmp/*", "--", "go", "run", "main.go"]
Usage:
docker build -f Containerfile.dev -t staccato-server:dev .
docker run -v $(pwd):/workspace -p 8080:8080 staccato-server:dev
FROM golang:1.23-alpine
RUN apk add --no-cache bash curl git
WORKDIR /workspace
CMD ["/bin/sh"]
Usage:
docker build -f Containerfile.dev -t staccato-cli:dev .
docker run -it -v $(pwd):/workspace staccato-cli:dev
# Inside container:
go build -o cli .
./cli health
FROM node:22
WORKDIR /workspace
EXPOSE 7007 3000
CMD ["yarn", "serve"]
Usage:
docker build -f Containerfile.dev -t backstage:dev .
docker run -v $(pwd):/workspace -p 7007:7007 -p 3000:3000 backstage:dev
Symptom: Source changes don't trigger rebuild/reload
Diagnosis:
# Verify volume mount
docker inspect <container-id> | grep Mounts -A 10
# Check if watch tool is running
docker exec <container-id> ps aux | grep watchexec
Solutions:
-v $(pwd):/workspace)Symptom: Container fails to start with "command not found"
Cause: Watch tool not installed in Containerfile
Solution:
# watchexec
RUN wget -qO- https://github.com/watchexec/watchexec/releases/download/v1.25.1/watchexec-1.25.1-x86_64-unknown-linux-musl.tar.xz | tar xJv && \
mv watchexec-1.25.1-x86_64-unknown-linux-musl/watchexec /usr/local/bin/
# air
RUN go install github.com/cosmtrek/air@latest
Symptom: Watch tool triggers on every file change, including build artifacts
Cause: Build artifacts (tmp/, dist/) not excluded from watch
Solution:
# watchexec: Exclude tmp/ and vendor/
CMD ["watchexec", "-r", "-e", "go", "-i", "tmp/*", "-i", "vendor/*", "--", "go", "run", "main.go"]
# air: Exclude in .air.toml
[build]
exclude_dir = ["tmp", "vendor", ".git"]
Symptom: docker run fails with "port is already allocated"
Cause: Another container or host process is using the port
Solution:
# Stop conflicting container
docker ps
docker stop <container-id>
# Or map to different host port
docker run -v $(pwd):/workspace -p 8081:8080 app:dev
Symptom: Container can't write to mounted volume
Cause: Container user UID doesn't match host user UID
Solution:
# Run container with host user UID
docker run --user $(id -u):$(id -g) -v $(pwd):/workspace app:dev
# Or fix permissions on host (not recommended for production)
chmod -R 777 <directory>
Symptom: Rebuild takes longer than expected
Cause: Dependencies re-downloaded on every rebuild
Solution:
go.mod and go.sum are cached (don't re-download dependencies)node_modules is not mounted from host (use named volume or install inside container)Symptom: Browser console shows websocket errors
Cause: Frontend dev server port not exposed or mapped correctly
Solution:
# Expose frontend dev server port
EXPOSE 7007 3000 # Backend, Frontend dev server
# Map frontend dev server port
docker run -v $(pwd):/workspace -p 7007:7007 -p 3000:3000 app:dev
Verify: Check browser console for websocket connection to ws://localhost:3000
tools
<!--VITE PLUS START--> # Using Vite+, the Unified Toolchain for the Web This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`. ## Vite+ Workflow `vp` is a global binary that handles the full development lifecycle. Run `vp help` to pr
development
Guide for building performant data tables. Uses tanstack-table for table logic (sorting, filtering, pagination) and tanstack-virtual for rendering large datasets efficiently.
development
Expert guidance for building observable, expressive, and fault-tolerant TypeScript applications using the effect-ts/effect ecosystem. Covers Effect<A, E, R> type, error management, dependency injection via Layers, observability (logging, metrics, tracing), concurrency with Fibers, retry/scheduling, Schema validation, Streams, and Sinks.
tools
Complete E2E (end-to-end) and integration testing skill for TypeScript/NestJS projects using Jest, real infrastructure via Docker, and GWT pattern. ALWAYS use this skill when user needs to: **SETUP** - Initialize or configure E2E testing infrastructure: - Set up E2E testing for a new project - Configure docker-compose for testing (Kafka, PostgreSQL, MongoDB, Redis) - Create jest-e2e.config.ts or E2E Jest configuration - Set up test helpers for database, Kafka, or Redis - Configure .env.e2e environment variables - Create test/e2e directory structure **WRITE** - Create or add E2E/integration tests: - Write, create, add, or generate e2e tests or integration tests - Test API endpoints, workflows, or complete features end-to-end - Test with real databases, message brokers, or external services - Test Kafka consumers/producers, event-driven workflows - Working on any file ending in .e2e-spec.ts or in test/e2e/ directory - Use GWT (Given-When-Then) pattern for tests **REVIEW** - Audit or evaluate E2E tests: - Review existing E2E tests for quality - Check test isolation and cleanup patterns - Audit GWT pattern compliance - Evaluate assertion quality and specificity - Check for anti-patterns (multiple WHEN actions, conditional assertions) **RUN** - Execute or analyze E2E test results: - Run E2E tests - Start/stop Docker infrastructure for testing - Analyze E2E test results - Verify Docker services are healthy - Interpret test output and failures **DEBUG** - Fix failing or flaky E2E tests: - Fix failing E2E tests - Debug flaky tests or test isolation issues - Troubleshoot connection errors (database, Kafka, Redis) - Fix timeout issues or async operation failures - Diagnose race conditions or state leakage - Debug Kafka message consumption issues **OPTIMIZE** - Improve E2E test performance: - Speed up slow E2E tests - Optimize Docker infrastructure startup - Replace fixed waits with smart polling - Reduce beforeEach cleanup time - Improve test parallelization where safe Keywords: e2e, end-to-end, integration test, e2e-spec.ts, test/e2e, Jest, supertest, NestJS, Kafka, Redpanda, PostgreSQL, MongoDB, Redis, docker-compose, GWT pattern, Given-When-Then, real infrastructure, test isolation, flaky test, MSW, nock, waitForMessages, fix e2e, debug e2e, run e2e, review e2e, optimize e2e, setup e2e