Run a local process as if it were inside your cluster: prefix any command with plug and it resolves the cluster DNS and reaches the cluster services like any workload of the stack - no code change, no proxy configuration in your app. One tiny agent container on the cluster side, one static CLI on yours. Docker, Swarm, Kubernetes and OpenShift.

How it works

Your process runs on your machine and behaves as if it ran in the cluster. It calls the cluster's services by their names, the cluster calls it by its name, and it has the environment, the files and the data of the service it stands in for. Nothing changes in your code or its configuration: you start it with plug in front.

plug in two animated rounds: the browser's GET data is served by the deployed service1, then plug parks it and the same request is served by your machine, which also queries postgres by name.

One connection, both directions

plug keeps a single encrypted connection between your machine and a small agent that lives in the cluster. Everything travels through it.

  • Outbound: your process reaches the cluster. When it asks for postgres or rabbitmq, the name is resolved in the cluster and the connection is opened from inside it, by the agent. Names that are not the cluster's, a public API or localhost, go out as they always did.
  • Inbound: the cluster reaches your process. With -s api:80:3000 your process takes the name api in the cluster, and whatever calls api there lands on your local port.

Taking a deployed service's place

If the name you serve already belongs to a deployed service, plug parks it for the session: it stops answering, and your process answers instead. When your command ends, the service is restored as it was. Nobody redeploys anything.

A service's configuration in two animated rounds: the deployed api runs with the values, secrets and config files the cluster gives it; then plug parks api, the agent reads that configuration and hands it through the SSH tunnel, and your local api starts with the same values, secrets and files.

What the cluster gave the service, its values, its secrets, its config files, is read by the agent and handed to your process when it starts. You copy nothing by hand, and your process behaves as the service did.

Standing in for a service means being it, so your process receives what the service had:

  • its environment, secrets included, with the cluster's values;
  • its secret and config files, a certificate or a keystore;
  • its data: the volumes it mounts, live.

Each of the three can be declined or borrowed from another service: see --no-env, --env-of and --no-mount in the CLI reference.

Its volumes, live

A workload's volume in two animated rounds: the deployed api mounts its PVC or volume and reads and writes it; then plug parks api, a plug helper mounts the same claim, and your local api writes a file that travels through the SSH tunnel and the agent to the helper, which writes it on the real volume.

The claim on the storage, a PVC or a volume, stays where it is. While your session lives, a plug helper started by the agent mounts it in place of the parked workload, and what your process reads and writes goes through the tunnel and the agent to that helper: its files are the real volume, nothing is copied. The helper is removed when the session ends, and the workload gets its claim back.

What it asks of your machine

Nothing in your application: no proxy setting, no library, no rewritten URL, whatever the language or the runtime. plug itself needs a system permission to route the cluster's names, granted once, at install; after that plug <cmd> runs as you. In the cluster, the agent is the only thing deployed.

A session cleans up after itself

Everything plug sets up belongs to the session: the name it serves, the service it parked, the helper on a volume. They go when your command ends. If your machine disappears instead, the agent notices and puts things back within the minute. And a connection that drops, a laptop that sleeps, a VPN that reconnects, an agent that restarts, is re-established without restarting your command.

Names that are not the cluster's

A name the cluster does not know is forwarded to the nameservers your machine already used, read from the system (scutil on macOS, the former resolv.conf on Linux, the adapter table on Windows) and ranked the way the OS ranks its interfaces, so a corporate VPN's resolver comes first. plug follows them through the session: a VPN connected or dropped, another network joined. plug doctor shows where lookups go now:

✓ dns forwarding   forwarding dotted names to 10.8.0.1:53, 192.168.1.1:53

With none found, plug falls back to a public resolver and says so: public names keep working, internal ones do not resolve, and those lookups leave your network.

What it does not carry

TCP to a name. UDP, QUIC and ping are not carried (most clients fall back to TCP), and neither is a hard-coded IPv6 literal; a service reached by its name is always fine.

Several clusters at once

Two terminals can be plugged into two different clusters at the same time, plug -p a and plug -p b, each resolving the same service names to its own cluster. See Profiles.

For an AI coding agent

plug mcp serves what plug knows to an agent, as tools with structured answers rather than prose for a person: which clusters this machine knows, what doctor finds and the exact remedy, the environment a deployed workload runs with, whether a name exists. An agent that reads "the pod's variables came through empty because the role lacks pods/exec" can fix that; one that reads a wall of text guesses. It is the launcher itself, over stdio, so nothing listens on a port and every cluster's version is handled the way it already is.

Going further

The mechanics, how names are captured, what the permission is on each OS, how flows are kept apart, are in Under the hood. What the agent may do in your cluster, and who may reach it, is in the Security model.