Development Commands
Development server and tools for local development
Development Commands
The forge dev command provides development tools and server management for local development. It supports hot reload, app discovery, Docker container development, and interactive development workflows.
Main Command
forge dev
Start development server and tools.
forge dev # Interactive app selection
forge dev -a api-gateway # Run specific app
forge dev -a api -p 8080 # Run on specific port
forge dev --watch # With hot reload (default)
forge dev --docker # Run inside Docker container
forge dev -d -a api --network forge-net # Docker with custom networkFlags:
-a, --app- App to run-w, --watch- Watch for changes (default:true)-p, --port- Port number-d, --docker- Run inside Docker container--network- Docker network name (requires--docker)
Behavior:
- If no app is specified, shows an interactive app selector
- Automatically discovers apps in your project
- Supports both single-module and multi-module layouts
- Sets
PORTenvironment variable if specified - With
--docker, builds a dev image and runs the app in a container with bind-mount hot reload
Subcommands
forge dev list (aliases: ls)
List all available apps in your project.
forge dev list
forge dev lsOutput: Shows a table with app information:
- Name: App name
- Type: App type (usually "app")
- Location: Path to app directory
- Status: Ready status
Example Output:
Name Type Location Status
api-gateway app cmd/api-gateway Ready
auth-service app cmd/auth-service Readyforge dev build
Build app for development.
forge dev build -a api-gateway
forge dev build --app auth-serviceFlags:
-a, --app- App to build (required)
Behavior:
- Builds the specified app using
go build - Outputs to
bin/<app-name>directory - Shows build progress with spinner
- Displays success/failure status
App Discovery
Forge automatically discovers apps in your project based on the layout:
Single-Module Layout
For single-module projects, Forge scans the cmd/ directory:
my-project/
cmd/
api-gateway/
main.go
auth-service/
main.go
worker/
main.go
.forge.yamlMulti-Module Layout
For multi-module projects, Forge scans the apps/ directory:
my-project/
apps/
api-gateway/
cmd/
server/
main.go
auth-service/
cmd/
server/
main.go
worker/
cmd/
server/
main.go
.forge.yamlDevelopment Features
Hot Reload
Hot reload automatically restarts your application when files change:
forge dev --watchThe file watcher monitors .go files across your project and uses a configurable debounce delay (default: 300ms) to avoid rapid successive restarts. Configure watch behavior in .forge.yaml:
dev:
hot_reload:
enabled: true
delay: 500ms # debounce delay before restart
watch:
enabled: true
paths:
- "./apps/**/internal/**/*.go"
- "./pkg/**/*.go"
- "./internal/**/*.go"
exclude:
- "**/*_test.go"
- "**/testdata/**"
- "**/vendor/**"Port Configuration
Set a custom port for your application:
forge dev -p 3000
forge dev --port 8080Port precedence:
--portCLI flag (highest priority)- App-level
.forge.yamlport (apps/<name>/.forge.yaml→dev.port) - Application default (no
PORTenv var set)
Interactive App Selection
When no app is specified, Forge shows an interactive selector:
forge devOutput:
? Select app to run:
api-gateway
auth-service
workerDocker Development Mode
The --docker (or -d) flag runs your app inside a Docker container with bind-mounted source code and hot reload. This ensures your development environment mirrors production and works consistently across machines.
Quick Start
# Run an app in Docker with hot reload
forge dev --docker -a api-gateway
# With port forwarding
forge dev -d -a api-gateway -p 8080
# With a custom Docker network
forge dev -d -a api-gateway --network forge-netHow It Works
When you run forge dev --docker, Forge performs the following steps:
- Verify Docker — checks that the
dockerbinary is inPATHand the daemon is running. - Resolve config — merges project-level
dev.docker, app-leveldev.docker, and CLI flags (highest priority). - Build dev image — uses your custom
Dockerfileif configured, otherwise auto-generates a development-optimized Dockerfile. - Run container — starts the container with the project root bind-mounted to
/app, port forwarding, and environment variables. - Watch for changes — monitors
.gofiles on the host; on change, restarts the container (docker restart) after a debounce delay. - Stream logs — container stdout/stderr is streamed to your terminal in real time.
- Graceful shutdown —
Ctrl+Cstops and removes the container.
The container name follows the pattern forge-dev-<app-name> and the image is tagged forge-dev-<app-name>:latest. Any previous container with the same name is automatically removed before starting.
Auto-Generated Dev Dockerfile
When no custom Dockerfile is configured, Forge generates a temporary Dockerfile optimized for development:
# Auto-generated by forge dev --docker
FROM golang:1.25-alpine
RUN apk add --no-cache git
WORKDIR /app
COPY go.mod go.sum* ./
RUN go mod download
# Forge config files
COPY .forge.yaml ./
COPY config/ ./config/
COPY . .
CMD ["go", "run", "./cmd/api-gateway"]The generator automatically discovers and adds COPY directives for:
.forge.yaml/.forge.ymlproject configconfig/directoryconfig.yaml,config.local.yamlruntime configs.env*files- Per-app
.forge.yamlfiles inapps/ database/directory (migrations and seeds)
This ensures Forge config files have their own Docker cache layer, so rebuilds after a source change do not re-download Go modules.
Docker Dev Configuration
Configure Docker dev settings at the project level in .forge.yaml:
dev:
docker:
image: golang:1.25-alpine # Base image (default: golang:1.25-alpine)
dockerfile: "" # Custom Dockerfile path (empty = auto-generate)
network: bridge # Docker network (default: bridge)
platform: linux/amd64 # Target platform (optional)
volumes: # Extra host:container volume mounts
/tmp/go-cache: /root/.cache/go-build
env: # Extra environment variables
DEBUG: "true"
LOG_LEVEL: debug
build_args: # Docker build arguments
GO_VERSION: "1.25"| Field | Type | Default | Description |
|---|---|---|---|
image | string | golang:1.25-alpine | Base Docker image for the dev container |
dockerfile | string | "" (auto-generate) | Path to a custom Dockerfile for dev |
network | string | bridge | Docker network to attach the container to |
platform | string | "" | Target platform (e.g., linux/amd64) |
volumes | map[string]string | {} | Extra volumes — key is host path, value is container path |
env | map[string]string | {} | Extra environment variables injected into the container |
build_args | map[string]string | {} | Docker build arguments passed to docker build |
Per-App Docker Configuration
Override Docker settings for individual apps by placing a .forge.yaml in the app's directory:
# apps/api-gateway/.forge.yaml
app:
name: api-gateway
type: web
dev:
port: 8080
docker:
image: golang:1.25-bookworm # Use Debian instead of Alpine
network: api-network
env:
SERVICE_NAME: api-gateway
volumes:
./certs: /app/certsConfig merging follows this priority (highest to lowest):
- CLI flags —
--networkoverrides everything - App-level
apps/<name>/.forge.yaml→dev.docker - Project-level
.forge.yaml→dev.docker
Maps (volumes, env, build_args) are merged — app-level keys override project-level keys with the same name; unique keys from both levels are preserved.
Custom Dev Dockerfile
For advanced setups, point to your own Dockerfile:
dev:
docker:
dockerfile: docker/dev.Dockerfile# docker/dev.Dockerfile
FROM golang:1.25-bookworm
# Install system dependencies
RUN apt-get update && apt-get install -y \
protobuf-compiler \
&& rm -rf /var/lib/apt/lists/*
# Install Go tools
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
CMD ["go", "run", "./cmd/api-gateway"]Docker Networking for Multi-Service Dev
When developing multiple services locally, use a shared Docker network so containers can reach each other by name:
# Create a shared network
docker network create forge-net
# Start each service on the shared network
forge dev -d -a api-gateway --network forge-net -p 8080
forge dev -d -a auth-service --network forge-net -p 8081
forge dev -d -a user-service --network forge-net -p 8082Or configure the network in .forge.yaml so you don't need the --network flag:
dev:
docker:
network: forge-netInside the containers, services can reach each other using the container name:
// From api-gateway container, call auth-service
resp, err := http.Get("http://forge-dev-auth-service:8081/verify")Each forge dev -d command runs in the foreground and streams logs. Open separate terminal windows for each service, or use a process manager like tmux or foreman.
Environment Variables
Forge injects the following environment variables into every Docker dev container automatically:
| Variable | Value | Description |
|---|---|---|
FORGE_DEV | true | Indicates development mode |
FORGE_HOT_RELOAD | true | Indicates hot reload is active |
FORGE_DOCKER | true | Indicates running inside Docker |
PORT | <port> | Only set if --port flag was provided |
Additional variables from dev.docker.env are appended after these defaults.
Project Requirements
Forge Project
The forge dev command requires a Forge project with a .forge.yaml file:
# If not in a Forge project
forge dev
# Error: no .forge.yaml found in current directory or any parent
# This doesn't appear to be a Forge project.
# To initialize a new project, run:
# forge initApp Structure
Each app must have a main.go file with a main() function:
package main
import (
"log"
"github.com/xraph/forge"
)
func main() {
app := forge.NewApp(forge.AppConfig{
Name: "my-app",
Version: "0.1.0",
})
// Register routes
app.Router().GET("/", func(c forge.Context) error {
return c.JSON(200, forge.Map{
"message": "Hello from my-app!",
})
})
// Start server
if err := app.Run(); err != nil {
log.Fatal(err)
}
}Configuration
Development Configuration
Configure development settings in .forge.yaml:
dev:
port: 8080
hot_reload: true
debug: true
extensions:
- auth
- databaseEnvironment Variables
Set environment variables for development:
export PORT=3000
export DEBUG=true
export LOG_LEVEL=debug
forge devTroubleshooting
No Apps Found
If no apps are found:
forge dev
# Warning: No apps found. Create one with: forge generate appSolution:
forge generate app --name=my-appApp Not Found
If the specified app doesn't exist:
forge dev -a nonexistent-app
# Error: app not found: nonexistent-appSolution:
# List available apps
forge dev list
# Or create the app
forge generate app --name=nonexistent-appBuild Failures
If app build fails:
forge dev build -a my-app
# Build failedCommon causes:
- Missing dependencies
- Syntax errors in code
- Missing main.go file
Solution:
# Retry the build
forge dev build -a my-app
# Install dependencies
go mod tidy
# Verify main.go exists
ls cmd/my-app/main.goBest Practices
- Use Interactive Mode — Let Forge discover and select apps automatically.
- Set Custom Ports — Use
-pflag to avoid port conflicts. - Enable Hot Reload — Watch mode is on by default; configure debounce delay if restarts are too frequent.
- Check App Status — Use
forge dev listto verify available apps. - Build Before Dev — Use
forge dev buildto catch build errors early. - Use Docker for Consistency — Use
--dockerto ensure your dev environment matches production (same OS, same Go version). - Shared Networks — When running multiple services in Docker, use a shared
--networkso containers can communicate by name. - Cache Go Modules — Mount a volume for the Go module cache to speed up Docker rebuilds:
dev: docker: volumes: /tmp/forge-gomod: /go/pkg/mod
For more information about code generation, see the Code Generation Commands documentation.
How is this guide?