Assay
Replaces your entire infrastructure scripting toolchain. One 9 MB binary, 46 built-in 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 29 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
Built-in API Reference
All 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 |
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
29 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 |
| 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
MIT
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