curio: Sudo's sandbox, in your terminal

Rafael
•

Two weeks ago we wrote about the tool Sudo has, which is one tool: a sandbox whose filesystem is the workspace configuration. Endpoints, AI tools, agents, schemas and scheduled tasks are files under /workspace. Sudo reads them, edits them, runs build, runs commit, and an admin approves the diff before anything reaches the workspace.

That sandbox lived behind a chat, in a browser tab. That is the right place to ask Sudo for something. It is the wrong place for the two users who most want to change a workspace by hand: a developer who wants their own editor, and the coding agent that developer already works with. Neither of them lives in a browser tab. Both live in a terminal.

So today we are releasing curio, the command line for Curiosity Studio. It opens the same sandbox, from your terminal, for both of them:

  • The same sandbox Sudo uses. A curio session is a Sudo conversation. Edits wait in it until a commit is staged and a person approves it, the same diff and the same approval as in the admin dock.
  • Plain text and exit codes. Every command does one thing, prints text and exits with a code that means something, so an agent, a script and a CI job can all drive it.
  • Skills from the workspace. An agent that has never seen your workspace reads Sudo's own skills through curio, in the version the workspace runs.
  • A two-panel commander for the keyboard. Run curio with no arguments and you get the sandbox on one side, your disk on the other, and F9 for the changes.

Install it and run it:

$ curl -fsSL https://curiosity.sh/install.sh | bash      # macOS, Linux
PS> irm https://curiosity.sh/install.ps1 | iex            # Windows
$ dotnet tool install --global Curiosity.Shell            # anywhere with the .NET SDK
$ curio

The first run asks for your workspace address, opens the browser to sign you in with any login the workspace supports, SSO included, and drops you into the two panels. It needs a system administrator account. Then give your agent the skill:

$ curio skills install          # writes .claude/skills/curio/SKILL.md

If your harness reads an instructions file rather than a skills folder, this is the gist of it, ready to paste:

Prompt for your coding agent
This project changes a Curiosity Studio workspace through curio, a command line.
Read .claude/skills/curio/SKILL.md first. If it is not there, run `curio skills show curio`.
Start a session of your own with `curio sessions new "<what this change is>"`.
Before a task, read the skill that matches it: `curio skills search <words>`, then
`curio skills show <name>`. Read /reference, /docs and /sdk instead of guessing an API.
Fetch a file with `curio get` before you overwrite it, and write it back with
`curio put <file> <path> --expected-hash <hash>` using the hash `get` printed.
Run `curio run -- build` after every change and fix what it reports.
Stage the change with `curio run -- commit -m "<message>"`, then `curio commit approve`.
If that opens the browser, you may not approve: say so and wait. Do not look for a way round it.
Exit codes: 77 not signed in, 78 not allowed, 75 conflict (re-read the file), 64 usage.

The site is curiosity.sh. Its first screen is a laptop running a simulated curio, with Claude Code working through it, that you can drive with the keyboard. The docs are at docs.curiosity.ai/curio.

The same sandbox, not a new API

The easy way to build a command line for a product is to wrap its API: one command per endpoint, and a second set of rules about what those commands may change. We already had a place where a workspace gets changed safely, with a build before every commit and an approval before every apply. We did not want a second one.

So a curio session is a Sudo conversation with its own sandbox. A session you open in curio is listed in the admin dock, and a dock session is listed in curio. Beside /workspace sit the mounts Sudo reads from: /reference, /docs, /sdk, /proc, and the front end under /frontend. Every sandbox command works from curio, too: build, commit, graph, query, uid, tasks and the rest.

Everything else follows from that. Edits stay in the session, marked M, A or D. build checks them against the workspace. commit stages them. Nothing is applied until the commit is approved, and every invariant from the Sudo post still holds, because curio talks to the same sandbox rather than around it.

Plain text and exit codes, because a program reads them

Each curio command does one thing, prints plain text and exits:

curio login [--server URL] [--approve|--no-approve]
curio logout | whoami
curio sessions [list | new [name] | use <id|name> | rename <name> | rm | reset | stop]
curio run -- <command line>        curio run -f script.sh
curio status | diff
curio commit [show | approve | discard]
curio ls [path] | cat <path> | get <path> [local] | put <local> <path> | rm [-r] <path>
curio upload <files...>
curio skills [list [--all] | search <words> | show <name> | install [folder] [--global]]

The exit code is what an agent and a pipeline branch on, so we made it carry information. curio run passes the sandbox command's own code through, so a failing build fails the step. curio's own codes are fixed: 64 for a usage error, 75 for a conflict, 77 when you are not signed in, 78 when you are not allowed. An agent that gets a 75 knows to re-read the file, and one that gets a 78 knows retrying will not help.

The commands that destroy something (sessions rm, reset, commit approve, commit discard) ask first. With standard input redirected they cannot ask, so they stop with exit code 1 instead of assuming yes. A script says --yes when it means it.

Your agent has never seen curio, so curio tells it

A coding agent knows the tools that were in its training data. curio was not, and neither is your workspace: its schemas, its endpoints, the way its agents are wired. An agent without that context writes confident, plausible, wrong code, and you pay for the round trip.

Sudo already has that context written down, as skills: the built-in ones and the ones your workspace adds. Those stay on the workspace, and curio reads them on demand:

curio skills list [--all]            what there is
curio skills search <words> [-n N]   which skills mention them, best first, with the passage
curio skills show <name>             one skill, as Sudo reads it

curio skills install writes a single curio skill into the agent's skills folder. It says how to work through curio, carries an index of Sudo's skills, and gives the commands to read one. Nothing else is copied. When the workspace changes a skill, the agent reads the new one the next time it asks, not the copy from the day you installed. It is the same argument as shipping skills inside the NuGet package: the documentation should come from the thing it documents.

Harness Setup
Claude Code curio skills install, or --global for ~/.claude/skills
OpenAI Codex curio skills install ./.agents, then point AGENTS.md at .agents/curio/SKILL.md
Mistral Vibe curio skills install ./.agents, then reference it from the project instructions
Anything else curio skills show curio prints the same instructions

Run it again to refresh the index. A copy you edited by hand is kept unless you pass --force.

Here is a session from the agent's side, asked for an endpoint that lists the open supplier notices for a part:

curio skills search "code endpoint"
curio skills show add-code-endpoint
curio cat /workspace/config/schemas/nodes/Part.cs
curio put open-notices.cs /workspace/code/endpoints/open-notices.cs
curio run -- build
curio run -- commit -m "Open supplier notices for a part"
curio commit approve        # a person answers on Sudo's review screen

It found the skill instead of guessing, read the schema it was about to query, and built before it committed. The last line hands the change to a person.

Three writers, one session

A session can have three writers at once: you, your agent through the CLI, and Sudo in the dock. curio keeps a WebSocket open to the session, so every change comes back as it happens: a file Sudo edits in the dock appears in your panel, and a commit your agent stages shows up in F9. You can watch in the commander what an agent is doing through the command line.

Watching is not enough when two of them write the same file. curio get prints the file's hash, and curio put --expected-hash <hash> refuses the write if the file changed since. An empty hash means the file must not exist yet. In the commander, an F4 save is refused on the same condition.

The agent stages. A person approves.

Signing in asks one question: may this curio approve and apply a staged commit by itself? A checkbox on the sign-in page answers it.

By default it may not. Approving opens the commit on Sudo's review screen in your browser, and curio waits until you approve or discard it there. The workspace enforces this, not curio: a token issued to such a curio is refused by the approve routes, and stays refused when it is renewed. An agent holding that token can stage as much as it likes and apply nothing, whatever its instructions say.

If you do allow it, curio commit approve and the Approve button in F9 apply the commit and stream the apply log. To change your mind, sign in again.

When you want the keyboard yourself

Some changes you want to make by hand. Run curio with no arguments and you get a two-panel file commander in the style of Midnight Commander:

 curio  https://acme.curiosity.ai  |  admin  |  session: fix-search  |  2 changed  |  live
╔╡ sandbox:/workspace/code/endpoints ╞════════╗╔╡ local:/home/me/defs ╞══════════════════════╗
║  /..                                        ║║  /..                                        ║
║M search-orders.cs         2.1K 09-29 12:04  ║║  notes.md                   1.2K 09-28 17:10║
║A export-invoices.cs        812 09-29 12:10  ║║  search-orders.cs           2.0K 09-29 11:58║
╚═════════════════════════════════════════════╝╚═════════════════════════════════════════════╝
/workspace/code/endpoints$ build
 1Help 2Sessions 3View 4Edit 5Copy 6Move 7Mkdir 8Delete 9Changes 10Quit

If your hands remember a commander, they already know it. F3 and F4 view and edit. F5 and F6 copy and move between your machine and the sandbox, both ways, so your own editor is one F5 away. F2 switches sessions, and Ctrl+L flips a panel between the sandbox and your computer. Typing anywhere starts a command, run in the sandbox in the active panel's directory.

F9 opens the changes: every file the session touched, its diff, and the buttons that take it to production. Build, commit, approve with the apply log streaming, discard, pull, revert.

In CI

For a pipeline, set the workspace and a session token in the environment. curio uses them and stores nothing:

#!/usr/bin/env bash
set -euo pipefail
# CURIOSITY_SERVER and CURIOSITY_TOKEN come from the pipeline's secrets
curio sessions new "ci-$GITHUB_RUN_ID"
for f in definitions/code/endpoints/*.cs; do
  curio put "$f" /workspace/code/endpoints/
done
curio run -- build                 # fails the job on a build error
curio diff
curio sessions rm --yes

That checks a set of definitions against the live workspace on every push, without applying any of them.

Signing in

curio login runs an OAuth loopback flow with PKCE. curio listens on 127.0.0.1, the workspace asks you to confirm, and the browser hands back a one-time code that is useless without the verifier curio kept.

The refresh token goes into the OS keyring: Windows Credential Manager, the macOS Keychain, or the Secret Service on Linux. Where there is none, in a container or over SSH, it goes into a file only you can read. The token is listed under Manage > Tokens as "curio on user@machine". Revoking it there signs curio out, and so does curio logout.

curio and curiosity-cli

If you already use curiosity-cli, keep using it. It is a different tool: it tests connections, ingests folders and promotes definitions between workspaces. It does not open a sandbox. curio is for changing one workspace, through Sudo's sandbox, with an approval at the end.

Get started

$ curl -fsSL https://curiosity.sh/install.sh | bash
$ curio

The scripts read the latest release, download the self-contained file for your system, check its SHA-256 against the release, and put it in ~/.curiosity/bin. That is the same folder curio keeps its config and sign-in in, so removing ~/.curiosity removes everything. Run the script again to update.

From there, your first session takes one endpoint from an edit to an approved change, and coding agents sets up Claude Code or Codex to do the same. Sudo is waiting.

Read next

Articles on context graphs, enterprise search and industrial AI

Connected knowledge for AI systems