Help us shape the future of Go! Take the 2026 Go Developer Survey

cmdiff

command module
v0.0.0-...-4d3262c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2025 License: MIT Imports: 2 Imported by: 0

README ΒΆ

cmdiff - ConfigMap Diff Tool

A command-line tool that compares local files used in Kustomize configMapGenerator with the actual files stored in ConfigMaps deployed to your Kubernetes cluster.

Why cmdiff?

When using Kustomize's configMapGenerator to manage configuration files, it's useful to know what changes you're about to apply before running kustomize build | kubectl apply. While kubectl diff shows the full ConfigMap diff, it doesn't provide a clear view of the actual file changes embedded within the ConfigMap data.

cmdiff solves this by:

  • Parsing your kustomization.yaml to find configMapGenerator entries
  • Fetching the corresponding ConfigMap from your Kubernetes cluster
  • Extracting and comparing individual files between local and cluster versions
  • Displaying beautiful, color-coded diffs with clear file-by-file comparisons

Features

  • 🎨 Beautiful CLI output using charmbracelet/lipgloss
  • πŸ–₯️ Interactive TUI mode - side-by-side diffs with bubbletea
  • πŸ“Š Clear diff visualization - unified diff format or side-by-side view
  • πŸ” Smart ConfigMap detection - automatically finds the latest ConfigMap or specify exact name
  • πŸ“ Multiple file support - handles ConfigMaps with multiple files
  • 🎯 Multiple ConfigMap support - diff specific ConfigMaps by name
  • ⚑ Fast and lightweight - written in Go
  • πŸ” Kubeconfig support - works with default kubeconfig or custom path
  • 🎹 Keyboard navigation - vim-style keybindings (h/j/k/l) in interactive mode

Installation

From source
go install github.com/stibi/cmdiff@latest
Build locally
git clone https://github.com/stibi/cmdiff
cd cmdiff
go build -o cmdiff

Usage

Basic usage

Run cmdiff in a directory containing kustomization.yaml:

cmdiff

This will:

  1. Parse the local kustomization.yaml
  2. Find the first configMapGenerator entry
  3. Use the namespace defined in kustomization.yaml (or "default" if not specified)
  4. Fetch the latest ConfigMap with matching name from the cluster
  5. Compare all files and display diffs
Specify a ConfigMap name

If you have multiple configMapGenerators or want to compare against a specific ConfigMap:

cmdiff --configmap my-config

This works two ways:

  • If --configmap matches a configMapGenerator name, it compares against the latest ConfigMap with that prefix
  • If --configmap is an exact ConfigMap name (e.g., my-config-abc123), it uses that specific ConfigMap
Namespace handling

cmdiff automatically uses the namespace from your kustomization.yaml:

# kustomization.yaml
namespace: production

configMapGenerator:
- name: my-config
  files:
  - config.yaml

When you run cmdiff, it will look for the ConfigMap in the production namespace.

Override with the --namespace flag:

cmdiff --namespace staging

Namespace priority (highest to lowest):

  1. --namespace flag (command-line override)
  2. namespace field in configMapGenerator (per-generator)
  3. namespace field in kustomization.yaml (global)
  4. "default" (fallback)
Custom kustomization path
cmdiff --path ./k8s/overlays/production
Interactive mode with side-by-side diffs

NEW! Use the -i or --interactive flag for an interactive TUI with side-by-side diffs:

cmdiff --interactive
# or
cmdiff -i

Features:

  • Side-by-side diff view - See Kubernetes vs Local files in parallel columns
  • Navigate between files - Use arrow keys or tab to switch between files
  • Scroll through diffs - Arrow keys to scroll up/down
  • Color-coded differences - Red (removed) and green (added) highlighting
  • File tabs - Visual tabs showing all files with status icons

Keyboard shortcuts:

  • β†’/← or l/h or tab/shift+tab - Navigate between files
  • ↑/↓ or k/j - Scroll up/down
  • q or esc - Quit
  • pgup/pgdown - Page up/down
  • home/end - Jump to top/bottom
Custom kubeconfig
cmdiff --kubeconfig ~/.kube/other-cluster-config
All flags combined
cmdiff \
  --interactive \
  --configmap app-config \
  --namespace production \
  --path ./k8s/overlays/prod \
  --kubeconfig ~/.kube/prod-cluster

Example Output

ConfigMap Diff Results

ConfigMap: app-config-m2k9tc5f8b

βœ“ config.yaml [identical]
~ settings.json [modified]
--- k8s/settings.json
+++ local/settings.json
@@ -1,5 +1,5 @@
 {
   "debug": false,
-  "timeout": 30,
+  "timeout": 60,
   "features": {
     "newUI": true
   }
 }
+ database.conf [only in local]

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1 identical β€’ 1 modified β€’ 1 only local     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Exit Codes

  • 0 - No differences found
  • 1 - Differences found or error occurred

This makes cmdiff perfect for use in CI/CD pipelines:

if cmdiff; then
  echo "No changes to apply"
else
  echo "Changes detected, applying..."
  kustomize build | kubectl apply -f -
fi

Example kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

configMapGenerator:
- name: app-config
  files:
  - config.yaml
  - settings.json
  - database.conf
- name: nginx-config
  files:
  - nginx.conf

How It Works

  1. Parse - Reads kustomization.yaml and extracts configMapGenerator entries
  2. Fetch - Connects to Kubernetes cluster and retrieves ConfigMap data
  3. Compare - Diffs each file between local and cluster versions
  4. Display - Shows beautiful, color-coded results with file-by-file breakdown

Requirements

  • Go 1.25+ (for building)
  • Access to a Kubernetes cluster with valid kubeconfig
  • A kustomization.yaml file with configMapGenerator entries

Learning Go?

This project is designed with clean, readable Go code to help you learn:

  • Package structure - Well-organized internal packages
  • Kubernetes client-go - How to interact with K8s API
  • YAML parsing - Using gopkg.in/yaml.v3
  • CLI development - Using cobra for command-line interfaces
  • Terminal UI - Using lipgloss for beautiful output
  • Error handling - Proper Go error patterns
  • Testing patterns - Clean, testable code structure

Project Structure

cmdiff/
β”œβ”€β”€ main.go                    # Entry point
β”œβ”€β”€ cmd/
β”‚   └── root.go               # CLI command definition
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ kustomize/
β”‚   β”‚   └── parser.go         # Kustomization.yaml parsing
β”‚   β”œβ”€β”€ k8s/
β”‚   β”‚   └── client.go         # Kubernetes API client
β”‚   β”œβ”€β”€ differ/
β”‚   β”‚   └── differ.go         # File comparison logic
β”‚   └── ui/
β”‚       └── display.go        # Terminal output formatting
β”œβ”€β”€ go.mod
└── README.md

Contributing

Contributions are welcome! This is a learning project, so:

  • Keep code simple and well-commented
  • Follow Go best practices
  • Add tests for new features
  • Update documentation

License

MIT License - feel free to use and modify!

Acknowledgments

Documentation ΒΆ

The Go Gopher

There is no documentation for this package.

Directories ΒΆ

Path Synopsis
internal
k8s
ui

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL