cd /news/ai-agents/strands-shell-give-your-agent-a-shel… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-31375] src=github.com β†— pub= topic=ai-agents verified=true sentiment=↑ positive

Strands Shell: Give your agent a shell without giving it keys to your machine

Strands Shell, a Bourne-compatible shell that runs in-process without fork or syscalls, launches to give AI agents isolated shell access with sub-millisecond cold starts. The tool provides over 50 built-in commands and mediates file, network, and credential access through a kernel, preventing agents from accessing host resources beyond declared binds. Available for Python and Node.js, it aims to replace Docker or cloud sandboxes for agentic workflows requiring speed and security.

read5 min views1 publishedJun 17, 2026

Documentation β—† MCP Server β—† Python β—† Node.js

Agents run shell commands in tight loops: Install deps, run tests, grep for errors, iterate. Those loops need speed and isolation.

Strands Shell is a Bourne-compatible shell that runs in-process. grep

, sed

, jq

, curl

, find

, 50+ commands and it does this without fork, exec, syscalls, or cold starts. You declare what the agent can reach (files, URLs, credentials) and everything else doesn't exist to the agent.

Docker Cloud sandbox Strands Shell
Cold start
~200ms ~1s (network) <1ms
Isolation
Container namespace MicroVM In-process VFS
Network
iptables / sidecar Platform policy URL allowlist + SSRF guard
Secrets
Env vars (agent can read them) Platform-specific Injected per-request, agent never sees them
Setup
Docker daemon API key + network pip install strands-shell
Platforms
Linux Cloud-only macOS, Linux, WASM

Drop this into your MCP client config:

{
  "mcpServers": {
    "shell": {
      "command": "uvx",
      "args": ["strands-shell", "--mcp"]
    }
  }
}

That's it and your agent gets shell

, read_file

, write_file

, list_dir

. All mediated through the Kernel.

pip install strands-shell
python
import strands_shell

shell = strands_shell.Shell(
    binds=[strands_shell.Bind("/my/project", "/workspace", mode="copy")],
    credentials=[strands_shell.Cred("https://api.example.com/", env_var="API_TOKEN")],
    allowed_urls=["https://api.example.com/"],
)

out = shell.run("grep -rn TODO /workspace")
print(out.stdout)
npm install @strands-agents/shell
js
import { Shell } from '@strands-agents/shell'

const shell = await Shell.create({
  binds: [{ source: '/my/project', destination: '/workspace', mode: 'copy' }],
})
const out = await shell.run('grep -rn TODO /workspace')
console.log(out.stdout)
flowchart TB
    agent["Your agent code\n(Strands, LangGraph, Pydantic AI, etc)"]
    agent -->|"MCP / Python / Node.js"| shell

    subgraph shell ["Strands Shell"]
        direction TB
        subgraph kernel ["Kernel (mediation boundary)"]
            vfs["VFS: isolated filesystem"]
            net["Network: SSRF guard + allowlist"]
            creds["Credentials: injected per-URL"]
            limits["Limits: timeout, output, fds"]
        end
        engine["Shell engine: parser, 25 builtins, 33 commands, Lua 5.4"]
    end

Written in Rust, with native bindings for Python (PyO3) and Node.js (napi-rs). State persists across run()

calls (env vars, working directory, functions). The filesystem is shared.

shell = strands_shell.Shell(
    binds=[
        strands_shell.Bind("/host/project", "/workspace", mode="copy"),
        strands_shell.Bind("/tmp/output", "/output", mode="direct"),
    ],
    credentials=[
        strands_shell.Cred("https://api.example.com/", env_var="API_TOKEN"),
    ],
    allowed_urls=["https://api.example.com/", "https://pypi.org/"],
    timeout=30.0,
    env={"PROJECT": "demo"},
    limits=strands_shell.Limits(
        max_output=1 << 20,
        max_file_size=10 << 20,
    ),
)

⚠️ The agent can read and modify host files in real time. Use only for designated output directories. Never direct-bind directories containing secrets, credentials, or configuration you don't want the agent to modify.mode: "direct"

mounts are live.

You can load all of this from a config file instead:

[[bind]]
mode = "copy"
source = "/host/project"
destination = "/workspace"

