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
    env: # Files surfaced in the TUI info aside (optional)
      files: [.env, .env.local, .env.development, .env.development.local]
FieldDescription
dirPath to the service directory
commandCustom 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
tierStartup tier for ordering. A service without one gets defaults.tier when set, else the default tier (runs last)
readinessHealth check configuration (see Readiness Checks)
logs.outputOutput streams to capture: stdout, stderr, or both (default: both)
watchHot-reload file watching configuration (see Hot-Reload)
env.filesList of .env files (relative to dir) parsed and shown in the TUI info aside's env tab. Defaults to .env, .env.local, .env.development, .env.development.local. Values are display-only — fuku does not export them to the child process

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

Set a project-wide fallback tier with defaults.tier:

fuku.yaml
defaults:
  tier: foundation # Tier for a service that sets none

Key points:

  • Tier order is defined by first appearance in the YAML file
  • Services within each tier are sorted alphabetically by name
  • A service without a tier gets defaults.tier when it's set, else it's 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
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 default profile runs 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. It listens on 127.0.0.1:3858 by default. Set server.listen to "" or none, or FUKU_API_DISABLED=1, to turn it off. A missing listen keeps the default. The token is optional. When server.auth.token is set, every endpoint except the probes (/api/v1/live, /api/v1/ready) requires a bearer token.

fuku.yaml
server:
  listen: "127.0.0.1:3858" # loopback address, default; "" or none turns the API off
  auth:
    token: "my-dev-token" # optional, requires a bearer token when set

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

exclude:
  - heavy-worker                        # skip this service locally

logging:
  level: debug # override log level

Merge Rules

TypeBehavior
ScalarOverride replaces base
MapDeep merge recursively (base key order preserved)
ArrayOverride items appended after base items (no deduplication)
NullRemoves the key from merged config (e.g. watch: null)
Mismatched typesOverride replaces base

Important Notes

  • Override loading is automatic when using default config discovery (fuku.yaml / fuku.yml)
  • Explicit --config skips the override merge
  • Fuku still checks for the override file under --config. An error other than a missing file, such as a permission error, fails the load
  • 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

Skipping services

Excluding services

Use the top-level exclude list to skip services at discovery time without mutating the service catalog. Excluded services keep their definitions in services: – so profile lists referencing them still pass config validation – and fuku run silently drops them at startup. This is the recommended way to disable services locally via fuku.override.yaml.

fuku.override.yaml
exclude:
  - heavy-worker
  - flaky-integration
  • Entries are trimmed of whitespace and deduplicated
  • Names that aren't defined in services: are ignored at runtime
  • Profile references to excluded services remain valid – they're filtered out before startup

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

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:3858"
  auth:
    token: "my-dev-token"