assay-lua 0.8.1

General-purpose enhanced Lua runtime. Batteries-included scripting, automation, and web services.
Documentation

Assay

Replaces your entire infrastructure scripting toolchain. One 9 MB binary, 50 modules.

CI Crates.io License: MIT

What is Assay?

A single ~9 MB static binary that replaces 50-250 MB Python/Node/kubectl containers in Kubernetes. Full-featured Lua 5.5 runtime with HTTP client/server, database, WebSocket, JWT, templates, native Temporal gRPC workflows, and 33 embedded stdlib modules for Kubernetes, monitoring, security, and AI agent integrations.

assay script.lua     # Run Lua with all builtins
assay checks.yaml    # Structured checks with retry/backoff/JSON output
assay exec -e 'log.info("hello")'   # Inline evaluation
assay context "grafana"              # LLM-ready module docs
assay modules                        # List all 50+ modules

Scripts that call http.serve() become web services. Scripts that call http.get() and exit are jobs. Same binary, same builtins.

Why Assay?

Runtime Compressed On-disk vs Assay Cold Start K8s-native
Assay 9 MB 15 MB 1x 5 ms Yes
Python alpine 17 MB 50 MB 2x 300 ms No
bitnami/kubectl 35 MB 90 MB 4x 200 ms Partial
Node.js alpine 57 MB 180 MB 6x 500 ms No
Deno 75 MB 200 MB 8x 50 ms No
Bun 115 MB 250 MB 13x 30 ms No
postman/newman 128 MB 350 MB 14x 800 ms No

Installation

# Pre-built binary (Linux x86_64 static)
curl -L -o assay https://github.com/developerinlondon/assay/releases/latest/download/assay-linux-x86_64
chmod +x assay && sudo mv assay /usr/local/bin/

# macOS (Apple Silicon)
curl -L -o assay https://github.com/developerinlondon/assay/releases/latest/download/assay-darwin-aarch64
chmod +x assay && sudo mv assay /usr/local/bin/

# Docker
docker pull ghcr.io/developerinlondon/assay:latest

# Cargo
cargo install assay-lua

Builtins API Reference

All 17 Rust builtins are available globally in .lua scripts — no require needed.

HTTP & Networking

Function Description
http.get(url, opts?) GET request, returns {status, body, headers}
http.post(url, body, opts?) POST (auto-JSON if body is table)
http.put/patch/delete(url, ...) PUT, PATCH, DELETE
http.serve(port, routes) HTTP server with async handlers + SSE streaming (header values can be strings or arrays — array values emit the header multiple times for Set-Cookie, Link, Vary, etc.)
ws.connect(url) WebSocket client (send, recv, close)

Serialization

Function Description
json.parse(str) / json.encode(tbl) JSON
yaml.parse(str) / yaml.encode(tbl) YAML
toml.parse(str) / toml.encode(tbl) TOML
base64.encode(str) / base64.decode(str) Base64

Filesystem & System

Function Description
fs.read(path) / fs.write(path, s) Read/write files
fs.exists(path) / fs.mkdir(path) / fs.glob(pattern) File operations
shell.exec(cmd, opts?) Execute shell commands
process.list() / process.kill(pid) Process management
disk.usage(path) / disk.sweep(dir, age) Disk info and cleanup
os.hostname() / os.arch() / os.platform() OS information
env.get(key) / env.set(key, val) Environment variables
sleep(secs) / time() Pause execution, Unix timestamp

Cryptography & Regex

Function Description
crypto.jwt_sign(claims, key, alg, opts?) Sign JWT (HS256, RS256/384/512, ES256/384)
crypto.hash(str, alg) SHA-256, SHA-384, SHA-512, SHA3
crypto.hmac(key, data, alg?, raw?) HMAC (all 8 hash algorithms)
crypto.random(len) Secure random hex string
regex.match/find/find_all/replace Regular expressions

Database, Templates & Async

Function Description
db.connect(url) Postgres, MySQL, SQLite
db.query(conn, sql, params?) Execute query, return rows
template.render(path, vars) Jinja2-compatible templates
async.spawn(fn) / async.spawn_interval(secs, fn) Async tasks with handles

Assertions & Logging

Function Description
assert.eq/ne/gt/lt/contains/not_nil/matches Test assertions
log.info/warn/error(msg) Structured logging

Temporal Workflow Engine (native gRPC)

Function Description
temporal.connect({ url, namespace? }) Connect to Temporal gRPC frontend
temporal.start({ url, ..., workflow_type, workflow_id, input? }) One-shot: connect + start
client:start_workflow(opts) Start a workflow execution
client:signal_workflow(opts) Signal a running workflow
client:query_workflow(opts) Query workflow state
client:describe_workflow(id) Get status, timestamps, history length
client:get_result({ workflow_id }) Block until workflow completes
client:cancel_workflow(id) Graceful cancellation
client:terminate_workflow(id) Force terminate

Stdlib Modules

33 embedded Lua modules loaded via require("assay.<name>"). All follow the client pattern: M.client(url, opts) then c:method().

