Configuration

Complete reference for fuku.yaml – services, tiers, profiles, and more.

Generate a config template with fuku init, or create fuku.yaml manually in your project root.

Services

Service definitions

Each service is defined with a name, directory, and optional settings:

fuku.yaml
services:
  backend:
    dir: backend # Path to service directory
    command: go run cmd/main.go # Custom start command (optional)
    tier: platform # Startup tier (optional)
    readiness: # Health check (optional)
      type: http
      url: http://localhost:8080/health
      timeout: 30s
      interval: 500ms
    logs: # Log output filter (optional)
      output: [stdout, stderr]
    watch: # Hot-reload config (optional)
      include: ["**/*.go"]
      ignore: ["**/*_test.go"]
      shared: ["pkg/common"]
      debounce: 1s
Field Description
dir Path to the service directory
command Custom start command (default: make run, which requires a Makefile with a run target in the service directory). Runs via sh -c, so shell features like pipes and env vars work
tier Startup tier for ordering. Services without a tier go to the default tier (runs last)
readiness Health check configuration (see Readiness Checks)
logs.output Output streams to capture: stdout, stderr, or both (default: both)
watch Hot-reload file watching configuration (see Hot-Reload)

Ordering

Tiers

Tiers control startup ordering. Services in earlier tiers start (and become ready) before later tiers begin. The order is determined by the first occurrence of each tier name in your config.

Common tier naming pattern:

  • foundation – core services (auth, config, gateway)
  • platform – business logic services
  • edge – client-facing services

Key points:

  • Tier order is defined by first appearance in the YAML file
  • Services within each tier are sorted alphabetically by name
  • Services without a tier are placed in a default tier that runs last
  • Tier names are case-insensitive and whitespace is trimmed
  • You can use any tier names you want – infrastructure, middleware, api, frontend, etc.

Grouping

Profiles

Profiles group services for batch operations:

fuku.yaml
defaults:
  profiles: [default] # Profiles used when no profile is specified

profiles:
  default: "*" # All services
  backend: [auth, backend] # Named list of services
  • "*" – selects all defined services
  • A list of service names – selects only those services
  • The defaults.profiles array controls which profiles run when you just type fuku

Concurrency

fuku.yaml
concurrency:
  workers: 5 # Max concurrent service starts (default: 5)

Controls how many services can start in parallel within a single tier.


Retry

fuku.yaml
retry:
  attempts: 3 # Max retry attempts (default: 3)
  backoff: 500ms # Initial backoff duration (default: 500ms)

Log Streaming

fuku.yaml
logs:
  buffer: 1000 # Broadcast channel depth for socket log streaming (default: 1000)
  history: 5000 # Number of recent log messages kept in memory for replay (default: 5000)

Logging

fuku.yaml
logging:
  format: console # "console" or "json"
  level: info # debug, info, warn, error

API

Server

Built-in REST API for external control. Disabled by default. When server.listen is set, server.auth.token is required. Probes (/api/v1/live, /api/v1/ready) are unauthenticated; all other endpoints require a bearer token.

fuku.yaml
server:
  listen: "127.0.0.1:9876" # TCP address to bind (must be loopback)
  auth:
    token: "my-dev-token" # Bearer token for authentication

Overrides

Local overrides

Create fuku.override.yaml (or fuku.override.yml) next to your base config to add local customizations without modifying the shared project config. Override files are typically .gitignored.

fuku.override.yaml
services:
  api:
    command: "dlv debug ./cmd/main.go" # override start command
    watch:
      include: ["*.templ"] # appended to base includes
  debug-tool:
    dir: tools/debug # add a local-only service

logging:
  level: debug # override log level

Merge Rules

Type Behavior
Scalar Override replaces base
Map Deep merge recursively (base key order preserved)
Array Override items appended after base items (no deduplication)
Null Removes the key from merged config (e.g. watch: null)
Mismatched types Override replaces base

Important Notes

  • Override loading is automatic when using default config discovery (fuku.yaml / fuku.yml)
  • Explicit --config disables override loading entirely
  • An override file without a base config is ignored
  • Null removal applies to the merged YAML – some removed keys may still have runtime defaults (e.g. logging: null still gets default log level)
  • If both fuku.override.yaml and fuku.override.yml exist, .yaml wins

DRY config

YAML anchors

Use YAML anchors (&) and merge keys (<<: *) to avoid repeating common configuration. Top-level keys prefixed with x- are ignored by fuku and serve as anchor definitions.

fuku.yaml
x-readiness-http: &readiness-http
  type: http
  timeout: 30s
  interval: 500ms

x-watch: &watch
  include: ["**/*.go"]
  ignore: ["**/*_test.go"]
  debounce: 1s

services:
  api:
    dir: ./api
    readiness:
      <<: *readiness-http
      url: http://localhost:8080/health
    watch:
      <<: *watch

Reference

Full example

fuku.yaml
version: 1

x-readiness-http: &readiness-http
  type: http
  timeout: 30s
  interval: 500ms

x-readiness-log: &readiness-log
  type: log
  pattern: "Service ready"
  timeout: 30s

x-logs: &logs
  output: [stdout, stderr]

x-watch: &watch
  include: ["**/*.go"]
  ignore: ["**/*_test.go"]
  shared: ["pkg/common"]
  debounce: 1s

services:
  auth:
    dir: auth
    tier: foundation
    command: go run cmd/main.go
    readiness:
      <<: *readiness-http
      url: http://localhost:8081/health

  backend:
    dir: backend
    tier: platform
    command: go run cmd/main.go
    readiness:
      <<: *readiness-http
      url: http://localhost:8080/health
    logs:
      <<: *logs
    watch:
      <<: *watch

  web:
    dir: frontend
    tier: edge
    readiness:
      <<: *readiness-http
      url: http://localhost:3000/health

defaults:
  profiles: [default]

profiles:
  default: "*"
  backend: [auth, backend]

concurrency:
  workers: 5

retry:
  attempts: 3
  backoff: 500ms

logs:
  buffer: 1000
  history: 5000

logging:
  format: console
  level: info

server:
  listen: "127.0.0.1:9876"
  auth:
    token: "my-dev-token"