[[cred]]
url = "https://api.openai.com/v1/"
methods = ["POST"]
kind = "bearer"
api_key_env = "OPENAI_API_KEY"

[[mcp]]
name = "my-tools"
command = "/path/to/mcp-server"
args = ["--stdio"]

The built-in MCP server exposes the shell over JSON-RPC on stdio, working with anything that speaks MCP.

uvx strands-shell --mcp                          # bare in-memory sandbox
uvx strands-shell --config sandbox.toml --mcp    # with mounts + credentials

If you declare [[mcp]]

servers in your TOML config, they show up as Lua modules inside the shell. Call require("my_tools")

and you get a table of the server's tools.

Strands Shell is a mediation layer, not a security sandbox.It enforces what the agentshouldaccess via Kernel-mediated deny-by-default. It does NOT protect against: memory-safety exploits in the shell engine itself, timing side-channels, or an attacker who controls the host process. For multi-tenant or adversarial workloads, run each Shell instance inside a container or microVM.

The Kernel mediates everything; it runs in the same process as your code, not in a VM. If your threat model is "untrusted tenant running arbitrary code," put Strands Shell inside a container too. For "my agent shouldn't access things I haven't explicitly allowed," the Kernel handles it.

Default-deny. You allowlist what the agent can reach:

  • Files: only bound paths exist, everything else is hidden.
  • Network: curl

blocks private ranges (RFC1918, link-local, loopback, IMDS) by default while letting public URLs pass through. Useallowed_urls

to permit specific internal hosts. - Secrets: the Kernel injects credentials per-URL at request time, ensuring the agent never holds them. The Kernel never re-injects on redirects, even back to the same host.

  • Syscalls: there are none; no fork

, noexec

because the shell is pure userspace.

If you bypass any of these, report it. See SECURITY.md.

Limits (best-effort): timeouts, output caps, fd limits, inode limits. These catch runaway agents but won't stop someone actively trying to break out. OS-level isolation for that.

Multi-tenant: a Shell instance is single-owner. If you're serving multiple agents, create one Shell per session. Construction is cheap (no containers, no VMs, just an in-memory VFS), so spinning up per-request is the intended pattern.

Out of the box, the shell is an empty sandbox β€” no files, no network, no credentials. When you grant access, follow least privilege:

Prefer Copy-on-create isolates the agent from your live files. Usemode: "copy"

overmode: "direct"

for source code.direct

only for output directories where the agent needs to persist results.Scope binds narrowly. Bind/my/project/src

rather than/my/project

or/

. The agent doesn't need your.git/

,.env

, ornode_modules/

.Allowlist URLs explicitly. Don't useallowed_urls: ["https://"]

β€” this disables SSRF protection entirely. List the specific API endpoints the agent needs.Set timeouts. The default has no per-command timeout. Settimeout

to bound runaway commands (30s is reasonable for most agent loops).Use limits. Setmax_output

to prevent agents from filling memory with unbounded command output (1MB is a good default).

25 builtins, 33 commands, and a Bourne-compatible shell with pipes, loops, functions, and subshells.

The commands agents use constantly: grep

, find

, cat

, head

, tail

, jq

for reading and searching. sed

, sort

, tr

, cut

for transforming output. cp

, mv

, rm

, mkdir

for managing files. curl

for HTTP (SSRF-guarded, credentials auto-injected). lua

for scripting when shell gets awkward.

The full command reference has the inventory with implementation status, supported flags, and known gaps vs GNU coreutils.

Read and write files without going through a shell command:

shell.write_file("/workspace/note.txt", b"hello")
data = shell.read_file("/workspace/note.txt")
entries = shell.list_files("/workspace")
shell.remove_file("/workspace/note.txt")

See CONTRIBUTING.md. Bug reports and design questions are just as useful as PRs.

Discord if you want to talk about it.

Apache-2.0

If you find a security issue, report it privately instead of opening a public issue. Bypasses of filesystem mediation, SSRF protection, or credential injection qualify. See SECURITY.md.

── more in #ai-agents 4 stories Β· sorted by recency
── more on @strands shell 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/strands-shell-give-y…] indexed:0 read:5min 2026-06-17 Β· β€”