Skip to content

Bundle mitmdump with packaged app #119

Closed

Description

@Juliusolsson05

Summary

Bundle the Claude proxy helper (mitmdump from mitmproxy) inside packaged Agent Code so normal users do not need to install mitmproxy/mitmdump separately. Sibling to the tmux bundling effort (see companion issue).

Why

Claude proxy streaming is a core runtime path. Depending on user-installed Homebrew mitmproxy adds setup friction and creates packaged-app failures when PATH, installation location, or mitmproxy version differs from the development machine. The bundled path also pins behavior to a known tested mitmproxy version.

Decisions

  • Use upstream mitmproxy's own prebuilt PyInstaller archive: mitmproxy-<ver>-darwin-arm64.tar.gz (~52 MiB compressed, ~87 MB on disk after extract). Ship the compressed archive in the app and extract on first proxy use into app.getPath('userData')/runtime/mitmproxy-<ver>/.
  • Pin via a committed manifest.json with version + per-arch sha256. Do NOT commit the binary itself to git.
  • Repo convention: runtime artifacts live under third_party/, source-only reference checkouts continue to live under vendor/.
  • Reusable packages (e.g. claude-code-headless) stay Electron-agnostic — Agent Code main resolves the path and passes mitmDumpPath into createProxyServer.
  • Dev contributors do NOT pay the download on npm i. Fetch only runs on npm run runtime:prepare:mac or in release CI.

Repo layout

Committed:

third_party/mitmproxy/
  manifest.json
  README.md
  LICENSE.md
  .gitignore             # ignores cache/
scripts/runtime-tools/
  fetch-mitmproxy.mjs
  verify-mitmproxy.mjs
  bump-mitmproxy.mjs     # optional
src/main/setup/runtimeTools.ts

Not committed:

third_party/mitmproxy/cache/   # downloaded archives, verified by sha256

Resolution order at runtime

  1. process.env.CLAUDE_HEADLESS_MITMDUMP
  2. Extracted bundled artifact in userData/runtime/mitmproxy-<ver>/
  3. Setup-cached PATH path
  4. PATH lookup
  5. Typed error with diagnostics

Setup gate

When bundled mitmdump exists, the setup gate must NOT prompt for mitmproxy install. Show it as Bundled with Agent Code. Keep Homebrew install path available for dev.

Packaging

  • Extend scripts/copy-packaged-resources.mjs to copy third_party/mitmproxy/cache/mitmproxy-<ver>-<os>-<arch>.tar.gz into out/main/runtime/mitmproxy/<os>-<arch>/mitmproxy.tar.gz.
  • electron-builder.yml adds out/main/runtime/**/* to asarUnpack.
  • CI release workflow runs npm run runtime:prepare:mac before electron-builder, caches third_party/mitmproxy/cache/ keyed by sha256 of the manifest.

Acceptance

  • Packaged Agent Code starts a Claude proxy session with no Homebrew mitmproxy installed on the user machine.
  • First-run extraction is idempotent and survives app updates that bump the pinned version.
  • Setup gate stops asking for mitmproxy in packaged builds.
  • Manifest is the single source of truth for version + hash. Version bumps are one-file PRs.

Size impact

Packaged DMG grows by ~52 MiB (mitmproxy compressed archive). Git repo size: unchanged. Installed-on-disk after first run: ~87 MB in userData (one time).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions