A tool for pipe streamed kubectl execution
March 15, 2026 · View on GitHub
Examples
show any kind of object (all kinds) with label app=web
_ api-resources | _ get {{kind}} -A -l app=web
from all clusters get pods in namespace prod with label app=web
_ config get-contexts | _ -n prod get pod -l app=web
restart all pods from prod namespace with not all containers ready
_ -n prod get pod | _ ? READY ?1 ne ?2 | _ delete pod {{name}}
show app.conf file from all clusters from east and west kubeconfig files, from all clusters names that match regexp ^prod, from web namespace and pods labeled with app=api
_ kconf-files east west | _ config-get-contexts ^prod | \
_ -n web get pod -l app=api | _ exec {{name}} -- cat /app.conf
More examples at the bottom.
Description
Instead of running set of bash kubectl commands in sequence, run them in pipelined workflow.
Features
Works as a kubectl plugin (kubectl line) or standalone (_) wrapper.
Behaves like kubectl when not used in a pipeline.
Run other plugins from this plugin.
Automatically passes context, namespace, kubeconfig, kind, name between piped commands.
Supports template tags ( {{name}}, {{kind}}, {{ctx}}, etc. )
Provides shortcuts ( api-r → api-resources, cgc → config get-contexts, ... ).
Adds filters for regex and conditional selection on columns.
Adds injectors extending manifests for better visibility (of stored files).
Extends kubectl abilities, you can run on multiple kubeconfig files, multiple commands, multiple resource kinds.
Reduces repetitive typing and makes complex multi-step and multi-cluster kubectl operations easier to express.
Installation and Setup
You can install the tool as kubectl-line.
cp kubectl-line /usr/local/bin
For convenience, I symlink it to:
ln -s kubectl-line kubectl-_
ln -s kubectl-line _
With above setup (ie linked kubectl-line to kubectl-_ and _ )
kubectl line get ns
should work as same as
kubectl _ get ns
or simpler
_ get ns
Purpose of this tool ?
With vanilla kubectl I often run something like:
kubectl --context cluster1 -n some-ns get pod --show-labels
observe output, and then select some subset of resources, and execute some action on those.
LIST=$(kubectl --context clst1 -n some get pod --no-headers -l app=some| awk '{print \$1 }') \
for i in $LIST ; do
kubectl --context clst1 -n some delete pod $i;
done
Sometimes I would delete pod, sometimes I would exec, edit, remove or add labels. Usual pattern of such executions is to get a list of items and then to operate on each item.
With this tool I can observe, then append line or _ after kubectl that selected resources, and add pipe:
kubectl line -n some get pod -l app=some | \
kubectl line delete pod {{name}}
or if you've linked kubectl-line to kubectl-_
kubectl _ -n some get pod -l app=some | \
kubectl _ line delete pod {{name}}
or if you've linked kubectl-line to _
_ -n some get pod -l app=some | \
_ delete pod {{name}}
In example above -n switch and value are passed from first (left side) command to second (right side of pipe) implicitly.
Example of a bit more advanced usage
Executing same kubectl operation already filtered objects
_ -n monitoring get pod -l app=prom | _ exec -- env
executing same kubectl operation on all available resource kinds (default cluster)
_ api-resources | _ get {{kind}} -A
dumping all resources by resource kind (faster, less organized)
_ --context us-east-001 api-resources | \
_ get {{kind}} -A \> /tmp/{{ctx}}_{{kind}}.yaml
dumping all resources by namespace, kind, name (slower, better organized)
_ --context mini api-resources | \
_ get {{kind}} -A | \
_ get {{kind}} {{name}} -o yaml \> /tmp/{{ctx}}_{{ns}}_{{kind}}_{{name}}.yaml
Executing same operation on multiple clusters
Single kubeconfig file, all clusters
_ config get-contexts | \
_ -n prod get pod -l app=web
Multiple kubeconfig files (kconf-file), all clusters
_ kconf-file first_kubeconfig_file second_kubeconfig_file | \
_ config get-contexts | \
_ -n prod get pod -l app=web
Multiple kubeconfig files writing to local files
You might need to check the layout of same objects across multiple clusters, so you can inspect differences. (for example pod, or config map, or secret)
_ kc-file ~/.kube/west ~/.kube/east | \
_ -n kube-system get pod -l component=etcd -o json \> /tmp/{{ctx}}_pod_etcd.json
Shortcuts
This kubectl wrapper provides some shortcuts like api-r instead of api-resources and cgc instead config get-contexts (to speed up typing), kcf instead of kc-file or kconf-file and few additional commands for filtering.
With supported shortcuts you could type same example from above in abbreviated form:
_ kcf ~/.kube/europe ~/.kube/america | \
_ cgc | \
_ api-r | \
_ get {{kind}} -A | \
_ get {{kind}} {{name}} -o yaml
Filtering
Filtering with separate pipe
If you have all contexts in single file you can filter contexts:
_ cgc | \
_ + NAME '^.*[euro|america].*$' |\
_ get ns
Internal filtering within cgc (config get-contexts shortcut)
$ _ cgc
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
miku minikube minikube default
* minikube minikube minikube default
$ _ cgc minikube
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* minikube minikube minikube default
$ _ cgc CLUSTER minikube
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
miku minikube minikube default
* minikube minikube minikube default
$ _ cgc NAME miku
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
miku minikube minikube default
note: if no column name in capital letters specified, NAME column is default
Internal filtering within api-r (api-resources shortcut)
$ _ api-r pods
NAME SHORTNAMES APIVERSION NAMESPACED KIND
pods po v1 true Pod
pods metrics.k8s.io/v1beta1 true PodMetrics
$ _ api-r KIND Pod
NAME SHORTNAMES APIVERSION NAMESPACED KIND
pods po v1 true Pod
podtemplates v1 true PodTemplate
pods metrics.k8s.io/v1beta1 true PodMetrics
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
$ _ api-r KIND 'Pod$'
NAME SHORTNAMES APIVERSION NAMESPACED KIND
pods po v1 true Pod
# _ api-r APIVERSION apps/v1
NAME SHORTNAMES APIVERSION NAMESPACED KIND
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
note: if no column name is specified (in capital letters), NAME column is default
Injecting extented yaml/json attributes
As you can dump multiple objects from multiple contexts and kubeconfig files, there are commands that can additionally inject (extend) format of yaml/json manifest files with specific kubernetes-config file and context attributes.
_ kc-file ~/.kube/config ~/.kube/account1 ~/.kube/account2 ~/.kube/region-eu | \
_ -n kube-system get pod etcd-minikube -o json | \
_ json_inject > /tmp/all.json
Now each item in output file will have extended json format with headers that look like:
{
"context": "minikube",
"kubeconfig" : "/Users/none/.kube/east",
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
...
Dumping to correctly named files
If you do not like to extend manifest, you can put objects in correctly named files you can always use available {{ }} tags for example:
_ config get-contexts | \
_ -n kube-system get pod -l k8s-app=kube-dns -o yaml \> /tmp/{{ctx}}_label_kube_dns_pods.yaml
or
_ config get-contexts | \
_ -n kube-system get pod -l k8s-app=kube-dns | \
_ get {{kind}} {{name}} \> /tmp/{{ctx}}_{{kind}}_{{name}}.yaml
Tags like {{ctx}} {{kind}}, {{name}}, if available, are replaced.
Given -n kube-system (context) and pod (kind) is silently passed via pipe stream, so last _ get {{kind}} {{name}} is expanded as:
kubectl --context {{ctx}} -n {{ns}} get {{kind}} {{name}}
and then executed with template variables being substituted for real values.
Advanced dumping
Check example below named 'storing all content of default context in structured directory'
How does it work - Passing arguments between pipes
If any parameter (like kubeconfig file, context, namespace) is being used on the previous pipe (to left) execution, it will be repeated on all other pipe executions (to the right)
For example:
_ --context minikube -n test-run get pods | _ get pod {{name}}
in second execution (_ get pod {{name}} ..) context and namespace are passed from left side of pipe execution, so execution on right is evaluated to kubectl --context minikube -n test-run get pod {{name}} and name is replaced for each item in name column that command on the left has printed out.
Same example could be executed with kind templated:
_ --context minikube -n test-run get pods | _ get {{kind}} {{name}}
Now you could execute:
_ --context minikube -n test-run get pods,svc | _ get {{kind}} {{name}}
and {{kind}} will be matched.
If you want to explicitly use some named column field (kubectl output of previous pipe section) you can use some of {{ }} tags, explained in the section below.
Available {{ }} tags
Overall tags that begin with ? mark are conditional, if they are not empty they will be shown, if they are empty they will be empty. Tags that have ?x are replaced with corresponding switch, or empty Tags without ?x: or ?: are either replaced or left as they are
kubeconfig file related tags:
?x:kc -> conditional switch kubeconfig -> --kubeconfig config_file | ''
?:kc -> conditional kubeconfig -> config_file | ''
kc -> kubeconfig -> config_file | {{kc}}
context related tags:
?x:ctx - conditional switch context -> --context ctx | ''
?:ctx - conditional context-> ctx | ''
ctx - context -> ctx | {{ctx}}
namespace related tags:
?x:ns - conditional switch namespace -> -n ns | ''
?:ns - conditional namespace -> namespace | ''
ns - namespace -> namespace | {{ns}}
kind tag:
kind -> kind | {{kind}}
name tag:
name -> name | {{name}}
column based dynamic tags
Also for any named column like ROLE, AGE, NAME, NAMESPACE ... in previous pipe result (previous pipe output that is input for currently executing pipe stage) one can address column names like {{ROLE}}, {{AGE}}, {{NAME}}, {{NAMESPACE}}.
few more words on named columns
Keep in mind that this tool relies on column names like NAME, NAMESPACE, KIND and such, but tries to be flexible on any column name format it gets. As long as you keep column names with all capital letters, you can use custom-columns formatting of output.
For example if you specify
-o custom-columns=ABCD:.metadata.name,XYZ:.metadata.namespace,OPQ:.kind
you should be able to use those columns (ABCD, XYZ, OPQ) with their custom names. so for example
... | _ sh 'echo {{ABCD}}'
should work in same way as
_ api-r KIND 'Pod$' | _ sh 'echo {{APIVERSION}}'
should work
when you should not rely on custom column names as tags
Command @ does have special format for tags, it supports format {{item?if_item_exists:if_item_does_not_exist}}, where item is kc, ctx, ns, kind, name Command @ render yaml and json and there are no columns in those formats.
Flow arrangements
Starters (ie generators):
Starters are those commands that you can start pipe sequence with: They either add some functionality (kc-file) or are able to display some information that can be used in following pipe executions. Starters generate some content one can work with in pipe sequence.
_ kc-file
_ kcf : shortcut for kc-file
_ cgc : shortcut for config get-contexts
_ config get-contexts injects all available context from conf files
_ api-r : shortcut for api-resources
_ api-resources shows all available resources
_ get : list required resources
_ top : displays required usage
Filters:
Group of commands dedicated to filtering between pipes:
Filter in or filter out specific column name on given regexp:
_ + <column_name>
_ - <column_name>
Filters out specific column with expression (gt,lt,le,ge,eq,ne,re):
_ ? <column_name>
Makes specific column values unique (like api-resources might return duplicate resource kind):
_ uniq <column_name>
Commands cgc and api-r have their own internal filter so you can filter quicker.
Terminators:
Group of commands that you will execute as last in pipe sequence.
_ get
get can also be terminator, as it can be starter
_ sh
execute shell with available {{ }} tags and environment variables
_ clean
cleans specific plugin # tags from input/output
_ yaml-inject
_ json-inject
inject context and kubeconfig file used to get that object used after kubectl -o json or -o yaml
_ @
will work only if previous output format is yaml or json, and it will store file in specific templated directory path (ie will make needed dirs)
Flow terminator (last command in sequence of piped executions of this tool) can be any other kubectl command (exec, logs, labels, ...) ie command that would break kubectl pipeline execution stream, or will not return named column results.
If you follow this tool communication rules, you could extend and add some new pipe sequence compatible command. (for example: ... | _ sh './some_script {{KIND}}' | _ get {{kind}} | ...)
Helpers:
_ -help
shows help for this tool
_ help
shows help of kubectl, as this tool is kubectl plugin/wrapper
_ examples show some examples
_ env-vars show environment variables that can be set to troubleshoot/debug execution of this tool
Natural flow pipe sequences
allowed pipe flow
Following execution pipe streams are allowed:
kc-inject -> [ config get-contexts | api-resources | get | top | sh | ... ]
config get-contexts -> [ api-resources | get | top | sh | ... ]
api-resources -> [ get | top | sh | ... ]
[ get | top ] -> [ get | top | sh | ... ]
example of wrong pipe flow
You can't combine any pipe flow you might imagine, for example
_ get ns | _ kc-inject
would not make sense.
Interesting examples to run
getting object that do not have labels
_ kc-inject ~/.kube/config|_ cgc|_ api-r|_ get {{kind}} -A --show-labels | _ + LABELS '<none>'
dumping all objects for all clusters ie contexts from ~/.kube/west and ~/.kube/east file
time /bin/bash -c "
_ kc-inject ~/.kube/west ~/.kube/east |_ cgc|_ api-r|_ get ns|_ get {{kind}}|_ get {{kind}} {{name}} "
dumping all objects for all contexts in default ~/.kube/config file
time /bin/bash -c "
_ cgc|_ api-r|_ get {{kind}} -A|_ get {{kind}} {{name}} "
getting env from all containers within test-run namespace
_ -n test-run top pod --containers | _ exec {{POD}} -c {{NAME}} -- env
getting all pods with not all containers ready
_ get pod -A | _ ? READY ?1 ne ?2
on field READY X/Y, compares (not equal) first number (X) to second (Y) number of READY X/Y
getting what rendered value keys (?x) are available for filtering READY column
_ get pod -A | _ ? READY _?
getting all pods that are restarted more than 3 times
_ -n test get pod | _ ? RESTARTS ?1 gt 3
getting all pods that are were restarted between 10min and 20min ago
_ get pod -A | _ ? RESTARTS ?seconds ge 600 | _ ? RESTARTS ?seconds le 1200
filtering out kubectl api-resources APIVERSION filed
_ api-r | _ + APIVERSION k8s.io
storing all content of default context in structured directory
_ api-r | _ get {{kind}} -A | _ get {{kind}} {{name}} -o yaml | _ @ /tmp/CLSTR/{{ns?NS:NONS}}/{{?:ns}}/{{kind}}/{{name}}.yaml
running kubectl tks plugin nginx_inspect script on clusters within east and west kc files, filter in only clusters with prod in their name, and run tks plugin script on all pods labeled with app=nginx in webapp namespace
_ kcf west east | _ cgc prod | _ tks -n webapp start -l app=nginx nginx_inspect > {{k8s_pod}}.env`
Requirements
kubectl python3 (no extra deps)