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 — Forth
# Download + setup
curl -O https://git.unturf.com/engineering/unturf/un-inception/-/raw/main/clients/forth/sync/src/un.forth && chmod +x un.forth && ln -sf un.forth 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.forth
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 Forth existente:
curl -O https://git.unturf.com/engineering/unturf/un-inception/-/raw/main/clients/forth/sync/src/un.forth
# 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 Forth app:
include un.fs
s" forth" s" .\" Hello from Forth running on unsandbox!\" cr bye" execute-code
result-stdout type \ Hello from Forth running on unsandbox!
gforth myapp.fth -e bye
6045ac4100c93cf5d9f7fa2986c202cd
SHA256: 4878afc37a7d74aec5a3985b75784e08af7aa78a3313efd9438c8e9f1589bd43
\ PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
\
\ This is free public domain 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, and 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.
\
\ Learn more: https://www.permacomputer.com
\
\ Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
\ software, either in source code form or as a compiled binary, for any purpose,
\ commercial or non-commercial, and by any means.
\
\ NO WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
\
\ That said, our permacomputer's digital membrane stratum continuously runs unit,
\ integration, and functional tests on all of it's own software - with our
\ permacomputer monitoring itself, repairing itself, with minimal human in the
\ loop guidance. Our agents do their best.
\
\ Copyright 2025 TimeHexOn & foxhop & russell@unturf
\ https://www.timehexon.com
\ https://www.foxhop.net
\ https://www.unturf.com/software
\ Unsandbox CLI in Forth
\ Usage: gforth un.forth <source_file>
\ gforth un.forth session [options]
\ gforth un.forth service [options]
\ gforth un.forth key [options]
\ Constants
: portal-base ( -- addr len )
s" https://unsandbox.com"
;
3600 constant LANGUAGES_CACHE_TTL
: languages-cache-file ( -- addr len )
s" $HOME/.unsandbox/languages.json"
;
\ Extension to language mapping (simple linear search)
: ext-lang ( addr len -- addr len | 0 0 )
2dup s" .jl" compare 0= if 2drop s" julia" exit then
2dup s" .r" compare 0= if 2drop s" r" exit then
2dup s" .cr" compare 0= if 2drop s" crystal" exit then
2dup s" .f90" compare 0= if 2drop s" fortran" exit then
2dup s" .cob" compare 0= if 2drop s" cobol" exit then
2dup s" .pro" compare 0= if 2drop s" prolog" exit then
2dup s" .forth" compare 0= if 2drop s" forth" exit then
2dup s" .4th" compare 0= if 2drop s" forth" exit then
2dup s" .py" compare 0= if 2drop s" python" exit then
2dup s" .js" compare 0= if 2drop s" javascript" exit then
2dup s" .ts" compare 0= if 2drop s" typescript" exit then
2dup s" .rb" compare 0= if 2drop s" ruby" exit then
2dup s" .php" compare 0= if 2drop s" php" exit then
2dup s" .pl" compare 0= if 2drop s" perl" exit then
2dup s" .lua" compare 0= if 2drop s" lua" exit then
2dup s" .sh" compare 0= if 2drop s" bash" exit then
2dup s" .go" compare 0= if 2drop s" go" exit then
2dup s" .rs" compare 0= if 2drop s" rust" exit then
2dup s" .c" compare 0= if 2drop s" c" exit then
2dup s" .cpp" compare 0= if 2drop s" cpp" exit then
2dup s" .java" compare 0= if 2drop s" java" exit then
2drop 0 0
;
\ Find extension in filename
: find-ext ( addr len -- addr len )
2dup
begin
1- dup 0>=
while
2dup + c@ [char] . =
if
>r >r 2dup r> r> + swap over - exit
then
repeat
2drop 0 0
;
\ Detect language from filename
: detect-language ( addr len -- addr len )
find-ext ext-lang
;
\ Account index for --account N flag (-1 = not set)
variable account-index
-1 account-index !
\ Argument shift: 0 normally, 2 when --account N is prepended
variable arg-shift
0 arg-shift !
\ Shifted arg accessor - applies arg-shift to all handler arg accesses
: sarg ( n -- addr len )
arg-shift @ + arg
;
\ Buffer for credentials loaded from CSV
256 constant MAX-KEY-LEN
create csv-pk-buf MAX-KEY-LEN allot
variable csv-pk-len
create csv-sk-buf MAX-KEY-LEN allot
variable csv-sk-len
\ Load credentials from accounts.csv at given index (n)
\ Writes PK/SK to /tmp/unsb_creds.txt; returns true if PK found
: load-accounts-csv-index ( n -- flag )
dup 0< if drop 0 exit then
\ Write a shell script with the index embedded
s" /tmp/unsb_cred_resolve.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IDX=" r@ write-file throw
dup 0 <# #s #> r@ write-file throw
s" " r@ write-line throw
s" CNT=-1; PK=''; SK=''" r@ write-line throw
s" for CSV in \"$HOME/.unsandbox/accounts.csv\" \"./accounts.csv\"; do" r@ write-line throw
s" [ -f \"$CSV\" ] || continue" r@ write-line throw
s" while IFS= read -r line || [ -n \"$line\" ]; do" r@ write-line throw
s" case \"$line\" in '#'*|'') continue ;; esac" r@ write-line throw
s" CNT=$((CNT+1))" r@ write-line throw
s" if [ \"$CNT\" -eq \"$IDX\" ]; then" r@ write-line throw
s" PK=$(echo \"$line\" | cut -d',' -f1 | tr -d ' ')" r@ write-line throw
s" SK=$(echo \"$line\" | cut -d',' -f2 | tr -d ' ')" r@ write-line throw
s" break 2" r@ write-line throw
s" fi" r@ write-line throw
s" done < \"$CSV\"" r@ write-line throw
s" done" r@ write-line throw
s" printf '%s\\n%s\\n' \"$PK\" \"$SK\" > /tmp/unsb_creds.txt" r@ write-line throw
s" [ -n \"$PK\" ]" r@ write-line throw
r> close-file throw
drop \ drop index
s" bash /tmp/unsb_cred_resolve.sh" system
0= if
\ Script exited 0: PK was found; read results
s" /tmp/unsb_creds.txt" r/o open-file
0= if
>r
csv-pk-buf MAX-KEY-LEN r@ read-line throw
drop csv-pk-len !
csv-sk-buf MAX-KEY-LEN r@ read-line throw
drop csv-sk-len !
r> close-file throw
-1
else
drop 0
then
else
0
then
;
\ Get API keys from environment (HMAC or legacy)
: get-public-key ( -- addr len )
account-index @ dup 0>= if
load-accounts-csv-index if
csv-pk-buf csv-pk-len @ exit
then
s" Error: Account index not found in accounts.csv" type cr
1 (bye)
else
drop
then
s" UNSANDBOX_PUBLIC_KEY" getenv
dup 0= if
2drop s" UNSANDBOX_API_KEY" getenv
then
dup 0= if
s" Error: UNSANDBOX_PUBLIC_KEY or UNSANDBOX_API_KEY not set" type cr
1 (bye)
then
;
: get-secret-key ( -- addr len )
account-index @ dup 0>= if
\ CSV already loaded if pk-buf is non-empty
csv-pk-len @ 0> if
drop csv-sk-buf csv-sk-len @ exit
then
\ Load it now
load-accounts-csv-index if
csv-sk-buf csv-sk-len @ exit
then
\ Index not found - error was printed by get-public-key; return empty
s" " exit
else
drop
then
s" UNSANDBOX_SECRET_KEY" getenv
dup 0= if
2drop s" UNSANDBOX_API_KEY" getenv
then
;
\ Get API key (legacy compatibility)
: get-api-key ( -- addr len )
get-public-key
;
\ Execute a file
: execute-file ( addr len -- )
\ Check file exists
2dup file-status nip 0<> if
s" Error: File not found" type cr
2drop
1 (bye)
then
\ Detect language
2dup detect-language
2dup 0 0 d= if
2drop 2drop
s" Error: Unknown language" type cr
1 (bye)
then
\ Get API key
get-api-key
\ Build curl command (simplified - stores filename and language in temp vars)
\ In a real implementation, would construct full command string
s" /tmp/unsandbox_script.sh" w/o create-file throw
>r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" LANG='" r@ write-file throw
2swap 2drop \ drop language, keep filename on stack
2dup r@ write-file throw
s" '" r@ write-line throw
s" FILE='" r@ write-file throw
r@ write-file throw
s" '" r@ write-line throw
s" BODY=$(jq -Rs '{language: \"'$LANG'\", code: .}' < \"$FILE\")" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/execute:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/execute -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" -o /tmp/unsandbox_resp.json" r@ write-line throw
s" RESP=$(cat /tmp/unsandbox_resp.json)" r@ write-line throw
s" if echo \"$RESP\" | grep -q \"timestamp\" && (echo \"$RESP\" | grep -Eq \"(401|expired|invalid)\"); then" r@ write-line throw
s" echo -e '\\x1b[31mError: Request timestamp expired (must be within 5 minutes of server time)\\x1b[0m' >&2" r@ write-line throw
s" echo -e '\\x1b[33mYour computer'\\''s clock may have drifted.\\x1b[0m' >&2" r@ write-line throw
s" echo 'Check your system time and sync with NTP if needed:' >&2" r@ write-line throw
s" echo ' Linux: sudo ntpdate -s time.nist.gov' >&2" r@ write-line throw
s" echo ' macOS: sudo sntp -sS time.apple.com' >&2" r@ write-line throw
s" echo -e ' Windows: w32tm /resync\\x1b[0m' >&2" r@ write-line throw
s" rm -f /tmp/unsandbox_resp.json" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
s" jq -r '.stdout // empty' /tmp/unsandbox_resp.json | sed 's/^/\\x1b[34m/' | sed 's/$/\\x1b[0m/'" r@ write-line throw
s" jq -r '.stderr // empty' /tmp/unsandbox_resp.json | sed 's/^/\\x1b[31m/' | sed 's/$/\\x1b[0m/' >&2" r@ write-line throw
s" rm -f /tmp/unsandbox_resp.json" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_script.sh && /tmp/unsandbox_script.sh && rm -f /tmp/unsandbox_script.sh" system
(bye)
;
\ Session list
: session-list ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/sessions:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/sessions -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq -r '.sessions[] | \"\\(.id) \\(.shell) \\(.status) \\(.created_at)\"' 2>/dev/null || echo 'No active sessions'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Session kill
: session-kill ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SESSION_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/sessions/$SESSION_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X DELETE https://api.unsandbox.com/sessions/$SESSION_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mSession terminated: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service list
: service-list ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/services:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/services -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq -r '.services[] | \"\\(.id) \\(.name) \\(.status)\"' 2>/dev/null || echo 'No services'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service info
: service-info ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/services/$SERVICE_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/services/$SERVICE_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service logs
: service-logs ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/services/$SERVICE_ID/logs:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/services/$SERVICE_ID/logs -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq -r '.logs'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service sleep
: service-sleep ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/services/$SERVICE_ID/freeze:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/services/$SERVICE_ID/freeze -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mService frozen: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service wake
: service-wake ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/services/$SERVICE_ID/unfreeze:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/services/$SERVICE_ID/unfreeze -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mService unfreezing: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service destroy
: service-destroy ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/services/$SERVICE_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X DELETE https://api.unsandbox.com/services/$SERVICE_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\")" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" BODY=$(echo \"$RESP\" | sed '$d')" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"428\" ]; then" r@ write-line throw
s" CHALLENGE_ID=$(echo \"$BODY\" | grep -o '\"challenge_id\":\"[^\"]*\"' | cut -d'\"' -f4)" r@ write-line throw
s" echo -e '\\x1b[33mConfirmation required. Check your email for a one-time code.\\x1b[0m' >&2" r@ write-line throw
s" echo -n 'Enter OTP: ' >&2" r@ write-line throw
s" read OTP" r@ write-line throw
s" if [ -z \"$OTP\" ]; then echo 'Error: Operation cancelled' >&2; exit 1; fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/services/$SERVICE_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X DELETE https://api.unsandbox.com/services/$SERVICE_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H \"X-Sudo-OTP: $OTP\" -H \"X-Sudo-Challenge: $CHALLENGE_ID\")" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" fi" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"200\" ]; then" r@ write-line throw
s" echo -e '\\x1b[32mService destroyed: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
s" else" r@ write-line throw
s" echo -e \"\\x1b[31mError: HTTP $HTTP_CODE\\x1b[0m\" >&2" r@ write-line throw
s" echo \"$BODY\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service resize
: service-resize ( service-id-addr service-id-len vcpu-addr vcpu-len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2over r@ write-file throw
s" '" r@ write-line throw
s" VCPU='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" if [ \"$VCPU\" -lt 1 ] || [ \"$VCPU\" -gt 8 ]; then" r@ write-line throw
s" echo -e '\\x1b[31mError: --vcpu must be between 1 and 8\\x1b[0m' >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
s" RAM=$((VCPU * 2))" r@ write-line throw
s" BODY='{\"vcpu\":'$VCPU'}'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:PATCH:/services/$SERVICE_ID:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X PATCH https://api.unsandbox.com/services/$SERVICE_ID -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" >/dev/null && echo -e \"\\x1b[32mService resized to $VCPU vCPU, $RAM GB RAM\\x1b[0m\"" r@ write-line throw
r> close-file throw
2drop 2drop \ clean up the stack
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service env status
: service-env-status ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/services/$SERVICE_ID/env:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET \"https://api.unsandbox.com/services/$SERVICE_ID/env\" -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service env set (with -e and --env-file support via shell script)
: service-env-set ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" SERVICE_ID=''; ENV_CONTENT=''; ENV_FILE=''" r@ write-line throw
s" i=4" r@ write-line throw
s" SERVICE_ID=$3" r@ write-line throw
s" while [ $i -le $# ]; do" r@ write-line throw
s" arg=${!i}" r@ write-line throw
s" case \"$arg\" in" r@ write-line throw
s" -e) ((i++)); VAL=${!i}" r@ write-line throw
s" if [ -n \"$ENV_CONTENT\" ]; then ENV_CONTENT=\"$ENV_CONTENT\n$VAL\"; else ENV_CONTENT=\"$VAL\"; fi ;;" r@ write-line throw
s" --env-file) ((i++)); ENV_FILE=${!i} ;;" r@ write-line throw
s" esac" r@ write-line throw
s" ((i++))" r@ write-line throw
s" done" r@ write-line throw
s" if [ -n \"$ENV_FILE\" ] && [ -f \"$ENV_FILE\" ]; then" r@ write-line throw
s" while IFS= read -r line || [ -n \"$line\" ]; do" r@ write-line throw
s" case \"$line\" in \"#\"*|\"\") continue ;; esac" r@ write-line throw
s" if [ -n \"$ENV_CONTENT\" ]; then ENV_CONTENT=\"$ENV_CONTENT\n$line\"; else ENV_CONTENT=\"$line\"; fi" r@ write-line throw
s" done < \"$ENV_FILE\"" r@ write-line throw
s" fi" r@ write-line throw
s" if [ -z \"$ENV_CONTENT\" ]; then echo -e '\\x1b[31mError: No environment variables to set\\x1b[0m' >&2; exit 1; fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:PUT:/services/$SERVICE_ID/env:$ENV_CONTENT\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" echo -e \"$ENV_CONTENT\" | curl -s -X PUT \"https://api.unsandbox.com/services/$SERVICE_ID/env\" -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H 'Content-Type: text/plain' --data-binary @- | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh \"$@\" && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service env export
: service-env-export ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/services/$SERVICE_ID/env/export:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST \"https://api.unsandbox.com/services/$SERVICE_ID/env/export\" -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq -r '.content // empty'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service env delete
: service-env-delete ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/services/$SERVICE_ID/env:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X DELETE \"https://api.unsandbox.com/services/$SERVICE_ID/env\" -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mVault deleted for: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service dump bootstrap
: service-dump-bootstrap ( service-id-addr service-id-len file-addr file-len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SERVICE_ID='" r@ write-file throw
2over r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" echo 'Fetching bootstrap script from $SERVICE_ID...' >&2" r@ write-line throw
s" BODY='{\"command\":\"cat /tmp/bootstrap.sh\"}'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/services/$SERVICE_ID/execute:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -X POST https://api.unsandbox.com/services/$SERVICE_ID/execute -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\")" r@ write-line throw
s" STDOUT=$(echo \"$RESP\" | jq -r '.stdout // empty')" r@ write-line throw
s" if [ -n \"$STDOUT\" ]; then" r@ write-line throw
2dup 0 0 d= if
\ No file specified, print to stdout
2drop
s" echo \"$STDOUT\"" r@ write-line throw
else
\ File specified, save to file
s" echo \"$STDOUT\" > '" r@ write-file throw
r@ write-file throw
s" ' && chmod 755 '" r@ write-file throw
2dup r@ write-file throw
s" ' && echo 'Bootstrap saved to " r@ write-file throw
r@ write-file throw
s" '" r@ write-line throw
then
s" else" r@ write-line throw
s" echo -e '\\x1b[31mError: Failed to fetch bootstrap\\x1b[0m' >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Service create (requires --name, optional --ports, --domains, --type, --bootstrap, -f, -e, --env-file)
: service-create ( -- )
get-api-key
\ Parse arguments (simplified - in real implementation would iterate through args)
\ For now, just create the curl command that will be constructed by bash
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" NAME=''; PORTS=''; DOMAINS=''; TYPE=''; BOOTSTRAP=''; BOOTSTRAP_FILE=''; INPUT_FILES=''" r@ write-line throw
s" ENV_CONTENT=''; ENV_FILE=''" r@ write-line throw
s" i=3" r@ write-line throw
s" while [ $i -lt $# ]; do" r@ write-line throw
s" arg=${!i}" r@ write-line throw
s" case \"$arg\" in" r@ write-line throw
s" --name) ((i++)); NAME=${!i} ;;" r@ write-line throw
s" --ports) ((i++)); PORTS=${!i} ;;" r@ write-line throw
s" --domains) ((i++)); DOMAINS=${!i} ;;" r@ write-line throw
s" --type) ((i++)); TYPE=${!i} ;;" r@ write-line throw
s" --bootstrap) ((i++)); BOOTSTRAP=${!i} ;;" r@ write-line throw
s" --bootstrap-file) ((i++)); BOOTSTRAP_FILE=${!i} ;;" r@ write-line throw
s" -e) ((i++)); VAL=${!i}" r@ write-line throw
s" if [ -n \"$ENV_CONTENT\" ]; then ENV_CONTENT=\"$ENV_CONTENT\n$VAL\"; else ENV_CONTENT=\"$VAL\"; fi ;;" r@ write-line throw
s" --env-file) ((i++)); ENV_FILE=${!i} ;;" r@ write-line throw
s" -f) ((i++)); FILE=${!i}" r@ write-line throw
s" if [ -f \"$FILE\" ]; then" r@ write-line throw
s" BASENAME=$(basename \"$FILE\")" r@ write-line throw
s" CONTENT=$(base64 -w0 \"$FILE\")" r@ write-line throw
s" if [ -z \"$INPUT_FILES\" ]; then" r@ write-line throw
s" INPUT_FILES=\"{\\\"filename\\\":\\\"$BASENAME\\\",\\\"content\\\":\\\"$CONTENT\\\"}\"" r@ write-line throw
s" else" r@ write-line throw
s" INPUT_FILES=\"$INPUT_FILES,{\\\"filename\\\":\\\"$BASENAME\\\",\\\"content\\\":\\\"$CONTENT\\\"}\"" r@ write-line throw
s" fi" r@ write-line throw
s" else" r@ write-line throw
s" echo \"Error: File not found: $FILE\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi ;;" r@ write-line throw
s" esac" r@ write-line throw
s" ((i++))" r@ write-line throw
s" done" r@ write-line throw
s" # Parse env file if specified" r@ write-line throw
s" if [ -n \"$ENV_FILE\" ] && [ -f \"$ENV_FILE\" ]; then" r@ write-line throw
s" while IFS= read -r line || [ -n \"$line\" ]; do" r@ write-line throw
s" case \"$line\" in \"#\"*|\"\") continue ;; esac" r@ write-line throw
s" if [ -n \"$ENV_CONTENT\" ]; then ENV_CONTENT=\"$ENV_CONTENT\n$line\"; else ENV_CONTENT=\"$line\"; fi" r@ write-line throw
s" done < \"$ENV_FILE\"" r@ write-line throw
s" fi" r@ write-line throw
s" [ -z \"$NAME\" ] && echo 'Error: --name required' && exit 1" r@ write-line throw
s" PAYLOAD='{\"name\":\"'\"$NAME\"'\"}'" r@ write-line throw
s" [ -n \"$PORTS\" ] && PAYLOAD=$(echo $PAYLOAD | jq --arg p \"$PORTS\" '. + {ports: ($p | split(\",\") | map(tonumber))}')" r@ write-line throw
s" [ -n \"$DOMAINS\" ] && PAYLOAD=$(echo $PAYLOAD | jq --arg d \"$DOMAINS\" '. + {domains: ($d | split(\",\"))}')" r@ write-line throw
s" [ -n \"$TYPE\" ] && PAYLOAD=$(echo $PAYLOAD | jq --arg t \"$TYPE\" '. + {service_type: $t}')" r@ write-line throw
s" [ -n \"$BOOTSTRAP\" ] && PAYLOAD=$(echo $PAYLOAD | jq --arg b \"$BOOTSTRAP\" '. + {bootstrap: $b}')" r@ write-line throw
s" if [ -n \"$BOOTSTRAP_FILE\" ]; then" r@ write-line throw
s" [ ! -f \"$BOOTSTRAP_FILE\" ] && echo -e '\\x1b[31mError: Bootstrap file not found: '$BOOTSTRAP_FILE'\\x1b[0m' >&2 && exit 1" r@ write-line throw
s" PAYLOAD=$(echo $PAYLOAD | jq --rawfile b \"$BOOTSTRAP_FILE\" '. + {bootstrap_content: $b}')" r@ write-line throw
s" fi" r@ write-line throw
s" if [ -n \"$INPUT_FILES\" ]; then" r@ write-line throw
s" PAYLOAD=$(echo $PAYLOAD | jq --argjson f \"[$INPUT_FILES]\" '. + {input_files: $f}')" r@ write-line throw
s" fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/services:$PAYLOAD\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -X POST https://api.unsandbox.com/services -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$PAYLOAD\")" r@ write-line throw
s" echo \"$RESP\" | jq ." r@ write-line throw
s" # Auto-set vault if env vars were provided" r@ write-line throw
s" if [ -n \"$ENV_CONTENT\" ]; then" r@ write-line throw
s" SERVICE_ID=$(echo \"$RESP\" | jq -r '.id // empty')" r@ write-line throw
s" if [ -n \"$SERVICE_ID\" ]; then" r@ write-line throw
s" echo -e '\\x1b[33mSetting vault for service...\\x1b[0m'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:PUT:/services/$SERVICE_ID/env:$ENV_CONTENT\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" echo -e \"$ENV_CONTENT\" | curl -s -X PUT \"https://api.unsandbox.com/services/$SERVICE_ID/env\" -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H 'Content-Type: text/plain' --data-binary @- | jq ." r@ write-line throw
s" fi" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Key validate
: validate-key ( extend-flag -- )
get-api-key
s" /tmp/unsandbox_key_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" PORTAL_BASE='" r@ write-file throw
portal-base r@ write-file throw
s" '" r@ write-line throw
s" BODY='{}'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/keys/validate:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
\ Check if extend flag is set
0= if
\ Normal validation
s" curl -s -X POST $PORTAL_BASE/keys/validate -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" -o /tmp/unsandbox_key_resp.json" r@ write-line throw
s" STATUS=$?" r@ write-line throw
s" if [ $STATUS -ne 0 ]; then" r@ write-line throw
s" echo -e '\\x1b[31mInvalid\\x1b[0m'" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
s" EXPIRED=$(jq -r '.expired // false' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" if [ \"$EXPIRED\" = \"true\" ]; then" r@ write-line throw
s" echo -e '\\x1b[31mExpired\\x1b[0m'" r@ write-line throw
s" echo 'Public Key: '$(jq -r '.public_key // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Tier: '$(jq -r '.tier // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Expired: '$(jq -r '.expires_at // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo -e '\\x1b[33mTo renew: Visit https://unsandbox.com/keys/extend\\x1b[0m'" r@ write-line throw
s" rm -f /tmp/unsandbox_key_resp.json" r@ write-line throw
s" exit 1" r@ write-line throw
s" else" r@ write-line throw
s" echo -e '\\x1b[32mValid\\x1b[0m'" r@ write-line throw
s" echo 'Public Key: '$(jq -r '.public_key // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Tier: '$(jq -r '.tier // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Status: '$(jq -r '.status // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Expires: '$(jq -r '.expires_at // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Time Remaining: '$(jq -r '.time_remaining // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Rate Limit: '$(jq -r '.rate_limit // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Burst: '$(jq -r '.burst // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" echo 'Concurrency: '$(jq -r '.concurrency // \"N/A\"' /tmp/unsandbox_key_resp.json)" r@ write-line throw
s" fi" r@ write-line throw
s" rm -f /tmp/unsandbox_key_resp.json" r@ write-line throw
else
\ Extend mode
s" RESP=$(curl -s -X POST $PORTAL_BASE/keys/validate -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\")" r@ write-line throw
s" FETCHED_PUBLIC_KEY=$(echo \"$RESP\" | jq -r '.public_key // \"N/A\"')" r@ write-line throw
s" xdg-open \"$PORTAL_BASE/keys/extend?pk=$FETCHED_PUBLIC_KEY\" 2>/dev/null" r@ write-line throw
then
r> close-file throw
s" chmod +x /tmp/unsandbox_key_cmd.sh && /tmp/unsandbox_key_cmd.sh && rm -f /tmp/unsandbox_key_cmd.sh" system
;
\ Handle key subcommand
: handle-key ( -- )
argc @ 3 < if
0 validate-key
0 (bye)
then
2 sarg 2dup s" --extend" compare 0= if
2drop
1 validate-key
0 (bye)
then
2drop
0 validate-key
0 (bye)
;
\ Session create with input_files support
: session-create ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" SHELL='bash'" r@ write-line throw
s" INPUT_FILES=''" r@ write-line throw
s" for ((i=2; i<$#; i++)); do" r@ write-line throw
s" case ${!i} in" r@ write-line throw
s" --shell|-s) ((i++)); SHELL=${!i} ;;" r@ write-line throw
s" -f) ((i++)); FILE=${!i}" r@ write-line throw
s" if [ -f \"$FILE\" ]; then" r@ write-line throw
s" BASENAME=$(basename \"$FILE\")" r@ write-line throw
s" CONTENT=$(base64 -w0 \"$FILE\")" r@ write-line throw
s" if [ -z \"$INPUT_FILES\" ]; then" r@ write-line throw
s" INPUT_FILES=\"{\\\"filename\\\":\\\"$BASENAME\\\",\\\"content\\\":\\\"$CONTENT\\\"}\"" r@ write-line throw
s" else" r@ write-line throw
s" INPUT_FILES=\"$INPUT_FILES,{\\\"filename\\\":\\\"$BASENAME\\\",\\\"content\\\":\\\"$CONTENT\\\"}\"" r@ write-line throw
s" fi" r@ write-line throw
s" else" r@ write-line throw
s" echo \"Error: File not found: $FILE\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi ;;" r@ write-line throw
s" esac" r@ write-line throw
s" done" r@ write-line throw
s" if [ -n \"$INPUT_FILES\" ]; then" r@ write-line throw
s" BODY=\"{\\\"shell\\\":\\\"$SHELL\\\",\\\"input_files\\\":[$INPUT_FILES]}\"" r@ write-line throw
s" else" r@ write-line throw
s" BODY=\"{\\\"shell\\\":\\\"$SHELL\\\"}\"" r@ write-line throw
s" fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/sessions:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" echo -e '\\x1b[33mCreating session...\\x1b[0m'" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/sessions -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\"" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh \"$@\" && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Handle session subcommand
: handle-session ( -- )
argc @ 3 < if
s" Error: Use --list or --kill ID" type cr
1 (bye)
then
2 sarg 2dup s" --list" compare 0= if
2drop session-list
0 (bye)
then
2dup s" -l" compare 0= if
2drop session-list
0 (bye)
then
2dup s" --kill" compare 0= if
2drop
argc @ 4 < if
s" Error: --kill requires session ID" type cr
1 (bye)
then
3 sarg session-kill
0 (bye)
then
\ Check for --shell or -f flags (create session)
2dup s" --shell" compare 0= if
2drop session-create
0 (bye)
then
2dup s" -s" compare 0= if
2drop session-create
0 (bye)
then
2dup s" -f" compare 0= if
2drop session-create
0 (bye)
then
\ Check if argument starts with '-'
2dup drop c@ [char] - = if
s" Unknown option: " type type cr
s" Usage: un.forth session [options]" type cr
2drop
1 (bye)
then
2drop
session-create
0 (bye)
;
\ Handle service subcommand
: handle-service ( -- )
argc @ 3 < if
s" Error: Use --name (create), --list, --info, --logs, --freeze, --unfreeze, or --destroy" type cr
1 (bye)
then
2 sarg 2dup s" --list" compare 0= if
2drop service-list
0 (bye)
then
2dup s" -l" compare 0= if
2drop service-list
0 (bye)
then
2dup s" --name" compare 0= if
2drop service-create
0 (bye)
then
2dup s" --info" compare 0= if
2drop
argc @ 4 < if
s" Error: --info requires service ID" type cr
1 (bye)
then
3 sarg service-info
0 (bye)
then
2dup s" --logs" compare 0= if
2drop
argc @ 4 < if
s" Error: --logs requires service ID" type cr
1 (bye)
then
3 sarg service-logs
0 (bye)
then
2dup s" --freeze" compare 0= if
2drop
argc @ 4 < if
s" Error: --freeze requires service ID" type cr
1 (bye)
then
3 sarg service-sleep
0 (bye)
then
2dup s" --unfreeze" compare 0= if
2drop
argc @ 4 < if
s" Error: --unfreeze requires service ID" type cr
1 (bye)
then
3 sarg service-wake
0 (bye)
then
2dup s" --destroy" compare 0= if
2drop
argc @ 4 < if
s" Error: --destroy requires service ID" type cr
1 (bye)
then
3 sarg service-destroy
0 (bye)
then
2dup s" --resize" compare 0= if
2drop
argc @ 4 < if
s" Error: --resize requires service ID" type cr
1 (bye)
then
\ Look for --vcpu or -v in remaining args
argc @ 5 < if
s" Error: --resize requires --vcpu N" type cr
1 (bye)
then
4 sarg 2dup s" --vcpu" compare 0= if
2drop
argc @ 6 < if
s" Error: --vcpu requires a value" type cr
1 (bye)
then
3 sarg 5 sarg service-resize
0 (bye)
then
2dup s" -v" compare 0= if
2drop
argc @ 6 < if
s" Error: -v requires a value" type cr
1 (bye)
then
3 sarg 5 sarg service-resize
0 (bye)
then
2drop
s" Error: --resize requires --vcpu N" type cr
1 (bye)
then
2dup s" --dump-bootstrap" compare 0= if
2drop
argc @ 4 < if
s" Error: --dump-bootstrap requires service ID" type cr
1 (bye)
then
3 sarg
\ Check for --dump-file
argc @ 5 >= if
4 sarg 2dup s" --dump-file" compare 0= if
2drop
argc @ 6 < if
s" Error: --dump-file requires filename" type cr
1 (bye)
then
5 sarg
else
2drop 0 0
then
else
0 0
then
service-dump-bootstrap
0 (bye)
then
\ Handle env subcommand: service env <action> <service_id> [options]
2dup s" env" compare 0= if
2drop
argc @ 4 < if
s" Usage: un.forth service env <status|set|export|delete> <service_id> [options]" type cr
1 (bye)
then
3 sarg 2dup s" status" compare 0= if
2drop
argc @ 5 < if
s" Error: status requires service ID" type cr
1 (bye)
then
4 sarg service-env-status
0 (bye)
then
2dup s" set" compare 0= if
2drop
argc @ 5 < if
s" Error: set requires service ID" type cr
1 (bye)
then
service-env-set
0 (bye)
then
2dup s" export" compare 0= if
2drop
argc @ 5 < if
s" Error: export requires service ID" type cr
1 (bye)
then
4 sarg service-env-export
0 (bye)
then
2dup s" delete" compare 0= if
2drop
argc @ 5 < if
s" Error: delete requires service ID" type cr
1 (bye)
then
4 sarg service-env-delete
0 (bye)
then
2drop
s" Error: Unknown env action. Use status, set, export, or delete" type cr
1 (bye)
then
2drop
s" Error: Use --name (create), --list, --info, --logs, --freeze, --unfreeze, --destroy, --dump-bootstrap, or env" type cr
1 (bye)
;
\ Languages list with caching
: languages-list ( json-flag -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" CACHE_TTL=3600" r@ write-line throw
s" CACHE_FILE=\"$HOME/.unsandbox/languages.json\"" r@ write-line throw
s" JSON_OUTPUT=" r@ write-file throw
if
s" 1" r@ write-line throw
else
s" 0" r@ write-line throw
then
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
\ Check cache first
s" if [ -f \"$CACHE_FILE\" ]; then" r@ write-line throw
s" CACHE_TS=$(jq -r '.timestamp // 0' \"$CACHE_FILE\" 2>/dev/null)" r@ write-line throw
s" CURRENT_TS=$(date +%s)" r@ write-line throw
s" AGE=$((CURRENT_TS - CACHE_TS))" r@ write-line throw
s" if [ $AGE -lt $CACHE_TTL ]; then" r@ write-line throw
s" if [ \"$JSON_OUTPUT\" = \"1\" ]; then" r@ write-line throw
s" jq -c '.languages' \"$CACHE_FILE\"" r@ write-line throw
s" else" r@ write-line throw
s" jq -r '.languages[]' \"$CACHE_FILE\"" r@ write-line throw
s" fi" r@ write-line throw
s" exit 0" r@ write-line throw
s" fi" r@ write-line throw
s" fi" r@ write-line throw
\ Fetch from API
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/languages:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -X GET https://api.unsandbox.com/languages -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\")" r@ write-line throw
s" LANGS=$(echo \"$RESP\" | jq -c '.languages // []')" r@ write-line throw
\ Save to cache
s" mkdir -p \"$HOME/.unsandbox\"" r@ write-line throw
s" echo \"{\\\"languages\\\":$LANGS,\\\"timestamp\\\":$(date +%s)}\" > \"$CACHE_FILE\"" r@ write-line throw
\ Output
s" if [ \"$JSON_OUTPUT\" = \"1\" ]; then" r@ write-line throw
s" echo \"$LANGS\"" r@ write-line throw
s" else" r@ write-line throw
s" echo \"$LANGS\" | jq -r '.[]'" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Handle languages subcommand
: handle-languages ( -- )
argc @ 3 < if
0 languages-list
0 (bye)
then
2 sarg 2dup s" --json" compare 0= if
2drop
1 languages-list
0 (bye)
then
2drop
0 languages-list
0 (bye)
;
\ Image list
: image-list ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/images:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/images -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image info
: image-info ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/images/$IMAGE_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/images/$IMAGE_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image delete
: image-delete ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/images/$IMAGE_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X DELETE https://api.unsandbox.com/images/$IMAGE_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\")" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" BODY=$(echo \"$RESP\" | sed '$d')" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"428\" ]; then" r@ write-line throw
s" CHALLENGE_ID=$(echo \"$BODY\" | grep -o '\"challenge_id\":\"[^\"]*\"' | cut -d'\"' -f4)" r@ write-line throw
s" echo -e '\\x1b[33mConfirmation required. Check your email for a one-time code.\\x1b[0m' >&2" r@ write-line throw
s" echo -n 'Enter OTP: ' >&2" r@ write-line throw
s" read OTP" r@ write-line throw
s" if [ -z \"$OTP\" ]; then echo 'Error: Operation cancelled' >&2; exit 1; fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/images/$IMAGE_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X DELETE https://api.unsandbox.com/images/$IMAGE_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H \"X-Sudo-OTP: $OTP\" -H \"X-Sudo-Challenge: $CHALLENGE_ID\")" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" fi" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"200\" ]; then" r@ write-line throw
s" echo -e '\\x1b[32mImage deleted: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
s" else" r@ write-line throw
s" echo -e \"\\x1b[31mError: HTTP $HTTP_CODE\\x1b[0m\" >&2" r@ write-line throw
s" echo \"$BODY\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image lock
: image-lock ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/lock:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/$IMAGE_ID/lock -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mImage locked: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image unlock
: image-unlock ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/unlock:{}\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X POST https://api.unsandbox.com/images/$IMAGE_ID/unlock -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H 'Content-Type: application/json' -d '{}')" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" BODY=$(echo \"$RESP\" | sed '$d')" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"428\" ]; then" r@ write-line throw
s" CHALLENGE_ID=$(echo \"$BODY\" | grep -o '\"challenge_id\":\"[^\"]*\"' | cut -d'\"' -f4)" r@ write-line throw
s" echo -e '\\x1b[33mConfirmation required. Check your email for a one-time code.\\x1b[0m' >&2" r@ write-line throw
s" echo -n 'Enter OTP: ' >&2" r@ write-line throw
s" read OTP" r@ write-line throw
s" if [ -z \"$OTP\" ]; then echo 'Error: Operation cancelled' >&2; exit 1; fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/unlock:{}\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X POST https://api.unsandbox.com/images/$IMAGE_ID/unlock -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H 'Content-Type: application/json' -H \"X-Sudo-OTP: $OTP\" -H \"X-Sudo-Challenge: $CHALLENGE_ID\" -d '{}')" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" fi" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"200\" ]; then" r@ write-line throw
s" echo -e '\\x1b[32mImage unlocked: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
s" else" r@ write-line throw
s" echo -e \"\\x1b[31mError: HTTP $HTTP_CODE\\x1b[0m\" >&2" r@ write-line throw
s" echo \"$BODY\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image visibility
: image-visibility ( image-id-addr image-id-len mode-addr mode-len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2over r@ write-file throw
s" '" r@ write-line throw
s" MODE='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" BODY='{\"visibility\":\"'$MODE'\"}'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/visibility:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/$IMAGE_ID/visibility -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" >/dev/null && echo -e \"\\x1b[32mImage visibility set to $MODE\\x1b[0m\"" r@ write-line throw
r> close-file throw
2drop 2drop \ clean up the stack
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image spawn
: image-spawn ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" NAME=''; PORTS=''" r@ write-line throw
s" i=4" r@ write-line throw
s" while [ $i -le $# ]; do" r@ write-line throw
s" arg=${!i}" r@ write-line throw
s" case \"$arg\" in" r@ write-line throw
s" --name) ((i++)); NAME=${!i} ;;" r@ write-line throw
s" --ports) ((i++)); PORTS=${!i} ;;" r@ write-line throw
s" esac" r@ write-line throw
s" ((i++))" r@ write-line throw
s" done" r@ write-line throw
s" BODY='{}'" r@ write-line throw
s" [ -n \"$NAME\" ] && BODY=$(echo $BODY | jq --arg n \"$NAME\" '. + {name: $n}')" r@ write-line throw
s" [ -n \"$PORTS\" ] && BODY=$(echo $BODY | jq --arg p \"$PORTS\" '. + {ports: ($p | split(\",\") | map(tonumber))}')" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/spawn:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/$IMAGE_ID/spawn -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" | jq ." r@ write-line throw
s" echo -e '\\x1b[32mService spawned from image\\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh \"$@\" && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image clone
: image-clone ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" NAME=''" r@ write-line throw
s" i=4" r@ write-line throw
s" while [ $i -le $# ]; do" r@ write-line throw
s" arg=${!i}" r@ write-line throw
s" case \"$arg\" in" r@ write-line throw
s" --name) ((i++)); NAME=${!i} ;;" r@ write-line throw
s" esac" r@ write-line throw
s" ((i++))" r@ write-line throw
s" done" r@ write-line throw
s" BODY='{}'" r@ write-line throw
s" [ -n \"$NAME\" ] && BODY=$(echo $BODY | jq --arg n \"$NAME\" '. + {name: $n}')" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/clone:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/$IMAGE_ID/clone -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" | jq ." r@ write-line throw
s" echo -e '\\x1b[32mImage cloned\\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh \"$@\" && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image publish
: image-publish ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" SOURCE_ID=''; SOURCE_TYPE=''; NAME=''" r@ write-line throw
s" i=3" r@ write-line throw
s" while [ $i -le $# ]; do" r@ write-line throw
s" arg=${!i}" r@ write-line throw
s" case \"$arg\" in" r@ write-line throw
s" --publish) ((i++)); SOURCE_ID=${!i} ;;" r@ write-line throw
s" --source-type) ((i++)); SOURCE_TYPE=${!i} ;;" r@ write-line throw
s" --name) ((i++)); NAME=${!i} ;;" r@ write-line throw
s" esac" r@ write-line throw
s" ((i++))" r@ write-line throw
s" done" r@ write-line throw
s" [ -z \"$SOURCE_TYPE\" ] && echo -e '\\x1b[31mError: --source-type required (service or snapshot)\\x1b[0m' >&2 && exit 1" r@ write-line throw
s" BODY='{\"source_type\":\"'$SOURCE_TYPE'\",\"source_id\":\"'$SOURCE_ID'\"}'" r@ write-line throw
s" [ -n \"$NAME\" ] && BODY=$(echo $BODY | jq --arg n \"$NAME\" '. + {name: $n}')" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/publish:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/publish -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" | jq ." r@ write-line throw
s" echo -e '\\x1b[32mImage published\\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh \"$@\" && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image grant access
: image-grant-access ( image-id-addr image-id-len key-addr key-len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2over r@ write-file throw
s" '" r@ write-line throw
s" TRUSTED_KEY='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" BODY='{\"trusted_api_key\":\"'$TRUSTED_KEY'\"}'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/grant-access:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/$IMAGE_ID/grant-access -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" >/dev/null && echo -e \"\\x1b[32mAccess granted to $TRUSTED_KEY\\x1b[0m\"" r@ write-line throw
r> close-file throw
2drop 2drop \ clean up the stack
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image revoke access
: image-revoke-access ( image-id-addr image-id-len key-addr key-len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2over r@ write-file throw
s" '" r@ write-line throw
s" TRUSTED_KEY='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" BODY='{\"trusted_api_key\":\"'$TRUSTED_KEY'\"}'" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/images/$IMAGE_ID/revoke-access:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/images/$IMAGE_ID/revoke-access -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" >/dev/null && echo -e \"\\x1b[32mAccess revoked from $TRUSTED_KEY\\x1b[0m\"" r@ write-line throw
r> close-file throw
2drop 2drop \ clean up the stack
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Image list trusted
: image-list-trusted ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" IMAGE_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/images/$IMAGE_ID/trusted:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/images/$IMAGE_ID/trusted -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot list
: snapshot-list ( -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/snapshots:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/snapshots -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot info
: snapshot-info ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SNAPSHOT_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:GET:/snapshots/$SNAPSHOT_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X GET https://api.unsandbox.com/snapshots/$SNAPSHOT_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" | jq ." r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot restore
: snapshot-restore ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SNAPSHOT_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/snapshots/$SNAPSHOT_ID/restore:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/snapshots/$SNAPSHOT_ID/restore -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mSnapshot restored: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot delete
: snapshot-delete ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SNAPSHOT_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/snapshots/$SNAPSHOT_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X DELETE https://api.unsandbox.com/snapshots/$SNAPSHOT_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\")" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" BODY=$(echo \"$RESP\" | sed '$d')" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"428\" ]; then" r@ write-line throw
s" CHALLENGE_ID=$(echo \"$BODY\" | grep -o '\"challenge_id\":\"[^\"]*\"' | cut -d'\"' -f4)" r@ write-line throw
s" echo -e '\\x1b[33mConfirmation required. Check your email for a one-time code.\\x1b[0m' >&2" r@ write-line throw
s" echo -n 'Enter OTP: ' >&2" r@ write-line throw
s" read OTP" r@ write-line throw
s" if [ -z \"$OTP\" ]; then echo 'Error: Operation cancelled' >&2; exit 1; fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:DELETE:/snapshots/$SNAPSHOT_ID:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X DELETE https://api.unsandbox.com/snapshots/$SNAPSHOT_ID -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H \"X-Sudo-OTP: $OTP\" -H \"X-Sudo-Challenge: $CHALLENGE_ID\")" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" fi" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"200\" ]; then" r@ write-line throw
s" echo -e '\\x1b[32mSnapshot deleted: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
s" else" r@ write-line throw
s" echo -e \"\\x1b[31mError: HTTP $HTTP_CODE\\x1b[0m\" >&2" r@ write-line throw
s" echo \"$BODY\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot lock
: snapshot-lock ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SNAPSHOT_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/snapshots/$SNAPSHOT_ID/lock:\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/snapshots/$SNAPSHOT_ID/lock -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" >/dev/null && echo -e '\\x1b[32mSnapshot locked: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot unlock
: snapshot-unlock ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SNAPSHOT_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/snapshots/$SNAPSHOT_ID/unlock:{}\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X POST https://api.unsandbox.com/snapshots/$SNAPSHOT_ID/unlock -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H 'Content-Type: application/json' -d '{}')" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" BODY=$(echo \"$RESP\" | sed '$d')" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"428\" ]; then" r@ write-line throw
s" CHALLENGE_ID=$(echo \"$BODY\" | grep -o '\"challenge_id\":\"[^\"]*\"' | cut -d'\"' -f4)" r@ write-line throw
s" echo -e '\\x1b[33mConfirmation required. Check your email for a one-time code.\\x1b[0m' >&2" r@ write-line throw
s" echo -n 'Enter OTP: ' >&2" r@ write-line throw
s" read OTP" r@ write-line throw
s" if [ -z \"$OTP\" ]; then echo 'Error: Operation cancelled' >&2; exit 1; fi" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/snapshots/$SNAPSHOT_ID/unlock:{}\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" RESP=$(curl -s -w '\\n%{http_code}' -X POST https://api.unsandbox.com/snapshots/$SNAPSHOT_ID/unlock -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -H 'Content-Type: application/json' -H \"X-Sudo-OTP: $OTP\" -H \"X-Sudo-Challenge: $CHALLENGE_ID\" -d '{}')" r@ write-line throw
s" HTTP_CODE=$(echo \"$RESP\" | tail -1)" r@ write-line throw
s" fi" r@ write-line throw
s" if [ \"$HTTP_CODE\" = \"200\" ]; then" r@ write-line throw
s" echo -e '\\x1b[32mSnapshot unlocked: " r@ write-file throw
r@ write-file throw
s" \\x1b[0m'" r@ write-line throw
s" else" r@ write-line throw
s" echo -e \"\\x1b[31mError: HTTP $HTTP_CODE\\x1b[0m\" >&2" r@ write-line throw
s" echo \"$BODY\" >&2" r@ write-line throw
s" exit 1" r@ write-line throw
s" fi" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && /tmp/unsandbox_cmd.sh && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Snapshot clone
: snapshot-clone ( addr len -- )
get-api-key
s" /tmp/unsandbox_cmd.sh" w/o create-file throw >r
s" #!/bin/bash" r@ write-line throw
s" SNAPSHOT_ID='" r@ write-file throw
2dup r@ write-file throw
s" '" r@ write-line throw
s" PUBLIC_KEY='" r@ write-file throw
get-public-key r@ write-file throw
s" '" r@ write-line throw
s" SECRET_KEY='" r@ write-file throw
get-secret-key r@ write-file throw
s" '" r@ write-line throw
s" CLONE_TYPE='session'; NAME=''; PORTS=''; SHELL=''" r@ write-line throw
s" i=4" r@ write-line throw
s" while [ $i -le $# ]; do" r@ write-line throw
s" arg=${!i}" r@ write-line throw
s" case \"$arg\" in" r@ write-line throw
s" --type) ((i++)); CLONE_TYPE=${!i} ;;" r@ write-line throw
s" --name) ((i++)); NAME=${!i} ;;" r@ write-line throw
s" --ports) ((i++)); PORTS=${!i} ;;" r@ write-line throw
s" --shell) ((i++)); SHELL=${!i} ;;" r@ write-line throw
s" esac" r@ write-line throw
s" ((i++))" r@ write-line throw
s" done" r@ write-line throw
s" BODY='{\"clone_type\":\"'$CLONE_TYPE'\"}'" r@ write-line throw
s" [ -n \"$NAME\" ] && BODY=$(echo $BODY | jq --arg n \"$NAME\" '. + {name: $n}')" r@ write-line throw
s" [ -n \"$PORTS\" ] && BODY=$(echo $BODY | jq --arg p \"$PORTS\" '. + {ports: ($p | split(\",\") | map(tonumber))}')" r@ write-line throw
s" [ -n \"$SHELL\" ] && BODY=$(echo $BODY | jq --arg s \"$SHELL\" '. + {shell: $s}')" r@ write-line throw
s" TIMESTAMP=$(date +%s)" r@ write-line throw
s" MESSAGE=\"$TIMESTAMP:POST:/snapshots/$SNAPSHOT_ID/clone:$BODY\"" r@ write-line throw
s" SIGNATURE=$(echo -n \"$MESSAGE\" | openssl dgst -sha256 -hmac \"$SECRET_KEY\" -hex | sed 's/.*= //')" r@ write-line throw
s" curl -s -X POST https://api.unsandbox.com/snapshots/$SNAPSHOT_ID/clone -H 'Content-Type: application/json' -H \"Authorization: Bearer $PUBLIC_KEY\" -H \"X-Timestamp: $TIMESTAMP\" -H \"X-Signature: $SIGNATURE\" -d \"$BODY\" | jq ." r@ write-line throw
s" echo -e '\\x1b[32mSnapshot cloned\\x1b[0m'" r@ write-line throw
r> close-file throw
s" chmod +x /tmp/unsandbox_cmd.sh && bash /tmp/unsandbox_cmd.sh \"$@\" && rm -f /tmp/unsandbox_cmd.sh" system
;
\ Handle snapshot subcommand
: handle-snapshot ( -- )
argc @ 3 < if
snapshot-list
0 (bye)
then
2 sarg 2dup s" --list" compare 0= if
2drop snapshot-list
0 (bye)
then
2dup s" -l" compare 0= if
2drop snapshot-list
0 (bye)
then
2dup s" --info" compare 0= if
2drop
argc @ 4 < if
s" Error: --info requires snapshot ID" type cr
1 (bye)
then
3 sarg snapshot-info
0 (bye)
then
2dup s" --restore" compare 0= if
2drop
argc @ 4 < if
s" Error: --restore requires snapshot ID" type cr
1 (bye)
then
3 sarg snapshot-restore
0 (bye)
then
2dup s" --delete" compare 0= if
2drop
argc @ 4 < if
s" Error: --delete requires snapshot ID" type cr
1 (bye)
then
3 sarg snapshot-delete
0 (bye)
then
2dup s" --lock" compare 0= if
2drop
argc @ 4 < if
s" Error: --lock requires snapshot ID" type cr
1 (bye)
then
3 sarg snapshot-lock
0 (bye)
then
2dup s" --unlock" compare 0= if
2drop
argc @ 4 < if
s" Error: --unlock requires snapshot ID" type cr
1 (bye)
then
3 sarg snapshot-unlock
0 (bye)
then
2dup s" --clone" compare 0= if
2drop
argc @ 4 < if
s" Error: --clone requires snapshot ID" type cr
1 (bye)
then
3 sarg snapshot-clone
0 (bye)
then
2drop
s" Error: Use --list, --info ID, --restore ID, --delete ID, --lock ID, --unlock ID, or --clone ID" type cr
1 (bye)
;
\ Handle image subcommand
: handle-image ( -- )
argc @ 3 < if
s" Error: Use --list, --info ID, --delete ID, --lock ID, --unlock ID, --publish ID, --visibility ID MODE, --spawn ID, or --clone ID" type cr
1 (bye)
then
2 sarg 2dup s" --list" compare 0= if
2drop image-list
0 (bye)
then
2dup s" -l" compare 0= if
2drop image-list
0 (bye)
then
2dup s" --info" compare 0= if
2drop
argc @ 4 < if
s" Error: --info requires image ID" type cr
1 (bye)
then
3 sarg image-info
0 (bye)
then
2dup s" --delete" compare 0= if
2drop
argc @ 4 < if
s" Error: --delete requires image ID" type cr
1 (bye)
then
3 sarg image-delete
0 (bye)
then
2dup s" --lock" compare 0= if
2drop
argc @ 4 < if
s" Error: --lock requires image ID" type cr
1 (bye)
then
3 sarg image-lock
0 (bye)
then
2dup s" --unlock" compare 0= if
2drop
argc @ 4 < if
s" Error: --unlock requires image ID" type cr
1 (bye)
then
3 sarg image-unlock
0 (bye)
then
2dup s" --publish" compare 0= if
2drop
argc @ 4 < if
s" Error: --publish requires source ID" type cr
1 (bye)
then
image-publish
0 (bye)
then
2dup s" --visibility" compare 0= if
2drop
argc @ 5 < if
s" Error: --visibility requires image ID and mode" type cr
1 (bye)
then
3 sarg 4 sarg image-visibility
0 (bye)
then
2dup s" --spawn" compare 0= if
2drop
argc @ 4 < if
s" Error: --spawn requires image ID" type cr
1 (bye)
then
3 sarg image-spawn
0 (bye)
then
2dup s" --clone" compare 0= if
2drop
argc @ 4 < if
s" Error: --clone requires image ID" type cr
1 (bye)
then
3 sarg image-clone
0 (bye)
then
2drop
s" Error: Use --list, --info ID, --delete ID, --lock ID, --unlock ID, --publish ID, --visibility ID MODE, --spawn ID, or --clone ID" type cr
1 (bye)
;
\ Main program
: main
\ Get command line argument count
argc @ 2 < if
s" Usage: gforth un.forth <source_file>" type cr
s" gforth un.forth session [options]" type cr
s" gforth un.forth service [options]" type cr
s" gforth un.forth image [options]" type cr
s" gforth un.forth key [options]" type cr
s" gforth un.forth languages [--json]" type cr
1 (bye)
then
\ Check for --account N as first argument (before arg-shift is applied)
1 arg 2dup s" --account" compare 0= if
2drop
argc @ 3 < if
s" Error: --account requires a numeric argument" type cr
1 (bye)
then
2 arg s>number drop account-index !
2 arg-shift !
else
2drop
then
\ Get subcommand (adjusted for arg-shift)
1 arg-shift @ + arg
\ Check for subcommands
2dup s" session" compare 0= if
2drop handle-session
0 (bye)
then
2dup s" service" compare 0= if
2drop handle-service
0 (bye)
then
2dup s" image" compare 0= if
2drop handle-image
0 (bye)
then
2dup s" snapshot" compare 0= if
2drop handle-snapshot
0 (bye)
then
2dup s" key" compare 0= if
2drop handle-key
0 (bye)
then
2dup s" languages" compare 0= if
2drop handle-languages
0 (bye)
then
\ Default: execute file
execute-file
;
main
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