Skip to content

CLI wrapper mode: proxy <pkg-manager> <args> #52

@andrew

Description

@andrew

The proxy binary could double as a transparent wrapper around package manager commands. Instead of starting the proxy server separately and configuring each package manager's registry URL, you'd run:

proxy npm install express
proxy pip install requests
proxy go get github.com/foo/bar

The proxy would handle registry injection automatically, so the package manager fetches through the caching proxy without any manual config.

How it would work

  1. Detect the ecosystem from the command name (npm, pip, cargo, gem, go, composer, etc.)
  2. Find or start a proxy server (see discovery below)
  3. Inject the appropriate registry override for that ecosystem
  4. Exec the package manager command
  5. If an ephemeral server was started, shut it down when the command exits

Proxy discovery order

Before spinning up a new server, check for an existing one:

  1. Config file - walk up the directory tree looking for .proxyrc, then fall back to ~/.proxyrc. Could be as simple as url=https://proxy.internal.company.com. This covers corporate setups where a shared proxy already exists.
  2. Default port - probe localhost on the default port and confirm it's a git-pkgs proxy (hit the health/API endpoint, not just check if the port is open).
  3. Ephemeral server - bind to :0, let the OS pick a port, start the server, run the command, tear down after.

Background daemon mode

Rather than starting and stopping the server on every command, the first invocation could start a background daemon that stays running with an idle timeout. Write the port to a pidfile, and subsequent invocations find it and connect immediately. Similar to how gpg-agent and ssh-agent work. This makes startup cost zero for the common case.

Registry override mechanisms

Each supported ecosystem already has documented configuration for pointing at the proxy. The wrapper would inject these automatically via env vars or flags, for example NPM_CONFIG_REGISTRY for npm, GOPROXY for Go, PIP_INDEX_URL for pip, etc.

Env vars are generally cleaner than injecting flags since they don't interfere with the user's arguments.

Shell aliases

Power users could alias the wrapper to replace their package manager entirely:

alias npm="proxy npm"
alias pip="proxy pip"
alias cargo="proxy cargo"

At that point every install goes through the proxy with zero friction.

Startup performance

Benchmarked on Apple Silicon (arm64). The proxy starts and accepts connections in ~48ms, which is negligible compared to any package install operation.

Metric Time
Server startup (avg of 10 runs) ~48ms
Cold npm metadata (express) 112ms (vs 133ms direct)
Second npm metadata request 61ms
Cold tarball fetch (is-odd) 66ms (vs 74ms direct)
Cached tarball fetch <1ms
Cold PyPI metadata (requests) 90ms (vs 124ms direct)

Even on cold requests the proxy adds no measurable overhead since it streams from upstream. Cached artifacts are served in under 1ms. The ephemeral startup mode would add ~48ms total to the install command, which is well within noise for any real package install.

Prior art

  • Socket Firewall (sfw-free) / sfw-installer - sfw npm install - spins up an ephemeral HTTP proxy that intercepts and scans packages. Security-focused, not caching.
  • Aikido Safe Chain - sets up shell aliases so package manager commands transparently route through a local scanning proxy. Security-focused.
  • Phylum CLI - phylum npm install - wraps package managers with policy enforcement. Security-focused.
  • JFrog CLI - jf npm install, jf pip install, jf go build - injects Artifactory registry URLs for caching. Requires a commercial Artifactory backend.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions