Shadow Environments

Test your exact working tree before you push

The stakes

You can't trust a change until you test it the way production installs it

Before you push, you want to know a change actually works. But your own machine can't answer that honestly — it's polluted with years of state, and it never installs your code the way the outside world will.

And there's a specific, repeatable way that lie shows up →

The same change, two different truths

A local filesystem install works. The git+https install from GitHub breaks. Identical code, opposite outcomes — and only one of them is the path production actually uses.

So how do teams find out which truth is real?

Local dev today
filesystem path
→ works
Production
git+https://github.com/…
→ breaks

The only honest test has been to push to CI

To hit the real remote-install path, you push and let CI install from GitHub. It works — but it's slow, it's public, and every trial clutters your git history to find out.

There had to be a way to run that real test privately, first →

Your working tree is copied INTO a clean container, not mounted

On start, the shadow runs docker cp to copy your workspace into an isolated container volume — it is NOT bind-mounted to the host. Experiments inside never touch your host filesystem.

Isolation is half of it — the other half makes your change look like the real remote →

# docker-compose.yaml (lines 48-50) # Isolated workspace volume (NOT mounted to host) # Files are copied in via `docker cp` - workspace-data:/workspace # gateway.py:687 copies host files in docker cp {workspace}/. {container}:/workspace/

A Gitea sidecar makes your local change look like the real remote

The shadow stands up a gitea/gitea:latest sidecar as a local git server on port 3000. An env var rewrites git URLs, so you install via git+http://gitea:3000/… — the exact remote-install path, not a filesystem shortcut.

Now the real test runs safely — but what happens to your work afterward? →

# docker-compose.yaml sidecar + env image: gitea/gitea:latest port: 3000:3000 AMPLIFIER_GIT_HOST=http://gitea:3000 AMPLIFIER_SHADOW_MODE=true SHADOW_NAME=default # install path production uses git+http://gitea:3000/…

Keep it, throw it away, or see exactly what changed

On start, your workspace is snapshotted outside any workspace. When you're done, you choose — a safe test becomes a safe, reversible workflow with no risk to your host or your history.

Which is what finally closes the gap we opened with →

The payoff

The “works locally, breaks on GitHub” surprise now happens in your shadow

Because the shadow installs your change via git+http://gitea:3000/… — the exact remote path production uses — the break surfaces before you push, privately, instead of in public CI history after.

And this isn't a sketch — it's shipping today →

Phase 0 is complete and shipping as amplifier-shadow v0.1.0

The foundational infrastructure is done — and named shadows can run in parallel on their own ports, so isolated experiments scale out side by side.

Status: Phase 0 Complete · v0.1.0 (Alpha)
0.1.0
amplifier-shadow (Alpha)
15
CLI subcommands
1,689
lines of core Python
3001–3002
parallel shadows, own ports
Sources

Research Methodology

Primary source: bkrabach/amplifier-shadow (PUBLIC) — reference implementation of Shadow Workspace tools for Amplifier. Verified against a fresh clone at HEAD 75ccb17d64ec9b475532879021dcecd75aafb39b.

Data as of: repo pushedAt 2025-12-20; 7 commits, Dec 6–20, 2025.

Feature status: Phase 0 Complete; package v0.1.0, Development Status :: 3 - Alpha, MIT, Python ≥3.11.

Commands run:

Gaps: Docker was not run end-to-end; command behavior is grounded in source and templates, not a live run. The doc's “~30s” startup figure is a design-doc self-assessment and is not used. Wider-ecosystem integration claims (parent repos/modules) are design-doc assertions absent from the clone and are not used.

Primary contributor: Brian Krabach — sole committer, 7 of 7 commits (100%).

More Amplifier Stories