A kubectl wrapper that only allows read-only commands. Designed to prevent accidental modifications when AI assistants (like Claude) explore Kubernetes clusters, including production.
kubectlmust be installed and available in your PATH
If you have Krew installed:
kubectl krew install readonlyThen use it as a kubectl plugin:
kubectl readonly get pods
kubectl readonly describe deployment nginx
kubectl readonly logs my-pod -fDownload the latest binary from the releases page and add it to your PATH.
Requires Go 1.25+:
go install github.com/Evaneos/kubectl-readonly@latest| OS | Architecture |
|---|---|
| Linux | amd64, arm64 |
| macOS | amd64, arm64 |
| Windows | amd64, arm64 |
Use kubectl-readonly (standalone) exactly like kubectl. If the binary is in your PATH, it also works as a kubectl plugin (kubectl readonly):
# Standalone
kubectl-readonly get pods
kubectl-readonly get pods -n kube-system -o wide
kubectl-readonly describe deployment nginx
kubectl-readonly logs my-pod -f --tail=100
kubectl-readonly top nodes
kubectl-readonly config use-context production
# As a kubectl plugin (if binary is in PATH)
kubectl readonly get pods
kubectl readonly describe deployment nginx
kubectl readonly logs my-pod -fIf you try a command that's not read-only, it will be blocked:
$ kubectl-readonly delete pod my-pod
This command is not safe for read-only access; use kubectl directly instead.
kubectl-readonly only allows read-only commands without side effects.
For a list of allowed commands, see: kubectl-readonly --helpUse --readonly-check-ok to verify if a command would be allowed without executing it:
$ kubectl-readonly --readonly-check-ok get pods
OK: This command is allowed by kubectl-readonly
$ kubectl-readonly --readonly-check-ok delete pod my-pod
BLOCKED: This command is not allowed in read-only mode| Command | Description |
|---|---|
get |
Display resources |
describe |
Show detailed resource info |
logs |
View container logs |
top |
Display resource usage (CPU/memory) |
explain |
Documentation for resources |
api-resources |
List available API resources |
api-versions |
List available API versions |
cluster-info |
Display cluster information |
version |
Show client/server versions |
events |
View cluster events |
wait |
Wait for a condition |
diff |
Show differences without applying |
kustomize |
Render kustomize manifests locally (restricted, see below) |
| Command | Allowed subcommands |
|---|---|
config |
view, get-contexts, get-clusters, get-users, current-context, use-context |
auth |
can-i, whoami |
rollout |
status, history |
krew |
list, search, info |
The kustomize command is allowed for local manifest rendering, but the following flags are blocked because they enable code execution, network access, or unrestricted file reads:
| Blocked flag | Risk |
|---|---|
--enable-alpha-plugins |
Executes arbitrary local binaries |
--enable-helm |
Invokes helm (may fetch remote charts) |
--network |
Enables network access for functions |
--load-restrictor=None |
Allows reading files outside the kustomization root |
kubectl-readonly allows you to see that secrets exist (metadata) but blocks access to their actual values:
# Allowed - shows secret names, types, and ages (no values)
kubectl-readonly get secrets
kubectl-readonly get secrets -o wide
kubectl-readonly get secrets -o name
kubectl-readonly describe secret my-secret # shows size, not values
# Blocked - these formats expose the base64-encoded values
kubectl-readonly get secrets -o yaml
kubectl-readonly get secrets -o json
kubectl-readonly get secret my-secret -o jsonpath='{.data}'
kubectl-readonly get --raw /api/v1/secretsThis lets you investigate which secrets exist and how they're configured, without risk of accidentally exposing credentials in logs or terminal history.
Some read-only commands can run indefinitely. These are allowed:
kubectl-readonly get pods --watch # Watch for changes
kubectl-readonly logs my-pod -f # Follow logs (stream)
kubectl-readonly top pods --watch # Continuous resource monitoringThese commands are safe (read-only) but will run until interrupted with Ctrl+C.
This tool was designed to let AI assistants safely explore Kubernetes clusters.
Add kubectl-readonly to Claude Code's permission allowlist.
For a single user (applies to all projects), edit ~/.claude/settings.local.json:
{
"permissions": {
"allow": [
"Bash(kubectl-readonly:*)"
]
}
}For a specific project (shared with the team via git), edit .claude/settings.json at the project root:
{
"permissions": {
"allow": [
"Bash(kubectl-readonly:*)"
]
}
}Tell Claude to prefer kubectl-readonly for read-only operations.
For a single user, create or edit ~/CLAUDE.md:
# Kubernetes
When exploring Kubernetes clusters, always use `kubectl-readonly` instead of `kubectl` for read-only operations (get, describe, logs, top, etc.). This command is pre-approved and prevents accidental modifications.
Only use `kubectl` directly for write operations (create, apply, delete, exec, etc.) which require explicit approval.For a specific project, create or edit CLAUDE.md at the project root with the same content.
Claude can then run any read-only kubectl command without asking for permission, while dangerous commands like delete, apply, or exec will be blocked.
When in doubt, block. This tool prefers false negatives (blocking legitimate commands) over false positives (allowing dangerous commands). If a command isn't explicitly in the allowlist, it's blocked.
- Accidental destructive operations: An AI agent running
kubectl deletewhen it meantkubectl get, forgetting--dry-runon an apply, or runningkubectl execto "quickly check something" - Human errors: Muscle memory typing the wrong command in a production context
- A compromised environment: If an attacker can modify environment variables and create files, they can bypass this tool via PATH hijacking or KUBECONFIG exec plugins
- Malicious intent: This tool is not designed to stop a determined attacker or a malicious AI actively trying to bypass restrictions
- Parser edge cases: We cannot guarantee 100% that the argument parser cannot be abused with shell tricks or special characters
In short: this tool prevents accidents, not attacks. If you need to secure kubectl against a hostile environment, additional measures (sandboxing, network policies, RBAC) are required.
This project uses GoReleaser to automate releases. When a new tag is pushed, GitHub Actions automatically builds binaries for all supported platforms and creates a GitHub release.
To create a new release:
git tag v1.0.0
git push origin v1.0.0Each release includes:
- Pre-built binaries for all platforms
- SHA256 checksums (
checksums.txt) - Automatically generated changelog
See CONTRIBUTING.md.