Create and manage E2B sandboxes for Dify workflows, with Claude Code and Next.js tooling.
Author: lysonober
Version: 0.0.3
Type: Tool
Better E2B Sandbox creates and manages E2B cloud sandboxes inside Dify workflows. It supports Claude Code integration, Next.js project scaffolding (npm and Bun), stateful interactive shell sessions, common package installation, file operations, template building, and full sandbox lifecycle management with pause, resume, and kill capabilities.
When you create a new workflow in Dify, the Web App and Backend Service API access points are enabled by default. This means anyone with the URL can trigger your workflow, which in turn can create sandboxes, run commands, read files, and consume your E2B and Anthropic API credits.
Before publishing or sharing your workflow, you must:
Without these precautions, a leaked workflow URL allows anyone to create sandboxes under your E2B account, run arbitrary code via Claude Code, and access any credentials (GitHub tokens, Vercel tokens, Anthropic keys) that you configured in the plugin. E2B bills per second for running sandboxes, so unauthorized usage can result in unexpected charges.
This is not a limitation of this plugin. It is a standard Dify workflow security consideration that applies to any plugin that manages external resources.
[Image blocked: Quick Start Workflow Flowchart]
The single most confusing concept in E2B is the sandbox timeout. If you do not understand this, you will waste money or lose work. Here is how it works.
When you create a sandbox, you set a timeout. For example, Create Claude Code Sandbox with gives you a 30-minute sandbox. This means the sandbox will automatically shut down 30 minutes after creation, regardless of what is running inside it.
Here is the critical part: every time you call Sandbox.connect(), the timeout resets. Every tool in this plugin that talks to an existing sandbox (Send Sandbox Input, Install Packages, Read Sandbox File, Write Sandbox File, Start Shell Session, Pause Sandbox, and so on) internally calls Sandbox.connect(). That connect call resets the sandbox timeout to whatever value the tool passes.
You create a Claude Code sandbox with (24 hours). The sandbox starts with a 24-hour clock. You store the sandbox_id. Five minutes later, you call Send Sandbox Input with the default (30 minutes). At that moment, the 24-hour clock is thrown away and replaced with a 30-minute clock. The sandbox will now die 30 minutes after that Send Sandbox Input call, not 24 hours after creation.
What you should do: If you need a long-lived sandbox, make sure every subsequent tool call also uses a long timeout. If you created a 24-hour sandbox, set (or use ) on every Send Sandbox Input call too. Or better yet, use Pause Sandbox between interactions, which preserves state indefinitely (up to 30 days) without consuming compute.
You have a sandbox running a background task. The user has not sent a message in 25 minutes, and the 30-minute timeout is about to expire. You call Send Sandbox Input with . This action does not run any command. It just connects with (1 hour), which resets the sandbox clock to 1 hour from now. The background task keeps running.
You want Claude Code to monitor an API endpoint every 5 minutes for the next 6 hours. You call Setup Sandbox Heartbeat with , , , and (6 hours). The tool sends a specialized prompt to Claude Code that tells it to create a background script with . Claude Code creates the script and starts it. The sandbox stays alive for 6 hours because of the timeout you set.
But what if your E2B plan only allows 1-hour sandboxes? Then you need a different approach: set the sandbox timeout to 1 hour, and have your Dify workflow call Send Sandbox Input with every 50 minutes. Each call resets the clock. The background task survives because the sandbox never expires.
This plugin provides 18 tools. Here is what each one does, when to use it, and how its parameters work.
The most basic creation tool. It starts a new sandbox from a template alias (or the default base template if you leave template_alias empty).
Parameters that matter:
Story: Creating a sandbox to analyze a private repository
You want Claude Code to review code in a private GitHub repo. You call Create Sandbox with , , , . The sandbox starts with GITHUB_TOKEN and GITHUB_USER injected. You then call Send Sandbox Input with , . The clone succeeds because the token is in the environment.
Creates a sandbox specifically optimized for Claude Code. This is the tool you should use when your primary goal is to run Claude Code prompts.
What it does that Create Sandbox does not:
Permissions presets:
Story: Setting up a Claude Code sandbox with project context
You are building a Dify bot for a law firm. Each lawyer has domain expertise that should persist across conversations. You call Create Claude Code Sandbox with:
The sandbox starts with Claude Code configured to bypass all permission prompts, the lawyer's expertise written to ~/.claude/CLAUDE.md, and project conventions written to CLAUDE.md in the working directory. Every Claude Code prompt in this sandbox will see both memory files.
Creates a sandbox with a fresh Next.js project scaffolded using the latest . This tool does not rely on any pre-built Next.js template. Instead, it always starts from the base template and runs the scaffolding commands at creation time, guaranteeing you get the latest Next.js and shadcn versions.
What happens step by step:
Important: This tool requires (it is the default). Without internet, npx cannot download packages.
Story: Creating a Next.js sandbox and then adding Claude Code
You want users to be able to create a Next.js project and then use Claude Code to modify it. Your Dify workflow does:
The user sees the dev server URL from step 1, and after step 3, the Next.js project has a dark mode toggle.
Same as Create Next.js Sandbox, but uses Bun instead of npm. The tool first installs Bun (), then uses and . The port readiness timeout is 90 seconds (longer than npm because Bun installation adds time). Dev server log goes to /tmp/nextjs-bun-dev.log.
The primary interaction tool. Once you have a sandbox_id, this is how you talk to it.
Actions:
What happens when Claude Code CLI is missing:
If you select on a sandbox that does not have Claude Code installed (for example, a sandbox created with Create Sandbox or Create Next.js Sandbox), the tool detects "command not found" in the error output and returns a clear message telling you to run Install Packages with the Claude Code Latest preset first. It does not crash.
What happens when Claude Code CLI is outdated:
If Claude Code CLI refuses to run because it needs an update (error message contains "needs an update" and "claude update"), the tool automatically runs the update sequence (same as Create Claude Code Sandbox) and retries the original command. This only triggers when the CLI explicitly refuses, not on every call.
Story: Multi-turn conversation with Claude Code
Turn 1: User says "Create a Python web scraper for Hacker News". Your workflow calls Create Claude Code Sandbox, stores sandbox_id, then calls Send Sandbox Input with , , . Claude Code creates the scraper. Workflow returns the output and pauses the sandbox.
Turn 2: User says "Add error handling and retry logic". Your workflow calls Send Sandbox Input with the same sandbox_id, , , . Claude Code remembers the scraper it created and modifies it. Because resume_session is true, it has full context from turn 1.
Turn 3: User says "Run it and show me the output". Your workflow calls Send Sandbox Input with , . The shell command runs the scraper and returns the JSON output.
Installs tools and packages in an existing sandbox. This is the general-purpose "add stuff to a sandbox" tool.
How to use:
Preset commands and what they actually run:
Presets execute first, then custom commands, in order. Each command runs sequentially as the user "user" (not root).
Story: Installing multiple tools at once
You created a base sandbox and want to set up a full development environment. You call Install Packages with:
This runs four commands in order: (1) npm install Claude Code, (2) npm install pnpm, (3) pip install requests and beautifulsoup4, (4) apt-get install jq. The output tells you which succeeded and which failed.
These three tools work together to provide stateful interactive shell sessions. They solve the problem that (used by Send Sandbox Input with action=shell_command) starts a fresh shell every time, so cd, exported variables, and shell history do not persist.
Start Shell Session:
Send Shell Session Input:
Kill Shell Session:
Story: Using a stateful shell to navigate and build a project
Step 1: Start Shell Session with , . Returns .
Step 2: Send Shell Session Input with , . Output shows the directory listing.
Step 3: Send Shell Session Input with , . Output shows the prompt changed to my-project directory.
Step 4: Send Shell Session Input with , , . The shell remembers you are in my-project because the PTY session is stateful.
Step 5: Send Shell Session Input with , , .
Step 6: Kill Shell Session with .
Notice how steps 3 through 5 all happen in the same shell. If you had used Send Sandbox Input with action=shell_command, each call would start in /home/user and you would have to prepend to every command.
A specialized Claude Code tool for creating periodic background tasks. It prepends a detailed system prompt to your task description that teaches Claude Code how to write a background loop script.
When to use: When you want something to happen repeatedly inside the sandbox over a long period. Examples: health checks, data polling, log rotation, periodic API calls.
Parameters:
Story: Monitoring a deployment
You just deployed a web app from a sandbox. You want to monitor it for the next 2 hours. You call Setup Sandbox Heartbeat with:
Claude Code creates a script like:
It runs it with and reports the PID. Two hours later, the sandbox expires. If you need to check the alerts before that, call Read Sandbox File with .
A security tool that blocks or redacts known secret values from output text before it reaches end users.
How it works:
Story: Preventing API key leakage in a chatbot
Your Dify workflow runs Claude Code and returns the output to users. Claude Code might accidentally print environment variables (for example, if the user asks "show me all environment variables" and Claude runs ). Without Guard Output, the ANTHROPIC_API_KEY would be sent to the user.
Your workflow: Send Sandbox Input (claude_code) -> Guard Output (text = output from previous step, mode = redact) -> Reply node. If Claude Code's output contains the API key, it gets replaced with [REDACTED] before reaching the user.
Reads a file or lists a directory from the sandbox filesystem.
For files: Returns the file content directly.
For directories: Lists all entries (files, directories, symlinks) in a tree format, then reads file contents in parallel using up to 50 concurrent threads. You can control how many files to read with (0 = tree only, -1 = read all, positive number = limit). Hidden files (starting with .) are excluded by default unless .
Story: Reviewing what Claude Code created
After running Claude Code to create a project, you call Read Sandbox File with . The tool returns:
To read the src directory, make another call with .
Writes content to a file in the sandbox. Parent directories are created automatically.
Story: Injecting a configuration file before running Claude Code
You want Claude Code to work with a specific .env file. You call Write Sandbox File with , . Then you call Send Sandbox Input with , .
Freezes a sandbox in place. The sandbox stops consuming compute resources, but its entire state (filesystem, memory, running processes) is preserved for up to 30 days.
Technical detail: Pausing takes approximately 4 seconds per 1 GiB of RAM.
When to use: Between user interactions in a multi-turn conversation. Pause after each response, resume (by calling any tool with the sandbox_id) when the user sends the next message.
Story: Cost-efficient multi-turn conversation
Your chatbot creates a sandbox for each user conversation. A user sends a message at 10:00 AM, you create a sandbox and run Claude Code. The response takes 30 seconds. Without pausing, the sandbox runs (and costs money) until the 30-minute timeout. With pausing, you pause immediately after getting the response. The sandbox costs 30 seconds of compute instead of 30 minutes. When the user replies at 10:15 AM, any tool call with that sandbox_id automatically resumes it.
Lists all sandboxes (running and paused) in your E2B account with optional filtering.
Filters:
Story: Cleaning up forgotten sandboxes
You notice your E2B bill is higher than expected. You call List Sandboxes with and see 15 running sandboxes. Most of them have and values. You identify 10 sandboxes from yesterday's testing that were never killed. You call Kill Sandbox for each one.
Permanently destroys a sandbox. All files, Claude Code conversation history, and running processes are gone. There is no undo.
When to use: When a conversation ends and you are certain you will not need the sandbox again.
Creates a reusable E2B template with pre-installed dependencies and repositories. The build runs on E2B's infrastructure, not on your Dify server.
Base strategies:
What you can pre-install:
Story: Building a template for a specific project
Your team works on a Python ML project. Every sandbox needs numpy, pandas, scikit-learn, and the project repo. You call Build Template with:
The build takes a few minutes. After that, every Create Sandbox with starts with everything pre-installed. No waiting for pip install or git clone.
Lists all templates in your E2B account with their aliases, build status, CPU, memory, and visibility settings.
All creation tools support environment variable injection with a clear three-layer priority system:
For example, if your provider credential has , your envs_json has , and your tool parameter has , the sandbox gets .
The parameter controls when variables are injected:
Vercel variables deserve special mention: when you set Vercel Team ID (via or provider credential), the plugin injects both and with the same value, because different Vercel tools expect different variable names.
Create Claude Code Sandbox writes inside the sandbox. This file controls what Claude Code is allowed to do.
You can append custom rules via , , and parameters. Format: semicolon-separated rules like or JSON array like .
Mistake: Using shell_command action for multi-step operations
Each call starts a fresh shell. If you call followed by , the second call runs in /home/user (the default), not in /home/user/project.
Fix: Either combine commands with (e.g., ), or use Start Shell Session for a stateful session.
Mistake: Forgetting that connect resets the timeout
As explained above, every tool call resets the sandbox timeout. If you create a sandbox with a 2-hour timeout but all your Send Sandbox Input calls use the default 30-minute timeout, the sandbox will die 30 minutes after the last interaction, not 2 hours after creation.
Fix: Set consistent timeouts across all tool calls, or use Pause Sandbox between interactions.
Mistake: Using claude_code action on a non-Claude-Code sandbox
If you create a sandbox with Create Sandbox or Create Next.js Sandbox, Claude Code CLI is not installed. Calling Send Sandbox Input with will fail.
Fix: Either use Create Claude Code Sandbox, or call Install Packages with before using the claude_code action.
Mistake: Not using Guard Output before replying to users
Claude Code might accidentally output API keys or tokens. If your workflow sends Claude Code output directly to a Reply node, those secrets reach the end user.
Fix: Always place Guard Output between Send Sandbox Input and the Reply node.
User Message -> Create Claude Code Sandbox -> Send Sandbox Input (claude_code) -> Guard Output -> Reply -> Kill Sandbox
First turn: User Message -> Create Claude Code Sandbox -> Store sandbox_id -> Send Sandbox Input (claude_code) -> Guard Output -> Reply -> Pause Sandbox
Subsequent turns: User Message -> Send Sandbox Input (claude_code, same sandbox_id, resume_session=true) -> Guard Output -> Reply -> Pause Sandbox
Final turn (detected by Dify logic): ... -> Reply -> Kill Sandbox
Create Next.js Sandbox -> Store sandbox_id -> Install Packages (claude_code_latest) -> Send Sandbox Input (claude_code, "modify the project...") -> Guard Output -> Reply
One-time setup: Build Template (with git repo, packages) -> Store template alias
Every conversation: Create Sandbox (template_alias=your-template) -> Send Sandbox Input -> ...
E2B bills per second for running sandboxes. Paused sandboxes preserve state without running compute costs.
Practical guidance: Use Pause Sandbox between interactions to stop paying for idle compute. A 30-minute running sandbox with 2 vCPU and 512 MiB RAM costs about $0.05 for the compute plus $0.004 for memory. Pausing reduces that to near zero between interactions.
Email: [email protected]