kdrift 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. kdrift-0.1.0/.cruft.json +21 -0
  2. kdrift-0.1.0/.editorconfig +15 -0
  3. kdrift-0.1.0/.env.example +6 -0
  4. kdrift-0.1.0/.github/workflows/build.yaml +48 -0
  5. kdrift-0.1.0/.github/workflows/publish.yaml +40 -0
  6. kdrift-0.1.0/.gitignore +25 -0
  7. kdrift-0.1.0/.pre-commit-config.yaml +32 -0
  8. kdrift-0.1.0/.python-version +1 -0
  9. kdrift-0.1.0/AGENTS.md +123 -0
  10. kdrift-0.1.0/CLAUDE.md +1 -0
  11. kdrift-0.1.0/Makefile +43 -0
  12. kdrift-0.1.0/PKG-INFO +13 -0
  13. kdrift-0.1.0/README.md +115 -0
  14. kdrift-0.1.0/docs/agents/AGENTS.md +21 -0
  15. kdrift-0.1.0/docs/agents/knowledge/KNOWLEDGE.md +129 -0
  16. kdrift-0.1.0/docs/agents/skills/SKILL.md +147 -0
  17. kdrift-0.1.0/docs/configuration.md +17 -0
  18. kdrift-0.1.0/docs/decisions/README.md +34 -0
  19. kdrift-0.1.0/docs/development.md +48 -0
  20. kdrift-0.1.0/pyproject.toml +127 -0
  21. kdrift-0.1.0/src/kdrift/__init__.py +5 -0
  22. kdrift-0.1.0/src/kdrift/__main__.py +5 -0
  23. kdrift-0.1.0/src/kdrift/cli.py +188 -0
  24. kdrift-0.1.0/src/kdrift/config.py +106 -0
  25. kdrift-0.1.0/src/kdrift/diff.py +232 -0
  26. kdrift-0.1.0/src/kdrift/discover.py +317 -0
  27. kdrift-0.1.0/src/kdrift/git.py +184 -0
  28. kdrift-0.1.0/src/kdrift/logging.py +82 -0
  29. kdrift-0.1.0/src/kdrift/lsp_server.py +576 -0
  30. kdrift-0.1.0/src/kdrift/mcp_server.py +165 -0
  31. kdrift-0.1.0/src/kdrift/models.py +145 -0
  32. kdrift-0.1.0/src/kdrift/pipeline.py +223 -0
  33. kdrift-0.1.0/src/kdrift/py.typed +0 -0
  34. kdrift-0.1.0/src/kdrift/render.py +182 -0
  35. kdrift-0.1.0/src/kdrift/watch.py +163 -0
  36. kdrift-0.1.0/tests/__init__.py +0 -0
  37. kdrift-0.1.0/tests/conftest.py +17 -0
  38. kdrift-0.1.0/tests/test_cli.py +85 -0
  39. kdrift-0.1.0/tests/test_config.py +66 -0
  40. kdrift-0.1.0/tests/test_diff.py +205 -0
  41. kdrift-0.1.0/tests/test_discover.py +140 -0
  42. kdrift-0.1.0/tests/test_git.py +165 -0
  43. kdrift-0.1.0/tests/test_logging.py +28 -0
  44. kdrift-0.1.0/tests/test_mcp_integration.py +196 -0
  45. kdrift-0.1.0/tests/test_models.py +113 -0
  46. kdrift-0.1.0/tests/test_pipeline.py +273 -0
  47. kdrift-0.1.0/tests/test_render.py +87 -0
  48. kdrift-0.1.0/tests/test_watch.py +51 -0
  49. kdrift-0.1.0/uv.lock +1209 -0
  50. kdrift-0.1.0/vscode-kdrift/.gitignore +4 -0
  51. kdrift-0.1.0/vscode-kdrift/.vscode/launch.json +13 -0
  52. kdrift-0.1.0/vscode-kdrift/.vscodeignore +7 -0
  53. kdrift-0.1.0/vscode-kdrift/README.md +98 -0
  54. kdrift-0.1.0/vscode-kdrift/esbuild.js +57 -0
  55. kdrift-0.1.0/vscode-kdrift/media/screenshots/hero.jpg +0 -0
  56. kdrift-0.1.0/vscode-kdrift/package.json +109 -0
  57. kdrift-0.1.0/vscode-kdrift/src/diffRunner.ts +77 -0
  58. kdrift-0.1.0/vscode-kdrift/src/driftPreviewProvider.ts +226 -0
  59. kdrift-0.1.0/vscode-kdrift/src/extension.ts +45 -0
  60. kdrift-0.1.0/vscode-kdrift/src/lspClient.ts +47 -0
  61. kdrift-0.1.0/vscode-kdrift/src/types.ts +39 -0
  62. kdrift-0.1.0/vscode-kdrift/src/webview/preview.ts +225 -0
  63. kdrift-0.1.0/vscode-kdrift/src/webview/styles.css +260 -0
  64. kdrift-0.1.0/vscode-kdrift/tsconfig.json +19 -0
@@ -0,0 +1,21 @@
1
+ {
2
+ "template": "https://github.com/missionlane/templates",
3
+ "commit": "81b9e092d4929564ea2805dc3f6c357765b2b6ee",
4
+ "checkout": null,
5
+ "context": {
6
+ "cookiecutter": {
7
+ "project_name": "kdrift",
8
+ "project_slug": "kdrift",
9
+ "package_name": "kdrift",
10
+ "description": "Kustomize manifest drift detection tool",
11
+ "python_version": "3.13",
12
+ "sonarqube_project_key": "mikedougherty.kdrift",
13
+ "has_web_server": "no",
14
+ "has_cli": "yes",
15
+ "needs_k8s_access": "no",
16
+ "_template": "https://github.com/missionlane/templates",
17
+ "_commit": "81b9e092d4929564ea2805dc3f6c357765b2b6ee"
18
+ }
19
+ },
20
+ "directory": "python-service"
21
+ }
@@ -0,0 +1,15 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 4
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+
11
+ [*.{yaml,yml,json,toml}]
12
+ indent_size = 2
13
+
14
+ [Makefile]
15
+ indent_style = tab
@@ -0,0 +1,6 @@
1
+ # kdrift Configuration
2
+ # Copy to .env and fill in values: cp .env.example .env
3
+
4
+ # --- Optional ---
5
+ # APP_LOG_LEVEL=INFO
6
+ # APP_LOG_FORMAT=json
@@ -0,0 +1,48 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths-ignore:
7
+ - "*.md"
8
+ - "!README.md"
9
+ pull_request:
10
+ branches: [main]
11
+ paths-ignore:
12
+ - "*.md"
13
+ - "!README.md"
14
+
15
+ permissions:
16
+ contents: read
17
+ pull-requests: write
18
+ checks: write
19
+
20
+ concurrency:
21
+ group: ${{ github.workflow }}-${{ github.ref }}
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ validate:
26
+ name: Lint, Type Check, Test
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - uses: astral-sh/setup-uv@v5
32
+ with:
33
+ enable-cache: true
34
+
35
+ - name: Install dependencies
36
+ run: uv sync --all-groups
37
+
38
+ - name: Lint
39
+ run: uv run ruff check .
40
+
41
+ - name: Format check
42
+ run: uv run ruff format --check .
43
+
44
+ - name: Type check
45
+ run: uv run mypy src/kdrift
46
+
47
+ - name: Test
48
+ run: uv run pytest
@@ -0,0 +1,40 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+ id-token: write
10
+
11
+ jobs:
12
+ build:
13
+ name: Build distribution
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: astral-sh/setup-uv@v5
19
+
20
+ - name: Build package
21
+ run: uv build
22
+
23
+ - uses: actions/upload-artifact@v4
24
+ with:
25
+ name: dist
26
+ path: dist/
27
+
28
+ publish:
29
+ name: Publish to PyPI
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment: pypi
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+
39
+ - name: Publish to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,25 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+
9
+ .venv/
10
+ .env
11
+
12
+ .mypy_cache/
13
+ .ruff_cache/
14
+ .pytest_cache/
15
+
16
+ coverage.xml
17
+ htmlcov/
18
+ test-results/
19
+ .coverage
20
+
21
+ .scannerwork/
22
+ .claude/
23
+
24
+ *.db
25
+ *.sqlite3
@@ -0,0 +1,32 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-toml
9
+ - id: check-added-large-files
10
+ - id: check-merge-conflict
11
+
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ rev: v0.11.12
14
+ hooks:
15
+ - id: ruff
16
+ args: [--fix]
17
+ - id: ruff-format
18
+
19
+ - repo: local
20
+ hooks:
21
+ - id: mypy
22
+ name: mypy
23
+ entry: uv run mypy src/kdrift
24
+ language: system
25
+ types: [python]
26
+ pass_filenames: false
27
+
28
+ - repo: https://github.com/compilerla/conventional-pre-commit
29
+ rev: v4.0.0
30
+ hooks:
31
+ - id: conventional-pre-commit
32
+ stages: [commit-msg]
@@ -0,0 +1 @@
1
+ 3.13
kdrift-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,123 @@
1
+ # kdrift
2
+
3
+ Kustomize manifest drift detection tool
4
+
5
+ ## Quick Reference
6
+
7
+ ```bash
8
+ make deps # Install dependencies
9
+ make validate # Run all checks (lint + typecheck + test)
10
+ make test # Run tests
11
+ make typecheck # Run mypy
12
+ ```
13
+
14
+ ## Architecture
15
+
16
+ - **Package layout:** `src/kdrift/` (src layout)
17
+ - **Config:** `pydantic-settings` BaseSettings in `config.py`, env vars with `KDRIFT_` prefix
18
+ - **Project config:** `.kdrift.yaml` with upward directory walking (project > org > user XDG)
19
+ - **Logging:** structlog with JSON output (production) / console (development)
20
+ - **Testing:** pytest with `unit`/`integration` markers, 80% coverage minimum
21
+
22
+ ### Module Map
23
+
24
+ | Module | Purpose |
25
+ |--------|---------|
26
+ | `cli.py` | click entry point, --watch/--check/--format flags |
27
+ | `discover.py` | Parse kustomization.yaml files, build reverse dependency DAG, find affected overlays |
28
+ | `render.py` | Run kustomize build as subprocess, baseline caching, parallel rendering |
29
+ | `diff.py` | Two-phase resource matching (exact GVK+ns+name, then generator-aware), unified diff |
30
+ | `pipeline.py` | Shared discover->render->diff orchestration for all frontends |
31
+ | `git.py` | Ref resolution, changed files, temporary worktree management |
32
+ | `models.py` | Pydantic models (ResourceId, OverlayResult, DiffResult, RenderResult) |
33
+ | `config.py` | AppConfig (env vars) + ProjectConfig (.kdrift.yaml hierarchy) |
34
+ | `watch.py` | Filesystem monitoring with debouncing via watchfiles |
35
+ | `logging.py` | structlog configuration |
36
+
37
+ ### Key Design Decisions
38
+
39
+ - **Kustomize as subprocess, not library:** decouples from kustomize version, user controls the binary
40
+ - **Git-status-driven discovery:** `git diff --name-only` determines changed files, dependency graph maps to overlays
41
+ - **Two-phase resource matching:** Phase 1 exact GVK+ns+name, Phase 2 generator-aware with kustomize hash charset (`bcdfghjklmnpqrstvwxz2456789`)
42
+ - **Baseline caching:** keyed by ref+overlay+kustomize-args+version, stored in `~/.cache/kdrift/`
43
+ - **Read-only git operations only:** worktrees for baseline rendering (separate index, no locks)
44
+
45
+ ## Conventions
46
+
47
+ - All tool config in `pyproject.toml` (ruff, mypy, pytest, coverage)
48
+ - mypy strict mode -- avoid `type: ignore` unless no alternative exists
49
+ - Use `pydantic.SecretStr` for credential fields in config
50
+ - Pre-commit hooks enforce formatting and type checking on every commit
51
+
52
+ ## CLI
53
+
54
+ - click-based CLI registered as `kdrift` entrypoint
55
+ - Run via `uv run kdrift` or `make run`
56
+ - Supports `-C`/`--repo` flag to target external repositories
57
+
58
+ ## Verification Commands
59
+
60
+ ```bash
61
+ make validate # Full CI-equivalent check
62
+ make test # Tests with coverage
63
+ make typecheck # mypy strict mode
64
+ make lint # ruff linter
65
+ ```
66
+
67
+ ## CI/CD
68
+
69
+ - CI runs on push to main and PRs: lint -> format-check -> typecheck -> test
70
+ - ubuntu-latest runners (not self-hosted)
71
+
72
+ ## Key Files
73
+
74
+ | File | Purpose |
75
+ |------|---------|
76
+ | `src/kdrift/config.py` | Application config (pydantic-settings) |
77
+ | `src/kdrift/logging.py` | structlog configuration |
78
+ | `src/kdrift/lsp_server.py` | LSP server (pygls) |
79
+ | `src/kdrift/mcp_server.py` | MCP server (FastMCP) |
80
+ | `tests/conftest.py` | Shared test fixtures |
81
+ | `tests/test_mcp_integration.py` | MCP integration test harness |
82
+ | `Makefile` | Standard development targets |
83
+ | `pyproject.toml` | All tool configuration |
84
+
85
+ ## Agent Development Loop
86
+
87
+ When iterating on kdrift itself, use `--debug` to enable file logging and verbose output:
88
+
89
+ ### LSP development
90
+
91
+ ```bash
92
+ # Configure VS Code: glspc.serverCommand="kdrift", glspc.serverCommandArguments=["lsp", "--debug"]
93
+ # Or without debug: glspc.serverCommandArguments=["lsp"]
94
+
95
+ # Hot-reload after code changes (no VS Code restart needed):
96
+ pkill -USR1 -f "kdrift lsp"
97
+
98
+ # Full reinstall (needed if lsp_server.py itself changes):
99
+ uv tool install -e ~/src/github.com/mikedougherty/kdrift --force
100
+ pkill -f "kdrift lsp" # VS Code auto-restarts
101
+
102
+ # Monitor logs:
103
+ tail -f ~/.cache/kdrift/kdrift.log
104
+ ```
105
+
106
+ ### MCP development
107
+
108
+ ```bash
109
+ # Run integration tests (self-contained, no session restart):
110
+ uv run python tests/test_mcp_integration.py
111
+
112
+ # Or test against a specific repo:
113
+ uv run python tests/test_mcp_integration.py /path/to/kustomize-repo
114
+ ```
115
+
116
+ ### Debug flag behavior
117
+
118
+ `--debug` on `lsp` and `mcp` subcommands enables:
119
+ - DEBUG log level (all internal events logged)
120
+ - File logging to `~/.cache/kdrift/kdrift.log`
121
+ - Full-repo diff on SIGUSR1 reload (LSP only)
122
+
123
+ Without `--debug`, LSP/MCP run quietly with WARNING level, no file log.
kdrift-0.1.0/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @./AGENTS.md
kdrift-0.1.0/Makefile ADDED
@@ -0,0 +1,43 @@
1
+ .PHONY: deps run lint format format-check typecheck test test-unit test-integration validate clean help
2
+
3
+ deps: ## Install/sync all dependencies
4
+ @uv sync --all-groups
5
+
6
+ run: ## Run the CLI
7
+ @uv run kdrift
8
+
9
+ lint: ## Run linter
10
+ @uv run ruff check .
11
+
12
+ format: ## Format code and fix auto-fixable lint issues
13
+ @uv run ruff format .
14
+ @uv run ruff check --fix .
15
+
16
+ format-check: ## Check formatting without modifying files
17
+ @uv run ruff format --check .
18
+
19
+ typecheck: ## Run type checker
20
+ @uv run mypy src/kdrift
21
+
22
+ test: ## Run all tests
23
+ @uv run pytest
24
+
25
+ test-unit: ## Run unit tests only
26
+ @uv run pytest -m unit
27
+
28
+ test-integration: ## Run integration tests only
29
+ @uv run pytest -m integration
30
+
31
+ validate: ## Run all checks (CI equivalent)
32
+ @$(MAKE) lint
33
+ @$(MAKE) format-check
34
+ @$(MAKE) typecheck
35
+ @$(MAKE) test
36
+
37
+ clean: ## Remove build artifacts
38
+ @rm -rf .mypy_cache .pytest_cache .ruff_cache htmlcov coverage.xml test-results/ .coverage
39
+
40
+ help: ## Show this help
41
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
42
+
43
+ .DEFAULT_GOAL := help
kdrift-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: kdrift
3
+ Version: 0.1.0
4
+ Summary: Kustomize manifest drift detection tool
5
+ Requires-Python: >=3.13
6
+ Requires-Dist: click>=8.0
7
+ Requires-Dist: mcp>=1.27.2
8
+ Requires-Dist: pydantic-settings>=2.0
9
+ Requires-Dist: pydantic>=2.0
10
+ Requires-Dist: pygls>=2.1.1
11
+ Requires-Dist: pyyaml>=6.0.3
12
+ Requires-Dist: structlog>=24.0
13
+ Requires-Dist: watchfiles>=1.2.0
kdrift-0.1.0/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # kdrift
2
+
3
+ CLI, MCP, LSP, and VS Code extension for kustomize manifest drift detection. Discovers which overlays are affected by your changes, renders baselines and candidates, and diffs per-resource.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ # From GitHub (recommended for now)
9
+ uv tool install git+https://github.com/mikedougherty/kdrift
10
+
11
+ # From PyPI (once published)
12
+ uv tool install kdrift
13
+ ```
14
+
15
+ Requires Python 3.13+ and `kustomize` on PATH.
16
+
17
+ ## Usage
18
+
19
+ ```bash
20
+ kdrift diff # diff all affected overlays vs HEAD
21
+ kdrift diff k8s/base/deployment.yaml # diff overlays affected by this file
22
+ kdrift diff --overlay k8s/dev # diff only this overlay
23
+ kdrift diff --ref main~3 # diff against a specific ref
24
+ kdrift diff --ref main~5..main~2 # compare two commits
25
+ kdrift diff -C /path/to/repo # target a different repository
26
+ kdrift diff --format json # structured JSON output
27
+ kdrift diff --check # exit non-zero if drift exists (CI/pre-commit)
28
+ kdrift diff --watch # continuous mode: re-diff on file save
29
+ ```
30
+
31
+ ## How It Works
32
+
33
+ 1. `git diff --name-only HEAD` finds changed files
34
+ 2. Dependency graph maps changes to affected leaf overlays (parses all `kustomization.yaml` reference types)
35
+ 3. `kustomize build` renders baseline (via git worktree, cached) and candidate (working tree)
36
+ 4. Two-phase per-resource diff: exact GVK+namespace+name match, then generator-aware matching for hash-suffixed ConfigMap/Secret names
37
+ 5. Output as unified diff or structured JSON
38
+
39
+ ## Configuration
40
+
41
+ Create `.kdrift.yaml` anywhere in your directory tree (searched upward from CWD):
42
+
43
+ ```yaml
44
+ kustomize_args:
45
+ - "--enable-helm"
46
+ - "--load-restrictor"
47
+ - "LoadRestrictionsNone"
48
+ ```
49
+
50
+ ## Development
51
+
52
+ ```bash
53
+ make deps # Install dependencies
54
+ make validate # Run all checks (lint + typecheck + test)
55
+ make test # Tests only
56
+ make typecheck # mypy strict mode
57
+ ```
58
+
59
+ See [docs/development.md](docs/development.md) for detailed setup.
60
+
61
+ ## Quick Start: MCP Server for Claude Code
62
+
63
+ Give your AI agent kustomize drift detection in two steps:
64
+
65
+ **1. Install kdrift:**
66
+
67
+ ```bash
68
+ uv tool install git+https://github.com/mikedougherty/kdrift
69
+ ```
70
+
71
+ **2. Add to your Claude Code MCP config** (`.claude.json` or project `.mcp.json`):
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "kdrift": {
77
+ "command": "kdrift",
78
+ "args": ["mcp"]
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ That's it. Your agent now has four tools: `kdrift_diff`, `kdrift_discover`, `kdrift_affected`, `kdrift_render`. Ask it to "check what my kustomize changes affect" and it will use them.
85
+
86
+ **3. (Optional) Add agent instructions** for deeper context on how to use kdrift:
87
+
88
+ ```markdown
89
+ @path/to/kdrift/docs/agents/AGENTS.md
90
+ ```
91
+
92
+ Or copy `docs/agents/` into your project's agent instructions directory. The files are self-contained and agent-agnostic.
93
+
94
+ ## Agent Integration
95
+
96
+ kdrift ships with agent-readable instructions in `docs/agents/`. These work with any AI coding assistant that supports `AGENTS.md` or similar instruction files.
97
+
98
+ ### VS Code Extension
99
+
100
+ The `vscode-kdrift/` directory contains a VS Code extension that shows drift diffs in a side panel, modeled after the built-in Markdown Preview. See [vscode-kdrift/README.md](vscode-kdrift/README.md) for setup and development.
101
+
102
+ ### LSP Server (IDE integration)
103
+
104
+ ```bash
105
+ kdrift lsp # stdio transport, configure in your LSP client
106
+ kdrift lsp --debug # enable file logging to ~/.cache/kdrift/kdrift.log
107
+ ```
108
+
109
+ Provides diagnostics on save, CodeLens annotations, and hover info.
110
+
111
+ ## Documentation
112
+
113
+ - [Development Guide](docs/development.md)
114
+ - [Configuration](docs/configuration.md)
115
+ - [Agent Instructions](docs/agents/AGENTS.md)
@@ -0,0 +1,21 @@
1
+ # kdrift Agent Instructions
2
+
3
+ Agent-readable instructions for using kdrift in kustomize repositories.
4
+
5
+ ## Load When
6
+
7
+ - Working in a repository with `kustomization.yaml` files
8
+ - Using kustomize, kubectl, or Helm to manage Kubernetes manifests
9
+ - Reviewing PRs that touch kustomize overlays, bases, or patches
10
+
11
+ ## Knowledge
12
+
13
+ Concepts, architecture, configuration, and tool reference:
14
+
15
+ @./knowledge/KNOWLEDGE.md
16
+
17
+ ## Skills
18
+
19
+ How to use kdrift (MCP tools and CLI) to detect manifest drift:
20
+
21
+ @./skills/SKILL.md
@@ -0,0 +1,129 @@
1
+ # kdrift Knowledge
2
+
3
+ Kustomize manifest drift detection. Shows exactly what your kustomize edits will change in rendered Kubernetes manifests before you commit, push, or apply.
4
+
5
+ ## Core Concepts
6
+
7
+ **Leaf overlay**: A kustomization directory that no other kustomization references. These are deployment targets (e.g., `k8s/dev`, `k8s/prod`). Base directories that get referenced by overlays are not leaves.
8
+
9
+ **Dependency graph**: kdrift builds a reverse dependency map from every file to the leaf overlays that transitively include it. When you edit `k8s/base/deployment.yaml`, kdrift knows which overlays (`k8s/dev`, `k8s/staging`, `k8s/prod`) are affected.
10
+
11
+ **Baseline vs candidate**: The baseline is the rendered output at a git ref (default: HEAD). The candidate is the rendered output from the working tree (or a second ref). kdrift diffs them per-resource.
12
+
13
+ **Two-phase resource matching**: Phase 1 matches resources by exact GVK + namespace + name. Phase 2 handles configMapGenerator/secretGenerator hash-suffixed names using the kustomize hash charset (`bcdfghjklmnpqrstvwxz2456789`).
14
+
15
+ **Two-ref comparison**: Compare any two git refs (`--ref main~5..main~2`) instead of working tree vs HEAD. Uses two temporary worktrees.
16
+
17
+ ## Delivery Surfaces
18
+
19
+ | Surface | Invocation | Best for |
20
+ |---------|-----------|----------|
21
+ | **CLI** | `kdrift diff` | Terminal workflows, CI/CD, pre-commit hooks |
22
+ | **MCP** | `kdrift mcp` (stdio) | AI agents (Claude Code, etc.) with structured JSON |
23
+ | **LSP** | `kdrift lsp` (stdio) | IDE integration (VS Code, Neovim) with diagnostics on save |
24
+
25
+ ## Configuration
26
+
27
+ ### Project config (`.kdrift.yaml`)
28
+
29
+ kdrift searches upward from CWD for `.kdrift.yaml`:
30
+
31
+ ```yaml
32
+ kustomize_args:
33
+ - "--enable-helm"
34
+ - "--load-restrictor"
35
+ - "LoadRestrictionsNone"
36
+ ```
37
+
38
+ Search order: project directory, parent directories, `$XDG_CONFIG_HOME/kdrift/`.
39
+
40
+ ### Environment variables
41
+
42
+ | Variable | Default | Description |
43
+ |----------|---------|-------------|
44
+ | `KDRIFT_LOG_LEVEL` | `WARNING` | Log level (DEBUG, INFO, WARNING, ERROR) |
45
+ | `KDRIFT_LOG_FORMAT` | `json` | Log format (`json` or `console`) |
46
+
47
+ ### MCP configuration
48
+
49
+ Add to your agent's MCP config (e.g., `.claude.json`, `claude_desktop_config.json`):
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "kdrift": {
55
+ "command": "kdrift",
56
+ "args": ["mcp"]
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ ### LSP configuration (VS Code)
63
+
64
+ Using the Generic LSP Client (glspc) extension:
65
+
66
+ ```json
67
+ {
68
+ "glspc.serverCommand": "kdrift",
69
+ "glspc.serverCommandArguments": ["lsp"]
70
+ }
71
+ ```
72
+
73
+ Add `--debug` to enable file logging to `~/.cache/kdrift/kdrift.log`.
74
+
75
+ ## MCP Tools Reference
76
+
77
+ | Tool | Description |
78
+ |------|-------------|
79
+ | `kdrift_diff` | Diff overlays against a baseline ref. Returns per-overlay, per-resource structured JSON. Supports `target_ref` for two-ref comparison. |
80
+ | `kdrift_discover` | Find leaf overlays. Defaults to git-changed overlays; `show_all=true` for the full list. |
81
+ | `kdrift_affected` | Given a list of changed files, find which overlays are affected. |
82
+ | `kdrift_render` | Render a single overlay to YAML. |
83
+
84
+ ## Output Structure
85
+
86
+ All tools return JSON. The diff result structure:
87
+
88
+ ```json
89
+ {
90
+ "ref": "abc1234",
91
+ "target_ref": null,
92
+ "overlays": [
93
+ {
94
+ "path": "k8s/dev",
95
+ "changes": [
96
+ {
97
+ "resource_id": {
98
+ "group": "apps", "version": "v1", "kind": "Deployment",
99
+ "namespace": "myapp", "name": "api-server"
100
+ },
101
+ "status": "modified",
102
+ "diff_text": "...",
103
+ "lines_added": 1,
104
+ "lines_removed": 1
105
+ }
106
+ ],
107
+ "error": null
108
+ }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ Status values: `modified`, `added`, `removed`.
114
+
115
+ ## Error Handling
116
+
117
+ When `kustomize build` fails for one overlay, kdrift reports the error and continues with others. The `error` field is set per-overlay. Exit code is non-zero if any overlay errored.
118
+
119
+ Baseline build failures (the ref version was already broken) are reported as `"baseline build failed (pre-existing)"` to distinguish from regressions you introduced.
120
+
121
+ ## Caching
122
+
123
+ Baseline renders are cached at `~/.cache/kdrift/` keyed by ref SHA + overlay path + kustomize version + args. Working tree renders are never cached.
124
+
125
+ ## Prerequisites
126
+
127
+ - `kustomize` binary on PATH (kdrift shells out to it, does not embed kustomize)
128
+ - Git repository with at least one commit
129
+ - Python 3.13+ (for installation via `uv tool install`)