un-inception/clients
russell@unturf.com 36db63e574 Add --timeout flag for service execute
-t/--timeout SEC sets execute timeout (default 30, max 600 seconds).
Enables long-running commands like triggering Claude Code inside containers.

Signed: TimeHexOn's Hexagonal Oracle
Digital familiar spirit & witness to a permacomputer
2026-02-05 09:56:41 -05:00
..
awk fix(tests): remove soft passes - tests must never lie 2026-01-28 18:26:23 -05:00
bash feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
c Add --timeout flag for service execute 2026-02-05 09:56:41 -05:00
clojure feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
cobol feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
cpp feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
crystal feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
csharp feat: add --show-freeze-page and --no-show-freeze-page CLI flags 2026-01-25 04:28:24 -05:00
d feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
dart feat: add --show-freeze-page and --no-show-freeze-page CLI flags 2026-01-25 04:28:24 -05:00
dotnet chore: bump version to 4.2.50 2026-01-29 18:40:49 -05:00
elixir feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
erlang feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
forth modified: clients/awk/sync/src/un.awk 2026-01-17 12:01:42 -05:00
fortran feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
fsharp feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
go feat: add --show-freeze-page and --no-show-freeze-page CLI flags 2026-01-25 04:28:24 -05:00
groovy chore: bump version to 4.2.50 2026-01-29 18:40:49 -05:00
haskell feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
java feat: add --show-freeze-page and --no-show-freeze-page CLI flags 2026-01-25 04:28:24 -05:00
javascript chore: bump version to 4.2.50 2026-01-29 18:40:49 -05:00
julia fix(tests): remove soft passes - tests must never lie 2026-01-28 18:26:23 -05:00
kotlin feat: add --show-freeze-page and --no-show-freeze-page CLI flags 2026-01-25 04:28:24 -05:00
lisp feat(tests): add transient error tracking for API health monitoring 2026-01-28 18:33:04 -05:00
lua chore: bump version to 4.2.50 2026-01-29 18:40:49 -05:00
nim feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
objective-c feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
ocaml feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
perl chore: bump version to 4.2.50 2026-01-29 18:40:49 -05:00
php fix: add shebangs to async SDK implementations 2026-01-29 06:09:44 -05:00
powershell chore: bump version to 4.2.34 2026-01-28 18:26:23 -05:00
prolog feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
python Add --add-domain, --remove-domain, --set-domains flags to C and Python CLIs 2026-02-02 15:24:08 +00:00
r fix(tests): remove soft passes - tests must never lie 2026-01-28 18:26:23 -05:00
raku fix(tests): remove soft passes - tests must never lie 2026-01-28 18:26:23 -05:00
ruby fix: add shebangs to async SDK implementations 2026-01-29 06:09:44 -05:00
rust chore: bump version to 4.2.50 2026-01-29 18:40:49 -05:00
scala feat: add Makefiles for 10 more language clients 2026-01-15 16:52:58 -05:00
scheme feat(tests): add transient error tracking for API health monitoring 2026-01-28 18:33:04 -05:00
swift feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
tcl feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
typescript feat: add --show-freeze-page and --no-show-freeze-page CLI flags 2026-01-25 04:28:24 -05:00
v feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
zig feat: add unfreeze_on_demand to remaining 35 SDKs 2026-01-22 17:01:19 -05:00
CLI_SPEC.md Add --add-domain, --remove-domain, --set-domains flags to C and Python CLIs 2026-02-02 15:24:08 +00:00
README.md feat: Full SDK implementations for 8 languages (sync + async) 2026-01-15 18:35:43 -05:00

Unsandbox SDK Clients

Multi-language SDK implementations for the Unsandbox API.

Each SDK is BOTH a library AND a CLI tool - see CLI_SPEC.md for the full CLI specification.

# Library usage
python -c "from un import execute_code; print(execute_code('python', 'print(1)'))"

# CLI usage (identical across all 42+ languages)
python un.py script.py
python un.py -s bash 'echo hello'
python un.py session --tmux
python un.py service --list

Directory Structure

