CLI
Cliente de linha de comando rápido para execução de código e sessões interativas. Mais de 42 linguagens, mais de 30 shells/REPLs.
Documentação Oficial OpenAPI Swagger ↗Início Rápido — Lua
# Download + setup
curl -O https://git.unturf.com/engineering/unturf/un-inception/-/raw/main/clients/lua/sync/src/un.lua && chmod +x un.lua && ln -sf un.lua un
export UNSANDBOX_PUBLIC_KEY="unsb-pk-xxxx-xxxx-xxxx-xxxx"
export UNSANDBOX_SECRET_KEY="unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx"
# Run code
./un script.lua
Baixar
Guia de Instalação →Características:
- 42+ languages - Python, JS, Go, Rust, C++, Java...
- Sessions - 30+ shells/REPLs, tmux persistence
- Files - Upload files, collect artifacts
- Services - Persistent containers with domains
- Snapshots - Point-in-time backups
- Images - Publish, share, transfer
Início Rápido de Integração ⚡
Adicione superpoderes unsandbox ao seu app Lua existente:
curl -O https://git.unturf.com/engineering/unturf/un-inception/-/raw/main/clients/lua/sync/src/un.lua
# Option A: Environment variables
export UNSANDBOX_PUBLIC_KEY="unsb-pk-xxxx-xxxx-xxxx-xxxx"
export UNSANDBOX_SECRET_KEY="unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx"
# Option B: Config file (persistent)
mkdir -p ~/.unsandbox
echo "unsb-pk-xxxx-xxxx-xxxx-xxxx,unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx" > ~/.unsandbox/accounts.csv
-- In your Lua app:
local Un = dofile("un.lua")
local result = Un.execute("lua", "print('Hello from Lua running on unsandbox!')")
print(result.stdout) -- Hello from Lua running on unsandbox!
lua myapp.lua
8237a48f86d42a73b413206929b126c7
SHA256: 72f23781d42389f567441c637f672ea8731209d951fbf26281ad2a580d7b9122
#!/usr/bin/env lua
-- PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
--
-- unsandbox.com Lua SDK (Synchronous)
-- Full API with execution, sessions, services, snapshots, and images.
--
-- Library Usage:
-- local Un = require("un")
-- local result = Un.execute("python", "print(42)")
-- print(result.stdout)
--
-- CLI Usage:
-- lua un.lua script.py
-- lua un.lua -s python 'print(42)'
-- lua un.lua session --list
-- lua un.lua service --list
--
-- Copyright 2025 TimeHexOn & foxhop & russell@unturf
local json = require("json")
local http = require("socket.http")
local https = require("ssl.https")
local ltn12 = require("ltn12")
local mime = require("mime")
local Un = {}
Un.API_BASE = "https://api.unsandbox.com"
Un.PORTAL_BASE = "https://unsandbox.com"
Un.VERSION = "4.3.4"
Un.LAST_ERROR = ""
Un.ACCOUNT_INDEX = -1 -- -1 means not set; set to N to use accounts.csv row N
-- Colors
local BLUE = "\027[34m"
local RED = "\027[31m"
local GREEN = "\027[32m"
local YELLOW = "\027[33m"
local RESET = "\027[0m"
-- Extension to language mapping
local EXT_MAP = {
py = "python", js = "javascript", ts = "typescript",
rb = "ruby", php = "php", pl = "perl", lua = "lua",
sh = "bash", go = "go", rs = "rust", c = "c",
cpp = "cpp", cc = "cpp", cxx = "cpp",
java = "java", kt = "kotlin", cs = "csharp", fs = "fsharp",
hs = "haskell", ml = "ocaml", clj = "clojure", scm = "scheme",
lisp = "commonlisp", erl = "erlang", ex = "elixir", exs = "elixir",
jl = "julia", r = "r", cr = "crystal",
d = "d", nim = "nim", zig = "zig", v = "v",
dart = "dart", groovy = "groovy", scala = "scala",
f90 = "fortran", f95 = "fortran", cob = "cobol",
pro = "prolog", forth = "forth", ["4th"] = "forth",
tcl = "tcl", raku = "raku", m = "objc"
}
-- ============================================================================
-- Utility Functions
-- ============================================================================
function Un.version()
return Un.VERSION
end
function Un.last_error()
return Un.LAST_ERROR
end
function Un.set_error(msg)
Un.LAST_ERROR = msg or ""
end
function Un.detect_language(filename)
if not filename then return nil end
local ext = filename:match("%.([^%.]+)$")
return ext and EXT_MAP[ext:lower()] or nil
end
function Un.hmac_sign(secret, message)
if not secret or not message then return nil end
-- Use openssl for HMAC-SHA256
local cmd = "echo -n '" .. message:gsub("'", "'\\''") .. "' | openssl dgst -sha256 -hmac '" .. secret:gsub("'", "'\\''") .. "' | sed 's/^.* //'"
local handle = io.popen(cmd)
local result = handle:read("*a")
handle:close()
return result and result:gsub("%s+", "") or nil
end
-- ============================================================================
-- Credential Management
-- ============================================================================
function Un.load_accounts_csv(path)
path = path or (os.getenv("HOME") .. "/.unsandbox/accounts.csv")
local file = io.open(path, "r")
if not file then return {} end
local accounts = {}
for line in file:lines() do
line = line:match("^%s*(.-)%s*$")
if line ~= "" and not line:match("^#") then
local pk, sk = line:match("([^,]+),(.+)")
if pk and sk then
table.insert(accounts, {pk, sk})
end
end
end
file:close()
return accounts
end
function Un.get_credentials(opts)
opts = opts or {}
-- Tier 1: Arguments
if opts.public_key and opts.secret_key then
return opts.public_key, opts.secret_key
end
-- Tier 2: --account N flag → bypass env vars, load CSV row N directly
local ai = opts.account_index
if (ai == nil) and Un.ACCOUNT_INDEX >= 0 then ai = Un.ACCOUNT_INDEX end
if ai and ai >= 0 then
local row = ai + 1 -- Lua tables are 1-indexed
local accounts = Un.load_accounts_csv()
if #accounts >= row then return accounts[row][1], accounts[row][2] end
accounts = Un.load_accounts_csv("./accounts.csv")
if #accounts >= row then return accounts[row][1], accounts[row][2] end
Un.set_error("Account index " .. ai .. " not found in accounts.csv")
return nil, nil
end
-- Tier 3: Environment
local pk = os.getenv("UNSANDBOX_PUBLIC_KEY")
local sk = os.getenv("UNSANDBOX_SECRET_KEY")
if pk and sk then return pk, sk end
-- Legacy fallback
if os.getenv("UNSANDBOX_API_KEY") then
return os.getenv("UNSANDBOX_API_KEY"), ""
end
-- Tier 4: Home directory
local accounts = Un.load_accounts_csv()
if #accounts > 0 then return accounts[1][1], accounts[1][2] end
-- Tier 5: Local directory
accounts = Un.load_accounts_csv("./accounts.csv")
if #accounts > 0 then return accounts[1][1], accounts[1][2] end
Un.set_error("No credentials found")
return nil, nil
end
-- ============================================================================
-- API Communication
-- ============================================================================
function Un.api_request(method, endpoint, body, opts, extra_headers)
opts = opts or {}
extra_headers = extra_headers or {}
local pk, sk = Un.get_credentials(opts)
if not pk then
Un.set_error("No credentials available")
return nil
end
local timestamp = tostring(os.time())
local url = Un.API_BASE .. endpoint
local body_str = ""
if body then
if type(body) == "table" then
body_str = json.encode(body)
else
body_str = body
end
end
local content_type = opts.content_type or "application/json"
local signature = ""
if sk and sk ~= "" then
signature = Un.hmac_sign(sk, timestamp .. ":" .. method .. ":" .. endpoint .. ":" .. body_str)
end
local headers = {
["Authorization"] = "Bearer " .. pk,
["Content-Type"] = content_type
}
if signature then
headers["X-Timestamp"] = timestamp
headers["X-Signature"] = signature
end
-- Add extra headers
for k, v in pairs(extra_headers) do
headers[k] = v
end
local resp_body = {}
local resp, status = https.request({
url = url,
method = method,
headers = headers,
source = body_str ~= "" and ltn12.source.string(body_str) or nil,
sink = ltn12.sink.table(resp_body)
})
if status ~= 200 and status ~= 201 then
Un.set_error("API error (" .. tostring(status) .. ")")
return nil, status
end
local response_text = table.concat(resp_body)
if response_text and response_text ~= "" then
local ok, result = pcall(json.decode, response_text)
if ok then return result, status end
end
return { success = true }, status
end
function Un.api_request_with_sudo(method, endpoint, body, opts)
opts = opts or {}
local pk, sk = Un.get_credentials(opts)
local timestamp = tostring(os.time())
local body_str = body and json.encode(body) or ""
local signature = ""
if sk and sk ~= "" then
signature = Un.hmac_sign(sk, timestamp .. ":" .. method .. ":" .. endpoint .. ":" .. body_str)
end
local headers = {
["Authorization"] = "Bearer " .. pk,
["Content-Type"] = "application/json"
}
if signature then
headers["X-Timestamp"] = timestamp
headers["X-Signature"] = signature
end
local resp_body = {}
local resp, status = https.request({
url = Un.API_BASE .. endpoint,
method = method,
headers = headers,
source = body_str ~= "" and ltn12.source.string(body_str) or nil,
sink = ltn12.sink.table(resp_body)
})
-- Handle 428 - Sudo OTP required
if status == 428 then
local response_text = table.concat(resp_body)
local response_data = {}
pcall(function() response_data = json.decode(response_text) end)
local challenge_id = response_data.challenge_id or ""
io.stderr:write(YELLOW .. "Confirmation required. Check your email for a one-time code." .. RESET .. "\n")
io.stderr:write("Enter OTP: ")
io.stderr:flush()
local otp = io.read("*line")
if not otp or otp == "" then
Un.set_error("Operation cancelled")
return nil
end
local extra = { ["X-Sudo-OTP"] = otp }
if challenge_id ~= "" then
extra["X-Sudo-Challenge"] = challenge_id
end
return Un.api_request(method, endpoint, body, opts, extra)
end
if status ~= 200 and status ~= 201 then
Un.set_error("API error (" .. tostring(status) .. ")")
return nil
end
local response_text = table.concat(resp_body)
if response_text and response_text ~= "" then
local ok, result = pcall(json.decode, response_text)
if ok then return result end
end
return { success = true }
end
-- ============================================================================
-- Execution Functions (8)
-- ============================================================================
function Un.execute(language, code, opts)
opts = opts or {}
local body = {
language = language,
code = code,
network_mode = opts.network_mode or "zerotrust",
ttl = opts.ttl or 60
}
if opts.env then body.env = opts.env end
if opts.input_files then body.input_files = opts.input_files end
if opts.return_artifacts then body.return_artifacts = true end
return Un.api_request("POST", "/execute", body, opts)
end
function Un.execute_async(language, code, opts)
opts = opts or {}
local body = {
language = language,
code = code,
network_mode = opts.network_mode or "zerotrust",
ttl = opts.ttl or 300
}
return Un.api_request("POST", "/execute/async", body, opts)
end
function Un.wait_job(job_id, opts)
opts = opts or {}
local delays = {300, 450, 700, 900, 650, 1600, 2000}
for i = 0, 119 do
local job = Un.get_job(job_id, opts)
if job and job.status == "completed" then return job end
if job and job.status == "failed" then
Un.set_error("Job failed")
return nil
end
local delay = delays[(i % 7) + 1] or 2000
require("socket").sleep(delay / 1000)
end
Un.set_error("Max polls exceeded")
return nil
end
function Un.get_job(job_id, opts)
return Un.api_request("GET", "/jobs/" .. job_id, nil, opts)
end
function Un.cancel_job(job_id, opts)
return Un.api_request("DELETE", "/jobs/" .. job_id, nil, opts)
end
function Un.list_jobs(opts)
return Un.api_request("GET", "/jobs", nil, opts)
end
function Un.get_languages(opts)
opts = opts or {}
local cache_ttl = opts.cache_ttl or 3600
local cache_path = os.getenv("HOME") .. "/.unsandbox/languages.json"
-- Try cache
local file = io.open(cache_path, "r")
if file then
local content = file:read("*a")
file:close()
local ok, cached = pcall(json.decode, content)
if ok and cached and cached.timestamp then
if os.time() - cached.timestamp < cache_ttl then
return cached.languages
end
end
end
-- Fetch from API
local result = Un.api_request("GET", "/languages", nil, opts)
local langs = result and result.languages or {}
-- Save to cache
os.execute("mkdir -p " .. os.getenv("HOME") .. "/.unsandbox")
file = io.open(cache_path, "w")
if file then
file:write(json.encode({ languages = langs, timestamp = os.time() }))
file:close()
end
return langs
end
-- ============================================================================
-- Session Functions (9)
-- ============================================================================
function Un.session_list(opts)
return Un.api_request("GET", "/sessions", nil, opts)
end
function Un.session_get(session_id, opts)
return Un.api_request("GET", "/sessions/" .. session_id, nil, opts)
end
function Un.session_create(opts)
opts = opts or {}
local body = { shell = opts.shell or "bash" }
if opts.network then body.network = opts.network end
if opts.vcpu then body.vcpu = opts.vcpu end
if opts.input_files then body.input_files = opts.input_files end
if opts.persistence then body.persistence = opts.persistence end
return Un.api_request("POST", "/sessions", body, opts)
end
function Un.session_destroy(session_id, opts)
return Un.api_request("DELETE", "/sessions/" .. session_id, nil, opts)
end
function Un.session_freeze(session_id, opts)
return Un.api_request("POST", "/sessions/" .. session_id .. "/freeze", {}, opts)
end
function Un.session_unfreeze(session_id, opts)
return Un.api_request("POST", "/sessions/" .. session_id .. "/unfreeze", {}, opts)
end
function Un.session_boost(session_id, vcpu, opts)
return Un.api_request("POST", "/sessions/" .. session_id .. "/boost", { vcpu = vcpu }, opts)
end
function Un.session_unboost(session_id, opts)
return Un.api_request("POST", "/sessions/" .. session_id .. "/unboost", {}, opts)
end
function Un.session_execute(session_id, command, opts)
return Un.api_request("POST", "/sessions/" .. session_id .. "/execute", { command = command }, opts)
end
-- ============================================================================
-- Service Functions (17)
-- ============================================================================
function Un.service_list(opts)
return Un.api_request("GET", "/services", nil, opts)
end
function Un.service_get(service_id, opts)
return Un.api_request("GET", "/services/" .. service_id, nil, opts)
end
function Un.service_create(opts)
opts = opts or {}
local body = { name = opts.name }
if opts.ports then body.ports = opts.ports end
if opts.domains then body.domains = opts.domains end
if opts.bootstrap then body.bootstrap = opts.bootstrap end
if opts.bootstrap_content then body.bootstrap_content = opts.bootstrap_content end
if opts.network then body.network = opts.network end
if opts.vcpu then body.vcpu = opts.vcpu end
if opts.service_type then body.service_type = opts.service_type end
if opts.input_files then body.input_files = opts.input_files end
if opts.unfreeze_on_demand then body.unfreeze_on_demand = true end
return Un.api_request("POST", "/services", body, opts)
end
function Un.service_destroy(service_id, opts)
return Un.api_request_with_sudo("DELETE", "/services/" .. service_id, nil, opts)
end
function Un.service_freeze(service_id, opts)
return Un.api_request("POST", "/services/" .. service_id .. "/freeze", {}, opts)
end
function Un.service_unfreeze(service_id, opts)
return Un.api_request("POST", "/services/" .. service_id .. "/unfreeze", {}, opts)
end
function Un.service_lock(service_id, opts)
return Un.api_request("POST", "/services/" .. service_id .. "/lock", {}, opts)
end
function Un.service_unlock(service_id, opts)
return Un.api_request_with_sudo("POST", "/services/" .. service_id .. "/unlock", {}, opts)
end
function Un.service_set_unfreeze_on_demand(service_id, enabled, opts)
return Un.api_request("PATCH", "/services/" .. service_id, { unfreeze_on_demand = enabled }, opts)
end
function Un.service_redeploy(service_id, opts)
opts = opts or {}
local body = {}
if opts.bootstrap then body.bootstrap = opts.bootstrap end
return Un.api_request("POST", "/services/" .. service_id .. "/redeploy", body, opts)
end
function Un.service_logs(service_id, opts)
opts = opts or {}
local endpoint = "/services/" .. service_id .. "/logs"
if opts.lines then endpoint = endpoint .. "?lines=" .. opts.lines end
return Un.api_request("GET", endpoint, nil, opts)
end
function Un.service_execute(service_id, command, opts)
opts = opts or {}
local body = { command = command }
if opts.timeout then body.timeout = opts.timeout end
return Un.api_request("POST", "/services/" .. service_id .. "/execute", body, opts)
end
function Un.service_env_get(service_id, opts)
return Un.api_request("GET", "/services/" .. service_id .. "/env", nil, opts)
end
function Un.service_env_set(service_id, env_content, opts)
opts = opts or {}
opts.content_type = "text/plain"
return Un.api_request("PUT", "/services/" .. service_id .. "/env", env_content, opts)
end
function Un.service_env_delete(service_id, opts)
return Un.api_request("DELETE", "/services/" .. service_id .. "/env", nil, opts)
end
function Un.service_env_export(service_id, opts)
return Un.api_request("POST", "/services/" .. service_id .. "/env/export", {}, opts)
end
function Un.service_resize(service_id, vcpu, opts)
return Un.api_request("PATCH", "/services/" .. service_id, { vcpu = vcpu }, opts)
end
-- ============================================================================
-- Snapshot Functions (9)
-- ============================================================================
function Un.snapshot_list(opts)
return Un.api_request("GET", "/snapshots", nil, opts)
end
function Un.snapshot_get(snapshot_id, opts)
return Un.api_request("GET", "/snapshots/" .. snapshot_id, nil, opts)
end
function Un.snapshot_session(session_id, opts)
opts = opts or {}
local body = {}
if opts.name then body.name = opts.name end
if opts.hot then body.hot = true end
return Un.api_request("POST", "/sessions/" .. session_id .. "/snapshot", body, opts)
end
function Un.snapshot_service(service_id, opts)
opts = opts or {}
local body = {}
if opts.name then body.name = opts.name end
if opts.hot then body.hot = true end
return Un.api_request("POST", "/services/" .. service_id .. "/snapshot", body, opts)
end
function Un.snapshot_restore(snapshot_id, opts)
return Un.api_request("POST", "/snapshots/" .. snapshot_id .. "/restore", {}, opts)
end
function Un.snapshot_delete(snapshot_id, opts)
return Un.api_request_with_sudo("DELETE", "/snapshots/" .. snapshot_id, nil, opts)
end
function Un.snapshot_lock(snapshot_id, opts)
return Un.api_request("POST", "/snapshots/" .. snapshot_id .. "/lock", {}, opts)
end
function Un.snapshot_unlock(snapshot_id, opts)
return Un.api_request_with_sudo("POST", "/snapshots/" .. snapshot_id .. "/unlock", {}, opts)
end
function Un.snapshot_clone(snapshot_id, opts)
opts = opts or {}
local body = { clone_type = opts.clone_type or "session" }
if opts.name then body.name = opts.name end
if opts.ports then body.ports = opts.ports end
if opts.shell then body.shell = opts.shell end
return Un.api_request("POST", "/snapshots/" .. snapshot_id .. "/clone", body, opts)
end
-- ============================================================================
-- Image Functions (13)
-- ============================================================================
function Un.image_list(opts)
opts = opts or {}
local endpoint = "/images"
if opts.filter then endpoint = endpoint .. "?filter=" .. opts.filter end
return Un.api_request("GET", endpoint, nil, opts)
end
function Un.image_get(image_id, opts)
return Un.api_request("GET", "/images/" .. image_id, nil, opts)
end
function Un.image_publish(opts)
opts = opts or {}
local body = {
source_type = opts.source_type,
source_id = opts.source_id
}
if opts.name then body.name = opts.name end
if opts.description then body.description = opts.description end
return Un.api_request("POST", "/images/publish", body, opts)
end
function Un.image_delete(image_id, opts)
return Un.api_request_with_sudo("DELETE", "/images/" .. image_id, nil, opts)
end
function Un.image_lock(image_id, opts)
return Un.api_request("POST", "/images/" .. image_id .. "/lock", {}, opts)
end
function Un.image_unlock(image_id, opts)
return Un.api_request_with_sudo("POST", "/images/" .. image_id .. "/unlock", {}, opts)
end
function Un.image_set_visibility(image_id, visibility, opts)
return Un.api_request("POST", "/images/" .. image_id .. "/visibility", { visibility = visibility }, opts)
end
function Un.image_grant_access(image_id, trusted_api_key, opts)
return Un.api_request("POST", "/images/" .. image_id .. "/access", { api_key = trusted_api_key }, opts)
end
function Un.image_revoke_access(image_id, trusted_api_key, opts)
return Un.api_request("DELETE", "/images/" .. image_id .. "/access/" .. trusted_api_key, nil, opts)
end
function Un.image_list_trusted(image_id, opts)
return Un.api_request("GET", "/images/" .. image_id .. "/access", nil, opts)
end
function Un.image_transfer(image_id, to_api_key, opts)
return Un.api_request("POST", "/images/" .. image_id .. "/transfer", { to_api_key = to_api_key }, opts)
end
function Un.image_spawn(image_id, opts)
opts = opts or {}
local body = {}
if opts.name then body.name = opts.name end
if opts.ports then body.ports = opts.ports end
if opts.bootstrap then body.bootstrap = opts.bootstrap end
if opts.network_mode then body.network_mode = opts.network_mode end
return Un.api_request("POST", "/images/" .. image_id .. "/spawn", body, opts)
end
function Un.image_clone(image_id, opts)
opts = opts or {}
local body = {}
if opts.name then body.name = opts.name end
if opts.description then body.description = opts.description end
return Un.api_request("POST", "/images/" .. image_id .. "/clone", body, opts)
end
-- ============================================================================
-- PaaS Logs Functions (2)
-- ============================================================================
function Un.logs_fetch(opts)
opts = opts or {}
local body = {
source = opts.source or "all",
lines = opts.lines or 100,
since = opts.since or "1h"
}
if opts.grep then body.grep = opts.grep end
return Un.api_request("POST", "/paas/logs", body, opts)
end
function Un.logs_stream(opts)
-- SSE streaming not easily supported in sync Lua
Un.set_error("logs_stream requires async support")
return nil
end
-- ============================================================================
-- Key Validation
-- ============================================================================
function Un.validate_keys(opts)
opts = opts or {}
local pk, sk = Un.get_credentials(opts)
local timestamp = tostring(os.time())
local signature = ""
if sk and sk ~= "" then
signature = Un.hmac_sign(sk, timestamp .. ":POST:/keys/validate:")
end
local headers = {
["Authorization"] = "Bearer " .. pk,
["Content-Type"] = "application/json"
}
if signature then
headers["X-Timestamp"] = timestamp
headers["X-Signature"] = signature
end
local resp_body = {}
local resp, status = https.request({
url = Un.PORTAL_BASE .. "/keys/validate",
method = "POST",
headers = headers,
sink = ltn12.sink.table(resp_body)
})
if status == 200 then
local response_text = table.concat(resp_body)
local ok, result = pcall(json.decode, response_text)
if ok then return result end
end
return nil
end
function Un.health_check(opts)
local resp_body = {}
local resp, status = https.request({
url = Un.API_BASE .. "/health",
method = "GET",
sink = ltn12.sink.table(resp_body)
})
return status == 200
end
-- ============================================================================
-- CLI Implementation
-- ============================================================================
local function run_file(filename)
local f = io.open(filename, "r")
if not f then
io.stderr:write(RED .. "Error: File not found: " .. filename .. RESET .. "\n")
os.exit(1)
end
local code = f:read("*a")
f:close()
local lang = Un.detect_language(filename)
if not lang then
io.stderr:write(RED .. "Error: Cannot detect language" .. RESET .. "\n")
os.exit(1)
end
local result = Un.execute(lang, code)
if result then
if result.stdout then print(result.stdout) end
if result.stderr then io.stderr:write(result.stderr) end
os.exit(result.exit_code or 0)
else
io.stderr:write(RED .. "Error: " .. Un.last_error() .. RESET .. "\n")
os.exit(1)
end
end
-- CLI entry point
if arg and arg[0] then
local args = arg
local i = 1
-- Pre-scan for --account N; strip it from args before dispatch
local _filtered = {}
local _j = 1
while _j <= #args do
if args[_j] == "--account" then
_j = _j + 1
Un.ACCOUNT_INDEX = tonumber(args[_j]) or -1
else
table.insert(_filtered, args[_j])
end
_j = _j + 1
end
for k = 1, #_filtered do args[k] = _filtered[k] end
for k = #_filtered + 1, #args do args[k] = nil end
if #args == 0 then
print("Usage: lua un.lua [options] <source_file>")
print(" lua un.lua -s <language> '<code>'")
print(" lua un.lua session [options]")
print(" lua un.lua service [options]")
print(" lua un.lua snapshot [options]")
print(" lua un.lua image [options]")
print(" lua un.lua languages [--json]")
print(" lua un.lua key [--extend]")
os.exit(1)
end
local cmd = args[1]
if cmd == "languages" then
local json_output = args[2] == "--json"
local langs = Un.get_languages()
if json_output then
print(json.encode(langs))
else
for _, lang in ipairs(langs) do
print(lang)
end
end
elseif cmd == "key" then
local result = Un.validate_keys()
if result then
if result.expired then
print(RED .. "Expired" .. RESET)
else
print(GREEN .. "Valid" .. RESET)
end
print("Public Key: " .. (result.public_key or "N/A"))
print("Tier: " .. (result.tier or "N/A"))
if result.expires_at then
print("Expires: " .. result.expires_at)
end
else
print(RED .. "Error: " .. Un.last_error() .. RESET)
end
elseif cmd == "session" then
i = 2
local action = nil
local target = nil
while i <= #args do
if args[i] == "--list" or args[i] == "-l" then
action = "list"
elseif args[i] == "--info" then
action = "info"
i = i + 1
target = args[i]
elseif args[i] == "--kill" then
action = "kill"
i = i + 1
target = args[i]
elseif args[i] == "--freeze" then
action = "freeze"
i = i + 1
target = args[i]
elseif args[i] == "--unfreeze" then
action = "unfreeze"
i = i + 1
target = args[i]
end
i = i + 1
end
if action == "list" then
local result = Un.session_list()
if result and result.sessions then
if #result.sessions == 0 then
print("No active sessions")
else
print(string.format("%-40s %-10s %-10s %s", "ID", "Shell", "Status", "Created"))
for _, s in ipairs(result.sessions) do
print(string.format("%-40s %-10s %-10s %s",
s.id or "N/A", s.shell or "N/A",
s.status or "N/A", s.created_at or "N/A"))
end
end
end
elseif action == "info" then
local result = Un.session_get(target)
print(json.encode(result))
elseif action == "kill" then
Un.session_destroy(target)
print(GREEN .. "Session terminated: " .. target .. RESET)
elseif action == "freeze" then
Un.session_freeze(target)
print(GREEN .. "Session frozen: " .. target .. RESET)
elseif action == "unfreeze" then
Un.session_unfreeze(target)
print(GREEN .. "Session unfreezing: " .. target .. RESET)
else
print("Usage: lua un.lua session --list|--info ID|--kill ID|--freeze ID|--unfreeze ID")
end
elseif cmd == "service" then
i = 2
local action = nil
local target = nil
while i <= #args do
if args[i] == "--list" or args[i] == "-l" then
action = "list"
elseif args[i] == "--info" then
action = "info"
i = i + 1
target = args[i]
elseif args[i] == "--destroy" then
action = "destroy"
i = i + 1
target = args[i]
elseif args[i] == "--freeze" then
action = "freeze"
i = i + 1
target = args[i]
elseif args[i] == "--unfreeze" then
action = "unfreeze"
i = i + 1
target = args[i]
elseif args[i] == "--logs" then
action = "logs"
i = i + 1
target = args[i]
end
i = i + 1
end
if action == "list" then
local result = Un.service_list()
if result and result.services then
if #result.services == 0 then
print("No services")
else
print(string.format("%-20s %-15s %-10s %-15s %s", "ID", "Name", "Status", "Ports", "Domains"))
for _, s in ipairs(result.services) do
local ports = table.concat(s.ports or {}, ",")
local domains = table.concat(s.domains or {}, ",")
print(string.format("%-20s %-15s %-10s %-15s %s",
s.id or "N/A", s.name or "N/A",
s.status or "N/A", ports, domains))
end
end
end
elseif action == "info" then
local result = Un.service_get(target)
print(json.encode(result))
elseif action == "destroy" then
Un.service_destroy(target)
print(GREEN .. "Service destroyed: " .. target .. RESET)
elseif action == "freeze" then
Un.service_freeze(target)
print(GREEN .. "Service frozen: " .. target .. RESET)
elseif action == "unfreeze" then
Un.service_unfreeze(target)
print(GREEN .. "Service unfreezing: " .. target .. RESET)
elseif action == "logs" then
local result = Un.service_logs(target)
if result and result.logs then
print(result.logs)
end
else
print("Usage: lua un.lua service --list|--info ID|--destroy ID|--freeze ID|--unfreeze ID|--logs ID")
end
elseif cmd == "snapshot" then
i = 2
local action = nil
local target = nil
while i <= #args do
if args[i] == "--list" or args[i] == "-l" then
action = "list"
elseif args[i] == "--info" then
action = "info"
i = i + 1
target = args[i]
elseif args[i] == "--delete" then
action = "delete"
i = i + 1
target = args[i]
elseif args[i] == "--restore" then
action = "restore"
i = i + 1
target = args[i]
end
i = i + 1
end
if action == "list" then
local result = Un.snapshot_list()
if result and result.snapshots then
if #result.snapshots == 0 then
print("No snapshots")
else
print(string.format("%-40s %-20s %-10s %s", "ID", "Name", "Type", "Created"))
for _, s in ipairs(result.snapshots) do
print(string.format("%-40s %-20s %-10s %s",
s.id or "N/A", s.name or "N/A",
s.type or "N/A", s.created_at or "N/A"))
end
end
end
elseif action == "info" then
local result = Un.snapshot_get(target)
print(json.encode(result))
elseif action == "delete" then
Un.snapshot_delete(target)
print(GREEN .. "Snapshot deleted: " .. target .. RESET)
elseif action == "restore" then
Un.snapshot_restore(target)
print(GREEN .. "Snapshot restored" .. RESET)
else
print("Usage: lua un.lua snapshot --list|--info ID|--delete ID|--restore ID")
end
elseif cmd == "image" then
i = 2
local action = nil
local target = nil
local name = nil
local ports = nil
local source_type = nil
local visibility_mode = nil
while i <= #args do
if args[i] == "--list" or args[i] == "-l" then
action = "list"
elseif args[i] == "--info" then
action = "info"
i = i + 1
target = args[i]
elseif args[i] == "--delete" then
action = "delete"
i = i + 1
target = args[i]
elseif args[i] == "--lock" then
action = "lock"
i = i + 1
target = args[i]
elseif args[i] == "--unlock" then
action = "unlock"
i = i + 1
target = args[i]
elseif args[i] == "--publish" then
action = "publish"
i = i + 1
target = args[i]
elseif args[i] == "--source-type" then
i = i + 1
source_type = args[i]
elseif args[i] == "--visibility" then
action = "visibility"
i = i + 1
target = args[i]
i = i + 1
visibility_mode = args[i]
elseif args[i] == "--spawn" then
action = "spawn"
i = i + 1
target = args[i]
elseif args[i] == "--clone" then
action = "clone"
i = i + 1
target = args[i]
elseif args[i] == "--name" then
i = i + 1
name = args[i]
elseif args[i] == "--ports" then
i = i + 1
ports = {}
for p in args[i]:gmatch("[^,]+") do
table.insert(ports, tonumber(p))
end
end
i = i + 1
end
if action == "list" then
local result = Un.image_list()
if result and result.images then
if #result.images == 0 then
print("No images")
else
print(string.format("%-40s %-20s %-10s %s", "ID", "Name", "Visibility", "Created"))
for _, img in ipairs(result.images) do
print(string.format("%-40s %-20s %-10s %s",
img.id or "N/A", img.name or "N/A",
img.visibility or "N/A", img.created_at or "N/A"))
end
end
end
elseif action == "info" then
local result = Un.image_get(target)
print(json.encode(result))
elseif action == "delete" then
Un.image_delete(target)
print(GREEN .. "Image deleted: " .. target .. RESET)
elseif action == "lock" then
Un.image_lock(target)
print(GREEN .. "Image locked: " .. target .. RESET)
elseif action == "unlock" then
Un.image_unlock(target)
print(GREEN .. "Image unlocked: " .. target .. RESET)
elseif action == "publish" then
if not source_type then
io.stderr:write(RED .. "Error: --source-type required" .. RESET .. "\n")
os.exit(1)
end
local result = Un.image_publish({ source_type = source_type, source_id = target, name = name })
print(GREEN .. "Image published" .. RESET)
print(json.encode(result))
elseif action == "visibility" then
Un.image_set_visibility(target, visibility_mode)
print(GREEN .. "Visibility set to " .. visibility_mode .. RESET)
elseif action == "spawn" then
local result = Un.image_spawn(target, { name = name, ports = ports })
print(GREEN .. "Service spawned from image" .. RESET)
print(json.encode(result))
elseif action == "clone" then
local result = Un.image_clone(target, { name = name })
print(GREEN .. "Image cloned" .. RESET)
print(json.encode(result))
else
print("Usage: lua un.lua image --list|--info ID|--delete ID|--lock ID|--unlock ID|--publish ID|--visibility ID MODE|--spawn ID|--clone ID")
end
elseif cmd == "-s" then
-- Inline code execution
local lang = args[2]
local code = args[3]
if not lang or not code then
io.stderr:write(RED .. "Error: -s requires language and code" .. RESET .. "\n")
os.exit(1)
end
local result = Un.execute(lang, code)
if result then
if result.stdout then print(result.stdout) end
if result.stderr then io.stderr:write(result.stderr) end
os.exit(result.exit_code or 0)
else
io.stderr:write(RED .. "Error: " .. Un.last_error() .. RESET .. "\n")
os.exit(1)
end
elseif cmd == "--help" or cmd == "-h" then
print("Usage: lua un.lua [options] <source_file>")
print(" lua un.lua -s <language> '<code>'")
print(" lua un.lua session [options]")
print(" lua un.lua service [options]")
print(" lua un.lua snapshot [options]")
print(" lua un.lua image [options]")
print(" lua un.lua languages [--json]")
print(" lua un.lua key [--extend]")
else
-- Assume it's a file to execute
run_file(cmd)
end
end
return Un
Esclarecimentos de documentação
Dependências
C Binary (un1) — requer libcurl e libwebsockets:
sudo apt install build-essential libcurl4-openssl-dev libwebsockets-dev
wget unsandbox.com/downloads/un.c && gcc -O2 -o un un.c -lcurl -lwebsockets
Implementações SDK — a maioria usa apenas stdlib (Ruby, JS, Go, etc). Alguns requerem dependências mínimas:
pip install requests # Python
Executar Código
Executar um script
./un hello.py
./un app.js
./un main.rs
Com variáveis de ambiente
./un -e DEBUG=1 -e NAME=World script.py
Com arquivos de entrada (teletransportar arquivos para sandbox)
./un -f data.csv -f config.json process.py
Obter binário compilado
./un -a -o ./bin main.c
Sessões interativas
Iniciar uma sessão de shell
# Default bash shell
./un session
# Choose your shell
./un session --shell zsh
./un session --shell fish
# Jump into a REPL
./un session --shell python3
./un session --shell node
./un session --shell julia
Sessão com acesso à rede
./un session -n semitrusted
Auditoria de sessão (gravação completa do terminal)
# Record everything (including vim, interactive programs)
./un session --audit -o ./logs
# Replay session later
zcat session.log*.gz | less -R
Coletar artefatos da sessão
# Files in /tmp/artifacts/ are collected on exit
./un session -a -o ./outputs
Persistência de sessão (tmux/screen)
# Default: session terminates on disconnect (clean exit)
./un session
# With tmux: session persists, can reconnect later
./un session --tmux
# Press Ctrl+b then d to detach
# With screen: alternative multiplexer
./un session --screen
# Press Ctrl+a then d to detach
Listar Trabalhos Ativos
./un session --list
# Output:
# Active sessions: 2
#
# SESSION ID CONTAINER SHELL TTL STATUS
# abc123... unsb-vm-12345 python3 45m30s active
# def456... unsb-vm-67890 bash 1h2m active
Reconectar à sessão existente
# Reconnect by container name (requires --tmux or --screen)
./un session --attach unsb-vm-12345
# Use exit to terminate session, or detach to keep it running
Encerrar uma sessão
./un session --kill unsb-vm-12345
Shells e REPLs disponíveis
Shells: bash, dash, sh, zsh, fish, ksh, tcsh, csh, elvish, xonsh, ash
REPLs: python3, bpython, ipython # Python
node # JavaScript
ruby, irb # Ruby
lua # Lua
php # PHP
perl # Perl
guile, scheme # Scheme
ghci # Haskell
erl, iex # Erlang/Elixir
sbcl, clisp # Common Lisp
r # R
julia # Julia
clojure # Clojure
Gerenciamento de Chave API
Verificar Status do Pagamento
# Check if your API key is valid
./un key
# Output:
# Valid: key expires in 30 days
Estender Chave Expirada
# Open the portal to extend an expired key
./un key --extend
# This opens the unsandbox.com portal where you can
# add more credits to extend your key's expiration
Autenticação
As credenciais são carregadas em ordem de prioridade (maior primeiro):
# 1. CLI flags (highest priority)
./un -p unsb-pk-xxxx -k unsb-sk-xxxxx script.py
# 2. Environment variables
export UNSANDBOX_PUBLIC_KEY=unsb-pk-xxxx-xxxx-xxxx-xxxx
export UNSANDBOX_SECRET_KEY=unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx
./un script.py
# 3. Config file (lowest priority)
# ~/.unsandbox/accounts.csv format: public_key,secret_key
mkdir -p ~/.unsandbox
echo "unsb-pk-xxxx-xxxx-xxxx-xxxx,unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx" > ~/.unsandbox/accounts.csv
./un script.py
As requisições são assinadas com HMAC-SHA256. O token bearer contém apenas a chave pública; a chave secreta calcula a assinatura (nunca é transmitida).
Escalonamento de Recursos
Definir Quantidade de vCPU
# Default: 1 vCPU, 2GB RAM
./un script.py
# Scale up: 4 vCPUs, 8GB RAM
./un -v 4 script.py
# Maximum: 8 vCPUs, 16GB RAM
./un --vcpu 8 heavy_compute.py
Reforço de Sessão Ao Vivo
# Boost a running session to 2 vCPU, 4GB RAM
./un session --boost sandbox-abc
# Boost to specific vCPU count (4 vCPU, 8GB RAM)
./un session --boost sandbox-abc --boost-vcpu 4
# Return to base resources (1 vCPU, 2GB RAM)
./un session --unboost sandbox-abc
Congelar/Descongelar Sessão
Congelar e Descongelar Sessões
# Freeze a session (stop billing, preserve state)
./un session --freeze sandbox-abc
# Unfreeze a frozen session
./un session --unfreeze sandbox-abc
# Note: Requires --tmux or --screen for persistence
Serviços Persistentes
Criar um Serviço
# Web server with ports
./un service --name web --ports 80,443 --bootstrap "python -m http.server 80"
# With custom domains
./un service --name blog --ports 8000 --domains blog.example.com
# Game server with SRV records
./un service --name mc --type minecraft --bootstrap ./setup.sh
# Deploy app tarball with bootstrap script
./un service --name app --ports 8000 -f app.tar.gz --bootstrap-file ./setup.sh
# setup.sh: cd /tmp && tar xzf app.tar.gz && ./app/start.sh
Gerenciar Serviços
# List all services
./un service --list
# Get service details
./un service --info abc123
# View bootstrap logs
./un service --logs abc123
./un service --tail abc123 # last 9000 lines
# Execute command in running service
./un service --execute abc123 'journalctl -u myapp -n 50'
# Dump bootstrap script (for migrations)
./un service --dump-bootstrap abc123
./un service --dump-bootstrap abc123 backup.sh
# Freeze/unfreeze service
./un service --freeze abc123
./un service --unfreeze abc123
# Service settings (auto-wake, freeze page display)
./un service --auto-unfreeze abc123 # enable auto-wake on HTTP
./un service --no-auto-unfreeze abc123 # disable auto-wake
./un service --show-freeze-page abc123 # show HTML payment page (default)
./un service --no-show-freeze-page abc123 # return JSON error instead
# Redeploy with new bootstrap
./un service --redeploy abc123 --bootstrap ./new-setup.sh
# Destroy service
./un service --destroy abc123
Snapshots
Listar Snapshots
./un snapshot --list
# Output:
# Snapshots: 3
#
# SNAPSHOT ID NAME SOURCE SIZE CREATED
# unsb-snapshot-a1b2-c3d4-e5f6-g7h8 before-upgrade session 512 MB 2h ago
# unsb-snapshot-i9j0-k1l2-m3n4-o5p6 stable-v1.0 service 1.2 GB 1d ago
Criar Snapshot da Sessão
# Snapshot with name
./un session --snapshot unsb-vm-12345 --name "before upgrade"
# Quick snapshot (auto-generated name)
./un session --snapshot unsb-vm-12345
Criar Snapshot do Serviço
# Standard snapshot (pauses container briefly)
./un service --snapshot unsb-service-abc123 --name "stable v1.0"
# Hot snapshot (no pause, may be inconsistent)
./un service --snapshot unsb-service-abc123 --hot
Restaurar a partir do Snapshot
# Restore session from snapshot
./un session --restore unsb-snapshot-a1b2-c3d4-e5f6-g7h8
# Restore service from snapshot
./un service --restore unsb-snapshot-i9j0-k1l2-m3n4-o5p6
Excluir Snapshot
./un snapshot --delete unsb-snapshot-a1b2-c3d4-e5f6-g7h8
Imagens
Imagens são imagens de container independentes e transferíveis que sobrevivem à exclusão do container. Diferente dos snapshots (que permanecem com seu container), imagens podem ser compartilhadas com outros usuários, transferidas entre chaves de API ou tornadas públicas no marketplace.
Listar Imagens
# List all images (owned + shared + public)
./un image --list
# List only your images
./un image --list owned
# List images shared with you
./un image --list shared
# List public marketplace images
./un image --list public
# Get image details
./un image --info unsb-image-xxxx-xxxx-xxxx-xxxx
Publicar Imagens
# Publish from a stopped or frozen service
./un image --publish-service unsb-service-abc123 \
--name "My App v1.0" --description "Production snapshot"
# Publish from a snapshot
./un image --publish-snapshot unsb-snapshot-xxxx-xxxx-xxxx-xxxx \
--name "Stable Release"
# Note: Cannot publish from running containers - stop or freeze first
Criar Serviços a partir de Imagens
# Spawn a new service from an image
./un image --spawn unsb-image-xxxx-xxxx-xxxx-xxxx \
--name new-service --ports 80,443
# Clone an image (creates a copy you own)
./un image --clone unsb-image-xxxx-xxxx-xxxx-xxxx
Proteção de Imagem
# Lock image to prevent accidental deletion
./un image --lock unsb-image-xxxx-xxxx-xxxx-xxxx
# Unlock image to allow deletion
./un image --unlock unsb-image-xxxx-xxxx-xxxx-xxxx
# Delete image (must be unlocked)
./un image --delete unsb-image-xxxx-xxxx-xxxx-xxxx
Visibilidade e Compartilhamento
# Set visibility level
./un image --visibility unsb-image-xxxx-xxxx-xxxx-xxxx private # owner only (default)
./un image --visibility unsb-image-xxxx-xxxx-xxxx-xxxx unlisted # can be shared
./un image --visibility unsb-image-xxxx-xxxx-xxxx-xxxx public # marketplace
# Share with specific user
./un image --grant unsb-image-xxxx-xxxx-xxxx-xxxx \
--key unsb-pk-friend-friend-friend-friend
# Revoke access
./un image --revoke unsb-image-xxxx-xxxx-xxxx-xxxx \
--key unsb-pk-friend-friend-friend-friend
# List who has access
./un image --trusted unsb-image-xxxx-xxxx-xxxx-xxxx
Transferir Propriedade
# Transfer image to another API key
./un image --transfer unsb-image-xxxx-xxxx-xxxx-xxxx \
--to unsb-pk-newowner-newowner-newowner-newowner
Referência de uso
Usage: ./un [options] <source_file>
./un session [options]
./un service [options]
./un snapshot [options]
./un image [options]
./un key
Commands:
(default) Execute source file in sandbox
session Open interactive shell/REPL session
service Manage persistent services
snapshot Manage container snapshots
image Manage container images (publish, share, transfer)
key Check API key validity and expiration
Options:
-e KEY=VALUE Set environment variable (can use multiple times)
-f FILE Add input file (can use multiple times)
-a Return and save artifacts from /tmp/artifacts/
-o DIR Output directory for artifacts (default: current dir)
-p KEY Public key (or set UNSANDBOX_PUBLIC_KEY env var)
-k KEY Secret key (or set UNSANDBOX_SECRET_KEY env var)
-n MODE Network mode: zerotrust (default) or semitrusted
-v N, --vcpu N vCPU count 1-8, each vCPU gets 2GB RAM (default: 1)
-y Skip confirmation for large uploads (>1GB)
-h Show this help
Authentication (priority order):
1. -p and -k flags (public and secret key)
2. UNSANDBOX_PUBLIC_KEY + UNSANDBOX_SECRET_KEY env vars
3. ~/.unsandbox/accounts.csv (format: public_key,secret_key per line)
Session options:
-s, --shell SHELL Shell/REPL to use (default: bash)
-l, --list List active sessions
--attach ID Reconnect to existing session (ID or container name)
--kill ID Terminate a session (ID or container name)
--freeze ID Freeze a session (requires --tmux/--screen)
--unfreeze ID Unfreeze a frozen session
--boost ID Boost session resources (2 vCPU, 4GB RAM)
--boost-vcpu N Specify vCPU count for boost (1-8)
--unboost ID Return to base resources
--audit Record full session for auditing
--tmux Enable session persistence with tmux (allows reconnect)
--screen Enable session persistence with screen (allows reconnect)
Service options:
--name NAME Service name (creates new service)
--ports PORTS Comma-separated ports (e.g., 80,443)
--domains DOMAINS Custom domains (e.g., example.com,www.example.com)
--type TYPE Service type: minecraft, mumble, teamspeak, source, tcp, udp
--bootstrap CMD Bootstrap command/file/URL to run on startup
-f FILE Upload file to /tmp/ (can use multiple times)
-l, --list List all services
--info ID Get service details
--tail ID Get last 9000 lines of bootstrap logs
--logs ID Get all bootstrap logs
--freeze ID Freeze a service
--unfreeze ID Unfreeze a service
--auto-unfreeze ID Enable auto-wake on HTTP request
--no-auto-unfreeze ID Disable auto-wake on HTTP request
--show-freeze-page ID Show HTML payment page when frozen (default)
--no-show-freeze-page ID Return JSON error when frozen
--destroy ID Destroy a service
--redeploy ID Re-run bootstrap script (requires --bootstrap)
--execute ID CMD Run a command in a running service
--dump-bootstrap ID [FILE] Dump bootstrap script (for migrations)
--snapshot ID Create snapshot of session or service
--snapshot-name User-friendly name for snapshot
--hot Create snapshot without pausing (may be inconsistent)
--restore ID Restore session/service from snapshot ID
Snapshot options:
-l, --list List all snapshots
--info ID Get snapshot details
--delete ID Delete a snapshot permanently
Image options:
-l, --list [owned|shared|public] List images (all, owned, shared, or public)
--info ID Get image details
--publish-service ID Publish image from stopped/frozen service
--publish-snapshot ID Publish image from snapshot
--name NAME Name for published image
--description DESC Description for published image
--delete ID Delete image (must be unlocked)
--clone ID Clone image (creates copy you own)
--spawn ID Create service from image (requires --name)
--lock ID Lock image to prevent deletion
--unlock ID Unlock image to allow deletion
--visibility ID LEVEL Set visibility (private|unlisted|public)
--grant ID --key KEY Grant access to another API key
--revoke ID --key KEY Revoke access from API key
--transfer ID --to KEY Transfer ownership to API key
--trusted ID List API keys with access
Key options:
(no options) Check API key validity
--extend Open portal to extend an expired key
Examples:
./un script.py # execute Python script
./un -e DEBUG=1 script.py # with environment variable
./un -f data.csv process.py # with input file
./un -a -o ./bin main.c # save compiled artifacts
./un -v 4 heavy.py # with 4 vCPUs, 8GB RAM
./un session # interactive bash session
./un session --tmux # bash with reconnect support
./un session --list # list active sessions
./un session --attach unsb-vm-12345 # reconnect to session
./un session --kill unsb-vm-12345 # terminate a session
./un session --freeze unsb-vm-12345 # freeze session
./un session --unfreeze unsb-vm-12345 # unfreeze session
./un session --boost unsb-vm-12345 # boost resources
./un session --unboost unsb-vm-12345 # return to base
./un session --shell python3 # Python REPL
./un session --shell node # Node.js REPL
./un session -n semitrusted # session with network access
./un session --audit -o ./logs # record session for auditing
./un service --name web --ports 80 # create web service
./un service --list # list all services
./un service --logs abc123 # view bootstrap logs
./un key # check API key
./un key --extend # extend expired key
./un snapshot --list # list all snapshots
./un session --snapshot unsb-vm-123 # snapshot a session
./un service --snapshot abc123 # snapshot a service
./un session --restore unsb-snapshot-xxxx # restore from snapshot
./un image --list # list all images
./un image --list owned # list your images
./un image --publish-service abc # publish image from service
./un image --spawn img123 --name x # create service from image
./un image --grant img --key pk # share image with user
CLI Inception
O UN CLI foi implementado em 42 linguagens de programação, demonstrando que a API do unsandbox pode ser acessada de praticamente qualquer ambiente.
Ver Todas as 42 Implementações →
Licença
DOMÍNIO PÚBLICO - SEM LICENÇA, SEM GARANTIA
Este é software gratuito de domínio público para o bem público de um permacomputador hospedado
em permacomputer.com - um computador sempre ativo pelo povo, para o povo. Um que é
durável, fácil de reparar e distribuído como água da torneira para inteligência de
aprendizado de máquina.
O permacomputador é infraestrutura de propriedade comunitária otimizada em torno de quatro valores:
VERDADE - Primeiros princípios, matemática & ciência, código aberto distribuído livremente
LIBERDADE - Parcerias voluntárias, liberdade da tirania e controle corporativo
HARMONIA - Desperdício mínimo, sistemas auto-renováveis com diversas conexões prósperas
AMOR - Seja você mesmo sem ferir os outros, cooperação através da lei natural
Este software contribui para essa visão ao permitir a execução de código em mais de 42
linguagens de programação através de uma interface unificada, acessível a todos. Código são
sementes que brotam em qualquer tecnologia abandonada.
Saiba mais: https://www.permacomputer.com
Qualquer pessoa é livre para copiar, modificar, publicar, usar, compilar, vender ou distribuir
este software, seja em forma de código-fonte ou como binário compilado, para qualquer propósito,
comercial ou não comercial, e por qualquer meio.
SEM GARANTIA. O SOFTWARE É FORNECIDO "COMO ESTÁ" SEM GARANTIA DE QUALQUER TIPO.
Dito isso, a camada de membrana digital do nosso permacomputador executa continuamente testes
unitários, de integração e funcionais em todo o seu próprio software - com nosso permacomputador
monitorando a si mesmo, reparando a si mesmo, com orientação humana mínima no ciclo.
Nossos agentes fazem o seu melhor.
Copyright 2025 TimeHexOn & foxhop & russell@unturf
https://www.timehexon.com
https://www.foxhop.net
https://www.unturf.com/software