Assay
Replaces your entire infrastructure scripting toolchain. One 9 MB binary, 50 modules.
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.
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)
&&
# macOS (Apple Silicon)
&&
# Docker
# Cargo
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
local c = k8s.
local deploy = c:
assert.
log.
Web Server with SSE
#!/usr/bin/assay
http.
Temporal Workflow
#!/usr/bin/assay
local client = temporal.
local handle = client:
log.
local info = client:
log.
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
OpenClaw Integration
Assay integrates with OpenClaw as an agent tool with human approval gates:
Install the extension: openclaw plugins install @developerinlondon/assay-openclaw-extension
Module Discovery
Find the right module before writing code:
Custom modules: place .lua files in ./modules/ (project) or ~/.assay/modules/ (global).
Development
License
Assay is licensed under the Apache License, Version 2.0. You can use, modify, and redistribute it freely — including in commercial and proprietary products — as long as you preserve the copyright notice and the license text.
Contributing
Pull requests are welcome. See CONTRIBUTING.md for the workflow and CLA.md for the Contributor License Agreement that all contributors are required to sign (it lets the project owner relicense or incorporate contributions into commercial editions in the future, while you keep the copyright on your contribution).
Links
- Website: https://assay.rs
- Crate: https://crates.io/crates/assay-lua
- Docker:
ghcr.io/developerinlondon/assay:latest - Changelog: https://assay.rs/changelog.html
- Module Reference: https://assay.rs/modules.html
- Comparison: https://assay.rs/comparison.html
- Agent Guides: https://assay.rs/agent-guides.html
- LLM Context: https://assay.rs/llms.txt