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 — Bash
# Download + setup
curl -O https://git.unturf.com/engineering/unturf/un-inception/-/raw/main/clients/bash/sync/src/un.sh && chmod +x un.sh && ln -sf un.sh 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.sh
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 Bash existente:
curl -O https://git.unturf.com/engineering/unturf/un-inception/-/raw/main/clients/bash/sync/src/un.sh
# 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
# Run code via CLI:
bash un.sh script.sh
# Or inline:
echo 'echo "Hello from Bash running on unsandbox!"' > /tmp/test.sh && bash un.sh /tmp/test.sh
# Output: Hello from Bash running on unsandbox!
bash myapp.sh
ab15e606d457ca0a4a31e3df8204fab8
SHA256: 85d81b53391060cbc136cbe0fd391c785788693bf8181c9e1c611f5259fa6d35
#!/bin/bash
# This is free software for the public good of a permacomputer hosted at
# permacomputer.com, an always-on computer by the people, for the people.
# One which is durable, easy to repair, & distributed like tap water
# for machine learning intelligence.
#
# The permacomputer is community-owned infrastructure optimized around
# four values:
#
# TRUTH First principles, math & science, open source code freely distributed
# FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
# HARMONY Minimal waste, self-renewing systems with diverse thriving connections
# LOVE Be yourself without hurting others, cooperation through natural law
#
# This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
# Code is seeds to sprout on any abandoned technology.
set -euo pipefail
VERSION="4.2.50"
API_BASE="https://api.unsandbox.com"
PORTAL_BASE="https://unsandbox.com"
LAST_ERROR=""
ACCOUNT_INDEX=-1
# Colors
BLUE='\033[34m'
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
RESET='\033[0m'
# ============================================================================
# Utility Functions
# ============================================================================
version() {
echo "$VERSION"
}
last_error() {
echo "$LAST_ERROR"
}
set_error() {
LAST_ERROR="$1"
}
detect_language() {
local file="$1"
case "$file" in
*.py) echo "python" ;;
*.js) echo "javascript" ;;
*.ts) echo "typescript" ;;
*.rb) echo "ruby" ;;
*.php) echo "php" ;;
*.pl) echo "perl" ;;
*.lua) echo "lua" ;;
*.sh) echo "bash" ;;
*.go) echo "go" ;;
*.rs) echo "rust" ;;
*.c) echo "c" ;;
*.cpp|*.cc|*.cxx) echo "cpp" ;;
*.java) echo "java" ;;
*.kt) echo "kotlin" ;;
*.cs) echo "csharp" ;;
*.fs) echo "fsharp" ;;
*.hs) echo "haskell" ;;
*.ml) echo "ocaml" ;;
*.clj) echo "clojure" ;;
*.scm) echo "scheme" ;;
*.lisp) echo "commonlisp" ;;
*.erl) echo "erlang" ;;
*.ex|*.exs) echo "elixir" ;;
*.jl) echo "julia" ;;
*.r|*.R) echo "r" ;;
*.cr) echo "crystal" ;;
*.d) echo "d" ;;
*.nim) echo "nim" ;;
*.zig) echo "zig" ;;
*.v) echo "v" ;;
*.dart) echo "dart" ;;
*.groovy) echo "groovy" ;;
*.scala) echo "scala" ;;
*.f90|*.f95) echo "fortran" ;;
*.cob) echo "cobol" ;;
*.tcl) echo "tcl" ;;
*.raku) echo "raku" ;;
*.pro) echo "prolog" ;;
*.forth|*.4th) echo "forth" ;;
*.m) echo "objc" ;;
*) return 1 ;;
esac
}
hmac_sign() {
local secret="$1"
local message="$2"
echo -n "$message" | openssl dgst -sha256 -hmac "$secret" -hex 2>/dev/null | sed 's/^.* //'
}
# ============================================================================
# Credential Management
# ============================================================================
load_accounts_csv() {
local path="${1:-$HOME/.unsandbox/accounts.csv}"
local row="${2:-0}"
[ -f "$path" ] || return 1
local n=0
while IFS= read -r line; do
[[ "$line" =~ ^# ]] && continue
[ -z "$line" ] && continue
if [ "$n" -eq "$row" ]; then
echo "$line"
return 0
fi
n=$((n + 1))
done < "$path"
return 1
}
get_credentials() {
# Tier 1: Arguments (via PUBLIC_KEY/SECRET_KEY globals)
if [ -n "${PUBLIC_KEY:-}" ] && [ -n "${SECRET_KEY:-}" ]; then
echo "$PUBLIC_KEY:$SECRET_KEY"
return
fi
# Tier 2: --account N flag → bypass env vars, load CSV row N directly
if [ "$ACCOUNT_INDEX" -ge 0 ] 2>/dev/null; then
local creds
creds=$(load_accounts_csv "$HOME/.unsandbox/accounts.csv" "$ACCOUNT_INDEX" 2>/dev/null || true)
[ -z "$creds" ] && creds=$(load_accounts_csv "./accounts.csv" "$ACCOUNT_INDEX" 2>/dev/null || true)
if [ -n "$creds" ]; then
echo "$creds"
return
fi
set_error "Account index $ACCOUNT_INDEX not found in accounts.csv"
return 1
fi
# Tier 3: Environment
if [ -n "${UNSANDBOX_PUBLIC_KEY:-}" ] && [ -n "${UNSANDBOX_SECRET_KEY:-}" ]; then
echo "$UNSANDBOX_PUBLIC_KEY:$UNSANDBOX_SECRET_KEY"
return
fi
# Legacy fallback
if [ -n "${UNSANDBOX_API_KEY:-}" ]; then
echo "$UNSANDBOX_API_KEY:"
return
fi
# Tier 4: Home directory
local creds
creds=$(load_accounts_csv "$HOME/.unsandbox/accounts.csv" 2>/dev/null || true)
if [ -n "$creds" ]; then
echo "$creds"
return
fi
# Tier 5: Local directory
creds=$(load_accounts_csv "./accounts.csv" 2>/dev/null || true)
if [ -n "$creds" ]; then
echo "$creds"
return
fi
set_error "No credentials found"
return 1
}
# ============================================================================
# API Communication
# ============================================================================
api_request() {
local method="$1"
local endpoint="$2"
local body="${3:-}"
local extra_headers="${4:-}"
local content_type="${5:-application/json}"
local creds
creds=$(get_credentials) || return 1
local pk="${creds%%:*}"
local sk="${creds#*:}"
local timestamp
timestamp=$(date +%s)
local body_str="${body:-}"
local signature=""
if [ -n "$sk" ]; then
signature=$(hmac_sign "$sk" "$timestamp:$method:$endpoint:$body_str")
fi
local curl_args=(-s -X "$method" "$API_BASE$endpoint"
-H "Authorization: Bearer $pk"
-H "Content-Type: $content_type")
if [ -n "$signature" ]; then
curl_args+=(-H "X-Timestamp: $timestamp" -H "X-Signature: $signature")
fi
if [ -n "$extra_headers" ]; then
eval "curl_args+=($extra_headers)"
fi
if [ -n "$body_str" ]; then
curl_args+=(-d "$body_str")
fi
curl "${curl_args[@]}"
}
api_request_with_sudo() {
local method="$1"
local endpoint="$2"
local body="${3:-}"
local creds
creds=$(get_credentials) || return 1
local pk="${creds%%:*}"
local sk="${creds#*:}"
local timestamp
timestamp=$(date +%s)
local body_str="${body:-}"
local signature=""
if [ -n "$sk" ]; then
signature=$(hmac_sign "$sk" "$timestamp:$method:$endpoint:$body_str")
fi
local result
result=$(curl -s -w '\n%{http_code}' -X "$method" "$API_BASE$endpoint" \
-H "Authorization: Bearer $pk" \
-H "Content-Type: application/json" \
${signature:+-H "X-Timestamp: $timestamp" -H "X-Signature: $signature"} \
${body_str:+-d "$body_str"})
local http_code
http_code=$(echo "$result" | tail -1)
local response_body
response_body=$(echo "$result" | sed '$d')
# Handle 428 - Sudo OTP required
if [ "$http_code" = "428" ]; then
local challenge_id
challenge_id=$(echo "$response_body" | jq -r '.challenge_id // empty' 2>/dev/null || true)
echo -e "${YELLOW}Confirmation required. Check your email for a one-time code.${RESET}" >&2
echo -n "Enter OTP: " >&2
read -r otp
if [ -z "$otp" ]; then
set_error "Operation cancelled"
return 1
fi
# Retry with sudo headers
timestamp=$(date +%s)
if [ -n "$sk" ]; then
signature=$(hmac_sign "$sk" "$timestamp:$method:$endpoint:$body_str")
fi
result=$(curl -s -w '\n%{http_code}' -X "$method" "$API_BASE$endpoint" \
-H "Authorization: Bearer $pk" \
-H "Content-Type: application/json" \
${signature:+-H "X-Timestamp: $timestamp" -H "X-Signature: $signature"} \
-H "X-Sudo-OTP: $otp" \
${challenge_id:+-H "X-Sudo-Challenge: $challenge_id"} \
${body_str:+-d "$body_str"})
http_code=$(echo "$result" | tail -1)
response_body=$(echo "$result" | sed '$d')
fi
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
set_error "API error ($http_code)"
return 1
fi
echo "$response_body"
}
# ============================================================================
# Execution Functions (8)
# ============================================================================
execute() {
local language="$1"
local code="$2"
local network_mode="${3:-zerotrust}"
local body
body=$(jq -n --arg lang "$language" --arg code "$code" --arg net "$network_mode" \
'{language: $lang, code: $code, network_mode: $net, ttl: 60}')
api_request "POST" "/execute" "$body"
}
execute_async() {
local language="$1"
local code="$2"
local network_mode="${3:-zerotrust}"
local body
body=$(jq -n --arg lang "$language" --arg code "$code" --arg net "$network_mode" \
'{language: $lang, code: $code, network_mode: $net, ttl: 300}')
api_request "POST" "/execute/async" "$body"
}
wait_job() {
local job_id="$1"
local delays=(300 450 700 900 650 1600 2000)
for i in $(seq 0 119); do
local job
job=$(get_job "$job_id")
local status
status=$(echo "$job" | jq -r '.status')
[ "$status" = "completed" ] && echo "$job" && return 0
[ "$status" = "failed" ] && { set_error "Job failed"; return 1; }
local delay=${delays[$((i % 7))]}
sleep "$(echo "scale=3; $delay/1000" | bc)"
done
set_error "Max polls exceeded"
return 1
}
get_job() {
local job_id="$1"
api_request "GET" "/jobs/$job_id" ""
}
cancel_job() {
local job_id="$1"
api_request "DELETE" "/jobs/$job_id" ""
}
list_jobs() {
api_request "GET" "/jobs" ""
}
get_languages() {
local cache_path="$HOME/.unsandbox/languages.json"
local cache_ttl=3600
if [ -f "$cache_path" ]; then
local age
age=$(($(date +%s) - $(stat -f%m "$cache_path" 2>/dev/null || stat -c%Y "$cache_path" 2>/dev/null || echo 0)))
if [ "$age" -lt "$cache_ttl" ]; then
cat "$cache_path"
return
fi
fi
local result
result=$(api_request "GET" "/languages" "")
mkdir -p "$HOME/.unsandbox"
echo "$result" | jq '.languages' > "$cache_path"
echo "$result" | jq '.languages'
}
# ============================================================================
# Session Functions (9)
# ============================================================================
session_list() {
api_request "GET" "/sessions" ""
}
session_get() {
local session_id="$1"
api_request "GET" "/sessions/$session_id" ""
}
session_create() {
local shell="${1:-bash}"
local network="${2:-}"
local vcpu="${3:-}"
local body
body=$(jq -n --arg shell "$shell" '{shell: $shell}')
if [ -n "$network" ]; then
body=$(echo "$body" | jq --arg net "$network" '. + {network: $net}')
fi
if [ -n "$vcpu" ]; then
body=$(echo "$body" | jq --argjson vcpu "$vcpu" '. + {vcpu: $vcpu}')
fi
api_request "POST" "/sessions" "$body"
}
session_destroy() {
local session_id="$1"
api_request "DELETE" "/sessions/$session_id" ""
}
session_freeze() {
local session_id="$1"
api_request "POST" "/sessions/$session_id/freeze" "{}"
}
session_unfreeze() {
local session_id="$1"
api_request "POST" "/sessions/$session_id/unfreeze" "{}"
}
session_boost() {
local session_id="$1"
local vcpu="${2:-2}"
api_request "POST" "/sessions/$session_id/boost" "{\"vcpu\":$vcpu}"
}
session_unboost() {
local session_id="$1"
api_request "POST" "/sessions/$session_id/unboost" "{}"
}
session_execute() {
local session_id="$1"
local command="$2"
api_request "POST" "/sessions/$session_id/execute" "{\"command\":$(echo "$command" | jq -Rs .)}"
}
# ============================================================================
# Service Functions (17)
# ============================================================================
service_list() {
api_request "GET" "/services" ""
}
service_get() {
local service_id="$1"
api_request "GET" "/services/$service_id" ""
}
service_create() {
local name="$1"
local ports="${2:-}"
local bootstrap="${3:-}"
local input_files_json="${4:-}"
local body
body=$(jq -n --arg name "$name" '{name: $name}')
if [ -n "$ports" ]; then
body=$(echo "$body" | jq --argjson ports "[$ports]" '. + {ports: $ports}')
fi
if [ -n "$bootstrap" ]; then
body=$(echo "$body" | jq --arg boot "$bootstrap" '. + {bootstrap: $boot}')
fi
if [ -n "$input_files_json" ]; then
body=$(echo "$body" | jq --argjson files "$input_files_json" '. + {input_files: $files}')
fi
api_request "POST" "/services" "$body"
}
service_destroy() {
local service_id="$1"
api_request_with_sudo "DELETE" "/services/$service_id" ""
}
service_freeze() {
local service_id="$1"
api_request "POST" "/services/$service_id/freeze" "{}"
}
service_unfreeze() {
local service_id="$1"
api_request "POST" "/services/$service_id/unfreeze" "{}"
}
service_lock() {
local service_id="$1"
api_request "POST" "/services/$service_id/lock" "{}"
}
service_unlock() {
local service_id="$1"
api_request_with_sudo "POST" "/services/$service_id/unlock" "{}"
}
service_set_unfreeze_on_demand() {
local service_id="$1"
local enabled="$2"
api_request "PATCH" "/services/$service_id" "{\"unfreeze_on_demand\":$enabled}"
}
service_redeploy() {
local service_id="$1"
local bootstrap="${2:-}"
local input_files_json="${3:-}"
local body="{}"
if [ -n "$bootstrap" ]; then
body=$(jq -n --arg boot "$bootstrap" '{bootstrap: $boot}')
fi
if [ -n "$input_files_json" ]; then
body=$(echo "$body" | jq --argjson files "$input_files_json" '. + {input_files: $files}')
fi
api_request "POST" "/services/$service_id/redeploy" "$body"
}
service_logs() {
local service_id="$1"
local lines="${2:-}"
local endpoint="/services/$service_id/logs"
[ -n "$lines" ] && endpoint="$endpoint?lines=$lines"
api_request "GET" "$endpoint" ""
}
service_execute() {
local service_id="$1"
local command="$2"
api_request "POST" "/services/$service_id/execute" "{\"command\":$(echo "$command" | jq -Rs .)}"
}
service_env_get() {
local service_id="$1"
api_request "GET" "/services/$service_id/env" ""
}
service_env_set() {
local service_id="$1"
local env_content="$2"
api_request "PUT" "/services/$service_id/env" "$env_content" "" "text/plain"
}
service_env_delete() {
local service_id="$1"
api_request "DELETE" "/services/$service_id/env" ""
}
service_env_export() {
local service_id="$1"
api_request "POST" "/services/$service_id/env/export" "{}"
}
service_resize() {
local service_id="$1"
local vcpu="$2"
api_request "PATCH" "/services/$service_id" "{\"vcpu\":$vcpu}"
}
# ============================================================================
# Snapshot Functions (9)
# ============================================================================
snapshot_list() {
api_request "GET" "/snapshots" ""
}
snapshot_get() {
local snapshot_id="$1"
api_request "GET" "/snapshots/$snapshot_id" ""
}
snapshot_session() {
local session_id="$1"
local name="${2:-}"
local hot="${3:-false}"
local body="{}"
if [ -n "$name" ] || [ "$hot" = "true" ]; then
body=$(jq -n --arg name "$name" --argjson hot "$hot" \
'{name: (if $name != "" then $name else null end), hot: $hot}')
fi
api_request "POST" "/sessions/$session_id/snapshot" "$body"
}
snapshot_service() {
local service_id="$1"
local name="${2:-}"
local hot="${3:-false}"
local body="{}"
if [ -n "$name" ] || [ "$hot" = "true" ]; then
body=$(jq -n --arg name "$name" --argjson hot "$hot" \
'{name: (if $name != "" then $name else null end), hot: $hot}')
fi
api_request "POST" "/services/$service_id/snapshot" "$body"
}
snapshot_restore() {
local snapshot_id="$1"
api_request "POST" "/snapshots/$snapshot_id/restore" "{}"
}
snapshot_delete() {
local snapshot_id="$1"
api_request_with_sudo "DELETE" "/snapshots/$snapshot_id" ""
}
snapshot_lock() {
local snapshot_id="$1"
api_request "POST" "/snapshots/$snapshot_id/lock" "{}"
}
snapshot_unlock() {
local snapshot_id="$1"
api_request_with_sudo "POST" "/snapshots/$snapshot_id/unlock" "{}"
}
snapshot_clone() {
local snapshot_id="$1"
local clone_type="${2:-session}"
local name="${3:-}"
local body
body=$(jq -n --arg type "$clone_type" --arg name "$name" \
'{clone_type: $type, name: (if $name != "" then $name else null end)}')
api_request "POST" "/snapshots/$snapshot_id/clone" "$body"
}
# ============================================================================
# Image Functions (13)
# ============================================================================
image_list() {
local filter="${1:-}"
local endpoint="/images"
[ -n "$filter" ] && endpoint="$endpoint?filter=$filter"
api_request "GET" "$endpoint" ""
}
image_get() {
local image_id="$1"
api_request "GET" "/images/$image_id" ""
}
image_publish() {
local source_type="$1"
local source_id="$2"
local name="${3:-}"
local body
body=$(jq -n --arg type "$source_type" --arg id "$source_id" --arg name "$name" \
'{source_type: $type, source_id: $id, name: (if $name != "" then $name else null end)}')
api_request "POST" "/images/publish" "$body"
}
image_delete() {
local image_id="$1"
api_request_with_sudo "DELETE" "/images/$image_id" ""
}
image_lock() {
local image_id="$1"
api_request "POST" "/images/$image_id/lock" "{}"
}
image_unlock() {
local image_id="$1"
api_request_with_sudo "POST" "/images/$image_id/unlock" "{}"
}
image_set_visibility() {
local image_id="$1"
local visibility="$2"
api_request "POST" "/images/$image_id/visibility" "{\"visibility\":\"$visibility\"}"
}
image_grant_access() {
local image_id="$1"
local trusted_key="$2"
api_request "POST" "/images/$image_id/access" "{\"api_key\":\"$trusted_key\"}"
}
image_revoke_access() {
local image_id="$1"
local trusted_key="$2"
api_request "DELETE" "/images/$image_id/access/$trusted_key" ""
}
image_list_trusted() {
local image_id="$1"
api_request "GET" "/images/$image_id/access" ""
}
image_transfer() {
local image_id="$1"
local to_key="$2"
api_request "POST" "/images/$image_id/transfer" "{\"to_api_key\":\"$to_key\"}"
}
image_spawn() {
local image_id="$1"
local name="${2:-}"
local ports="${3:-}"
local body="{}"
if [ -n "$name" ] || [ -n "$ports" ]; then
body="{"
local first=1
if [ -n "$name" ]; then
body="$body\"name\":\"$name\""
first=0
fi
if [ -n "$ports" ]; then
[ "$first" -eq 0 ] && body="$body,"
body="$body\"ports\":[$ports]"
fi
body="$body}"
fi
api_request "POST" "/images/$image_id/spawn" "$body"
}
image_clone() {
local image_id="$1"
local name="${2:-}"
local body="{}"
if [ -n "$name" ]; then
body="{\"name\":\"$name\"}"
fi
api_request "POST" "/images/$image_id/clone" "$body"
}
# ============================================================================
# PaaS Logs Functions (2)
# ============================================================================
logs_fetch() {
local source="${1:-all}"
local lines="${2:-100}"
local since="${3:-1h}"
local grep_pattern="${4:-}"
local body
body=$(jq -n --arg source "$source" --argjson lines "$lines" --arg since "$since" --arg grep "$grep_pattern" \
'{source: $source, lines: $lines, since: $since, grep: (if $grep != "" then $grep else null end)}')
api_request "POST" "/paas/logs" "$body"
}
logs_stream() {
set_error "logs_stream requires async support"
return 1
}
# ============================================================================
# Key Validation
# ============================================================================
validate_keys() {
local creds
creds=$(get_credentials) || return 1
local pk="${creds%%:*}"
local sk="${creds#*:}"
local timestamp
timestamp=$(date +%s)
local signature=""
if [ -n "$sk" ]; then
signature=$(hmac_sign "$sk" "$timestamp:POST:/keys/validate:")
fi
curl -s -X POST "$PORTAL_BASE/keys/validate" \
-H "Authorization: Bearer $pk" \
-H "Content-Type: application/json" \
${signature:+-H "X-Timestamp: $timestamp" -H "X-Signature: $signature"}
}
health_check() {
local result
result=$(curl -s -o /dev/null -w '%{http_code}' "$API_BASE/health")
[ "$result" = "200" ]
}
# ============================================================================
# CLI Implementation
# ============================================================================
run_file() {
local file="$1"
if [ ! -f "$file" ]; then
echo -e "${RED}Error: File not found: $file${RESET}" >&2
exit 1
fi
local code
code=$(cat "$file")
local lang
lang=$(detect_language "$file") || {
echo -e "${RED}Error: Cannot detect language${RESET}" >&2
exit 1
}
local result
result=$(execute "$lang" "$code")
if ! echo "$result" | jq -e . >/dev/null 2>&1; then
echo -e "${RED}Error: Failed to execute${RESET}" >&2
exit 1
fi
echo "$result" | jq -r '.stdout // empty'
echo "$result" | jq -r '.stderr // empty' >&2
local exit_code
exit_code=$(echo "$result" | jq -r '.exit_code // 0')
exit "${exit_code:-0}"
}
cmd_languages() {
local json_output=0
for arg in "$@"; do
if [ "$arg" = "--json" ]; then
json_output=1
fi
done
local result
result=$(get_languages)
if [ "$json_output" -eq 1 ]; then
echo "$result" | jq -c '.'
else
echo "$result" | jq -r '.[]'
fi
}
cmd_key() {
local extend=0
for arg in "$@"; do
if [ "$arg" = "--extend" ]; then
extend=1
fi
done
local result
result=$(validate_keys)
local pk
pk=$(echo "$result" | jq -r '.public_key // empty')
if [ "$extend" -eq 1 ] && [ -n "$pk" ]; then
local url="$PORTAL_BASE/keys/extend?pk=$pk"
echo -e "${BLUE}Opening browser to extend key...${RESET}"
xdg-open "$url" 2>/dev/null || open "$url" 2>/dev/null &
return
fi
if echo "$result" | jq -e '.expired' >/dev/null 2>&1; then
echo -e "${RED}Expired${RESET}"
echo "Public Key: $pk"
echo "Tier: $(echo "$result" | jq -r '.tier // "N/A"')"
echo -e "${YELLOW}To renew: Visit $PORTAL_BASE/keys/extend${RESET}"
exit 1
fi
echo -e "${GREEN}Valid${RESET}"
echo "Public Key: $pk"
echo "Tier: $(echo "$result" | jq -r '.tier // "N/A"')"
echo "Status: $(echo "$result" | jq -r '.status // "N/A"')"
echo "Expires: $(echo "$result" | jq -r '.expires_at // "N/A"')"
echo "Time Remaining: $(echo "$result" | jq -r '.time_remaining // "N/A"')"
}
cmd_session() {
local action=""
local target=""
while [ $# -gt 0 ]; do
case "$1" in
--list|-l) action="list" ;;
--info) action="info"; target="$2"; shift ;;
--kill) action="kill"; target="$2"; shift ;;
--freeze) action="freeze"; target="$2"; shift ;;
--unfreeze) action="unfreeze"; target="$2"; shift ;;
--boost) action="boost"; target="$2"; shift ;;
--unboost) action="unboost"; target="$2"; shift ;;
*) ;;
esac
shift
done
case "$action" in
list)
local result
result=$(session_list)
echo "$result" | jq -r '.sessions[] | "\(.id)\t\(.shell)\t\(.status)\t\(.created_at)"' 2>/dev/null || echo "No sessions"
;;
info)
session_get "$target" | jq .
;;
kill)
session_destroy "$target"
echo -e "${GREEN}Session terminated: $target${RESET}"
;;
freeze)
session_freeze "$target"
echo -e "${GREEN}Session frozen: $target${RESET}"
;;
unfreeze)
session_unfreeze "$target"
echo -e "${GREEN}Session unfreezing: $target${RESET}"
;;
boost)
session_boost "$target"
echo -e "${GREEN}Session boosted: $target${RESET}"
;;
unboost)
session_unboost "$target"
echo -e "${GREEN}Session unboosted: $target${RESET}"
;;
*)
echo "Usage: bash un.sh session --list|--info ID|--kill ID|--freeze ID|--unfreeze ID" >&2
exit 1
;;
esac
}
cmd_service() {
local action=""
local target=""
local name=""
local ports=""
local bootstrap=""
local bootstrap_file=""
local -a files=()
while [ $# -gt 0 ]; do
case "$1" in
--list|-l) action="list" ;;
--info) action="info"; target="$2"; shift ;;
--destroy) action="destroy"; target="$2"; shift ;;
--freeze) action="freeze"; target="$2"; shift ;;
--unfreeze) action="unfreeze"; target="$2"; shift ;;
--lock) action="lock"; target="$2"; shift ;;
--unlock) action="unlock"; target="$2"; shift ;;
--logs) action="logs"; target="$2"; shift ;;
--redeploy) action="redeploy"; target="$2"; shift ;;
--name) name="$2"; shift ;;
--ports) ports="$2"; shift ;;
--bootstrap) bootstrap="$2"; shift ;;
--bootstrap-file) bootstrap_file="$2"; shift ;;
-f|--file) files+=("$2"); shift ;;
*) ;;
esac
shift
done
# Build input_files JSON from -f args
local input_files_json=""
if [ ${#files[@]} -gt 0 ]; then
input_files_json="["
local first=1
for fpath in "${files[@]}"; do
if [ ! -f "$fpath" ]; then
echo -e "${RED}Error: File not found: $fpath${RESET}" >&2
exit 1
fi
local encoded
encoded=$(base64 -w0 "$fpath" 2>/dev/null || base64 "$fpath" 2>/dev/null)
local fname
fname=$(basename "$fpath")
[ "$first" -eq 0 ] && input_files_json="$input_files_json,"
input_files_json="$input_files_json{\"filename\":$(echo "$fname" | jq -Rs .),\"content\":$(echo "$encoded" | jq -Rs .)}"
first=0
done
input_files_json="$input_files_json]"
fi
# Resolve bootstrap from file if provided
if [ -n "$bootstrap_file" ]; then
if [ ! -f "$bootstrap_file" ]; then
echo -e "${RED}Error: Bootstrap file not found: $bootstrap_file${RESET}" >&2
exit 1
fi
bootstrap=$(cat "$bootstrap_file")
fi
case "$action" in
list)
local result
result=$(service_list)
echo "$result" | jq -r '.services[] | "\(.id)\t\(.name)\t\(.status)\t\(.ports | join(","))"' 2>/dev/null || echo "No services"
;;
info)
service_get "$target" | jq .
;;
destroy)
service_destroy "$target"
echo -e "${GREEN}Service destroyed: $target${RESET}"
;;
freeze)
service_freeze "$target"
echo -e "${GREEN}Service frozen: $target${RESET}"
;;
unfreeze)
service_unfreeze "$target"
echo -e "${GREEN}Service unfreezing: $target${RESET}"
;;
lock)
service_lock "$target"
echo -e "${GREEN}Service locked: $target${RESET}"
;;
unlock)
service_unlock "$target"
echo -e "${GREEN}Service unlocked: $target${RESET}"
;;
logs)
local result
result=$(service_logs "$target")
echo "$result" | jq -r '.logs // empty'
;;
redeploy)
local result
result=$(service_redeploy "$target" "$bootstrap" "$input_files_json")
echo -e "${GREEN}Service redeployed: $target${RESET}"
;;
*)
if [ -n "$name" ]; then
local result
result=$(service_create "$name" "$ports" "$bootstrap" "$input_files_json")
echo -e "${GREEN}Service created${RESET}"
echo "$result" | jq -r '"ID: \(.id)\nName: \(.name)"'
else
echo "Usage: bash un.sh service --list|--info ID|--destroy ID|--redeploy ID|--name NAME" >&2
exit 1
fi
;;
esac
}
cmd_snapshot() {
local action=""
local target=""
while [ $# -gt 0 ]; do
case "$1" in
--list|-l) action="list" ;;
--info) action="info"; target="$2"; shift ;;
--delete) action="delete"; target="$2"; shift ;;
--restore) action="restore"; target="$2"; shift ;;
--lock) action="lock"; target="$2"; shift ;;
--unlock) action="unlock"; target="$2"; shift ;;
*) ;;
esac
shift
done
case "$action" in
list)
local result
result=$(snapshot_list)
echo "$result" | jq -r '.snapshots[] | "\(.id)\t\(.name)\t\(.type)\t\(.created_at)"' 2>/dev/null || echo "No snapshots"
;;
info)
snapshot_get "$target" | jq .
;;
delete)
snapshot_delete "$target"
echo -e "${GREEN}Snapshot deleted: $target${RESET}"
;;
restore)
snapshot_restore "$target"
echo -e "${GREEN}Snapshot restored${RESET}"
;;
lock)
snapshot_lock "$target"
echo -e "${GREEN}Snapshot locked: $target${RESET}"
;;
unlock)
snapshot_unlock "$target"
echo -e "${GREEN}Snapshot unlocked: $target${RESET}"
;;
*)
echo "Usage: bash un.sh snapshot --list|--info ID|--delete ID|--restore ID" >&2
exit 1
;;
esac
}
cmd_image() {
local action=""
local target=""
local source_type=""
local visibility_mode=""
local name=""
local ports=""
while [ $# -gt 0 ]; do
case "$1" in
--list|-l) action="list" ;;
--info) action="info"; target="$2"; shift ;;
--delete) action="delete"; target="$2"; shift ;;
--lock) action="lock"; target="$2"; shift ;;
--unlock) action="unlock"; target="$2"; shift ;;
--publish) action="publish"; target="$2"; shift ;;
--source-type) source_type="$2"; shift ;;
--visibility) action="visibility"; target="$2"; visibility_mode="$3"; shift 2 ;;
--spawn) action="spawn"; target="$2"; shift ;;
--clone) action="clone"; target="$2"; shift ;;
--name) name="$2"; shift ;;
--ports) ports="$2"; shift ;;
*) ;;
esac
shift
done
case "$action" in
list)
local result
result=$(image_list)
echo "$result" | jq -r '.images[] | "\(.id)\t\(.name // "-")\t\(.visibility)\t\(.created_at)"' 2>/dev/null || echo "No images"
;;
info)
image_get "$target" | jq .
;;
delete)
image_delete "$target"
echo -e "${GREEN}Image deleted: $target${RESET}"
;;
lock)
image_lock "$target"
echo -e "${GREEN}Image locked: $target${RESET}"
;;
unlock)
image_unlock "$target"
echo -e "${GREEN}Image unlocked: $target${RESET}"
;;
publish)
if [ -z "$source_type" ]; then
echo -e "${RED}Error: --source-type required${RESET}" >&2
exit 1
fi
local result
result=$(image_publish "$source_type" "$target" "$name")
echo -e "${GREEN}Image published${RESET}"
echo "$result" | jq -r '"Image ID: \(.id)"'
;;
visibility)
image_set_visibility "$target" "$visibility_mode"
echo -e "${GREEN}Visibility set to $visibility_mode${RESET}"
;;
spawn)
local result
result=$(image_spawn "$target" "$name" "$ports")
echo -e "${GREEN}Service spawned from image${RESET}"
echo "$result" | jq -r '"Service ID: \(.id)"'
;;
clone)
local result
result=$(image_clone "$target" "$name")
echo -e "${GREEN}Image cloned${RESET}"
echo "$result" | jq -r '"Image ID: \(.id)"'
;;
*)
echo "Usage: bash un.sh image --list|--info ID|--delete ID|--publish ID|--spawn ID|--clone ID" >&2
exit 1
;;
esac
}
show_help() {
cat << 'EOF'
Unsandbox CLI - Execute code in secure sandboxes
Usage:
bash un.sh [options] <source_file>
bash un.sh -s <language> '<code>'
bash un.sh session [options]
bash un.sh service [options]
bash un.sh snapshot [options]
bash un.sh image [options]
bash un.sh languages [--json]
bash un.sh key [--extend]
Commands:
languages List available programming languages
key Validate API key
session Manage interactive sessions
service Manage persistent services
snapshot Manage snapshots
image Manage images
Session options:
--list List all sessions
--info ID Get session details
--kill ID Terminate session
--freeze ID Freeze session
--unfreeze ID Unfreeze session
--boost ID Boost session CPU
--unboost ID Unboost session CPU
Service options:
--list List all services
--info ID Get service details
--destroy ID Destroy service
--freeze ID Freeze service
--unfreeze ID Unfreeze service
--lock ID Lock service
--unlock ID Unlock service
--logs ID Get service logs
--redeploy ID Re-run bootstrap (supports -f, --bootstrap)
--name NAME Create service with name
--ports PORTS Service ports (comma-separated)
--bootstrap CMD Bootstrap command
--bootstrap-file FILE Bootstrap from file
-f, --file FILE Add input file (can repeat)
Snapshot options:
--list List all snapshots
--info ID Get snapshot details
--delete ID Delete snapshot
--restore ID Restore from snapshot
--lock ID Lock snapshot
--unlock ID Unlock snapshot
Image options:
--list List all images
--info ID Get image details
--delete ID Delete image
--lock ID Lock image
--unlock ID Unlock image
--publish ID Publish from service/snapshot (needs --source-type)
--source-type TYPE Source type (service or snapshot)
--visibility ID MODE Set visibility (private|unlisted|public)
--spawn ID Spawn service from image
--clone ID Clone image
--name NAME Name for spawned service or cloned image
--ports PORTS Ports for spawned service
Environment:
UNSANDBOX_PUBLIC_KEY API public key
UNSANDBOX_SECRET_KEY API secret key
EOF
}
# CLI entry point
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
if [ $# -eq 0 ]; then
show_help
exit 1
fi
# Pre-scan for --account N before dispatching
_args=("$@")
_new_args=()
_i=0
while [ $_i -lt ${#_args[@]} ]; do
if [ "${_args[$_i]}" = "--account" ]; then
_i=$((_i + 1))
ACCOUNT_INDEX="${_args[$_i]}"
else
_new_args+=("${_args[$_i]}")
fi
_i=$((_i + 1))
done
set -- "${_new_args[@]+"${_new_args[@]}"}"
case "$1" in
languages)
shift
cmd_languages "$@"
;;
key)
shift
cmd_key "$@"
;;
session)
shift
cmd_session "$@"
;;
service)
shift
cmd_service "$@"
;;
snapshot)
shift
cmd_snapshot "$@"
;;
image)
shift
cmd_image "$@"
;;
-s)
lang="$2"
code="$3"
if [ -z "$lang" ] || [ -z "$code" ]; then
echo -e "${RED}Error: -s requires language and code${RESET}" >&2
exit 1
fi
result=$(execute "$lang" "$code")
echo "$result" | jq -r '.stdout // empty'
echo "$result" | jq -r '.stderr // empty' >&2
exit_code=$(echo "$result" | jq -r '.exit_code // 0')
exit "${exit_code:-0}"
;;
--help|-h)
show_help
;;
*)
run_file "$1"
;;
esac
fi
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