Configuration Reference

Wippy reads runtime configuration from .wippy.yaml files.

Use the repeatable wippy run --set section.path=value option to override the configuration fields below at launch. To override individual registry entries rather than configuration sections, use the override: section or -o; see Overriding Entries.

Config Composition

--config is repeatable; files compose left to right using the same schema:

wippy run --config .wippy.yaml --config .wippy.local.yaml
  • Later files override matching values and keep everything else.
  • Every explicitly named file must exist. Without --config, the default .wippy.yaml is optional.
  • The first file anchors the directory used to resolve relative paths.
  • Filenames carry no reserved meaning; nothing besides the default is auto-discovered.

Configuration applies in this order: composed files, selected --profile overlays, and then --set overrides. For applications run from packs, packed runtime defaults have lower precedence than all three; see Publishing Runtime Defaults.

Profiles

A configuration file may declare named overlays under profiles:. Each profile body mirrors the standard configuration sections. Selecting it with --profile <name> applies those values over the merged base configuration:

version: "1.0"

vars:
  port: 8085

override:
  app:db:kind: db.sql.sqlite

disable:
  namespaces: ["legacy.**"]

profiles:
  pg:
    vars:
      port: 18085
    override:
      app:db:kind: db.sql.postgres
    disable:
      namespaces.add: ["experimental.**"]
wippy run --profile pg
  • --profile is repeatable; profiles compose left to right, after file composition and before --set. An unknown name is an error.
  • Values merge per leaf (last writer wins). The profiles: section itself is stripped from the resolved config.
  • The disable section supports list operations inside profiles — namespaces.add, namespaces.remove, entries.add, entries.remove — so a profile can adjust the base list instead of replacing it.
  • ${name} references interpolate from the merged vars: section. OS environment references are not allowed inside profile vars; use ${env:NAME} in the base config, resolved at file load.

wippy run, test, and pack accept --profile; run list, install, update, lint, and registry accept it as well for workspace profiles (together with --set). Applications can ship profiles inside packs — see Publishing Profiles.

Logger

Controls the zap logger encoder. CLI flags (-v, -c, -s) override the level and output; encoding is the only YAML-configured option.

Field Type Default Description
encoding string console Encoder: console (humanized) or json (structured)
logger:
  encoding: json

Log Manager

Controls runtime log routing. Console output is configured via CLI flags (-v, -c, -s).

Field Type Default Description
propagate_downstream bool true Send logs to console/file output
stream_to_events bool false Publish logs to event bus for programmatic access
min_level int 0 (-1 with -v) Minimum level: -1=debug, 0=info, 1=warn, 2=error. The CLI writes this key from its flags after the file is read, so a file value is ignored; change it with --set logmanager.min_level=<n>
logmanager:
  propagate_downstream: true
  stream_to_events: false

See: Logger Module

Profiler

Go pprof HTTP server for CPU/memory profiling. Enable with -p flag or config.

Field Type Default Description
enabled bool false Start profiler server
address string localhost:6060 Listen address
read_timeout duration 15s HTTP read timeout
write_timeout duration 15s HTTP write timeout
idle_timeout duration 60s Keep-alive timeout
profiler:
  enabled: true
  address: "localhost:6060"

When enabled with the default address, the profiler is available at http://localhost:6060/debug/pprof/.

Security

Global security behavior. Individual policies are defined as security.policy entries.

Field Type Default Description
strict_mode bool true Deny access when the security context is incomplete
security:
  strict_mode: false

See: Security System, Security Module

Registry

Entry storage and version history. The registry holds all configuration entries.

Field Type Default Description
enable_history bool true Track entry versions
history_type string memory Storage: memory, sqlite, postgres, nil
history_path string .wippy/registry.db SQLite file path (used when history_type: sqlite)
history_dsn string Postgres DSN (used when history_type: postgres)
history_schema string Postgres schema name (used when history_type: postgres)
event_wait_timeout duration 30s Per-operation wait for listener acknowledgement during a registry apply
dispatch_internal_kinds string[] [registry.entry, ns.dependency, ns.requirement, ns.definition] Entry kinds handled internally instead of dispatched to component listeners
dependency_resolve_timeout duration 0 (none) Bound on dependency resolution
dependency_download_timeout duration 0 (none) Bound on each module download and download-URL request
dependency_lock_path string discovered wippy.lock Lock file the dependency handler reads and writes
dependency_vendor_dir string <lock dir>/<directories.modules>/vendor Directory holding downloaded module packs
registry:
  history_type: sqlite
  history_path: /var/lib/wippy/registry.db
registry:
  history_type: postgres
  history_dsn: ${env:WIPPY_REGISTRY_HISTORY_DSN}
  history_schema: wippy_registry

See: Registry Concept, Registry Module

Artifact

Output root for materialized build-time artifacts.

Field Type Default Description
materialization_root string parent of the dependency vendor directory Application-owned root under which each artifact format writes its own subtree
artifact:
  materialization_root: build/wippy

See: Build-time artifacts

Workspace

Local module replacements, keyed by org/module. Values are directories; relative paths resolve against the first --config file's directory, and null disables a replacement inherited from an earlier config layer or profile.

workspace:
  replacements:
    acme/http: ../local-http
    acme/sql: null

Replacements are never written to wippy.lock. See Local Development with Replacements.

Relay

Message routing between processes across nodes.

Field Type Default Description
node_name string derived per-instance ID Identifier for this relay node (default: UUIDv5 of machine-id/hostname + working dir; overridable via WIPPY_NODE_ID / WIPPY_RELAY_NODE_NAME)
relay:
  node_name: worker-1

See: Process Model

Supervisor

Service lifecycle management. Controls the supervisor's internal control mailbox used to dispatch lifecycle events.

Field Type Default Description
host.buffer_size int 1024 Internal control mailbox capacity
host.worker_count int 16 Concurrent dispatcher workers
supervisor:
  host:
    buffer_size: 2048
    worker_count: 32

See: Supervision Guide

Per-`process.host` workers and queues are configured on the entry itself (`workers`, `queue_size`, `local_queue_size`), not in this global section. See the [Process Host](system/process-host.md) entry kind.

Lua Runtime

Lua VM caching and expression evaluation.

Field Type Default Description
cache.enabled bool type_system.enabled Persist compiled bytecode/typecheck cache to disk; follows type_system.enabled unless set explicitly
cache.dir string .wippy/cache/lua Cache directory path (relative to the config/working directory)
cache.mode string readwrite Cache mode: readwrite (default), readonly, off; unknown values fall back to readwrite
cache.compile.enabled bool true Persist compiled bytecode (when cache.enabled)
cache.typecheck.enabled bool true Persist typecheck results (when cache.enabled)
cache.max_bytes int 1073741824 On-disk cache size ceiling in bytes
cache.max_entries int 20000 Maximum cached entries
cache.prune_interval int 256 Writes between cache prune passes
type_system.enabled bool false Enable static type checking
type_system.strict bool false Treat type warnings as errors
invalidation_wait_timeout duration registry.event_wait_timeout (30s) Wait for code invalidation to be acknowledged after an entry changes
eval.max_steps int 10000 Default scheduler-step budget for an eval run; negative values are rejected
eval.cache_size int 256 Compiled-program cache entries for evaluated source
eval.cache_ttl duration 0 (no expiry) Lifetime of a cached compiled program
lua:
  cache:
    enabled: true
    dir: .cache/lua
  type_system:
    enabled: true

See: Lua Overview

Scheduler

Core partitioning for the WASM runtime. When enabled, reserved_cores CPUs are set aside for WASM execution and the rest serve the actor scheduler; an invalid split (for example more reserved cores than available) is logged and ignored.

Field Type Default Description
wasm_isolation.enabled bool false Partition cores between WASM and actor work
wasm_isolation.reserved_cores int 1 Cores reserved for WASM execution
scheduler:
  wasm_isolation:
    enabled: true
    reserved_cores: 2

Finder

Registry search caching. Used internally for entry lookups.

Field Type Default Description
query_cache_size int 1000 Cached query results
regex_cache_size int 100 Compiled regex patterns
finder:
  query_cache_size: 2000

OpenTelemetry

Distributed tracing and metrics export via OTLP.

Field Type Default Description
enabled bool false Enable OTEL
endpoint string localhost:4318 OTLP endpoint
protocol string http/protobuf Protocol: grpc, http/protobuf
service_name string wippy-runtime Service identifier
service_version string Service version tag
insecure bool true Allow plaintext OTLP connection
sample_rate float 1.0 Trace sampling (0.0-1.0)
propagators string[] [tracecontext, baggage] Context propagators
traces_enabled bool true Export traces
metrics_enabled bool false Export metrics
http.enabled bool true Trace HTTP requests
http.extract_headers bool true Extract trace context from inbound headers
http.inject_headers bool true Inject trace context into the HTTP response
process.enabled bool true Trace process lifecycle
process.trace_lifecycle bool true Emit spans for spawn/terminate
interceptor.enabled bool true Trace function calls
interceptor.order int 100 Decoded compatibility field; runtime v0.3.32a registers the interceptor at order 100 regardless of this value
queue.enabled bool true Trace queue publish/consume
temporal.enabled bool false Trace Temporal workflows
otel:
  enabled: true
  endpoint: "http://jaeger:4318"
  traces_enabled: true
  process:
    trace_lifecycle: true

Standard OTEL environment variables (OTEL_SDK_DISABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_INSECURE, OTEL_SERVICE_NAME, OTEL_SERVICE_VERSION, OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG, OTEL_PROPAGATORS) override the matching fields.

See: Observability Guide

Shutdown

Graceful shutdown behavior.

Field Type Default Description
timeout duration 30s Max wait for components to stop
shutdown:
  timeout: 60s

Metrics

Internal metrics collection buffer.

Field Type Default Description
buffer.size int 10000 Metrics buffer capacity
interceptor.enabled bool true Auto-track function calls
metrics:
  buffer:
    size: 20000
  interceptor:
    enabled: true

See: Metrics Module, Observability Guide

Prometheus

Prometheus metrics endpoint.

Field Type Default Description
enabled bool false Start metrics server
address string Listen address; must be set explicitly when enabled: true, otherwise the metrics server does not start
max_cardinality int 1024 Distinct label sets retained per metric (LRU); 0 or less uses the default
prometheus:
  enabled: true
  address: "0.0.0.0:9090"

Exposes /metrics endpoint for Prometheus scraping, plus /livez.

See: Observability Guide

Cluster

Multi-node clustering: gossip membership plus a bounded Raft consensus core. See the Cluster Guide for the architecture and operational model; this section is the config-key reference.

Top-level

Field Type Default Description
enabled bool false Enable clustering
name string hostname Node name; must be unique across the cluster
failure_domain string Zone/rack label; advertised in gossip so voters spread across domains
kv_crdt_tombstone_retention duration 0 Age after which store.kv.crdt delete tombstones are reclaimed; 0 disables age-based GC
kv_crdt_tombstone_gc_alive_peers bool false Use the current alive membership as the tombstone acknowledgement set

Membership (gossip)

SWIM gossip via memberlist. Used for node discovery, failure detection, and metadata dissemination.

Field Type Default Description
membership.bind_addr string 0.0.0.0 Gossip bind address
membership.bind_port int 7946 Gossip bind port (TCP+UDP)
membership.advertise_addr string Address peers use to reach this node (NAT/k8s)
membership.join_addrs string Comma-separated seed host:port pairs
membership.secret_key string Base64-encoded gossip encryption key (inline)
membership.secret_file string Path to file holding the gossip encryption key
membership.gossip_interval duration 500ms Gossip dissemination period
membership.push_pull_interval duration 5s Full state sync period
membership.dead_node_reclaim_time duration 30s When a dead node's name/address can be reclaimed
membership.probe_interval duration 1s Failure-detection probe cycle
membership.probe_timeout duration 200ms Ack wait per probe
membership.tcp_timeout duration 1s TCP fallback probe timeout
membership.suspicion_mult int 3 Suspicion timeout multiplier

A gossip secret is required. Set membership.secret_key or membership.secret_file (the file wins if both are given); with neither, the cluster component fails to start. The value is base64-encoded.

The four probe keys inherit memberlist's local-network defaults when unset; raise them for high-latency links (e.g. probe_interval: 2s, probe_timeout: 500ms, suspicion_mult: 5).

Internode (transport)

TCP mesh carrying the relay and Raft traffic between nodes. Raft rides this mesh over internode request/reply; there is no separate Raft port.

Field Type Default Description
internode.bind_addr string 0.0.0.0 Mesh bind address
internode.bind_port int 0 Mesh port (0 = auto: 7950-7959, then ephemeral)
internode.auto_port bool true Discover the actual port at boot, pin it, and advertise it in gossip
internode.advertise_addr string Additional relay endpoint (IP or DNS name) published for upgraded peers — for NAT or load-balanced reachability
internode.advertise_port int 0 Port for advertise_addr (0 = bind port; requires advertise_addr)
internode.identity_key string Base64-encoded ed25519 private key identifying this node (inline)
internode.identity_key_file string Path to a file holding that key
internode.trusted_peer_keys map Base64-encoded ed25519 public key per node name, including this node
internode.tls.enabled bool false Enable mutual TLS on the internode TCP mesh
internode.tls.cert_file string PEM node certificate; required with TLS
internode.tls.key_file string Matching private key; required with TLS
internode.tls.ca_file string PEM CA bundle for client and server verification; required with TLS

advertise_addr/advertise_port publish an additive endpoint in node metadata while the bind endpoint stays advertised unchanged, so mixed-version clusters keep connecting during a rolling upgrade.

Internode identity is mandatory whenever clustering is enabled. identity_key and identity_key_file are mutually exclusive and one of them must be present; the value decodes (standard or raw base64) to either a 32-byte ed25519 seed or a 64-byte ed25519 private key. trusted_peer_keys maps each node name to that node's 32-byte ed25519 public key, and must contain an entry for the local cluster.name whose value matches the local identity — otherwise startup fails. See the Cluster Guide.

TLS requires all three credential paths and TLS 1.2 or later. Unknown settings, invalid values, unreadable or invalid credentials, and credential paths supplied while TLS is disabled fail startup. The ed25519 identity configuration remains required. See Internode TLS for an example.

Raft (consensus)

The bounded Raft core stores durable state under raft.data_dir by default (~/.wippy/store). A restarted node rejoins quorum from its peers. store.kv.raft entries replicate through this core, and gossip coordinates bootstrap using a bootstrap_expect model.

Field Type Default Description
raft.data_dir string ~/.wippy/store Directory for fs-durable Raft state and durable CRDT snapshots (under <data_dir>/_sys/). Diskless only when no path resolves (no home dir and none set)
raft.enabled bool true Run a Raft node; false makes this a gossip-only client
raft.role string server server runs a Raft node; client is gossip-only
raft.eligible bool true Whether this node may be selected as a voter or standby; false keeps it outside Raft as a client
raft.priority int 100 Voter selection priority (lower is preferred)
raft.bootstrap_expect int 1 Initial quorum size: 0=join existing, 1=single-node, N=wait for N eligible nodes including the local node, then form quorum
raft.max_voters int 5 Voter ceiling (must be odd); up to max_standbys additional eligible nodes become standbys, and the rest remain clients
raft.max_standbys int 4 Non-voting members kept warm for promotion; nodes beyond voters+standbys are not Raft members
raft.reconcile_debounce duration 2s Coalesce window after a gossip event before the voter reconciler runs
raft.reconcile_timeout duration 2s Bound per reconcile pass
raft.heartbeat_timeout duration 3s Follower idle wait before starting an election
raft.election_timeout duration 3s Candidate election timeout (clamped to >= heartbeat)
raft.commit_timeout duration 500ms Idle leader heartbeat cadence
raft.snapshot_threshold uint64 8192 Log entries since last snapshot before a new one
raft.snapshot_interval duration 2m Snapshot check interval
raft.snapshot_retain int 3 Snapshots retained
raft.trailing_logs uint64 10240 Log entries retained after a snapshot
raft.max_append_entries int 16 Max entries per AppendEntries RPC
raft.leader_probe_interval duration 3s Global-registry leader-reachability probe cadence
raft.leader_probe_grace int 3 Consecutive probe failures before leader is declared unreachable
raft.registry_backend string kv Cluster name-registry implementation: kv (shared kv keyspace) or fsm (dedicated Raft FSM)
raft.global_dissem_tombstone_retention duration 0 How long the global-name dissemination cache keeps delete tombstones

Single-node (development) — clustering on, bootstraps itself immediately:

cluster:
  enabled: true
  name: dev
  membership:
    secret_key: "d2lwcHktZG9jcy1nb3NzaXAtc2VjcmV0LTMyYnl0ZXM="
  internode:
    identity_key: "d2lwcHktZG9jcy1kZXYtbm9kZS1leGFtcGxlc2VlZCE="
    trusted_peer_keys:
      dev: "rNqImcjOzef28dzvma80mSrCW1px5LBAc5TbaYqAgm0="
  raft:
    bootstrap_expect: 1

Three-node voting cluster — each node lists the others as seeds and waits for all three before forming quorum. Every node carries the same trusted_peer_keys map and its own private key:

cluster:
  enabled: true
  name: node-1
  failure_domain: us-east-1a
  membership:
    bind_port: 7946
    join_addrs: "node-2:7946,node-3:7946"
    secret_file: /etc/wippy/cluster.key
  internode:
    identity_key_file: /etc/wippy/node-1.key
    trusted_peer_keys:
      node-1: "okmamN3PKkMpPwPBurknHy2Wi3dwp/rz+uTM2fF9aD0="
      node-2: "PWX+oOYrFdtjUxbgmTkXCFI0KEvG++ZM52HOWfDkqP8="
      node-3: "QfP0fgllbj4s95VAztTORhy3bv9mst1l0lwuUNvO/hE="
  raft:
    bootstrap_expect: 3
    max_voters: 5

Gossip-only client — joins the cluster for naming/messaging but never runs Raft. It still needs its own identity and must appear in every node's trusted map:

cluster:
  enabled: true
  name: edge-7
  membership:
    join_addrs: "node-1:7946,node-2:7946"
    secret_file: /etc/wippy/cluster.key
  internode:
    identity_key_file: /etc/wippy/edge-7.key
    trusted_peer_keys:
      node-1: "okmamN3PKkMpPwPBurknHy2Wi3dwp/rz+uTM2fF9aD0="
      node-2: "PWX+oOYrFdtjUxbgmTkXCFI0KEvG++ZM52HOWfDkqP8="
      node-3: "QfP0fgllbj4s95VAztTORhy3bv9mst1l0lwuUNvO/hE="
      edge-7: "7lzP4jBAkC3P+0jq4vtMsC45571BlVXk3mSlOD/Z0SA="
  raft:
    role: client

LSP

Language Server Protocol server for editor integrations.

Field Type Default Description
enabled bool false Enable the LSP service and TCP server; the HTTP transport also requires this
address string :7777 TCP listen address
http_enabled bool false Enable the HTTP transport
http_address string :7778 HTTP listen address
http_path string /lsp HTTP endpoint path
http_allow_origin string * CORS allowed origin
max_message_bytes int 8388608 Max incoming message size
lsp:
  enabled: true
  address: ":7777"
  http_enabled: true

See: LSP Guide

Network Service

Overlay network manager (SOCKS5, I2P, Tailscale drivers).

Field Type Default Description
state_dir string .wippy/net Driver state storage directory
default_network string Default network ID applied when entries omit network
network_service:
  state_dir: /var/lib/wippy/net
  default_network: app:tailscale

See: Network Overlays

HTTP Dispatcher

Tuning for the shared HTTP client pool used by HTTP-dispatched functions and outbound requests.

Field Type Default Description
dispatcher.http.timeout duration 0 (none) Per-request timeout
dispatcher.http.max_idle_conns int 0 (stdlib) Max idle connections across all hosts
dispatcher.http.max_idle_per_host int 0 (stdlib) Max idle connections per host
dispatcher.http.idle_conn_timeout duration 0 (stdlib) Idle connection timeout
dispatcher.http.max_clients int 0 (unbounded) Max distinct pooled clients
dispatcher:
  http:
    timeout: 30s
    max_idle_per_host: 32

Modules

Module registry client used by wippy install/update.

Field Type Default Description
registry_url string https://hub.wippy.ai Registry endpoint
modules:
  registry_url: https://internal-registry.example.com

Extensions

Native Go plugin extensions loaded at boot (Unix only).

Field Type Default Description
enabled bool true Load extensions
paths string[] Plugin file paths (relative to config dir)
extensions:
  enabled: true
  paths:
    - ./extensions/myplugin.so

Environment Variables

Variable Description
GOMEMLIMIT Memory limit fallback when --memory-limit flag is not set (precedence: --memory-limit flag > GOMEMLIMIT > 1G default)

See Also