unsandbox.com
Anonymous remote code, compile, & execution API for humans & machine learning agents.
Docs 📚 View Pricing →
F#
UN CLI
un.fs
Usage
# Run this implementation to execute a Python script
dotnet fsi cli/inception/un.fs test/fib.py test/fib.py
Source Code 📄
// 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
// un.fs - Unsandbox CLI Client (F# Implementation)
// Compile: fsharpc un.fs
// Run: mono un.exe [options] <source_file>
// Requires: UNSANDBOX_API_KEY environment variable
open System
open System.IO
open System.Net
open System.Text
open System.Security.Cryptography
let apiBase = "https://api.unsandbox.com"
let portalBase = "https://unsandbox.com"
let blue = "\x1B[34m"
let red = "\x1B[31m"
let green = "\x1B[32m"
let yellow = "\x1B[33m"
let reset = "\x1B[0m"
let extMap =
Map.ofList [
(".py", "python"); (".js", "javascript"); (".ts", "typescript")
(".rb", "ruby"); (".php", "php"); (".pl", "perl"); (".lua", "lua")
(".sh", "bash"); (".go", "go"); (".rs", "rust"); (".c", "c")
(".cpp", "cpp"); (".cc", "cpp"); (".cxx", "cpp")
(".java", "java"); (".kt", "kotlin"); (".cs", "csharp"); (".fs", "fsharp")
(".hs", "haskell"); (".ml", "ocaml"); (".clj", "clojure"); (".scm", "scheme")
(".lisp", "commonlisp"); (".erl", "erlang"); (".ex", "elixir"); (".exs", "elixir")
(".jl", "julia"); (".r", "r"); (".R", "r"); (".cr", "crystal")
(".d", "d"); (".nim", "nim"); (".zig", "zig"); (".v", "v")
(".dart", "dart"); (".groovy", "groovy"); (".scala", "scala")
(".f90", "fortran"); (".f95", "fortran"); (".cob", "cobol")
(".pro", "prolog"); (".forth", "forth"); (".4th", "forth")
(".tcl", "tcl"); (".raku", "raku"); (".m", "objc")
]
type Args = {
mutable Command: string option
mutable SourceFile: string option
mutable ApiKey: string option
mutable Network: string option
mutable Vcpu: int
Env: ResizeArray<string>
Files: ResizeArray<string>
mutable Artifacts: bool
mutable OutputDir: string option
mutable SessionList: bool
mutable SessionShell: string option
mutable SessionKill: string option
mutable ServiceList: bool
mutable ServiceName: string option
mutable ServicePorts: string option
mutable ServiceType: string option
mutable ServiceBootstrap: string option
mutable ServiceInfo: string option
mutable ServiceLogs: string option
mutable ServiceTail: string option
mutable ServiceSleep: string option
mutable ServiceWake: string option
mutable ServiceDestroy: string option
mutable ServiceExecute: string option
mutable ServiceCommand: string option
mutable ServiceDumpBootstrap: string option
mutable ServiceDumpFile: string option
mutable KeyExtend: bool
}
let getApiKeys (argsKey: string option) =
let publicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY")
let secretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY")
// Fall back to UNSANDBOX_API_KEY for backwards compatibility
if String.IsNullOrEmpty(publicKey) || String.IsNullOrEmpty(secretKey) then
let legacyKey = match argsKey with | Some k -> k | None -> Environment.GetEnvironmentVariable("UNSANDBOX_API_KEY")
if String.IsNullOrEmpty(legacyKey) then
eprintfn "%sError: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY not set%s" red reset
exit 1
(legacyKey, null)
else
(publicKey, secretKey)
let detectLanguage (filename: string) =
let dotIndex = filename.LastIndexOf('.')
if dotIndex = -1 then
failwith "Cannot detect language: no file extension"
let ext = filename.Substring(dotIndex).ToLower()
match Map.tryFind ext extMap with
| Some lang -> lang
| None -> failwithf "Unsupported file extension: %s" ext
let jsonEscape (s: string) =
let sb = StringBuilder("\"")
for c in s do
match c with
| '"' -> sb.Append("\\\"") |> ignore
| '\\' -> sb.Append("\\\\") |> ignore
| '\n' -> sb.Append("\\n") |> ignore
| '\r' -> sb.Append("\\r") |> ignore
| '\t' -> sb.Append("\\t") |> ignore
| _ -> sb.Append(c) |> ignore
sb.Append("\"") |> ignore
sb.ToString()
let rec toJson (obj: obj) =
match obj with
| null -> "null"
| :? string as s -> jsonEscape s
| :? int as i -> i.ToString()
| :? float as f -> f.ToString()
| :? bool as b -> b.ToString().ToLower()
| :? Map<string, obj> as m ->
let entries = m |> Map.toSeq |> Seq.map (fun (k, v) -> sprintf "\"%s\":%s" k (toJson v)) |> String.concat ","
sprintf "{%s}" entries
| :? ResizeArray<obj> as lst ->
let items = lst |> Seq.map toJson |> String.concat ","
sprintf "[%s]" items
| :? (string * obj) list as lst ->
let entries = lst |> List.map (fun (k, v) -> sprintf "\"%s\":%s" k (toJson v)) |> String.concat ","
sprintf "{%s}" entries
| _ -> jsonEscape (obj.ToString())
let extractJsonValue (json: string) (key: string) =
let pattern = sprintf "\"%s\":" key
let startIndex = json.IndexOf(pattern)
if startIndex = -1 then None
else
let mutable idx = startIndex + pattern.Length
while idx < json.Length && Char.IsWhiteSpace(json.[idx]) do
idx <- idx + 1
if json.[idx] = '"' then
idx <- idx + 1
let sb = StringBuilder()
let mutable escaped = false
let mutable found = false
let mutable i = idx
while i < json.Length && not found do
let c = json.[i]
if escaped then
match c with
| 'n' -> sb.Append('\n') |> ignore
| 'r' -> sb.Append('\r') |> ignore
| 't' -> sb.Append('\t') |> ignore
| '"' -> sb.Append('"') |> ignore
| '\\' -> sb.Append('\\') |> ignore
| _ -> sb.Append(c) |> ignore
escaped <- false
else if c = '\\' then
escaped <- true
else if c = '"' then
found <- true
else
sb.Append(c) |> ignore
i <- i + 1
Some (sb.ToString())
else
let sb = StringBuilder()
let mutable i = idx
while i < json.Length && (Char.IsDigit(json.[i]) || json.[i] = '-') do
sb.Append(json.[i]) |> ignore
i <- i + 1
Some (sb.ToString())
let parseJson (json: string) =
let trimmed = json.Trim()
if not (trimmed.StartsWith("{")) then Map.empty
else
let result = ResizeArray<string * obj>()
let mutable i = 1
while i < trimmed.Length do
while i < trimmed.Length && Char.IsWhiteSpace(trimmed.[i]) do i <- i + 1
if trimmed.[i] = '}' then i <- trimmed.Length
elif trimmed.[i] = '"' then
let keyStart = i + 1
i <- i + 1
while i < trimmed.Length && trimmed.[i] <> '"' do
if trimmed.[i] = '\\' then i <- i + 1
i <- i + 1
let key = trimmed.Substring(keyStart, i - keyStart).Replace("\\\"", "\"").Replace("\\\\", "\\")
i <- i + 1
while i < trimmed.Length && (Char.IsWhiteSpace(trimmed.[i]) || trimmed.[i] = ':') do i <- i + 1
let value = extractJsonValue trimmed key
match value with
| Some v -> result.Add((key, box v))
| None -> ()
while i < trimmed.Length && (Char.IsWhiteSpace(trimmed.[i]) || trimmed.[i] = ',' || trimmed.[i] = '"' || Char.IsLetterOrDigit(trimmed.[i]) || trimmed.[i] = '\\') do i <- i + 1
else
i <- i + 1
result |> Seq.map (fun (k, v) -> k, v) |> Map.ofSeq
let apiRequest (endpoint: string) (method: string) (data: (string * obj) list option) (publicKey: string) (secretKey: string) =
ServicePointManager.SecurityProtocol <- SecurityProtocolType.Tls12 ||| SecurityProtocolType.Tls11 ||| SecurityProtocolType.Tls
let request = WebRequest.Create(apiBase + endpoint) :?> HttpWebRequest
request.Method <- method
request.ContentType <- "application/json"
request.Timeout <- 300000
let body = match data with | Some d -> toJson (box d) | None -> ""
// Add HMAC authentication headers if secretKey is provided
if not (String.IsNullOrEmpty(secretKey)) then
let timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
let message = sprintf "%d:%s:%s:%s" timestamp method endpoint body
use hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey))
let hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message))
let signature = BitConverter.ToString(hash).Replace("-", "").ToLower()
request.Headers.Add("Authorization", sprintf "Bearer %s" publicKey)
request.Headers.Add("X-Timestamp", timestamp.ToString())
request.Headers.Add("X-Signature", signature)
else
// Legacy API key authentication
request.Headers.Add("Authorization", sprintf "Bearer %s" publicKey)
match data with
| Some d ->
let bytes = Encoding.UTF8.GetBytes(body)
request.ContentLength <- int64 bytes.Length
use stream = request.GetRequestStream()
stream.Write(bytes, 0, bytes.Length)
| None -> ()
try
use response = request.GetResponse() :?> HttpWebResponse
if response.StatusCode <> HttpStatusCode.OK then
failwithf "HTTP %A" response.StatusCode
use reader = new StreamReader(response.GetResponseStream())
let responseText = reader.ReadToEnd()
parseJson responseText
with
| :? WebException as ex ->
let errorMsg =
if ex.Response <> null then
use reader = new StreamReader(ex.Response.GetResponseStream())
reader.ReadToEnd()
else
ex.Message
// Check for clock drift error
if errorMsg.Contains("timestamp") && (errorMsg.Contains("401") || errorMsg.Contains("expired") || errorMsg.Contains("invalid")) then
eprintfn "%sError: Request timestamp expired (must be within 5 minutes of server time)%s" red reset
eprintfn "%sYour computer's clock may have drifted.%s" yellow reset
eprintfn "Check your system time and sync with NTP if needed:"
eprintfn " Linux: sudo ntpdate -s time.nist.gov"
eprintfn " macOS: sudo sntp -sS time.apple.com"
eprintfn " Windows: w32tm /resync%s" reset
exit 1
failwithf "HTTP error - %s" errorMsg
let cmdExecute (args: Args) =
let (publicKey, secretKey) = getApiKeys args.ApiKey
let code = File.ReadAllText(args.SourceFile.Value)
let language = detectLanguage args.SourceFile.Value
let mutable payload = [("language", box language); ("code", box code)]
if args.Env.Count > 0 then
let envVars = args.Env |> Seq.choose (fun e ->
let parts = e.Split([|'='|], 2)
if parts.Length = 2 then Some (parts.[0], box parts.[1]) else None
) |> Seq.toList
if not (List.isEmpty envVars) then
payload <- payload @ [("env", box envVars)]
if args.Files.Count > 0 then
let inputFiles = args.Files |> Seq.map (fun filepath ->
let content = File.ReadAllBytes(filepath)
[("filename", box (Path.GetFileName(filepath))); ("content_base64", box (Convert.ToBase64String(content)))]
) |> Seq.toList
payload <- payload @ [("input_files", box inputFiles)]
if args.Artifacts then
payload <- payload @ [("return_artifacts", box true)]
if args.Network.IsSome then
payload <- payload @ [("network", box args.Network.Value)]
if args.Vcpu > 0 then
payload <- payload @ [("vcpu", box args.Vcpu)]
let result = apiRequest "/execute" "POST" (Some payload) publicKey secretKey
match result.TryFind "stdout" with
| Some stdout when not (String.IsNullOrEmpty(stdout.ToString())) ->
printf "%s%s%s" blue (stdout.ToString()) reset
| _ -> ()
match result.TryFind "stderr" with
| Some stderr when not (String.IsNullOrEmpty(stderr.ToString())) ->
eprintf "%s%s%s" red (stderr.ToString()) reset
| _ -> ()
if args.Artifacts && result.ContainsKey("artifacts") then
let outDir = match args.OutputDir with | Some d -> d | None -> "."
Directory.CreateDirectory(outDir) |> ignore
eprintfn "%sSaved artifacts to %s%s" green outDir reset
let exitCode = match result.TryFind "exit_code" with | Some ec -> int (ec.ToString()) | None -> 0
exit exitCode
let cmdSession (args: Args) =
let (publicKey, secretKey) = getApiKeys args.ApiKey
if args.SessionList then
let result = apiRequest "/sessions" "GET" None publicKey secretKey
printfn "%-40s %-10s %-10s %s" "ID" "Shell" "Status" "Created"
printfn "No sessions (list parsing not implemented)"
elif args.SessionKill.IsSome then
let result = apiRequest (sprintf "/sessions/%s" args.SessionKill.Value) "DELETE" None publicKey secretKey
printfn "%sSession terminated: %s%s" green args.SessionKill.Value reset
else
let mutable payload = [("shell", box (match args.SessionShell with | Some s -> s | None -> "bash"))]
if args.Network.IsSome then
payload <- payload @ [("network", box args.Network.Value)]
if args.Vcpu > 0 then
payload <- payload @ [("vcpu", box args.Vcpu)]
printfn "%sCreating session...%s" yellow reset
let result = apiRequest "/sessions" "POST" (Some payload) publicKey secretKey
match result.TryFind "id" with
| Some id -> printfn "%sSession created: %s%s" green (id.ToString()) reset
| None -> printfn "%sSession created%s" green reset
printfn "%s(Interactive sessions require WebSocket - use un2 for full support)%s" yellow reset
let openBrowser (url: string) =
try
let os = Environment.OSVersion.Platform
let cmd =
if os = PlatformID.Unix || os = PlatformID.MacOSX then
if System.IO.File.Exists("/usr/bin/xdg-open") then
System.Diagnostics.Process.Start("xdg-open", url)
else
System.Diagnostics.Process.Start("open", url)
else
System.Diagnostics.Process.Start("cmd", sprintf "/c start %s" url)
cmd.WaitForExit()
with ex ->
eprintfn "%sError opening browser: %s%s" red ex.Message reset
let cmdKey (args: Args) =
let apiKey = getApiKey args.ApiKey
ServicePointManager.SecurityProtocol <- SecurityProtocolType.Tls12 ||| SecurityProtocolType.Tls11 ||| SecurityProtocolType.Tls
let request = WebRequest.Create(portalBase + "/keys/validate") :?> HttpWebRequest
request.Method <- "POST"
request.ContentType <- "application/json"
request.Headers.Add("Authorization", sprintf "Bearer %s" apiKey)
request.Timeout <- 30000
try
use response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream())
let responseText = reader.ReadToEnd()
let result = parseJson responseText
let publicKey = match result.TryFind "public_key" with | Some v -> v.ToString() | None -> "N/A"
let tier = match result.TryFind "tier" with | Some v -> v.ToString() | None -> "N/A"
let status = match result.TryFind "status" with | Some v -> v.ToString() | None -> "N/A"
let expiresAt = match result.TryFind "expires_at" with | Some v -> v.ToString() | None -> "N/A"
let timeRemaining = match result.TryFind "time_remaining" with | Some v -> v.ToString() | None -> "N/A"
let rateLimit = match result.TryFind "rate_limit" with | Some v -> v.ToString() | None -> "N/A"
let burst = match result.TryFind "burst" with | Some v -> v.ToString() | None -> "N/A"
let concurrency = match result.TryFind "concurrency" with | Some v -> v.ToString() | None -> "N/A"
let expired = match result.TryFind "expired" with | Some v -> v.ToString() = "True" | None -> false
if args.KeyExtend && publicKey <> "N/A" then
let extendUrl = sprintf "%s/keys/extend?pk=%s" portalBase publicKey
printfn "%sOpening browser to extend key...%s" blue reset
openBrowser extendUrl
elif expired then
printfn "%sExpired%s" red reset
printfn "Public Key: %s" publicKey
printfn "Tier: %s" tier
printfn "Expired: %s" expiresAt
printfn "%sTo renew: Visit https://unsandbox.com/keys/extend%s" yellow reset
exit 1
else
printfn "%sValid%s" green reset
printfn "Public Key: %s" publicKey
printfn "Tier: %s" tier
printfn "Status: %s" status
printfn "Expires: %s" expiresAt
printfn "Time Remaining: %s" timeRemaining
printfn "Rate Limit: %s" rateLimit
printfn "Burst: %s" burst
printfn "Concurrency: %s" concurrency
with
| :? WebException as ex ->
printfn "%sInvalid%s" red reset
let errorMsg =
if ex.Response <> null then
use reader = new StreamReader(ex.Response.GetResponseStream())
let body = reader.ReadToEnd()
try
let errorResult = parseJson body
match errorResult.TryFind "error" with
| Some err -> err.ToString()
| None -> body
with _ -> body
else
ex.Message
// Check for clock drift error
if errorMsg.Contains("timestamp") && (errorMsg.Contains("401") || errorMsg.Contains("expired") || errorMsg.Contains("invalid")) then
eprintfn "%sError: Request timestamp expired (must be within 5 minutes of server time)%s" red reset
eprintfn "%sYour computer's clock may have drifted.%s" yellow reset
eprintfn "Check your system time and sync with NTP if needed:"
eprintfn " Linux: sudo ntpdate -s time.nist.gov"
eprintfn " macOS: sudo sntp -sS time.apple.com"
eprintfn " Windows: w32tm /resync%s" reset
exit 1
printfn "Reason: %s" errorMsg
exit 1
let cmdService (args: Args) =
let (publicKey, secretKey) = getApiKeys args.ApiKey
if args.ServiceList then
let result = apiRequest "/services" "GET" None publicKey secretKey
printfn "%-20s %-15s %-10s %-15s %s" "ID" "Name" "Status" "Ports" "Domains"
printfn "No services (list parsing not implemented)"
elif args.ServiceInfo.IsSome then
let result = apiRequest (sprintf "/services/%s" args.ServiceInfo.Value) "GET" None publicKey secretKey
printfn "%s" (toJson (box result))
elif args.ServiceLogs.IsSome then
let result = apiRequest (sprintf "/services/%s/logs" args.ServiceLogs.Value) "GET" None publicKey secretKey
match result.TryFind "logs" with
| Some logs -> printfn "%s" (logs.ToString())
| None -> ()
elif args.ServiceTail.IsSome then
let result = apiRequest (sprintf "/services/%s/logs?lines=9000" args.ServiceTail.Value) "GET" None publicKey secretKey
match result.TryFind "logs" with
| Some logs -> printfn "%s" (logs.ToString())
| None -> ()
elif args.ServiceSleep.IsSome then
let result = apiRequest (sprintf "/services/%s/sleep" args.ServiceSleep.Value) "POST" None publicKey secretKey
printfn "%sService sleeping: %s%s" green args.ServiceSleep.Value reset
elif args.ServiceWake.IsSome then
let result = apiRequest (sprintf "/services/%s/wake" args.ServiceWake.Value) "POST" None publicKey secretKey
printfn "%sService waking: %s%s" green args.ServiceWake.Value reset
elif args.ServiceDestroy.IsSome then
let result = apiRequest (sprintf "/services/%s" args.ServiceDestroy.Value) "DELETE" None publicKey secretKey
printfn "%sService destroyed: %s%s" green args.ServiceDestroy.Value reset
elif args.ServiceExecute.IsSome then
let payload = [("command", box args.ServiceCommand.Value)]
let result = apiRequest (sprintf "/services/%s/execute" args.ServiceExecute.Value) "POST" (Some payload) publicKey secretKey
match result.TryFind "stdout" with
| Some stdout when not (String.IsNullOrEmpty(stdout.ToString())) ->
printf "%s%s%s" blue (stdout.ToString()) reset
| _ -> ()
match result.TryFind "stderr" with
| Some stderr when not (String.IsNullOrEmpty(stderr.ToString())) ->
eprintf "%s%s%s" red (stderr.ToString()) reset
| _ -> ()
elif args.ServiceDumpBootstrap.IsSome then
eprintfn "Fetching bootstrap script from %s..." args.ServiceDumpBootstrap.Value
let payload = [("command", box "cat /tmp/bootstrap.sh")]
let result = apiRequest (sprintf "/services/%s/execute" args.ServiceDumpBootstrap.Value) "POST" (Some payload) publicKey secretKey
match result.TryFind "stdout" with
| Some bootstrap when not (String.IsNullOrEmpty(bootstrap.ToString())) ->
let bootstrapText = bootstrap.ToString()
if args.ServiceDumpFile.IsSome then
try
File.WriteAllText(args.ServiceDumpFile.Value, bootstrapText)
printfn "Bootstrap saved to %s" args.ServiceDumpFile.Value
with ex ->
eprintfn "%sError: Could not write to %s: %s%s" red args.ServiceDumpFile.Value ex.Message reset
exit 1
else
printf "%s" bootstrapText
| _ ->
eprintfn "%sError: Failed to fetch bootstrap (service not running or no bootstrap file)%s" red reset
exit 1
elif args.ServiceName.IsSome then
let mutable payload = [("name", box args.ServiceName.Value)]
if args.ServicePorts.IsSome then
let ports = args.ServicePorts.Value.Split(',') |> Array.map (fun p -> box (int (p.Trim())))
payload <- payload @ [("ports", box ports)]
if args.ServiceType.IsSome then
payload <- payload @ [("service_type", box args.ServiceType.Value)]
if args.ServiceBootstrap.IsSome then
payload <- payload @ [("bootstrap", box args.ServiceBootstrap.Value)]
if args.Network.IsSome then
payload <- payload @ [("network", box args.Network.Value)]
if args.Vcpu > 0 then
payload <- payload @ [("vcpu", box args.Vcpu)]
let result = apiRequest "/services" "POST" (Some payload) publicKey secretKey
match result.TryFind "id" with
| Some id -> printfn "%sService created: %s%s" green (id.ToString()) reset
| None -> printfn "%sService created%s" green reset
match result.TryFind "name" with
| Some name -> printfn "Name: %s" (name.ToString())
| None -> ()
match result.TryFind "url" with
| Some url -> printfn "URL: %s" (url.ToString())
| None -> ()
else
eprintfn "%sError: Specify --name to create a service, or use --list, --info, etc.%s" red reset
exit 1
let parseArgs (argv: string[]) =
let args = {
Command = None
SourceFile = None
ApiKey = None
Network = None
Vcpu = 0
Env = ResizeArray<string>()
Files = ResizeArray<string>()
Artifacts = false
OutputDir = None
SessionList = false
SessionShell = None
SessionKill = None
ServiceList = false
ServiceName = None
ServicePorts = None
ServiceType = None
ServiceBootstrap = None
ServiceInfo = None
ServiceLogs = None
ServiceTail = None
ServiceSleep = None
ServiceWake = None
ServiceDestroy = None
ServiceExecute = None
ServiceCommand = None
ServiceDumpBootstrap = None
ServiceDumpFile = None
KeyExtend = false
}
let mutable i = 0
while i < argv.Length do
match argv.[i] with
| "session" -> args.Command <- Some "session"
| "service" -> args.Command <- Some "service"
| "key" -> args.Command <- Some "key"
| "-k" | "--api-key" -> i <- i + 1; args.ApiKey <- Some argv.[i]
| "-n" | "--network" -> i <- i + 1; args.Network <- Some argv.[i]
| "-v" | "--vcpu" -> i <- i + 1; args.Vcpu <- int argv.[i]
| "-e" | "--env" -> i <- i + 1; args.Env.Add(argv.[i])
| "-f" | "--files" -> i <- i + 1; args.Files.Add(argv.[i])
| "-a" | "--artifacts" -> args.Artifacts <- true
| "-o" | "--output-dir" -> i <- i + 1; args.OutputDir <- Some argv.[i]
| "-l" | "--list" ->
match args.Command with
| Some "session" -> args.SessionList <- true
| Some "service" -> args.ServiceList <- true
| _ -> ()
| "-s" | "--shell" -> i <- i + 1; args.SessionShell <- Some argv.[i]
| "--kill" -> i <- i + 1; args.SessionKill <- Some argv.[i]
| "--name" -> i <- i + 1; args.ServiceName <- Some argv.[i]
| "--ports" -> i <- i + 1; args.ServicePorts <- Some argv.[i]
| "--type" -> i <- i + 1; args.ServiceType <- Some argv.[i]
| "--bootstrap" -> i <- i + 1; args.ServiceBootstrap <- Some argv.[i]
| "--info" -> i <- i + 1; args.ServiceInfo <- Some argv.[i]
| "--logs" -> i <- i + 1; args.ServiceLogs <- Some argv.[i]
| "--tail" -> i <- i + 1; args.ServiceTail <- Some argv.[i]
| "--freeze" -> i <- i + 1; args.ServiceSleep <- Some argv.[i]
| "--unfreeze" -> i <- i + 1; args.ServiceWake <- Some argv.[i]
| "--destroy" -> i <- i + 1; args.ServiceDestroy <- Some argv.[i]
| "--execute" -> i <- i + 1; args.ServiceExecute <- Some argv.[i]
| "--command" -> i <- i + 1; args.ServiceCommand <- Some argv.[i]
| "--dump-bootstrap" -> i <- i + 1; args.ServiceDumpBootstrap <- Some argv.[i]
| "--dump-file" -> i <- i + 1; args.ServiceDumpFile <- Some argv.[i]
| "--extend" -> args.KeyExtend <- true
| arg when not (arg.StartsWith("-")) -> args.SourceFile <- Some arg
| _ -> ()
i <- i + 1
args
let printHelp () =
printfn "Usage: un [options] <source_file>"
printfn " un session [options]"
printfn " un service [options]"
printfn " un key [options]"
printfn ""
printfn "Execute options:"
printfn " -e KEY=VALUE Set environment variable"
printfn " -f FILE Add input file"
printfn " -a Return artifacts"
printfn " -o DIR Output directory for artifacts"
printfn " -n MODE Network mode (zerotrust/semitrusted)"
printfn " -v N vCPU count (1-8)"
printfn " -k KEY API key"
printfn ""
printfn "Session options:"
printfn " --list List active sessions"
printfn " --shell NAME Shell/REPL to use"
printfn " --kill ID Terminate session"
printfn ""
printfn "Service options:"
printfn " --list List services"
printfn " --name NAME Service name"
printfn " --ports PORTS Comma-separated ports"
printfn " --type TYPE Service type (minecraft/mumble/teamspeak/source/tcp/udp)"
printfn " --bootstrap CMD Bootstrap command"
printfn " --info ID Get service details"
printfn " --logs ID Get all logs"
printfn " --tail ID Get last 9000 lines"
printfn " --freeze ID Freeze service"
printfn " --unfreeze ID Unfreeze service"
printfn " --destroy ID Destroy service"
printfn " --execute ID Execute command in service"
printfn " --command CMD Command to execute (with --execute)"
printfn " --dump-bootstrap ID Dump bootstrap script"
printfn " --dump-file FILE File to save bootstrap (with --dump-bootstrap)"
printfn ""
printfn "Key options:"
printfn " --extend Open browser to extend key"
printfn " -k KEY API key to validate"
[<EntryPoint>]
let main argv =
try
let args = parseArgs argv
match args.Command with
| Some "session" -> cmdSession args; 0
| Some "service" -> cmdService args; 0
| Some "key" -> cmdKey args; 0
| _ ->
match args.SourceFile with
| Some _ -> cmdExecute args; 0
| None -> printHelp(); 1
with ex ->
eprintfn "%sError: %s%s" red ex.Message reset
1
License
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
that 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 all 42
programming languages through a unified interface, accessible to everyone. 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 its own software - with our permacomputer
monitoring itself, repairing itself, with minimal human guidance in the loop.
Our agents do their best.
Copyright 2025 TimeHexOn & foxhop & russell@unturf
https://www.timehexon.com
https://www.foxhop.net
https://www.unturf.com/software