kekkai-cli 2.0.1__tar.gz → 2.2.1__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 (149) hide show
  1. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/PKG-INFO +19 -30
  2. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/README.md +18 -29
  3. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/pyproject.toml +2 -2
  4. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/cli.py +49 -1
  5. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/output.py +1 -1
  6. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/__init__.py +6 -0
  7. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/app.py +12 -0
  8. kekkai_cli-2.2.1/src/kekkai/triage/code_context.py +369 -0
  9. kekkai_cli-2.2.1/src/kekkai/triage/editor_support.py +166 -0
  10. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/fix_screen.py +34 -4
  11. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/screens.py +240 -0
  12. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_cli.egg-info/PKG-INFO +19 -30
  13. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_cli.egg-info/SOURCES.txt +6 -0
  14. kekkai_cli-2.2.1/tests/test_editor_support.py +172 -0
  15. kekkai_cli-2.2.1/tests/test_triage_code_context.py +333 -0
  16. kekkai_cli-2.2.1/tests/test_triage_editor.py +408 -0
  17. kekkai_cli-2.2.1/tests/test_triage_security.py +194 -0
  18. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/setup.cfg +0 -0
  19. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/__init__.py +0 -0
  20. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/__init__.py +0 -0
  21. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/hipaa.py +0 -0
  22. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/mappings.py +0 -0
  23. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/owasp.py +0 -0
  24. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/owasp_agentic.py +0 -0
  25. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/pci_dss.py +0 -0
  26. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/compliance/soc2.py +0 -0
  27. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/config.py +0 -0
  28. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/dojo.py +0 -0
  29. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/dojo_import.py +0 -0
  30. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/fix/__init__.py +0 -0
  31. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/fix/audit.py +0 -0
  32. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/fix/differ.py +0 -0
  33. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/fix/engine.py +0 -0
  34. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/fix/prompts.py +0 -0
  35. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/github/__init__.py +0 -0
  36. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/github/commenter.py +0 -0
  37. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/github/models.py +0 -0
  38. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/github/sanitizer.py +0 -0
  39. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/installer/__init__.py +0 -0
  40. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/installer/errors.py +0 -0
  41. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/installer/extract.py +0 -0
  42. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/installer/manager.py +0 -0
  43. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/installer/manifest.py +0 -0
  44. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/installer/verify.py +0 -0
  45. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/manifest.py +0 -0
  46. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/paths.py +0 -0
  47. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/policy.py +0 -0
  48. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/report/__init__.py +0 -0
  49. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/report/compliance_matrix.py +0 -0
  50. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/report/generator.py +0 -0
  51. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/report/html.py +0 -0
  52. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/report/pdf.py +0 -0
  53. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/report/unified.py +0 -0
  54. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/runner.py +0 -0
  55. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/__init__.py +0 -0
  56. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/backends/__init__.py +0 -0
  57. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/backends/base.py +0 -0
  58. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/backends/docker.py +0 -0
  59. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/backends/native.py +0 -0
  60. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/base.py +0 -0
  61. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/container.py +0 -0
  62. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/falco.py +0 -0
  63. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/gitleaks.py +0 -0
  64. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/semgrep.py +0 -0
  65. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/trivy.py +0 -0
  66. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/url_policy.py +0 -0
  67. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/scanners/zap.py +0 -0
  68. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/__init__.py +0 -0
  69. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/artifacts.py +0 -0
  70. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/chunking.py +0 -0
  71. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/core.py +0 -0
  72. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/mermaid.py +0 -0
  73. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/model_adapter.py +0 -0
  74. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/prompts.py +0 -0
  75. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/redaction.py +0 -0
  76. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/threatflow/sanitizer.py +0 -0
  77. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/audit.py +0 -0
  78. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/ignore.py +0 -0
  79. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/loader.py +0 -0
  80. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/models.py +0 -0
  81. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai/triage/widgets.py +0 -0
  82. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_cli.egg-info/dependency_links.txt +0 -0
  83. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_cli.egg-info/entry_points.txt +0 -0
  84. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_cli.egg-info/requires.txt +0 -0
  85. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_cli.egg-info/top_level.txt +0 -0
  86. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/__init__.py +0 -0
  87. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/ci/__init__.py +0 -0
  88. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/ci/benchmarks.py +0 -0
  89. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/ci/metadata.py +0 -0
  90. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/ci/validators.py +0 -0
  91. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/docker/__init__.py +0 -0
  92. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/docker/metadata.py +0 -0
  93. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/docker/sbom.py +0 -0
  94. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/docker/security.py +0 -0
  95. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/docker/signing.py +0 -0
  96. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/redaction.py +0 -0
  97. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/slsa/__init__.py +0 -0
  98. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/slsa/verify.py +0 -0
  99. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/windows/__init__.py +0 -0
  100. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/windows/chocolatey.py +0 -0
  101. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/windows/installer.py +0 -0
  102. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/windows/scoop.py +0 -0
  103. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/src/kekkai_core/windows/validators.py +0 -0
  104. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_cli_output.py +0 -0
  105. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_compliance.py +0 -0
  106. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_dojo_import.py +0 -0
  107. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_fix_engine.py +0 -0
  108. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_github_commenter_filter.py +0 -0
  109. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_github_commenter_format.py +0 -0
  110. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_github_commenter_limit.py +0 -0
  111. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_github_commenter_sanitize.py +0 -0
  112. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_installer_checksum.py +0 -0
  113. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_installer_extract.py +0 -0
  114. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_installer_manager.py +0 -0
  115. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_installer_manifest.py +0 -0
  116. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_installer_platform.py +0 -0
  117. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_cli.py +0 -0
  118. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_config.py +0 -0
  119. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_dojo.py +0 -0
  120. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_dojo_cli.py +0 -0
  121. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_manifest.py +0 -0
  122. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_paths.py +0 -0
  123. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_kekkai_runner.py +0 -0
  124. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_mermaid.py +0 -0
  125. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_policy.py +0 -0
  126. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_redaction.py +0 -0
  127. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_report.py +0 -0
  128. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_backends.py +0 -0
  129. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_base.py +0 -0
  130. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_container.py +0 -0
  131. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_digest_defaults.py +0 -0
  132. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_falco.py +0 -0
  133. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_gitleaks.py +0 -0
  134. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_native.py +0 -0
  135. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_semgrep.py +0 -0
  136. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_trivy.py +0 -0
  137. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_scanner_zap.py +0 -0
  138. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_slsa_provenance.py +0 -0
  139. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_threatflow_chunking.py +0 -0
  140. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_threatflow_model_adapter.py +0 -0
  141. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_threatflow_prompts.py +0 -0
  142. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_threatflow_redaction.py +0 -0
  143. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_threatflow_sanitizer.py +0 -0
  144. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_triage_audit.py +0 -0
  145. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_triage_ignore.py +0 -0
  146. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_triage_loader.py +0 -0
  147. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_triage_models.py +0 -0
  148. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_unified_report.py +0 -0
  149. {kekkai_cli-2.0.1 → kekkai_cli-2.2.1}/tests/test_url_policy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kekkai-cli
3
- Version: 2.0.1
3
+ Version: 2.2.1
4
4
  Summary: Terminal UI for Trivy/Semgrep/Gitleaks. Local-first security triage.
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -14,19 +14,20 @@ Requires-Dist: jinja2>=3.1.6
14
14
  <img src="https://raw.githubusercontent.com/kademoslabs/assets/main/logos/kekkai-slim.png" alt="Kekkai CLI Logo" width="250"/>
15
15
  </p>
16
16
 
17
- <p align="center"><strong>Stop parsing JSON. Security triage in your terminal.</strong></p>
17
+ <p align="center"><strong>Interactive security triage in the terminal.</strong></p>
18
18
 
19
19
  <p align="center">
20
20
  <img src="https://img.shields.io/github/actions/workflow/status/kademoslabs/kekkai/docker-publish.yml?logo=github"/>
21
21
  <img src="https://img.shields.io/circleci/build/github/kademoslabs/kekkai?logo=circleci"/>
22
- <img src="https://img.shields.io/pypi/v/kekkai-cli?pypiBaseUrl=https%3A%2F%2Fpypi.org&logo=pypi"/>
22
+ <img alt="PyPI - Version" src="https://img.shields.io/pypi/v/kekkai-cli">
23
+
23
24
  </p>
24
25
 
25
26
  ---
26
27
 
27
28
  # Kekkai
28
29
 
29
- **Interactive security triage in the terminal.**
30
+ **Stop parsing JSON.**
30
31
 
31
32
  Kekkai is a small open-source CLI that wraps existing security scanners (Trivy, Semgrep, Gitleaks) and focuses on the part that tends to be slow and frustrating: reviewing and triaging results.
32
33
 
@@ -73,6 +74,17 @@ kekkai triage
73
74
  # Interactive TUI to review findings with keyboard navigation
74
75
  ```
75
76
 
77
+ ### ⚡️ Auto-Install (Pre-commit)
78
+
79
+ Add this to your `.pre-commit-config.yaml` to scan on every commit:
80
+
81
+ ```yaml
82
+ - repo: [https://github.com/kademoslabs/kekkai](https://github.com/kademoslabs/kekkai)
83
+ rev: v2.0.1
84
+ hooks:
85
+ - id: kekkai-scan
86
+ ```
87
+
76
88
  No signup, no cloud service required.
77
89
 
78
90
  ---
@@ -114,34 +126,11 @@ kekkai triage
114
126
 
115
127
  ---
116
128
 
117
- ### CI/CD Policy Gate
118
-
119
- Break builds on severity thresholds.
120
-
121
- Kekkai can be used as a CI gate based on severity thresholds.
129
+ ### 🚦 CI/CD in 1 Second
122
130
 
131
+ Don't write YAML. Run this in your repo:
123
132
  ```bash
124
- # Fail on any critical or high findings
125
- kekkai scan --ci --fail-on high
126
-
127
- # Fail only on critical
128
- kekkai scan --ci --fail-on critical
129
- ```
130
-
131
- **Exit Codes:**
132
- | Code | Meaning |
133
- |------|---------|
134
- | 0 | No findings above threshold |
135
- | 1 | Findings exceed threshold |
136
- | 2 | Scanner error |
137
-
138
- **GitHub Actions Example:**
139
-
140
- ```yaml
141
- - name: Security Scan
142
- run: |
143
- pipx install kekkai-cli
144
- kekkai scan --ci --fail-on high
133
+ kekkai init --ci
145
134
  ```
146
135
 
147
136
  [Full CI Documentation →](docs/ci/ci-mode.md)
@@ -2,19 +2,20 @@
2
2
  <img src="https://raw.githubusercontent.com/kademoslabs/assets/main/logos/kekkai-slim.png" alt="Kekkai CLI Logo" width="250"/>
3
3
  </p>
4
4
 
5
- <p align="center"><strong>Stop parsing JSON. Security triage in your terminal.</strong></p>
5
+ <p align="center"><strong>Interactive security triage in the terminal.</strong></p>
6
6
 
7
7
  <p align="center">
8
8
  <img src="https://img.shields.io/github/actions/workflow/status/kademoslabs/kekkai/docker-publish.yml?logo=github"/>
9
9
  <img src="https://img.shields.io/circleci/build/github/kademoslabs/kekkai?logo=circleci"/>
10
- <img src="https://img.shields.io/pypi/v/kekkai-cli?pypiBaseUrl=https%3A%2F%2Fpypi.org&logo=pypi"/>
10
+ <img alt="PyPI - Version" src="https://img.shields.io/pypi/v/kekkai-cli">
11
+
11
12
  </p>
12
13
 
13
14
  ---
14
15
 
15
16
  # Kekkai
16
17
 
17
- **Interactive security triage in the terminal.**
18
+ **Stop parsing JSON.**
18
19
 
19
20
  Kekkai is a small open-source CLI that wraps existing security scanners (Trivy, Semgrep, Gitleaks) and focuses on the part that tends to be slow and frustrating: reviewing and triaging results.
20
21
 
@@ -61,6 +62,17 @@ kekkai triage
61
62
  # Interactive TUI to review findings with keyboard navigation
62
63
  ```
63
64
 
65
+ ### ⚡️ Auto-Install (Pre-commit)
66
+
67
+ Add this to your `.pre-commit-config.yaml` to scan on every commit:
68
+
69
+ ```yaml
70
+ - repo: [https://github.com/kademoslabs/kekkai](https://github.com/kademoslabs/kekkai)
71
+ rev: v2.0.1
72
+ hooks:
73
+ - id: kekkai-scan
74
+ ```
75
+
64
76
  No signup, no cloud service required.
65
77
 
66
78
  ---
@@ -102,34 +114,11 @@ kekkai triage
102
114
 
103
115
  ---
104
116
 
105
- ### CI/CD Policy Gate
106
-
107
- Break builds on severity thresholds.
108
-
109
- Kekkai can be used as a CI gate based on severity thresholds.
117
+ ### 🚦 CI/CD in 1 Second
110
118
 
119
+ Don't write YAML. Run this in your repo:
111
120
  ```bash
112
- # Fail on any critical or high findings
113
- kekkai scan --ci --fail-on high
114
-
115
- # Fail only on critical
116
- kekkai scan --ci --fail-on critical
117
- ```
118
-
119
- **Exit Codes:**
120
- | Code | Meaning |
121
- |------|---------|
122
- | 0 | No findings above threshold |
123
- | 1 | Findings exceed threshold |
124
- | 2 | Scanner error |
125
-
126
- **GitHub Actions Example:**
127
-
128
- ```yaml
129
- - name: Security Scan
130
- run: |
131
- pipx install kekkai-cli
132
- kekkai scan --ci --fail-on high
121
+ kekkai init --ci
133
122
  ```
134
123
 
135
124
  [Full CI Documentation →](docs/ci/ci-mode.md)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kekkai-cli"
3
- version = "2.0.1"
3
+ version = "2.2.1"
4
4
  description = "Terminal UI for Trivy/Semgrep/Gitleaks. Local-first security triage."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -21,7 +21,7 @@ line-length = 100
21
21
  extend-exclude = ["dist", "build", ".venv"]
22
22
  lint.select = ["E", "F", "I", "B", "UP", "S", "SIM"]
23
23
  lint.ignore = ["S101"] # allow asserts in tests
24
- lint.per-file-ignores = { "tests/**" = ["S"], "src/kekkai_core/docker/**" = ["S603"], "src/kekkai_core/slsa/**" = ["S603", "S607"], "src/kekkai/github/**" = ["S105"] }
24
+ lint.per-file-ignores = { "tests/**" = ["S", "SIM117"], "src/kekkai_core/docker/**" = ["S603"], "src/kekkai_core/slsa/**" = ["S603", "S607"], "src/kekkai/github/**" = ["S105"] }
25
25
 
26
26
  [tool.mypy]
27
27
  python_version = "3.12"
@@ -221,6 +221,17 @@ def main(argv: Sequence[str] | None = None) -> int:
221
221
  type=str,
222
222
  help="Path for .kekkaiignore output (default: .kekkaiignore)",
223
223
  )
