Skip to content

Entry Kinds Reference

Complete reference of all entry kinds available in Wippy.

Entries reference each other using namespace:name format. The registry automatically wires dependencies together based on these references, ensuring resources are initialized in the correct order.

KindDescription
function.luaLua function entry point
process.luaLong-running Lua process
workflow.luaTemporal workflow (deterministic)
library.luaShared Lua library
module.luaLua module surface
function.lua.bcPrecompiled function bytecode
library.lua.bcPrecompiled library bytecode
process.lua.bcPrecompiled process bytecode
workflow.lua.bcPrecompiled workflow bytecode
- name: handler
kind: function.lua
source: file://handler.lua
method: main
modules:
- http
- json
imports:
utils: app.lib:helpers # Import another entry as module
Use imports to reference other Lua entries. They become available via require("alias_name") in your code.
KindDescription
http.serviceHTTP server (binds port)
http.routerRoute prefix and middleware
http.endpointHTTP endpoint (method + path)
http.staticStatic file serving
# HTTP server
- name: gateway
kind: http.service
addr: ":8080"
lifecycle:
auto_start: true
# Router with middleware
- name: api
kind: http.router
meta:
server: gateway
prefix: /api
middleware:
- cors
- ratelimit
# Endpoint
- name: users_list
kind: http.endpoint
meta:
router: app:api
method: GET
path: /users
func: list_handler

Lua API: See HTTP Module

local http = require("http")
local req = http.request()
local resp = http.response()
resp:set_status(200)
resp:write_json({users = get_users()})
KindDescription
db.sql.sqliteSQLite database
db.sql.postgresPostgreSQL database
db.sql.mysqlMySQL database
- name: database
kind: db.sql.sqlite
file: "./data/app.db"
lifecycle:
auto_start: true
# In-memory for testing
- name: testdb
kind: db.sql.sqlite
file: ":memory:"
- name: database
kind: db.sql.postgres
host: localhost
port: 5432
database: dbname
username: user
password: pass
options:
sslmode: disable
pool:
max_open: 25
max_idle: 5
max_lifetime: "30m"
lifecycle:
auto_start: true
- name: database
kind: db.sql.mysql
host: localhost
port: 3306
database: dbname
username: user
password: pass
options:
parseTime: "true"
lifecycle:
auto_start: true

See Database for *_env suffix variants, TLS options, and connection pool tuning.

Lua API: See SQL Module

local sql = require("sql")
local db, err = sql.get("app:database")
local rows, err = db:query("SELECT * FROM users WHERE id = ?", user_id)
db:execute("INSERT INTO logs (msg) VALUES (?)", message)
KindDescription
store.memoryIn-memory key-value store
store.sqlSQL-backed key-value store
store.kv.raftCluster-replicated, strongly-consistent KV (shared Raft)
store.kv.crdtCluster-replicated, eventually-consistent KV (gossip/CRDT)
# Memory store
- name: cache
kind: store.memory
lifecycle:
auto_start: true
# SQL-backed store
- name: persistent_store
kind: store.sql
database: app:database
table: kv_store
lifecycle:
auto_start: true
# Cluster-replicated store (requires clustering)
- name: deployments
kind: store.kv.raft
namespace: deploy

The store.kv.* kinds need clustering enabled. See Store for the consistency tradeoffs.

Lua API: See Store Module

local store = require("store")
local s, err = store.get("app:cache")
s:set("user:123", user_data, 3600) -- TTL in seconds
local data = s:get("user:123")
KindDescription
queue.driver.memoryIn-memory queue driver
queue.driver.amqpAMQP (RabbitMQ) driver
queue.driver.sqsAWS SQS driver
queue.queueQueue declaration
queue.consumerQueue consumer
# Driver
- name: queue_driver
kind: queue.driver.memory
lifecycle:
auto_start: true
# Queue
- name: jobs
kind: queue.queue
driver: queue_driver
# Consumer
- name: job_consumer
kind: queue.consumer
queue: app:jobs
func: job_handler
concurrency: 4
prefetch: 10
lifecycle:
auto_start: true

Lua API: See Queue Module

local queue = require("queue")
-- Publish a message
queue.publish("app:jobs", {task = "process", id = 123})
-- In a consumer handler: the message body is the handler's argument
local function main(data)
-- access delivery metadata via the current message
local msg = queue.message()
local id = msg:id()
local priority = msg:header("priority")
msg:ack()
end
The consumer's func is invoked once per message with the message body as its argument. Use queue.message() inside the handler for the delivery's id(), header()/headers(), and ack()/nack().
KindDescription
process.hostProcess execution host
process.serviceSupervised process (wraps process.lua)
terminal.hostTerminal/CLI host
# Process host (where processes run)
- name: processes
kind: process.host
host:
workers: 32 # Worker goroutines (default: NumCPU)
queue_size: 1024 # Global queue capacity
local_queue_size: 256 # Per-worker queue
lifecycle:
auto_start: true
# Process definition
- name: worker_process
kind: process.lua
source: file://worker.lua
method: main
# Supervised process service
- name: worker
kind: process.service
process: app:worker_process
host: app:processes
input: ["arg1", "arg2"]
lifecycle:
auto_start: true
restart:
max_attempts: 10
- name: terminal
kind: terminal.host
lifecycle:
auto_start: true
Use process.service when you need a process to run as a supervised service with automatic restart. The process field references a process.lua entry.
KindDescription
temporal.clientTemporal client connection
temporal.workerTemporal worker
- name: temporal_client
kind: temporal.client
address: "localhost:7233"
namespace: "default"
auth:
type: none # none, api_key, mtls
lifecycle:
auto_start: true
- name: temporal_worker
kind: temporal.worker
client: temporal_client
task_queue: "main-queue"
lifecycle:
auto_start: true
KindDescription
config.awsAWS configuration
cloudstorage.s3S3 bucket access
- name: aws
kind: config.aws
region: "us-east-1"
access_key_id_env: "AWS_ACCESS_KEY_ID"
secret_access_key_env: "AWS_SECRET_ACCESS_KEY"
- name: uploads
kind: cloudstorage.s3
config: app:aws
bucket: "my-uploads"
endpoint: "" # Optional, for S3-compatible services

Lua API: See Cloud Storage Module

local cloudstorage = require("cloudstorage")
local storage, err = cloudstorage.get("app:uploads")
storage:upload_object("files/doc.pdf", file_content)
local url = storage:presigned_get_url("files/doc.pdf", {expiration = 3600}) -- seconds, default 3600
Use endpoint to connect to S3-compatible services like MinIO or DigitalOcean Spaces.
KindDescription
fs.directoryDirectory access
fs.embedRead-only embedded filesystem
- name: data_dir
kind: fs.directory
directory: "./data"
auto_init: true # Create if not exists
mode: "0755" # Permissions

Lua API: See Filesystem Module

local fs = require("fs")
local filesystem, err = fs.get("app:data_dir")
local file = filesystem:open("output.txt", "w")
file:write("Hello, World!")
file:close()
KindDescription
env.storage.memoryIn-memory env storage
env.storage.fileFile-based env storage
env.storage.osOS environment
env.storage.staticRead-only static key-value storage
env.storage.routerEnv router (multiple storages)
env.variableEnvironment variable
- name: os_env
kind: env.storage.os
- name: file_env
kind: env.storage.file
file_path: ".env"
auto_create: true
- name: defaults
kind: env.storage.static
values:
PUBLIC_API_HOST: "https://api.example.com"
APP_ENV: "production"
- name: app_env
kind: env.storage.router
storages:
- app:os_env
- app:file_env
- app:defaults

Lua API: See Env Module

local env = require("env")
local api_key = env.get("API_KEY")
env.set("CACHE_TTL", "3600")
The router tries storages in order. First match wins for reads; writes go to the first writable storage.
KindDescription
template.jetIndividual Jet template
template.setTemplate set configuration
# Template set with engine configuration
- name: templates
kind: template.set
engine:
development_mode: false
extensions:
- ".jet"
- ".html.jet"
# Individual template
- name: email_template
kind: template.jet
source: file://templates/email.jet
set: app:templates

Lua API: See Template Module

local templates = require("templates")
local set, err = templates.get("app:templates")
local html = set:render("email", {
user = "Alice",
message = "Welcome!"
})
KindDescription
security.policySecurity policy with conditions
security.policy.exprExpression-based policy
security.token_storeToken storage
# Condition-based policy
- name: admin_policy
kind: security.policy
policy:
actions: "*"
resources: "*"
effect: allow
conditions:
- field: "actor.meta.role"
operator: eq
value: "admin"
# Expression-based policy
- name: owner_policy
kind: security.policy.expr
policy:
actions: "*"
resources: "*"
effect: allow
expression: 'actor.id == meta.owner_id || actor.meta.role == "admin"'

Lua API: See Security Module

local security = require("security")
-- Check permission before action
if security.can("delete", "users", {user_id = id}) then
delete_user(id)
end
-- Get current actor
local actor = security.actor()
Policies are evaluated in order. The first matching policy determines access. Place more specific policies before general ones.
KindDescription
contract.definitionInterface with method specifications
contract.bindingMaps contract methods to function implementations
# Define the contract interface
- name: greeter
kind: contract.definition
methods:
- name: greet
description: Returns a greeting message
- name: greet_with_name
description: Returns a personalized greeting
input_schemas:
- format: "application/schema+json"
definition: {"type": "string"}
output_schemas:
- format: "application/schema+json"
definition: {"type": "string"}
# Implementation functions
- name: greeter_greet
kind: function.lua
source: file://greeter_greet.lua
method: main
- name: greeter_greet_name
kind: function.lua
source: file://greeter_greet_name.lua
method: main
# Bind contract methods to implementations
- name: greeter_impl
kind: contract.binding
contracts:
- contract: app:greeter
default: true
methods:
greet: app:greeter_greet
greet_with_name: app:greeter_greet_name

Usage from Lua:

local contract = require("contract")
-- Open binding by ID
local greeter, err = contract.open("app:greeter_impl")
-- Call methods
local result = greeter:greet()
local personalized = greeter:greet_with_name("Alice")
-- Check if instance implements contract
local is_greeter = contract.is(greeter, "app:greeter")

Lua API: See Contract Module

Mark one binding as default: true to use it when opening a contract without specifying a binding ID (only works when no context_required fields are set).
KindDescription
exec.nativeNative command execution
exec.dockerDocker container execution
- name: native_exec
kind: exec.native
default_work_dir: "/app"
command_whitelist:
- "ls"
- "cat"
- name: docker_exec
kind: exec.docker
image: "python:3.11-slim"
default_work_dir: "/workspace"
auto_remove: true
memory_limit: 536870912 # 512MB
command_whitelist:
- "python"
KindDescription
function.watWebAssembly function (WAT text format)
function.wasmWebAssembly function (binary)
process.wasmWebAssembly process
- name: sum
kind: function.wasm
source: file://sum.wasm
transport: payload # or wasi-http

See WASM Overview.

KindDescription
networkBase network overlay
network.socks5SOCKS5 proxy overlay
network.i2pI2P network overlay
network.tailscaleTailscale overlay

Referenced by http.service via network:, by funcs/process via the network option, and by http_client via the overlay_network option. See Network.

KindDescription
registry.entryEntry descriptor (internal)
ns.definitionNamespace definition
ns.requirementNamespace requirement declaration
ns.dependencyNamespace dependency

These are produced by the registry loader from _index.yaml frontmatter and dependency declarations. Authors generally don’t define them directly — they appear as a result of version:, namespace:, and dependency blocks being resolved.

Most entries support lifecycle configuration:

- name: service
kind: some.kind
lifecycle:
auto_start: true # Start automatically
start_timeout: 10s # Max startup time
stop_timeout: 10s # Max shutdown time
stable_threshold: 5s # Time to consider stable
depends_on:
- app:database
restart: # Retry policy
initial_delay: 1s
max_delay: 90s
backoff_factor: 2.0
max_attempts: 0 # 0 = infinite
Use depends_on to ensure entries start in the correct order. The supervisor waits for dependencies to become stable before starting dependent entries.

Entries are referenced using namespace:name format:

# Definition
namespace: app.users
entries:
- name: handler
kind: function.lua
# Reference from another entry
func: app.users:handler

Any entry’s fields — including its kind — can be overridden at launch without editing the source YAML, using the override: config section or the -o CLI flag. Keys use namespace:entry:path format:

override:
app:gateway:addr: ":9090" # data field (a bare path targets data.*)
app:worker:meta.priority: high # meta field
app:db:kind: db.sql.postgres # the entry's typed kind
app:db:data.kind: custom # a payload field literally named "kind"
PathTargets
kindThe entry’s typed kind (must be a non-empty string)
data.<field> or bare <field>A field in the entry’s data payload
meta.<field>A field in the entry’s metadata

The same overrides apply from the CLI:

Terminal window
wippy run -o app:db:kind=db.sql.postgres -o app:gateway:addr=:9090

CLI (-o) values coerce by shape (true/false to bool, numbers to numbers, otherwise string); override: section values keep their YAML type. To override global configuration sections instead of entries, use --set.