Dev Env Diff & Flight Recorder

VS Code extension that kills "works on my machine".
One click → snapshot of your dev environment → diff it against a teammate's or a previous one → get a Markdown report with concrete shell commands to fix the drift.
100% local. No telemetry. No network calls (except the explicit Import from URL command).
Pick A/B with one click
 |
Color-coded diff report
 |
What gets captured
| Category |
Sources |
| Host |
platform, arch, kernel release |
| Runtimes |
node, npm, pnpm, yarn, python, go, java, ruby, rustc, dotnet, git |
| Docker |
engine version, containers (incl. compose) with state + ports |
| Ports |
listening TCP via lsof / ss / netstat |
| Env |
.env* keys and process.env (masked by default) |
| Scripts |
package.json, Makefile, .vscode/launch.json, docker-compose.yml |
| Lockfiles |
SHA-256 of package-lock.json, yarn.lock, pnpm-lock.yaml, Pipfile.lock, poetry.lock, go.sum, Cargo.lock, Gemfile.lock, composer.lock, requirements.txt |
| Git |
branch, commit, dirty, remote, ahead/behind upstream |
| VS Code extensions |
id + version of every installed (non-builtin) extension |
| Shell config |
SHA-256 fingerprints of ~/.zshrc, ~/.bashrc, fish config, .tool-versions, .nvmrc, … |
| PATH |
ordered list of $PATH entries (order matters for shadowing) |
Snapshots land in <workspace>/.dev-env-diff/ as snapshot-<timestamp>-<host>.json.
Usage
- Activity Bar → Dev Env Diff → click Record snapshot.
- Share the JSON (commit, paste, or host it). Your teammate runs
Dev Env: Import Snapshot from URL… or …from Clipboard.
- Click the circle next to any snapshot to pin it as A (baseline), click another to pin as B — the diff opens automatically. Click a pinned circle to unpin. The Clear button in the view title resets both.
- Export Markdown Report — copy a report with recommendations like
nvm install 20.11.1 or npm ci.
Commands
| Command |
Description |
Dev Env: Record Snapshot |
Capture current environment. |
Dev Env: Compare Snapshot With… |
Open diff WebView against another stored / external snapshot. |
Dev Env: Compare Latest vs Previous |
Diff the two most recent snapshots without prompts. |
Dev Env: Tag Snapshot… |
Label a snapshot (e.g. before-upgrade, prod-mirror). |
Dev Env: Export Markdown Report |
Generate Markdown report with actionable commands. |
Dev Env: Import Snapshot from Clipboard |
Paste a snapshot JSON. |
Dev Env: Import Snapshot from URL… |
Fetch a snapshot over HTTP(S) (≤ 5 MB, ≤ 10 s). |
Dev Env: Delete Snapshot |
Move snapshot to Trash. |
Dev Env: Refresh |
Refresh the Snapshots view. |
Dev Env: Preferences |
Open extension settings. |
Settings
| Setting |
Default |
Description |
devEnvDiff.envValueMode |
keysOnly |
keysOnly / masked / full. full is not recommended. |
devEnvDiff.excludePorts |
[] |
Ports to omit from snapshots. |
devEnvDiff.stripHomePaths |
true |
Replace $HOME with ~ in stored strings. |
devEnvDiff.autoSnapshotOnStartup |
false |
Auto-record on workspace open. |
devEnvDiff.snapshotDir |
.dev-env-diff |
Workspace-relative folder for snapshots. |
devEnvDiff.execTimeoutMs |
5000 |
Per-command timeout (500…60000 ms). |
devEnvDiff.retentionKeep |
50 |
Keep only the last N snapshots (1…1000). |
devEnvDiff.collectExtensions |
true |
Record installed VS Code extensions. |
devEnvDiff.collectShellRc |
true |
Hash shell rc files (~/.zshrc, ~/.bashrc, …). |
devEnvDiff.collectPath |
true |
Record $PATH entries (ordered). |
Privacy & Security
- No telemetry and no network calls except the explicit Import from URL command.
- Env values are keys-only by default; secrets are masked even in
masked mode by pattern (secret, token, password, api_key, …).
- Home-directory paths are replaced with
~ before persistence.
- All external commands run without
sudo, with a bounded timeout and 4 MB output cap.
- Remote imports are capped at 5 MB and 10 s; only
http/https URLs accepted.
- For vulnerability reports, see the bundled
SECURITY.md (in the extension folder).
Snapshot schema (v3)
{
"schemaVersion": 3,
"timestamp": "2026-05-25T09:14:10Z",
"tag": "before-upgrade",
"host": { "platform": "darwin", "arch": "arm64", "release": "23.0.0" },
"git": { "available": true, "branch": "main", "commit": "abc1234", "dirty": false },
"runtimes": { "node": "20.11.1", "python": "3.12.3" },
"docker": { "available": true, "version": "26.1.1", "containers": [] },
"ports": [{ "port": 3000, "protocol": "tcp", "process": "node" }],
"env": [{ "key": "DATABASE_URL", "source": "dotenv", "file": ".env" }],
"scripts":[{ "source": "package.json", "name": "dev", "command": "vite" }],
"lockfiles":[{ "file": "package-lock.json", "manager": "npm", "sha256": "…", "size": 12345 }],
"extensions":[{ "id": "ms-python.python", "version": "2024.1.0", "builtin": false }],
"shellRc": [{ "file": "~/.zshrc", "sha256": "…", "size": 4096 }],
"path": ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"],
"warnings": []
}
v1 and v2 snapshots are auto-migrated to v3 on read.
Feedback
Bug reports and feature requests: contact@alekseialeinikov.com.
License
MIT © Aleksei Aleinikov
| |