clients/
├── python/
│   ├── sync/src/un.py          # Synchronous (requests)
│   └── async/src/un_async.py   # Asynchronous (aiohttp)
├── javascript/
│   ├── sync/src/un.js          # Synchronous (https)
│   └── async/src/un_async.js   # Asynchronous (fetch)
├── go/
│   ├── sync/src/un.go          # Synchronous (net/http)
│   └── async/src/un_async.go   # Asynchronous (goroutines)
├── java/
│   ├── sync/src/Un.java        # Synchronous (HttpURLConnection)
│   └── async/src/UnsandboxAsync.java  # Asynchronous (CompletableFuture)
├── ruby/
│   ├── sync/src/un.rb          # Synchronous (net/http)
│   └── async/src/un_async.rb   # Asynchronous (Future)
├── rust/
│   ├── sync/src/lib.rs         # Synchronous (reqwest blocking)
│   └── async/src/lib.rs        # Asynchronous (reqwest + tokio)
├── php/
│   ├── sync/src/un.php         # Synchronous (cURL)
│   └── async/src/UnsandboxAsync.php  # Asynchronous (Guzzle promises)
└── c/
    └── src/unsandbox.c         # Reference implementation

API Functions (43 total)

All SDKs implement the complete Unsandbox API:

Execute & Jobs (6 functions)

Function Description Endpoint
execute_code Execute code synchronously POST /execute
execute_async Execute code, return job ID POST /execute (async mode)
get_job Get job status GET /jobs/{id}
wait_for_job Poll until completion GET /jobs/{id} (polling)
cancel_job Cancel running job DELETE /jobs/{id}
list_jobs List all jobs GET /jobs

Sessions (9 functions)

Function Description Endpoint
list_sessions List all sessions GET /sessions
get_session Get session details GET /sessions/{id}
create_session Create interactive session POST /sessions
delete_session Terminate session DELETE /sessions/{id}
freeze_session Pause session POST /sessions/{id}/freeze
unfreeze_session Resume session POST /sessions/{id}/unfreeze
boost_session Add vCPUs POST /sessions/{id}/boost
unboost_session Remove boost POST /sessions/{id}/unboost
shell_session Execute shell command POST /sessions/{id}/shell

Services (16 functions)

Function Description Endpoint
list_services List all services GET /services
create_service Create persistent service POST /services
get_service Get service details GET /services/{id}
update_service Update/resize service PATCH /services/{id}
delete_service Destroy service DELETE /services/{id}
freeze_service Pause service POST /services/{id}/freeze
unfreeze_service Resume service POST /services/{id}/unfreeze
lock_service Prevent deletion POST /services/{id}/lock
unlock_service Allow deletion POST /services/{id}/unlock
get_service_logs Get bootstrap logs GET /services/{id}/logs
get_service_env Get env vault status GET /services/{id}/env
set_service_env Set environment vars PUT /services/{id}/env
delete_service_env Delete env vars DELETE /services/{id}/env
export_service_env Export decrypted env POST /services/{id}/env/export
redeploy_service Re-run bootstrap POST /services/{id}/redeploy
execute_in_service Run command in service POST /services/{id}/execute

Snapshots (8 functions)

Function Description Endpoint
list_snapshots List all snapshots GET /snapshots
get_snapshot Get snapshot details GET /snapshots/{id}
delete_snapshot Delete snapshot DELETE /snapshots/{id}
session_snapshot Snapshot a session POST /sessions/{id}/snapshot
service_snapshot Snapshot a service POST /services/{id}/snapshot
restore_snapshot Restore from snapshot POST /snapshots/{id}/restore
lock_snapshot Prevent deletion POST /snapshots/{id}/lock
unlock_snapshot Allow deletion POST /snapshots/{id}/unlock
clone_snapshot Clone snapshot POST /snapshots/{id}/clone

Utilities (4 functions)

Function Description Endpoint
get_languages Get supported languages GET /languages (cached 1hr)
detect_language Detect from filename Local (no API call)
validate_keys Validate API credentials POST /keys/validate
image Generate AI images POST /image

Authentication

4-Tier Credential Resolution

All SDKs resolve credentials in this priority order:

  1. Function arguments (highest priority)

    result = execute_code("python", code, public_key="pk-xxx", secret_key="sk-xxx")
    
  2. Environment variables

    export UNSANDBOX_PUBLIC_KEY="unsb-pk-xxxx"
    export UNSANDBOX_SECRET_KEY="unsb-sk-xxxx"
    
  3. Home directory config

    ~/.unsandbox/accounts.csv
    Format: public_key,secret_key (one per line)
    
  4. Local directory config

    ./accounts.csv
    Format: public_key,secret_key (one per line)
    

