CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Cowork
Cowork/2026-05-23Intermediate

When pip install Stops with externally-managed-environment in Cowork's Bash Sandbox — Three Patterns for PEP 668

Why pip install fails with externally-managed-environment in Cowork's Bash sandbox, and three practical fixes — --break-system-packages, venv, and pipx — written from real scheduled-task experience.

Cowork33pipPython17PEP 668troubleshooting87Bash4sandbox7

I first wanted to call a small Python tool from a Cowork scheduled task around the time I was wiring quality gates into my four-site article pipeline. Just a quick pandas aggregation. Should have been one line.

$ pip install pandas
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

Run pip in an Ubuntu 22.04-based sandbox and you hit this. It is not about sudo, networking, or a PyPI outage. PEP 668 (Externally Managed Environments), adopted widely from Python 3.11 onward, is intentionally refusing the install to keep the system-wide Python from being broken.

I'm Masaki Hirokawa, an indie iOS/Android developer and artist who has been shipping apps since 2014 (50M+ cumulative downloads). I run daily article-publishing pipelines on four sites via Cowork scheduled tasks, and small Python utilities show up in those pipelines often. Here is the diagnosis flow and the three fix patterns I use, drawn from running into this exact error more than once.


Why PEP 668 rejects pip

Linux distributions like Ubuntu and Debian rely on Python for parts of the OS itself. apt has Python-based components; sandboxes like Cowork's also have toolchains (Node, ripgrep, others) that depend on the system Python.

If you overwrite a globally installed package with pip install, the version the OS expected silently shifts, and other tools may stop working. PEP 668 prevents that by letting the distributor drop a marker file — EXTERNALLY-MANAGED — that tells pip "do not touch this Python."

You can confirm the marker in one line.

ls /usr/lib/python3.*/EXTERNALLY-MANAGED 2>/dev/null && echo "PEP 668 environment"

In a Cowork sandbox, /usr/lib/python3.10/EXTERNALLY-MANAGED is there. The error is correct behaviour, not a bug.


Pattern 1: --break-system-packages to make your intent explicit

The smallest-effort option. Tell pip "I know this might break things, install anyway."

pip install pandas --break-system-packages

For one-line scheduled-task work, or when you only need one or two packages for a quick aggregation, this is usually enough. Cowork's system Python is largely disposable per VM, so even if you break it, the next session rebuilds the environment.

Two caveats. First, even when pip install succeeds, it may conflict with a same-name package shipped by the distribution. Always confirm where the install landed.

pip show pandas | grep Location
# Location: /usr/local/lib/python3.10/dist-packages

If it shows /usr/local/lib/.../dist-packages, you have not overwritten the distribution's /usr/lib/python3/dist-packages. Python's import precedence favours /usr/local, so the newer copy is loaded.

Second, do not use this flag in clean CI environments. The venv approach below is more reproducible and easier to track for dependencies.


Pattern 2: Isolate with venv (recommended)

Slightly more steps, but the most honest option if you actually use Python in scheduled tasks on a regular basis.

python3 -m venv /tmp/venv
source /tmp/venv/bin/activate
pip install pandas requests
python my_script.py

PEP 668's marker has no effect inside a venv, so neither --break-system-packages nor sudo is needed. Delete /tmp/venv when you're done and cleanup is trivial.

When using this in Cowork scheduled tasks, remember that each bash invocation is a fresh shell — env vars from one call do not survive to the next. Keep the source and the script execution inside a single bash call, or invoke /tmp/venv/bin/python by its full path.

# All in one bash invocation
python3 -m venv /tmp/venv && \
  /tmp/venv/bin/pip install -q pandas requests && \
  /tmp/venv/bin/python /sessions/*/mnt/work/script.py

When called this way from a SKILL.md scheduled task, you get a clean environment every run even across sandbox restarts. This is the shape I eventually settled on for stabilising the article-publishing pipeline.


Pattern 3: pipx for isolated CLI installs

For single CLI tools like black or ruff, pipx is the cleaner fit. It builds a venv for each tool automatically and only exposes the CLI's symlink on your PATH.

pip install pipx --break-system-packages
pipx install ruff
ruff --version

Pipx itself still needs --break-system-packages to bootstrap — a one-time compromise to put pipx into the system. After that, every pipx install lives inside its own clean venv.

If you want five to ten CLI tools rather than libraries, pipx keeps the environment tidier than running pip install --break-system-packages over and over.


Choosing a pattern

  • One-shot aggregation or experiment → --break-system-packages
  • Recurring use in scheduled tasks → python3 -m venv /tmp/venv
  • Multiple CLI tools → pipx install
  • Strict dependency resolution → venv (or uv)

For new projects I have been reaching for uv lately. It keeps a pip-compatible interface but creates venvs and installs packages dramatically faster. In a Cowork sandbox that rebuilds environments every run, raw startup speed translates directly into shorter task runtimes.

pip install uv --break-system-packages
uv venv /tmp/venv
uv pip install -p /tmp/venv/bin/python pandas

The need to bootstrap uv itself with --break-system-packages is the same situation as pipx.


Common gotchas

--user does not save you: pip install --user pandas looks like a clean escape into $HOME/.local, but PEP 668 blocks user installs too. You still need --break-system-packages.

sudo pip install is the worst option: It feels intuitive to try sudo when blocked, but PEP 668's protection is designed with root in mind first. The combination most likely to overwrite apt-managed packages is sudo --break-system-packages. Avoid it outside disposable VMs like Cowork.

venv built but packages invisible: You probably ran source in a separate bash call. Cowork's bash calls are independent, so source does not persist. Keep it in one call, or call python3 by full path.

pip install --upgrade pip rejected before requirements.txt: Upgrading pip itself is also blocked by PEP 668. Get into the venv first, then upgrade freely.


What to do next

When you hit this error, first confirm it really is PEP 668 by checking for the marker file: ls /usr/lib/python3.*/EXTERNALLY-MANAGED. The wording may look similar to other errors. Once confirmed, pick exactly one pattern from the list above that matches your use case. Reaching for "venv for everything" by default tends to be overkill for one-shot experiments.

I leaned heavily on --break-system-packages at first, but as scheduled tasks accumulated, venv became the calmer choice for daily operations. I hope this helps if you hit the same wall.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Cowork2026-06-23
Stopping an Unattended Writer From Publishing the Same Article Twice
When a Cowork scheduled task generates articles every day, the real danger isn't a crash — it's quietly publishing a piece that overlaps with one from a few days ago. Here is a gate that compares slug similarity and the day's log before publishing, built from a near-miss I caught this morning.
Cowork2026-05-15
git clone Fails in Cowork Scheduled Tasks — Diagnosing /tmp Permission Errors and Disk Space Issues
When git clone fails with Permission denied or No space left on device in Cowork automated tasks, the root cause is often /tmp directory ownership or disk exhaustion. Learn how to diagnose both and apply a $HOME fallback pattern for reliable automation.
Cowork2026-05-06
Claude in Chrome Not Working? A Practical Troubleshooting Guide
Buttons that do nothing, pages that never load, tasks that report success but change nothing. Symptom-by-symptom fixes, plus the 42-run log where adding waits and verification steps moved completion from 62% to 95%.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →