Security

You stay in control. Always.

The principle

AI is powerful, but power without control is just risk. ThinkingScript is built on a simple rule: nothing happens without your permission.

We're not asking you to trust AI blindly. We're giving you a locked room with a window, and you decide when to open the door.

Runs in a sandbox

Every thought runs inside goja, a pure-Go JavaScript engine. No CGo, no external dependencies, no attack surface from native code. The entire runtime compiles into a single static binary.

Instead of open-ended system access, the sandbox gets a small set of controlled bridges. Each bridge is purpose-built, narrowly scoped, and gated by the approval system.

Controlled bridges

These are the only ways a thought can interact with the outside world.

fs.*

Read and write files. Current directory is read-only; workspace is read-write; other paths require approval.

Approval for writes outside workspace
net.fetch()

Make HTTP requests. Each host requires separate approval.

Per-host approval
env.get()

Read environment variables.

Requires approval
sys.*

System introspection: CPU, memory, uptime, terminal size.

No approval
console.*

Log to stderr for debugging. Never touches stdout.

No approval

That's the full list. If it's not here, the sandbox can't do it.

Workspaces

Each thought gets its own private directory at ~/.thinkingscript/thoughts/<name>/workspace. This is where it stores caches, downloaded data, and intermediate files between runs.

Isolated by default

A thought can freely read and write inside its own workspace. It cannot see other thoughts' workspaces. It cannot access files outside the current directory or workspace without triggering an approval prompt.

Persists across edits

Workspaces are keyed by script name, so they survive edits and rebuilds. If you tweak your weather.txt and reinstall it, the cached data is still there.

Terminal
$ thought open weather
Opens ~/.thinkingscript/thoughts/weather/ in file manager

You can inspect, edit, or delete a workspace at any time. It's just a directory.

The approval system

When a thought tries to access something sensitive (a file outside the working directory, a network request, an environment variable) it stops and asks you first.

You see exactly what's happening before you decide.

Approval prompt
   NET  api.weather.gov

 1 Allow
  2 Deny

Your options

Allow
Save to policy

Approve and remember. Won't ask again for this thought.

Deny
Save to policy

Reject and remember. The LLM adapts and tries another approach.

Policy files

When you choose "Allow", the decision is saved to a policy file. Each thought gets its own policy at ~/.thinkingscript/thoughts/<name>/policy.json.

~/.thinkingscript/thoughts/weather/policy.json
{
  "version": 1,
  "paths": {
    "default": "prompt",
    "entries": [
      {"path": "/Users/me/data", "mode": "rw", "approval": "allow"}
    ]
  },
  "env": {
    "default": "prompt",
    "entries": [
      {"name": "HOME", "approval": "allow"},
      {"name": "AWS_*", "approval": "deny"}
    ]
  },
  "net": {
    "hosts": {
      "default": "prompt",
      "entries": [
        {"host": "api.weather.gov", "approval": "allow"},
        {"host": "*.github.com", "approval": "allow"}
      ]
    }
  }
}

Path permissions

Path entries use chmod-style modes: r (read), w (write), d (delete). A path with "mode": "rw" can read and write but not delete.

Wildcards

Environment variables support suffix wildcards (AWS_* matches AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc). Hosts support prefix wildcards (*.github.com matches api.github.com, raw.githubusercontent.com).

Managing policies

Terminal
$ thought policy ls weather
Paths:
  /Users/me/data (rw) allow

Env:
  HOME allow
  AWS_* deny

Hosts:
  api.weather.gov allow
  *.github.com allow

$ thought policy add host weather "api.openweathermap.org"
Added host api.openweathermap.org → allow

$ thought policy rm env weather "AWS_*"
Removed env AWS_*

How trust works

Trust is tied to the code

Approvals are stored alongside a hash of the script's contents. If the script changes, all approvals reset automatically. You're trusting this version of the code, not the filename.

Non-interactive mode

In non-interactive environments (CI, cron, background jobs), sensitive actions are denied by default. No prompt means no approval. Safe out of the box.

Global policy

A global policy at ~/.thinkingscript/policy.json sets defaults for all thoughts. Per-thought policies override global settings. This lets teams define baseline security rules while individual thoughts can request additional permissions.

Get started

Terminal
$ curl -fsSL https://thinkingscript.com/install.sh | sh
$ thought setup
$ think https://thinkingscript.com/hi.txt