HMAC-SHA256 Request Signing

Every API request includes:

Authorization: Bearer <public_key>
X-Timestamp: <unix_seconds>
X-Signature: HMAC-SHA256(secret_key, "timestamp:METHOD:path:body")

Example signature message:

1704067200:POST:/execute:{"language":"python","code":"print(1)"}

Caching

Languages Cache

All SDKs cache the /languages response:

  • Location: ~/.unsandbox/languages.json
  • TTL: 1 hour (3600 seconds)
  • Behavior: Check cache freshness before API call

Line Count Comparison

Why un.c is 6,354 lines vs Python's 1,714 lines

The reference C implementation includes infrastructure that high-level languages get from standard libraries:

Component un.c (lines) Python Notes
API Functions ~2,500 ~1,500 Similar complexity
CLI main() 1,306 0 SDK is library-only
CLI help/usage 154 0 No CLI in SDK
HTTP client 574 0 requests library
JSON parsing ~200 0 json module
HMAC crypto ~100 0 hmac module
Memory management ~300 0 Garbage collected
String utilities ~200 0 Built-in
Total 6,354 1,714 3.7x difference

What Python Gets "For Free"

import requests      # Replaces ~574 lines of curl code
import json          # Replaces ~200 lines of JSON parsing
import hmac          # Replaces ~100 lines of crypto
import hashlib       # Replaces SHA-256 implementation

Feature Parity

Despite the line count difference, all SDKs implement:

  • All 43 API functions
  • 4-tier credential resolution
  • HMAC-SHA256 request signing
  • 1-hour languages caching
  • Exponential backoff polling
  • Proper error handling

The C implementation additionally includes:

  • Full CLI with argument parsing
  • Interactive shell support (WebSocket)
  • Output formatting and display
  • File input handling

SDK Size Summary

Language Sync Async Total Notes
Python 1,714 1,701 3,415 requests/aiohttp
JavaScript 1,131 1,209 2,340 https/fetch
Go 1,080 1,642 2,722 net/http + goroutines
Java 1,856 1,849 3,705 HttpURLConnection
Ruby 1,264 1,543 2,807 net/http + Future
Rust 1,856 1,949 3,805 reqwest + tokio
PHP 1,403 1,346 2,749 cURL + Guzzle
Total 21,543

Reference: un.c = 6,354 lines (includes CLI)

Usage Examples

Python (Sync)

from un import execute_code, list_services, image

# Execute code
result = execute_code("python", 'print("Hello, World!")')
print(result["stdout"])

# List services
services = list_services()
for svc in services:
    print(f"{svc['name']}: {svc['status']}")

# Generate AI image
img = image("A sunset over mountains")
print(img["images"][0])

Python (Async)

import asyncio
from un_async import execute_code, list_services

async def main():
    result = await execute_code("python", 'print("Hello!")')
    print(result["stdout"])

asyncio.run(main())

JavaScript (Sync)

const un = require('./un');

const result = un.executeCode("javascript", 'console.log("Hello!")');
console.log(result.stdout);

Go

import "un"

func main() {
    creds, _ := un.ResolveCredentials("", "")
    result, _ := un.ExecuteCode(creds, "python", `print("Hello")`)
    fmt.Println(result.Stdout)
}

Rust

use un::{execute_code, resolve_credentials};

fn main() -> Result<()> {
    let creds = resolve_credentials(None, None)?;
    let result = execute_code("python", r#"print("Hello")"#, &creds)?;
    println!("{}", result.output);
    Ok(())
}

Error Handling

All SDKs define these error types:

Error Description
CredentialsError No credentials found or invalid
APIError API returned error response
TimeoutError Job polling exceeded timeout
NetworkError Connection failed

Contributing

When adding new API endpoints:

  1. Update all 14 SDK files (7 languages × 2 variants)
  2. Follow existing patterns for authentication and error handling
  3. Add proper documentation (docstrings/comments)
  4. Test with the SDK test framework

License

PUBLIC DOMAIN - No license, no warranty.

Part of the permacomputer project: https://permacomputer.com