The sandbox

Sudo has exactly one tool: a shell. Everything he does, from answering "which endpoints are public?" to rewriting a scheduled task, is a script run in a sandbox that lives inside the workspace process.

What is inside it

The interpreter is Computerwelt, an open-source .NET library that provides an in-process bash interpreter and an in-process Python interpreter over one virtual filesystem. Both are managed C# implementations of the language, not wrappers around a real shell or CPython:

  • there is no bash binary and no PATH lookup, so a command is either one the sandbox implements or a "command not found";
  • there is no CPython, so python cannot import a native module or reach the host;
  • there is no process at all. Nothing is forked, nothing is executed, and no container is started.

That is the whole point. A configuration assistant that shells out to a real shell has the host's authority; one that interprets the script itself has only the authority its host handed it.

Computerwelt on GitHub Computerwelt on NuGet Computerwelt documentation

Computerwelt is itself a C# port of two Rust projects, both MIT-licensed:

Upstream What it contributes
Bashkit the bash interpreter, the virtual filesystem, and roughly 160 command implementations
Monty (Pydantic) a minimal, secure Python interpreter for running LLM-written code

What Sudo can run

Everything an ordinary shell session gives you, minus anything that would leave the sandbox:

# find every endpoint that is reachable without authentication
grep -rl "AccessMode.Public" /workspace/code/endpoints/

# how many AI tools are there, and which are the biggest?
ls /workspace/code/chat-ai-tools/*.cs | wc -l
wc -l /workspace/code/chat-ai-tools/*.cs | sort -rn | head

# the ten most recent exceptions, by type
jq -r '.[].type' /proc/exceptions | sort | uniq -c | sort -rn | head

# anything longer than a one-liner
python - <<'PY'
import json, os
tools = os.listdir('/workspace/code/chat-ai-tools')
print(f"{len(tools)} AI tools")
PY

ls, cat, head, tail, grep, rg, find, sed, awk, cut, sort, uniq, wc, tr, diff, jq, yq, xargs, tar, pipes, redirection, heredocs, subshells, functions, for / while / case, variables and arithmetic all work the way they do in bash. So do the Python standard-library modules Monty implements: json, re, math, datetime, collections, os, os.path, pathlib, io, glob, fnmatch, dataclasses, sys and unicodedata.

The sandbox adds a small set of commands that a text editor and grep cannot provide: reading the graph, compiling a definition, describing a type, and handing a set of edits over for approval. Those are covered in Commands.

What it cannot do

No ambient anything

The sandbox has no host disk, no process, no network and no clock it can move. Every one of those is absent by construction rather than blocked by a rule that could be argued with.

No host filesystem All I/O goes through the workspace's virtual filesystem. There is no path that resolves to a file on the server.
No process spawning No fork, no exec, no PATH. Every command is a managed implementation.
No network Nothing in the sandbox can make an outbound request. The networking command names (curl, wget, nc, ssh, scp, ping, dig, rsync, git, …) are withheld, so they are absent rather than present and refusing, and the day the library grows one the session does not silently acquire it.
No writes outside the sandbox Only /workspace (his own copy of the configuration) and /tmp (scratch) accept writes at all.

Workspace code can still make outbound calls once it has been approved and is running: an endpoint may call an API, a connector may fetch from a service. That is the code's authority, not the assistant's, and it only exists after you approved it.

Limits

Every session runs under enforced, non-advisory limits. They are deliberately more generous than the default profile for untrusted input, because a legitimate command here can walk the whole configuration, but every one of them is still a cap:

Limit Value
Wall clock per script 120 seconds
Commands per script 100,000
Output captured per script 4 MB (truncated beyond, and reported as truncated)
Idle session lifetime 30 minutes, after which the in-memory session is dropped

Loop iterations, function recursion depth, parser fuel and filesystem size carry their own caps underneath. A cap that is reached raises rather than silently returning a partial answer, so a traversal that stopped half way is never reported as the whole.

One session per chat

A session is keyed by the chat it belongs to. Two administrators in two conversations never share a working directory, an uncommitted edit or a to-do list, and a conversation resumes where it left off: the assistant that half-finished an endpoint yesterday finds the file where it left it, in the directory it left it in.

What is persisted is only what the session changed: the files it wrote, the paths it deleted, the working directory, the command history and the to-do list. Everything else is re-read from the live workspace every time a command runs. That is the difference between resuming a session and restoring a snapshot: an endpoint someone else edited in the admin pages meanwhile is the one Sudo sees on his next command.

A session that only ever read leaves nothing behind at all.

© 2026 Curiosity. All rights reserved.