{"slug": "ephemeral-runtime-harness-for-agentic-workflows-open-source", "title": "Ephemeral runtime harness for agentic workflows open source", "summary": "Drun, an open-source platform for virtualizing host components into ephemeral runtimes for agentic workflows, has been released. It provides a sandboxed workspace with guardrails for network, command execution, filesystem access, and resource limits, and integrates with Claude Code, Ollama, and LiteLLM. The platform aims to enable safe parallel exploration of agent trajectories without disrupting the host state.", "body_md": "Drun is a platform that allows you to virtualize components of your host into an ephemeral runtime to serve as the agent's workspace with git-like primitives which allow the agent to explore trajectories in parallel and discard dead-ends without disrupting the host state.\n\nDrun surfaces a runtime abstraction layer with reliability harnesses to guardrail the agent's behavior across a range of OS-level aspects:\n\n- Network domains (e.g. allowlisted domains)\n- Command execution (e.g. forbidden commands)\n- Access to filesystem paths (e.g. restrict filesystem access)\n- Resource limits (e.g. memory and duration caps)\n\nRather than granting your agent raw access to your host, Drun exposes and enforces a highly-customizable policy layer with deterministic knobs for you to place absolute limits that can't be breached by design.\n\nThe drun framework can be consumed in the following ways:\n\n: drun's MCP tools replace Claude's native file/shell/network tools inside a sandboxed workspace.[Via Claude Code](#claude-code): a CLI agentic loop that's integrated with[Standalone CLI](#standalone-cli)[Ollama](https://ollama.com/)and[LiteLLM](https://docs.litellm.ai/).: script sandboxed sessions directly, no LLM or daemon required.[Using the Python SDK](#python-sdk)\n\nNOTE: There are plans in the future to support additional model providers like Codex and Gemini CLI. Consider this document as the official reference of production-ready offerings.\n\nAll journeys except for the [Python SDK](#using-the-python-sdk) require the\n`drun-mcp`\n\ndaemon installed and running in the host machine to operate. This is\ndone once with:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/dmosc/drun/main/install.sh | bash\n```\n\nThis installs and configures a few things (skips if not applicable):\n\n- The\n`drun-mcp`\n\nbinary under`/usr/local/bin/drun-mcp`\n\n. - A global config at\n`~/.drun/config.toml`\n\nwith sensible defaults. `drun-mcp`\n\nas a persistent background daemon (`launchd`\n\non macOS,`systemd`\n\non Linux) so a single process serves all simultaneous sessions running on the host.- The MCP registration in Claude Code pointing at the running daemon over SSE\n(\n`http://127.0.0.1:7273/sse`\n\n).\n\nOnce installed, the following endpoints are available:\n\n| Endpoint | Purpose |\n|---|---|\n`http://127.0.0.1:7273/sse` |\nMCP transport (SSE); used by Claude Code |\n`http://127.0.0.1:7273/mcp` |\nMCP transport (streamable HTTP); used by the CLI |\n`http://127.0.0.1:7274` |\nWeb interface to manage sessions |\n\nRun the following commands to upgrade drun's MCP to the latest release:\n\nThe upgrade operation hard-reloads the daemon process, effectively dropping all in-memory objects, including ongoing sessions. Be sure to snapshot and close your sessions before updating.\n\n```\n# MCP binary\ncurl -fsSL https://raw.githubusercontent.com/dmosc/drun/main/update.sh | bash\n\n# Update to a specific version\ncurl -fsSL https://raw.githubusercontent.com/dmosc/drun/main/update.sh | bash -s -- v0.3.8\n```\n\nRun the following command to uninstall drun from your host:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/dmosc/drun/main/uninstall.sh | bash\n```\n\n- Stops the background daemon and removes the\n`launchd`\n\nagent (macOS) or`systemd`\n\nuser service (Linux). - Removes the drun MCP binary from\n`/usr/local/bin/drun-mcp`\n\n. - Unlinks the MCP reference from Claude Code.\n- Removes\n`.claude/settings.json`\n\nfrom each project so native Claude tools are restored automatically. - Leaves\n`~/.drun/config.toml`\n\nand any`CLAUDE.md`\n\nfiles untouched; delete these manually if not needed.\n\n[Claude Code](https://code.claude.com/docs/en/quickstart#step-1-install-claude-code).- The\n`drun-mcp`\n\ndaemon[installed](#global-install-once-per-machine)above.\n\nFrom the root of any project you want drun to manage:\n\n```\ndrun-mcp init\n```\n\nCreates two files in the current directory (appends if they already exist):\n\n`.claude/settings.json`\n\n— restricts Claude to drun tools only for this workspace. Native file (`Read`\n\n,`Edit`\n\n,`Write`\n\n,`NotebookEdit`\n\n,`Glob`\n\n,`Grep`\n\n), shell (`Bash`\n\n,`BashOutput`\n\n,`KillBash`\n\n), network (`WebFetch`\n\n,`WebSearch`\n\n), and subagent delegation (`Task`\n\n) tools are all blocked, and drun's MCP tools are pre-allowed so Claude isn't prompted on every call.`CLAUDE.md`\n\n— tells Claude to use drun tools instead of native ones and how to bootstrap a session (`create_session`\n\nthen`session_mount`\n\n).\n\nThis restriction is intentionally per-project; you wouldn't want native tools\nblocked globally across every workspace. Run `drun-mcp init`\n\nfrom any project\nroot to opt that project into the drun sandbox.\n\nValidate that the MCP is live:\n\n```\nclaude mcp list\n```\n\n`drun chat`\n\ndrives an LLM — local via [Ollama](https://ollama.com) or any cloud\nmodel supported by [LiteLLM](https://docs.litellm.ai/docs/providers) — against a\nsandboxed session.\n\n- Python 3.9+.\n- The\n`drun-mcp`\n\ndaemon[installed](#global-install-once-per-machine)above. [Ollama](https://ollama.com)for local models, or an API key for a cloud model.\n\n```\npip install 'drun-sandbox[chat]'\n```\n\nFor a local model, install Ollama and pull a tool-calling-capable model:\n\n```\nollama pull qwen2.5:14b\n```\n\nThen run:\n\n```\ndrun chat \"your prompt\" --mount ./my-project\n```\n\n`--model`\n\ndefaults to `ollama_chat/qwen2.5:14b`\n\n. To use a cloud model instead,\npass `--model`\n\nand set the provider's API key:\n\n```\nANTHROPIC_API_KEY=... drun chat \"your prompt\" --model claude-sonnet-4-6\n```\n\nEach `drun chat`\n\ncall creates a new session by default. Pass `--session-id`\n\nto\nattach to one that's already running instead:\n\n```\ndrun chat \"keep going on the report in results.md\" --session-id <id>\n```\n\nRun `drun chat --help`\n\nfor all flags.\n\nUseful to spin up drun sessions programatically.\n\n- Python 3.9+.\n\n```\npip install drun-sandbox\npython\nfrom drun import Session\n\nsession = Session()\nsession.write_file(\"hello.py\", b\"print('hi')\")\ncheckpoint = session.execute_bash(\"python3 hello.py\")\nprint(checkpoint.stdout)\n```\n\nSee [ examples/quickstart.py](/dmosc/drun/blob/main/examples/quickstart.py) for a fuller walkthrough\n(bash execution, write, diff, rollback, export).\n\nThe behavior of the drun MCP is orchestrated via `~/.drun/config.toml`\n\n, a single\nglobal file shared by the background daemon. It's re-read on every tool call;\nwithout it, built-in defaults apply.\n\nThe following is a reference of all the controls available for tuning. All fields are optional.\n\n| Field | Default | Description |\n|---|---|---|\n`domain_allowlist` |\n`[\"pypi.org\", \"files.pythonhosted.org\", \"cdn.jsdelivr.net\"]` |\nDomains reachable via `session_fetch` . Defaults to the three built-ins if the key is absent; setting it explicitly (including `[]` ) replaces the defaults outright, so an operator can restrict below them. Use `[\"*\"]` to allow all, or `\"*.example.com\"` for subdomains. |\n`fetch_timeout_ms` |\n`60000` |\nTimeout for the full `session_fetch` response in milliseconds. |\n`connect_timeout_ms` |\n`30000` |\nTCP connection timeout for `session_fetch` in milliseconds. |\n`bash_timeout_ms` |\n`30000` |\nMaximum wall time for a single `session_bash` call. |\n`max_workspace_mb` |\n`512` |\nMaximum workspace size per session in megabytes. Checked before each new checkpoint is appended. |\n`max_sessions` |\n`50` |\nMaximum number of concurrent sessions. |\n`max_checkpoints` |\n`200` |\nMaximum checkpoints stored per session. When the limit is reached, squash or drop old checkpoints. |\n`session_idle_timeout_secs` |\n`3600` |\nSeconds of inactivity before a session is considered abandoned and rejected. |\n`mount_allowlist` |\n`[]` |\nHost path prefixes that `session_mount` may read from. Empty means all paths are permitted. Non-empty restricts mounts to the listed prefixes. |\n`mount_overlay_paths` |\n`[\"node_modules\", \".venv\", \"venv\", \"target\", \"__pycache__\", \".git\"]` |\nDirectory names that `session_mount` registers as read-only host overlays instead of loading into the workspace. Overlay dirs are symlinked at execution time and never checkpointed. Set to `[]` to disable. |\n`export_root` |\n`\"drun-export\"` |\nDirectory that `session_export` must write into. Relative paths are resolved from the current working directory. |\n`snapshots_dir` |\n`\"drun-snapshots\"` |\nDirectory where `session_snapshot` writes `.drun` files. |\n`snapshot_on_close` |\n`false` |\nWhen `true` , automatically write a snapshot when `session_close` is called. |\n`env_allowlist` |\n`[]` |\nHost environment variable names exposed to agents via `session_get_env` . Empty means no variables are exposed. |\n`bash_command_denylist` |\n`[]` |\nCommand substrings always rejected by `session_bash` before execution. |\n`bash_command_allowlist` |\n`[]` |\nCommand substrings permitted by `session_bash` . Empty means all commands are allowed (subject to the denylist). |\n`web_port` |\n`7274` |\nTCP port for the trajectory viewer web UI. Set to `0` , or remove the field from the config file, to disable it. |\n\nA couple of utility commands to update the configuration via the `drun-mcp`\n\nCLI\nare available:\n\n```\ndrun-mcp config add-domain example.com\ndrun-mcp config add-path /path/to/allow\ndrun-mcp config remove-domain example.com\ndrun-mcp config remove-path /path/to/allow\n# To validate latest changes to config.\ndrun-mcp config list\n```\n\nRun `drun-mcp config --help`\n\nto print a list of available commands.\n\n`~/.drun/config.toml`\n\nis re-read on every tool call, so edits — via the CLI\nabove or by hand — take effect on the very next call, no restart, no dropped\nsessions. `drun-mcp init`\n\nalso allowlists the current project directory for\n`session_mount`\n\nautomatically.\n\nThe two exceptions are `web_port`\n\nand `session_idle_timeout_secs`\n\n: both are only\napplied at daemon startup, so changing either still requires a restart:\n\n**macOS**\n\n```\nlaunchctl unload ~/Library/LaunchAgents/com.drun.mcp-server.plist\nlaunchctl load -w ~/Library/LaunchAgents/com.drun.mcp-server.plist\n```\n\n**Linux**\n\n```\nsystemctl --user restart drun-mcp.service\n```\n\nA dead or crash-looping daemon can look identical to an idle one from the\noutside. See\n[docs/troubleshooting.md's Health check section](/dmosc/drun/blob/main/docs/troubleshooting.md#health-check--is-drun-actually-running)\nfor commands to confirm it's running exactly once, actually listening, and not\nstuck being killed and retried by launchd/systemd.", "url": "https://wpnews.pro/news/ephemeral-runtime-harness-for-agentic-workflows-open-source", "canonical_source": "https://github.com/dmosc/drun", "published_at": "2026-07-18 05:30:16+00:00", "updated_at": "2026-07-18 05:51:34.522855+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-safety", "ai-infrastructure"], "entities": ["Drun", "Claude Code", "Ollama", "LiteLLM", "Codex", "Gemini CLI"], "alternates": {"html": "https://wpnews.pro/news/ephemeral-runtime-harness-for-agentic-workflows-open-source", "markdown": "https://wpnews.pro/news/ephemeral-runtime-harness-for-agentic-workflows-open-source.md", "text": "https://wpnews.pro/news/ephemeral-runtime-harness-for-agentic-workflows-open-source.txt", "jsonld": "https://wpnews.pro/news/ephemeral-runtime-harness-for-agentic-workflows-open-source.jsonld"}}