Observed since 21 Oct, 10:49 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
ai-govern
CLI-first AI Governance platform that audits AI-enabled repositories for AI engineering best practices
"AI Govern verifies that your AI system is engineered correctly — not that your application code is written correctly."
AI Govern is a CLI-first AI Governance platform that audits AI-enabled repositories for AI engineering best practices. Think of it as ESLint + Lighthouse + SonarQube — but exclusively for AI systems.
AI Govern scans only the AI layer of your repository:
✅ Analyzes — CLAUDE.md, AGENTS.md, GEMINI.md, Cursor rules, Copilot instructions, prompt templates, skill definitions, agent workflows, MCP servers, tool definitions, LLM configurations, RAG configs, memory strategies
❌ Ignores — CRUD endpoints, React components, CSS, database schemas, authentication, general business logic
pip install ai-govern
# Scan current directory and open dashboard
ai-govern run
# Scan a specific repository
ai-govern run /path/to/your/ai-repo
# Generate standalone HTML report
ai-govern report
# Auto-fix issues interactively
ai-govern fix
# CI mode (returns exit code 1 if score below threshold)
ai-govern run --ci --output json
# Initialize configuration
ai-govern init
# List all governance rules
ai-govern plugins
Running ai-govern run launches a local dashboard at http://localhost:5172:
| Category | Weight | Example Rules |
|---|---|---|
| Security | 20% | Hardcoded API keys, prompt injection |
| Context | 15% | Missing CLAUDE.md, poor context quality |
| Prompt Engineering | 15% | Missing system prompt, duplicate prompts |
| Cost Optimization | 10% | No caching, no token limits |
| Agents | 10% | Missing descriptions, circular workflows |
| Observability | 8% | No telemetry, no token tracking |
| Documentation | 7% | Missing skill docs, no README AI section |
| RAG | 5% | No chunking strategy, no embedding model spec |
| Memory | 4% | No memory strategy, unbounded history |
| Tools/MCP | 3% | Missing tool descriptions, insecure transport |
| Model Governance | 3% | Unpinned model versions |
| Automation | 1% | LLM used for UUID/JSON/date formatting |
Create ai-govern.yaml in your repository root:
# Governance Policy
min_governance_score: 70.0
fail_on_critical: true
# Disable specific rules
disabled_rules:
- PE001 # Hardcoded prompts (if you prefer inline prompts)
# LLM Analysis (optional)
llm:
enabled: false
provider: openai
model: gpt-4o-mini
api_key_env: OPENAI_API_KEY
# Dashboard
dashboard_port: 5172
auto_open_browser: true
Run ai-govern init to generate this file automatically.
# .github/workflows/ai-governance.yml
- name: AI Governance Check
run: |
pip install ai-govern
ai-govern run --ci --output sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ai-govern-report.sarif
Write custom governance rules:
from ai_govern.plugins.sdk import GovernanceRule, RuleCategory, Severity, ScanContext, GovernanceIssue
class MyCustomRule(GovernanceRule):
rule_id = "CUSTOM001"
name = "My Custom Rule"
category = RuleCategory.AGENTS
severity = Severity.MEDIUM
def evaluate(self, context: ScanContext) -> list[GovernanceIssue]:
# Your rule logic here
return []
Register in pyproject.toml:
[project.entry-points."ai_govern.rules"]
my_rule = "my_plugin.rules:MyCustomRule"
ai-govern run
│
├── FileScanner (AI-only file discovery)
│ └── AI relevance filtering (50+ patterns)
│
├── RuleEngine
│ ├── RuleRegistry (built-in + plugins via entry_points)
│ ├── RuleExecutor (concurrent, thread-pool)
│ └── Scorer (weighted category scoring)
│
├── AutoFixEngine (propose → preview → approve → apply → rollback)
│
└── FastAPI Server
├── API v1 (scan, issues, fixes, plugins, config)
└── React Dashboard (pre-built, served as static files)
MIT License — see LICENSE for details.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
aiofilesEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aiofiles>=23.2.0 | runtime |
anyioEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | anyio>=4.4.0 | runtime |
fastapiEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | fastapi>=0.115.0 | runtime |
gitpythonEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | gitpython>=3.1.0 | runtime |
httpxEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | httpx>=0.27.0 | runtime |
jinja2Environment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | jinja2>=3.1.0 | runtime |
pathspecEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pathspec>=0.12.0 | runtime |
pydantic-settingsEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pydantic-settings>=2.3.0 | runtime |
pydanticEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pydantic>=2.7.0 | runtime |
pyyamlEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pyyaml>=6.0.0 | runtime |
richEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | rich>=13.7.0 | runtime |
typerEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | typer>=0.12.0 | runtime |
uvicornEnvironment{
"extras": "standard",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | uvicorn[standard]>=0.30.0 | runtime |
blackEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | black>=24.4.0; extra == "dev" | runtime |
httpxEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | httpx>=0.27.0; extra == "dev" | runtime |
mypyEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | mypy>=1.10.0; extra == "dev" | runtime |
pre-commitEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pre-commit>=3.7.0; extra == "dev" | runtime |
pytest-asyncioEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pytest-asyncio>=0.23.0; extra == "dev" | runtime |
pytest-covEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pytest-cov>=5.0.0; extra == "dev" | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pytest>=8.2.0; extra == "dev" | runtime |
ruffEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | ruff>=0.5.0; extra == "dev" | runtime |
bdist_wheel · 284.33 KB · Python py3
sdist · 307.48 KB · Python source
Observed since 21 Oct, 10:49 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:3cb83edbc07600dd30cf5aff1e260a2173c44ade7b6e63e54c700f5174cec846