Skip to content

shell

Overview

Opens a shell in a deployed app, or runs one command when arguments are passed after --.

podplane shell <name> [-- command...] [flags]

Modes

podplane shell has four possible modes:

  1. Interactive app shell: podplane shell hello tries bash -l, then sh, in the selected app container.
  2. One-off command: podplane shell hello -- <command...> runs exactly that command with kubectl exec. Debug containers and the shell prompt are not used in this mode.
  3. Ephemeral debug container: if the app container has no bash or sh, Podplane can use kubectl debug to start a toolbox container in the same pod.
  4. Shell prompt fallback: if debug is declined, unavailable, or fails, Podplane opens a small client-side prompt that runs each line as a separate kubectl exec command.

Examples

podplane shell hello
podplane shell hello -c web
podplane shell hello -- npm run migrate
podplane shell hello -- env

Container selection

By default, Podplane chooses the same app container as podplane logs: the kubectl.kubernetes.io/default-container annotation, then a recognized app container name, then the only container. If multiple containers remain, Podplane prompts in an interactive terminal.

Use -c, --container to choose explicitly.

Ephemeral debug container fallback

For interactive shells, Podplane tries bash -l, then sh. If neither exists, Podplane may ask whether to start an ephemeral debug container in the same pod. This uses kubectl debug, modifies the pod by adding an ephemeral container, and requires RBAC permission for ephemeral containers.

Podplane only offers this fallback when the selected pod is managed by a Deployment, StatefulSet, or DaemonSet, so it can offer a safe restart cleanup afterwards. ReplicaSet-owned pods are resolved back to their owning Deployment. Bare pods, Jobs, and unknown owners skip debug fallback and go straight to the shell prompt.

Podplane labels pods that receive a debug container so they can be filtered:

kubectl get pods -l podplane.dev/shell-debug=true

It also adds one unique annotation per debug container for storing metadata which will not be overwritten by later shell sessions:

podplane.dev/shell-debug-<debug-id>: |
  {"container":"<debug-container>","target":"<app-container>","createdAt":"<timestamp>"}

After the debug shell exits, Podplane asks whether to restart the owning workload to remove the ephemeral container. Ephemeral containers cannot be removed directly; they disappear when the pod is recreated.

Use --debug to skip the debug prompt when no app shell is available, --no-debug to skip this fallback, and --debug-image to choose the debug image. These flags only apply to interactive shell fallback, not to -- <command...> one-off commands.

Shell prompt fallback

If the debug container is declined or fails, Podplane opens a small shell prompt.

The prompt is client-side: each entered line runs as a new kubectl exec command. It always supports exit. If the container has an env binary, it also supports export, unset, and local env output; otherwise those commands report an error if invoked.

The prompt does not emulate a shell. Pipes, globbing, redirection, aliases, functions, pwd, and cd require a real shell in the container.

Options

FlagDescription
-c, --container stringContainer to shell into
--debugStart an ephemeral debug container without prompting when no shell is available
--debug-image stringImage to use for ephemeral debug containers (default: busybox:latest)
--no-debugSkip ephemeral debug container fallback
-n, --namespace stringKubernetes namespace the app was deployed into
--context stringThe name of the kubeconfig context to use (default: current kubeconfig context)
--kubeconfig stringPath to the kubeconfig file (default: $KUBECONFIG or ~/.kube/config)