Module Description
Monitoring
assay.prometheus PromQL queries, alerts, targets, rules, series
assay.alertmanager Alerts, silences, receivers
assay.loki Log push, query (LogQL), labels, series
assay.grafana Health, dashboards, datasources, annotations
Kubernetes & GitOps
assay.k8s 30+ resource types, CRDs, readiness, pod logs
assay.argocd Apps, sync, health, projects, repositories
assay.kargo Stages, freight, promotions, pipelines
assay.flux GitRepositories, Kustomizations, HelmReleases
assay.traefik Routers, services, middlewares
Security & Identity
assay.vault / assay.openbao KV secrets, transit, PKI, policies
assay.certmanager Certificates, issuers, ACME
assay.eso ExternalSecrets, SecretStores
assay.dex OIDC discovery, JWKS
assay.zitadel OIDC identity, JWT machine auth
assay.kratos Ory Kratos — login/registration/recovery flows, identities, sessions
assay.hydra Ory Hydra — OAuth2/OIDC clients, authorize, tokens, login/consent
assay.keto Ory Keto — ReBAC relation tuples, permission checks, expand
assay.ory Ory stack wrapper — ory.connect() builds kratos/hydra/keto in one call
Infrastructure
assay.crossplane Providers, XRDs, compositions
assay.velero Backups, restores, schedules
assay.harbor Projects, repos, vulnerability scanning
assay.temporal Workflows, task queues, schedules (HTTP REST)
Data & Storage
assay.postgres User/database management, grants
assay.s3 S3-compatible storage with Sig V4 auth
assay.unleash Feature flags, environments, strategies
assay.healthcheck HTTP checks, JSON path, latency
AI Agent
assay.openclaw Agent tools, state, diff, approve, LLM tasks
assay.github PRs, issues, actions, repos, GraphQL
assay.gmail Search, read, reply, send (OAuth2)
assay.gcal Calendar events CRUD (OAuth2)
assay.oauth2 Google OAuth2 token management
assay.email_triage Email classification and triage

Examples

Kubernetes Health Check

#!/usr/bin/assay
local k8s = require("assay.k8s")
local c = k8s.client("https://kubernetes.default.svc", {
  token = fs.read("/var/run/secrets/kubernetes.io/serviceaccount/token"),
})

local deploy = c:deployment("default", "my-app")
assert.eq(deploy.status.readyReplicas, deploy.spec.replicas, "Not all replicas ready")
log.info("Deployment ready: " .. deploy.metadata.name)

Web Server with SSE

#!/usr/bin/assay
http.serve(8080, {
  GET = {
    ["/health"] = function(req)
      return { status = 200, json = { ok = true } }
    end,
    ["/login"] = function(req)
      -- Array header values emit the same header name multiple times.
      -- Required for setting multiple Set-Cookie values in one response.
      return {
        status = 200,
        headers = {
          ["Set-Cookie"] = {
            "session=abc; Path=/; HttpOnly",
            "csrf=xyz; Path=/",
          },
        },
        json = { ok = true },
      }
    end,
    ["/events"] = function(req)
      return {
        sse = function(send)
          send({ data = "connected" })
          for i = 1, 10 do
            sleep(1)
            send({ event = "update", data = json.encode({ count = i }), id = tostring(i) })
          end
        end
      }
    end
  }
})

Temporal Workflow

#!/usr/bin/assay
local client = temporal.connect({
  url = "temporal-frontend:7233",
  namespace = "production",
})

local handle = client:start_workflow({
  task_queue = "promotions",
  workflow_type = "PromoteToEnv",
  workflow_id = "promote-prod-v1.2.0",
  input = { version = "v1.2.0", target = "prod" },
})
log.info("Started: " .. handle.run_id)

local info = client:describe_workflow("promote-prod-v1.2.0")
log.info("Status: " .. info.status)

YAML Check Mode

timeout: 120s
retries: 3
backoff: 5s

checks:
  - name: api-health
    type: http
    url: https://api.example.com/health
    expect:
      status: 200
      json: ".status == \"healthy\""

  - name: prometheus-targets
    type: prometheus
    url: http://prometheus:9090
    query: "count(up)"
    expect:
      min: 1
assay checks.yaml   # Exit 0 if all pass, 1 if any fail

OpenClaw Integration

Assay integrates with OpenClaw as an agent tool with human approval gates:

assay run --mode tool script.lua              # Structured JSON output for agents
assay resume --token <token> --approve yes    # Resume after human approval

Install the extension: openclaw plugins install @developerinlondon/assay-openclaw-extension

Module Discovery

Find the right module before writing code:

assay context "grafana"   # Returns method signatures for LLM prompts
assay context "vault"     # Exact API docs, no hallucination
assay modules             # List all 50+ modules

Custom modules: place .lua files in ./modules/ (project) or ~/.assay/modules/ (global).

Development

cargo build --release     # Release build (~9 MB)
cargo clippy -- -D warnings
cargo test
dprint fmt                # Format (Rust, Markdown, YAML, JSON, TOML)

License

MIT

Links