Skip to content

Getting started

outprobe has two halves: a laptop CLI and an in-cluster relay. The CLI creates the relay and routing objects, opens a reverse tunnel through a Kubernetes port-forward, and forwards matched requests to your local app.

You need:

  • a Kubernetes cluster using Istio;
  • kubectl in your PATH, with a working kubeconfig;
  • namespace-level permission to create a Deployment, Service, and the routing resource used by your traffic mode;
  • a local HTTP service to receive requests (the default is http://localhost:8080);
  • Homebrew to install the CLI.

Gateway API is needed only for optional browser/ingress interception. Docker is needed only when pulling or running a container image.

Terminal window
brew install outprobe/outprobe
outprobe --help

This is the laptop CLI used for init, up, down, status, and routes.

From the project where you run your local service:

Terminal window
outprobe init

This writes .outprobe.yaml without overwriting an existing file. Its first line points editors at the hosted schema:

# yaml-language-server: $schema=https://outprobe.dev/schemas/outprobe.schema.json

Use outprobe init --manifests only if you also want editable copies of the Kubernetes manifests under .outprobe/.

Start with the smallest useful config:

.outprobe.yaml
version: "0.0.1"
namespace: my-namespace
target: my-service
image: ghcr.io/flaticols/outprobe-relay:v0.0.16
localTarget: http://localhost:8080
rules:
- type: jwt
property: "" # top-level claim
matchers:
- key: email
value: you@example.com

The value must equal the value carried by your request. For an email claim, useful lookups are:

Provider Command Note
GKE / gcloud gcloud config get-value account Usually the email in the token.
fly.io fly auth whoami Returns your email.
AWS aws sts get-caller-identity Returns an ARN, not necessarily your JWT email.
Any provider Decode the bearer token at jwt.io The token claim is the source of truth.

Prefer a header instead? Replace the rule with:

.outprobe.yaml
rules:
- type: header
matchers:
- key: x-debug-user
value: denis

See Request matching for namespaced claims, feed filters, and current v1 rule selection.

Run a local copy of the target service at the configured localTarget. With the default:

http://localhost:8080

Run it under Delve or attach your editor if you want to stop at a breakpoint. outprobe forwards the original method, path, headers, and body to this endpoint.

Terminal window
outprobe up

The CLI will:

  1. resolve settings using flag/environment → config → built-in defaults;
  2. apply and wait for the relay;
  3. open an in-process port-forward to the relay’s loopback-only control port;
  4. connect 32 tunnel workers and register your rule;
  5. apply routing only after workers are connecting;
  6. wait until you press Ctrl-C.

When ready, the log ends with a line similar to:

outprobe is live — drive the app; Ctrl-C to tear down mode=divert target=my-namespace/my-service match="jwt email=you@example.com" local=http://localhost:8080

Drive the shared application. Requests with your matching claim or header should now reach the local service; unmatched requests continue to the real target.

Press Ctrl-C to tear down. outprobe deletes routing objects first, then the relay, so direct routing is restored before the pod disappears.

If a previous process exited unexpectedly:

Terminal window
outprobe status
outprobe down

Understand the request path

See how outprobe works, including relay dispatch and the reverse tunnel.

Catch browser traffic

Add a narrowly scoped Gateway API route with the ingress guide.

Call cluster dependencies

Expose in-cluster TCP services locally through egress tunnels.