{"slug": "opencode-is-powerful-thats-exactly-the-problem", "title": "OpenCode Is Powerful. That’s Exactly the Problem.", "summary": "OpenCode, an open-source coding agent similar to Claude Code, poses a risk because it autonomously runs shell commands, which can inadvertently execute destructive actions like deleting files via symlinks or running malicious postinstall scripts. To mitigate this, Tensorlake offers a plugin that reroutes the agent's shell commands into a disposable cloud sandbox, isolating any damage from the user's local machine.", "body_md": "OpenCode is an open-source coding agent with a workflow similar to Claude Code.\n\nYou type what you want; it reads your codebase, edits files, and runs shell commands on its own. Same basic idea as Claude Code. Free though, open source, and you’re not locked into one model.\n\nWhich is great, until you actually sit with what “runs shell commands on its own” means.\n\n**The first time you hand a terminal agent that kind of access, there’s one question you can’t quite shake:** what happens the moment it runs something you didn’t expect?\n\nMost people pick a folder they don’t care about and hope for the best. Or they don’t think about it at all until something breaks.\n\nI didn’t love either option, so before I let OpenCode near anything that mattered, I went looking for a third one.\n\n**That’s how I ended up moving the agent’s shell into a disposable sandbox from ****Tensorlake****, **that runs these as a cloud service, while leaving everything else right where it was on my laptop.\n\nHere’s what that looked like, and what actually surprised me once I had it running.\n\nA coding agent’s real risk has nothing to do with intelligence. Most of the time it gets things right. What it doesn’t do is pause. It doesn’t stop to double-check whether the command it’s about to fire off is the one you actually meant to approve.\n\n**One scenario kept nagging at me before I typed anything.**\n\nI ask it to clean up build artifacts, and it runs rm -rf ./build. Except ./build turns out to be a symlink into somewhere I still needed, the kind of thing an agent skims right past, and honestly, the kind of thing I don't always catch either when I'm moving fast.\n\nOr I ask it to install a dependency. npm install fires a postinstall script. That script rewrites a config file I never agreed to touch. I've seen postinstall scripts do weirder things than that with a human sitting right there watching.\n\n**Neither one is a bug, to be honest.**\n\nThat’s just what shell access does when nothing stands between a command and your machine.\n\nThen I thought bigger than my own laptop. Same agent, but now it’s refactoring a production monorepo that ten other engineers are actively pushing commits to. Same misread symlink. Same rogue postinstall script. Except now it’s not just my afternoon on the line.\n\nbash, write, edit. These aren't agent-specific features. They're shell and filesystem access, handed to a process making its own calls about what to run next.\n\nThe instinct is to fix this with more caution. Review every diff. Approve every command. That works right up until it doesn’t, because the entire point of an autonomous agent is that you eventually stop reviewing every single step.\n\n**The real fix turned out to be a different blast radius.**\n\nPut the agent’s commands somewhere disposable instead of on my machine, and now a bad command won’t harm my system.\n\nRunning locally isn’t wrong, to be clear. For a throwaway project, or a workflow you already trust, it’s exactly what you want. What changes the math is pointing autonomous shell access at something a mistake would actually cost you.\n\nOne table covers the whole shift. The wiring behind it takes a little longer to explain.\n\n**Local OpenCodeOpenCode + Tensorlake** Commands runOn your laptopRemotely, in a sandboxFilesystemYour actual filesystemIsolated, disposableDependenciesWhatever’s on your machineDisposable environmentA bad command affectsYour machineThe sandbox, not you\n\nThat’s the outcome. The wiring is simpler than it sounds.\n\nTensorlake ships a plugin called [tensorlake-opencode](https://www.npmjs.com/package/tensorlake-opencode). The plugin doesn't replace OpenCode.It intercepts specific tool calls and reroutes them. Once I actually understood that distinction, the idea turned out simpler than I expected.\n\nOpenCode on your laptop, tools in a sandbox, that’s the actual shape of it. The OpenCode harness itself, the interface, your session, all of that keeps running on your machine exactly like before.\n\nThe model call still goes out to whichever provider you’ve configured, Anthropic, OpenAI, whoever, the same as it always did; that part was never local to begin with, and this plugin doesn’t change it.\n\nWhat changed was where each individual tool call landed:\n\nThe model call still goes wherever you configured your provider. Only the tool calls, the hands, move into the sandbox.\n\nwebfetch and websearch are the two exceptions that stay local, since neither touches a filesystem. bash, write, edit, read, ls, glob, and grep are the ones that get rerouted.\n\nEvery intercepted command now makes a network round trip instead of running instantly on my machine.\n\n**Tensorlake’s sandbox starts up in a few seconds, with the underlying VM image itself booting in hundreds of milliseconds.**\n\nTheir GitHub page and product site separately claim resume from a suspended state also lands under a second.\n\nMy own first sandbox, the one the plugin spun up automatically on that uname -a call, took 2.3 seconds end to end, per the timestamp the plugin logged, which fits comfortably inside what the docs describe. That's likely the plugin's own provisioning and connection overhead stacked on top of the raw VM boot, not just the VM starting up.\n\n**Either way, it's not something you sit around waiting on.**\n\nThe whole setup turned out to be one config entry and one environment variable, typed in this order.\n\nFirst, the plugin, added to ~/.config/opencode/opencode.json:\n\n```\n{  \"$schema\": \"https://opencode.ai/config.json\",  \"plugin\": [\"tensorlake-opencode\"]}\n```\n\nOpenCode installs it automatically, no separate npm install needed. Then the API key, exported in the same shell I was about to launch OpenCode from:\n\n```\nexport TENSORLAKE_API_KEY=your_api_key_hereopencode\n```\n\nNothing happened. No sandbox spun up on launch, which threw me for a second. First instinct was that I’d messed up the config somehow, and I almost went back to check the JSON for a typo before actually rereading what I’d just set up: lazy creation, not eager.\n\nTailing ~/.local/share/opencode/log/tensorlake.log just confirmed the plugin had loaded, nothing more, until I actually asked the agent to do something that needed a sandbox.\n\nSandbox creation in this plugin is lazy. It waits for the first tool call that actually needs the filesystem or a shell, not the moment you launch the session.\n\nI didn’t want to point it at anything that mattered yet, so the first command I actually gave it was about as low-stakes as they come:\n\n```\nRun: uname -a\n```\n\nThat single bash call was what triggered everything. A \"Sandbox created\" toast showed up in the terminal, and I had the log tailing in a second window the whole time. It read almost exactly what the docs describe: a line saying a new sandbox was being created for the session, then a second line confirming it was live, at 2.3 seconds.\n\nThe output said Linux. My laptop runs macOS. Not going to lie, that one word convinced me faster than any architecture diagram would have.\n\n**Next I asked it to prove the filesystem side too:**\n\n```\nWrite \"Hello Tensorlake\" to /tmp/workspace/test.txt, then read it back.\n```\n\nThe write and read both happened entirely inside the sandbox, confirming that filesystem operations were isolated from my machine.\n\n/tmp/workspace was the agent's working directory inside the sandbox, not a folder anywhere on my disk. Nothing in either test would have cost me anything if it had gone wrong.\n\nWith the sandbox working, I wanted to move beyond smoke tests and verify the full developer workflow on a real repository.\n\n```\nClone https://github.com/benjaminp/six.git, find the ensure_str function, improve its TypeError message so it names the function it came from, then run the test suite and tell me if anything broke.\n```\n\nThis was intentionally a tiny change — the goal wasn’t to contribute a feature, but to verify that OpenCode could complete the same edit–test loop I’d expect during normal development.\n\nsix is a small, well-known Python compatibility library: one source file, a straightforward test suite, and just enough structure to exercise a realistic edit–test workflow.\n\nOpenCode cloned the repository, located ensure_str, modified the function, and ran the test suite entirely inside the sandbox.\n\nThe original implementation raised TypeError(\"not expecting type '%s'\" % type(s)).\n\nThe edit made it TypeError(\"ensure_str: not expecting type '%s'\" % type(s))—a deliberately small edit that was easy to verify with the existing test suite. Because the tests only verify that a TypeError is raised rather than checking the exact message text, this made for a safe, minimal edit, and the run confirmed it: 184 passed, 16 skipped, 0 failed.\n\nSame as before the change.\n\nThat’s the part that mattered to me. Not the specific repo or the specific one-line fix, but that a clone, a real edit, and a full test run all happened inside the sandbox, on an actual project, without me once worrying about what would happen to my own machine if something in that chain went sideways.\n\nI expected the isolation. The other two took me by surprise.\n\n**Isolation.** A bad command genuinely has nowhere real to land. A runaway install, an rm aimed at the wrong path, a dependency that half-installs and leaves things broken. All of it happens in a sandbox I can throw away, not my actual working tree.\n\n**Reproducibility** mattered more once I pictured someone else on the team running this same setup. Whatever’s actually installed on my laptop stops being relevant, because the agent isn’t running on my laptop anymore. Register one image with the right toolchain baked in, point every future session at it, and the “works on my machine” conversation just stops happening.\n\nThen there’s **persistence**, the one I hadn’t planned for. A named sandbox doesn’t vanish when OpenCode restarts. It just sits there, parked. Come back later and the same working directory, the same installed packages, the same warm caches are all still exactly where I left them. Nothing rebuilt, nothing reinstalled.\n\nA disposable CI container vanishes the second a run finishes. This one was still there the next day, same as I’d left it.\n\nTook me an hour of lost installed state before that actually registered.\n\nOnce I trusted it with something more than a test file, I went back and actually sized it properly. The plugin reads a small set of environment variables once, at the moment the first sandbox gets created, so they need to be set before you launch OpenCode, not after:\n\n```\nexport TENSORLAKE_CPUS=4export TENSORLAKE_MEMORY_MB=8192export TENSORLAKE_DISK_MB=20480export TENSORLAKE_IMAGE=my-custom-image\n```\n\n**VariableDefaultControls** TENSORLAKE_CPUS2vCPUsTENSORLAKE_MEMORY_MB4096RAM in MBTENSORLAKE_DISK_MB10240Disk in MBTENSORLAKE_IMAGEplatform defaultThe image the sandbox boots from\n\nIf you’re using a Personal Access Token instead of a project-scoped key, you’ll also need TENSORLAKE_ORGANIZATION_ID and TENSORLAKE_PROJECT_ID.\n\nTENSORLAKE_IMAGE is the one actually worth using. Bake your language runtime, system packages, and project dependencies into a registered image once:\n\n```\ntl sbx image create Dockerfile --registered-name my-custom-imageexport TENSORLAKE_IMAGE=my-custom-image\n```\n\nEvery session after that starts already warm. I stopped watching the agent reinstall my stack from scratch every time I opened a new session.\n\n*Note: **export only lasts for the current shell, so I added these to my shell profile once I knew I'd be using this setup regularly.*\n\nBefore trusting this with anything real, I wanted answers to a few things that don’t come up in a quick demo. Worth being upfront about one thing here: most of what follows is documented at the Tensorlake SDK and platform level. I haven’t confirmed that the OpenCode plugin specifically exposes or manages each of these the same way, only that the underlying sandboxes it creates support them. Where that distinction matters, I’ve called it out below.\n\n**What if I just walk away mid-session?** Named sandboxes auto-suspend after their idle timeout rather than terminating, at the platform level. Tensorlake’s product site says the meter stops the moment it suspends, and their GitHub page puts resume at under a second, with filesystem, memory, and running processes exactly where you left them, not rebuilt. I haven’t independently timed a resume myself, and I haven’t confirmed whether the OpenCode plugin surfaces any control over this behavior or just inherits the platform default, so take the specific number as Tensorlake’s claim about the platform, not a tested claim about this plugin.\n\n**What if the agent kicks off something long-running, like a build or a test suite?** The underlying Tensorlake SDK supports starting background processes inside a sandbox that outlive the single command that launched them. I haven’t tested whether the OpenCode plugin’s bash interception uses this pattern specifically, or whether a long-running command inside OpenCode just holds the tool call open for the duration. Either way, the sandbox itself isn't the bottleneck.\n\n**What if my connection drops mid-command?** Tensorlake has written publicly about this exact failure mode at the platform level: when the transport hiccups mid-run, they retry and reap orphaned sandboxes so a flaky connection doesn’t cost you the whole task. Again, this is a platform-level guarantee. I haven’t tested how the plugin itself behaves if your local connection drops mid-tool-call.\n\n**What if the sandbox itself crashes outright, not just an idle timeout?** Here’s where I’ll be straight with you: I didn’t find documentation covering a hard crash mid-command specifically, at either the platform or plugin level, and I didn’t manage to force one during testing either. If you’re planning to run this against something you really can’t afford to lose, that’s worth confirming directly with Tensorlake rather than taking my word for it.\n\nBy the end I had a rough rule for myself. Picture a coding agent refactoring a production monorepo while another engineer is pushing commits at the same time. The question was never whether the model was smart enough. It was whether I wanted its shell commands landing on my own workstation.\n\nThis isn’t the right setup for every OpenCode session, and I don’t pretend otherwise:\n\n**My situationWhat I’d do** Personal throwaway projectRun locallyClient repositoryUse TensorlakeProduction codebaseUse TensorlakeLetting the agent experiment freely with shell commandsUse TensorlakeShared engineering environmentUse Tensorlake\n\nThe sandbox earns its place anywhere the blast radius of a wrong command actually matters. If I’m the only person who’ll ever touch the repo and I’d shrug off losing it, I’m solving a problem I don’t have yet.\n\nWorth a quick word on why this isn’t just Docker or a Codespace with extra steps. A Docker container shares your host’s kernel, which is fine for packaging an app but a thinner isolation boundary than a full VM if you’re worried about what an autonomous agent might run.\n\nA local VM gives you the stronger boundary but is heavy and slow to spin up and tear down for something you might want to throw away every few minutes. GitHub Codespaces and Dev Containers solve a different problem: a consistent, persistent dev environment tied to a specific repo, not a fast, disposable environment built to be created and discarded on every session.\n\nThe MicroVM approach here is closer to a VM’s isolation with something closer to a container’s boot speed, and it’s built specifically to be thrown away.\n\nHere’s the order I’d do it in, knowing what I know now.\n\n**Step 1:** Install OpenCode, add tensorlake-opencode to opencode.json. This just gets the plugin loaded, nothing else happens yet.\n\n**Step 2:** Export TENSORLAKE_API_KEY, launch OpenCode, confirm the plugin loaded via the log file. This is the \"is it actually on\" check.\n\n**Step 3:** Ask it to run something trivial, like uname -a. This is what triggers sandbox creation and gives you visible proof the command ran remotely.\n\n**Step 4:** Set TENSORLAKE_CPUS, TENSORLAKE_MEMORY_MB, and TENSORLAKE_DISK_MB to match your real workload, before your next session starts, not mid-session.\n\n**Later:** Build a custom image with your actual toolchain baked in, once the default image starts feeling like it’s missing things you keep reinstalling.\n\nI went looking for a third option: an agent with full autonomy, running somewhere that wasn’t my laptop. Got that part working fast. What actually surprised me was how little I had to think about afterward.\n\n**I stopped reading every command before approving it once this was running.**\n\nWasn’t carelessness. Just nothing left on my machine for a bad command to reach.\n\nTurns out the part that mattered was never whether the agent could run commands. It was where they landed. Not stopping mistakes. Just making sure they happen somewhere disposable instead of somewhere that costs me.\n\nIf you’ve started letting an autonomous coding agent anywhere near your shell, moving that shell execution into a disposable sandbox is one of the highest-leverage changes you can make, and Tensorlake’s own numbers put the setup at a few minutes, not an afternoon. The config entry and the environment variable up above are the whole thing.\n\n[OpenCode Is Powerful. That’s Exactly the Problem.](https://pub.towardsai.net/opencode-is-powerful-thats-exactly-the-problem-06eebf266279) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/opencode-is-powerful-thats-exactly-the-problem", "canonical_source": "https://pub.towardsai.net/opencode-is-powerful-thats-exactly-the-problem-06eebf266279?source=rss----98111c9905da---4", "published_at": "2026-07-21 03:45:53+00:00", "updated_at": "2026-07-21 04:29:20.409085+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "ai-safety", "developer-tools"], "entities": ["OpenCode", "Claude Code", "Tensorlake", "tensorlake-opencode"], "alternates": {"html": "https://wpnews.pro/news/opencode-is-powerful-thats-exactly-the-problem", "markdown": "https://wpnews.pro/news/opencode-is-powerful-thats-exactly-the-problem.md", "text": "https://wpnews.pro/news/opencode-is-powerful-thats-exactly-the-problem.txt", "jsonld": "https://wpnews.pro/news/opencode-is-powerful-thats-exactly-the-problem.jsonld"}}