224
+ triage_parser.add_argument(
225
+ "--repo",
226
+ type=str,
227
+ help="Repository root path (default: auto-detect from run.json)",
228
+ )
229
+ triage_parser.add_argument(
230
+ "--context-lines",
231
+ type=int,
232
+ default=10,
233
+ help="Context lines before/after line (default: 10, range: 5-100)",
234
+ )
224
235
 
225
236
  # Fix subcommand - AI-powered remediation
226
237
  fix_parser = subparsers.add_parser("fix", help="generate AI-powered code fixes for findings")
@@ -1186,6 +1197,11 @@ def _command_triage(parsed: argparse.Namespace) -> int:
1186
1197
 
1187
1198
  input_path_str = cast(str | None, getattr(parsed, "input", None))
1188
1199
  output_path_str = cast(str | None, getattr(parsed, "output", None))
1200
+ repo_path_str = cast(str | None, getattr(parsed, "repo", None))
1201
+ context_lines = cast(int, getattr(parsed, "context_lines", 10))
1202
+
1203
+ # Validate context_lines range
1204
+ context_lines = max(5, min(100, context_lines))
1189
1205
 
1190
1206
  # Default to latest run if no input specified
1191
1207
  if not input_path_str:
@@ -1232,7 +1248,39 @@ def _command_triage(parsed: argparse.Namespace) -> int:
1232
1248
 
1233
1249
  console.print(f"[info]Loaded {len(findings)} finding(s)[/info]\n")
1234
1250
 
1235
- return run_triage(findings=findings, output_path=output_path)
1251
+ # Auto-detect repo_path from run.json if not explicitly provided
1252
+ repo_path: Path | None = None
1253
+ if repo_path_str:
1254
+ repo_path = Path(repo_path_str).expanduser().resolve()
1255
+ elif input_path.is_dir():
1256
+ # Try to read repo_path from run.json
1257
+ manifest_path = input_path / "run.json"
1258
+ if manifest_path.exists():
1259
+ try:
1260
+ import json
1261
+
1262
+ with manifest_path.open() as f:
1263
+ manifest_data = json.load(f)
1264
+ stored_repo = manifest_data.get("repo_path")
1265
+ if stored_repo:
1266
+ repo_path = Path(stored_repo).expanduser().resolve()
1267
+ console.print(f"[dim]Using repo path from run metadata: {repo_path}[/dim]\n")
1268
+ except (OSError, json.JSONDecodeError, KeyError):
1269
+ pass
1270
+
1271
+ # Fall back to current directory if still not set (with warning)
1272
+ if repo_path is None:
1273
+ repo_path = Path.cwd()
1274
+ console.print("[warning]⚠ Repo path not detected. Using current directory.[/warning]")
1275
+ console.print("[dim]Tip: Use --repo to specify repository root explicitly.[/dim]")
1276
+ console.print(f"[dim]Current directory: {repo_path}[/dim]\n")
1277
+
1278
+ return run_triage(
1279
+ findings=findings,
1280
+ output_path=output_path,
1281
+ repo_path=repo_path,
1282
+ context_lines=context_lines,
1283
+ )
1236
1284
 
1237
1285
 
1238
1286
  def _command_fix(parsed: argparse.Namespace) -> int:
@@ -57,7 +57,7 @@ BANNER_ASCII = r"""
57
57
  /_/\_\\___/_/\_/_/\_\\_,_/_/
58
58
  """
59
59
 
60
- VERSION = "2.0.1"
60
+ VERSION = "2.2.1"
61
61
 
62
62
 
63
63
  def print_dashboard() -> None:
@@ -29,6 +29,8 @@ def run_triage(
29
29
  input_path: Path | None = None,
30
30
  output_path: Path | None = None,
31
31
  findings: Sequence[FindingEntry] | None = None,
32
+ repo_path: Path | None = None,
33
+ context_lines: int = 10,
32
34
  ) -> int:
33
35
  """Run the triage TUI (lazy import).
34
36
 
@@ -36,6 +38,8 @@ def run_triage(
36
38
  input_path: Path to findings JSON file.
37
39
  output_path: Path for .kekkaiignore output.
38
40
  findings: Pre-loaded findings (alternative to input_path).
41
+ repo_path: Repository root path for code context display.
42
+ context_lines: Number of lines to show before/after vulnerable line.
39
43
 
40
44
  Returns:
41
45
  Exit code (0 for success).
@@ -50,6 +54,8 @@ def run_triage(
50
54
  input_path=input_path,
51
55
  output_path=output_path,
52
56
  findings=findings,
57
+ repo_path=repo_path,
58
+ context_lines=context_lines,
53
59
  )
54
60
  except ImportError as e:
55
61
  raise RuntimeError(
@@ -51,6 +51,8 @@ class TriageApp(App[None]):
51
51
  input_path: Path | None = None,
52
52
  output_path: Path | None = None,
53
53
  audit_path: Path | None = None,
54
+ repo_path: Path | None = None,
55
+ context_lines: int = 10,
54
56
  ) -> None:
55
57
  """Initialize triage application.
56
58
 
@@ -59,6 +61,8 @@ class TriageApp(App[None]):
59
61
  input_path: Path to findings JSON file.
60
62
  output_path: Path for .kekkaiignore output.
61
63
  audit_path: Path for audit log.
64
+ repo_path: Repository root path for code context display.
65
+ context_lines: Number of lines to show before/after vulnerable line.
62
66
  """
63
67
  super().__init__()
64
68
  self._input_path = input_path
@@ -66,6 +70,8 @@ class TriageApp(App[None]):
66
70
  self.ignore_file = IgnoreFile(output_path)
67
71
  self.audit_log = TriageAuditLog(audit_path)
68
72
  self._decisions: dict[str, TriageDecision] = {}
73
+ self.repo_path = repo_path or Path.cwd()
74
+ self.context_lines = context_lines
69
75
 
70
76
  @property
71
77
  def findings(self) -> list[FindingEntry]:
@@ -148,6 +154,8 @@ def run_triage(
148
154
  input_path: Path | None = None,
149
155
  output_path: Path | None = None,
150
156
  findings: Sequence[FindingEntry] | None = None,
157
+ repo_path: Path | None = None,
158
+ context_lines: int = 10,
151
159
  ) -> int:
152
160
  """Run the triage TUI.
153
161
 
@@ -155,6 +163,8 @@ def run_triage(
155
163
  input_path: Path to findings JSON file.
156
164
  output_path: Path for .kekkaiignore output.
157
165
  findings: Pre-loaded findings (alternative to input_path).
166
+ repo_path: Repository root path for code context display.
167
+ context_lines: Number of lines to show before/after vulnerable line.
158
168
 
159
169
  Returns:
160
170
  Exit code (0 for success).
@@ -163,6 +173,8 @@ def run_triage(
163
173
  findings=findings,
164
174
  input_path=input_path,
165
175
  output_path=output_path,
176
+ repo_path=repo_path,
177
+ context_lines=context_lines,
166
178
  )
167
179
  app.run()
168
180
  return 0