๐ 100% Open Source | ๐ค Bring Your Own LLM | ๐ Self-Hosted Kubernetes Risk Analysis
Stop preventable production incidents before they happen
Quick Start โข How It Works โข Features โข Support
After one too many 3am pages from production incidents that could've been caught earlier, I built PatchPulse. It's a self-hosted tool that analyzes your Kubernetes changes before they hit production, combining rule-based guardrails with optional AI analysis to give you explainable risk scores.
Think of it as a safety net for your deployments - it catches the stuff that slips through code review and CI/CD checks.
I've been there - you merge a PR, deploy to production, and suddenly pods are OOMKilled because someone forgot resource limits. Or worse, a security misconfiguration opens up your cluster. PatchPulse catches these issues before they become incidents.
- ๐ก๏ธ Catch Problems Early: See risky changes before they reach production
- ๐ Understand Why: Get clear explanations when something's flagged
- ๐ค Optional AI: Use AI for deeper analysis, or skip it entirely - your call
- โก Real-Time Alerts: Know immediately when something's wrong
- ๐ 100% Open Source: No vendor lock-in, no SaaS fees, just code you can trust
- ๐ Your Data, Your Control: Everything runs on your infrastructure
- ๐ Fully Open Source - Non-commercial license, no vendor lock-in
- ๐ค Bring Your Own LLM - Use OpenAI, DeepSeek, Claude, Gemini, or any OpenAI-compatible API
- ๐ Self-Hosted - Your data stays on your infrastructure
- ๐ก๏ธ 11+ Guardrails - Rule-based checks for Kubernetes best practices
- ๐ง AI-Powered Analysis - Security scanning, recommendations, incident prediction
- โก Real-Time - WebSocket updates and instant notifications
- ๐ Integrations - GitHub, GitLab, Slack, Teams, PagerDuty, Email
- ๐ Enterprise Features - Admission webhooks, policy bundles, SBOM verification, multi-tenancy
- Resource Limits - Ensures CPU/memory limits are set
- Resource Requests - Validates resource requests are configured
- Readiness Probes - Checks for readiness probe configuration
- Liveness Probes - Validates liveness probe setup
- Security Context - Enforces security context settings
- Image Tags - Prevents
latesttag usage - Namespace Validation - Ensures proper namespace usage
- Service Account - Validates service account configuration
- Network Policies - Checks network policy compliance
- Resource Quotas - Validates resource quota adherence
- Pod Disruption Budgets - Ensures PDB configuration
- Docker (running) - Required for containerized deployment
- Python 3.11+ - For local development
- Go 1.21+ - For agent development (optional)
- kubectl - For Kubernetes integration (optional)
git clone https://github.com/amarkdotdev/patchpulse.git
cd patchpulsePatchPulse supports multiple AI providers. You only need to provide an API key for ONE provider:
# Create .env file
touch .env
# Option 1: OpenAI (recommended for best results)
echo "OPENAI_API_KEY=sk-your-key-here" >> .env
# Option 2: DeepSeek (cost-effective alternative)
# echo "DEEPSEEK_API_KEY=sk-your-key-here" >> .env
# Option 3: Claude (Anthropic)
# echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" >> .env
# Note: Requires: pip install anthropic
# Option 4: Google Gemini
# echo "GEMINI_API_KEY=your-key-here" >> .env
# Note: Requires: pip install google-generativeai
# Optionally specify which provider to use (defaults to first available)
# echo "AI_PROVIDER=openai" >> .env๐ก No LLM? No Problem! PatchPulse works perfectly fine without any AI - you'll still get all the rule-based guardrails and risk scoring. The AI stuff is just extra if you want it.
# Start all services
docker compose up -d
# Check logs
docker compose logs -f backend
# Wait for services to be ready (about 10-15 seconds)Once PatchPulse is running, access it at:
-
Dashboard: http://localhost:8000/dashboard
- Main user interface for monitoring decisions, viewing analytics, and managing configurations
- Real-time updates via WebSocket
- Risk visualization and decision history
-
API Documentation: http://localhost:8000/docs
- Interactive Swagger/OpenAPI documentation
- Test API endpoints directly from the browser
- Full API reference
-
Health Check: http://localhost:8000/health
- Service health status
- Database connectivity check
-
API Root: http://localhost:8000/api
- API information and available endpoints
- Access the Dashboard: Open http://localhost:8000/dashboard in your browser
- View Decisions: See real-time risk analysis and decisions
- Configure Integrations: Set up GitHub, GitLab, Slack, or other integrations via the API
- Monitor Analytics: Track risk trends, blocked changes, and system health
Note: The dashboard is the main interface for PatchPulse. The website (patchpulse.dev) is a separate marketing site and not part of this repository.
PatchPulse can be deployed in two ways:
Backend runs separately (Docker Compose, VM, or anywhere):
- Backend service runs independently
- Agent runs outside your Kubernetes cluster
- Agent connects to your cluster using
kubeconfig - Best for: Testing, development, or when you don't want to deploy into your cluster
# 1. Start backend (runs anywhere)
docker compose up -d
# 2. Run agent locally (connects to your cluster via kubeconfig)
cd app/agent
export BACKEND_URL=http://localhost:8000
export KUBECONFIG=$HOME/.kube/config # Points to your cluster
go run cmd/agent/main.goBoth backend and agent run inside Kubernetes:
- Backend deployed as a Kubernetes Deployment
- Agent deployed in the same or different namespace
- Agent uses in-cluster config (ServiceAccount)
- Best for: Production deployments, full integration
# Deploy both backend and agent to your cluster
helm install patchpulse-backend ./helm/backend --namespace patchpulse
helm install patchpulse-agent ./helm/agent --namespace patchpulsePatchPulse works in two ways:
- Monitors GitHub/GitLab PRs/MRs
- Analyzes Kubernetes manifests in diffs
- Evaluates guardrails before code is merged
- Sends notifications if risky changes detected
# Example: PR with risky deployment.yaml
# PatchPulse detects: "Missing resource limits"
# โ Risk score: 50
# โ Decision: Advisory (allows, but warns)- Agent watches your Kubernetes cluster
- Collects deployment signals, pod events, node status
- Detects issues in running workloads
- Provides real-time cluster health insights
โโโโโโโโโโโโโโโโโโโ
โ Developer โ
โ Creates PR โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ Git Integrationโโโโโโถโ PatchPulse โ
โ (GitHub/GitLab)โ โ Backend โ
โโโโโโโโโโโโโโโโโโโ โ (FastAPI) โ
โโโโโโโโโโฌโโโโโโโโโโ
โ
โโโโโโโโโโผโโโโโโโโโโ
โ Policy Engine โ
โ + AI Analysis โ
โโโโโโโโโโฌโโโโโโโโโโ
โ
โโโโโโโโโโผโโโโโโโโโโ
โ Risk Score โ
โ Decision โ
โโโโโโโโโโฌโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ Notification โ โ Dashboard โ โ Kubernetes โ
โ (Slack/Email) โ โ (Web UI) โ โ Agent โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Your K8s โ
โ Cluster โ
โโโโโโโโโโโโโโโโโโโ
- Ensure you have access to your cluster:
# Test cluster access
kubectl get nodes
# If using a remote cluster, make sure kubeconfig is set
export KUBECONFIG=$HOME/.kube/config- Start the agent pointing to your cluster:
# The agent will automatically use your kubeconfig
export BACKEND_URL=http://localhost:8000 # Where backend is running
cd app/agent
go run cmd/agent/main.go- Deploy PatchPulse to your cluster:
# Create namespace
kubectl create namespace patchpulse
# Deploy backend
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--set env.DATABASE_URL="postgresql://..."
# Deploy agent (automatically connects to cluster)
helm install patchpulse-agent ./helm/agent \
--namespace patchpulse \
--set env.BACKEND_URL="http://patchpulse-backend:8000"- The agent automatically uses in-cluster config (no kubeconfig needed)
- Kubernetes manifests (Deployments, Services, ConfigMaps, etc.)
- Changes to resource limits, requests, probes
- Security context changes
- Image tag updates
- Network policy changes
- Deployment availability and replica counts
- Pod restart counts
- Node readiness status
- Warning events
- Resource utilization trends
- Architecture
- Configuration
- LLM Provider Setup
- API Usage
- Deployment
- Development
- Use Cases
- Contributing
- Support
- License
- REST API for change events and decisions
- Policy engine with 11+ guardrails
- AI-powered risk analysis (bring your own LLM!)
- PostgreSQL database for persistence
- WebSocket support for real-time updates
- Kubernetes cluster monitoring
- Resource snapshotting
- Event watching
- Least-privilege RBAC
- GitHub PR analysis
- GitLab MR analysis
- Diff parsing and manifest extraction
- Slack notifications with interactive approval buttons
- Email notifications
- Microsoft Teams integration
- PagerDuty integration
- Real-time decision monitoring via WebSocket
- Risk visualization and analytics
- Decision history and filtering
- Export functionality (CSV/JSON)
- Accessible at
/dashboardendpoint
1. Developer creates PR/MR โ Git integration detects change
2. Change event sent to backend โ Policy engine evaluates
3. AI analysis runs (if configured) โ Security scan, recommendations, predictions
4. Risk score calculated (0-100) โ Decision made (allow/block)
5. Notification sent to Slack/Teams โ Decision stored in database
6. Dashboard updates in real-time via WebSocket
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ GitHub โโโโโโถโ Git Poller โโโโโโถโ Backend โ
โ GitLab โ โ โ โ (FastAPI) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโฌโโโโโโโ
โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ Kubernetes โโโโโโถโ Agent โโโโโโโโโโโโโโโ
โ Cluster โ โ (Go) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโผโโโโโโโ
โ Slack โโโโโโโ Notificationsโโโโโโโ PostgreSQL โ
โ Teams โ โ โ โ Database โ
โ PagerDuty โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโ
โ Email โ
โโโโโโโโโโโโโโโ
Create a .env file in the root directory:
# Database
DATABASE_URL=postgresql://patchpulse:patchpulse@postgres:5432/patchpulse
# Policy Mode (advisory or enforce)
POLICY_MODE=advisory
# Logging
LOG_LEVEL=INFO
# AI Provider - Choose ONE (see LLM Provider Setup section)
OPENAI_API_KEY=your_openai_api_key
# OR
# DEEPSEEK_API_KEY=your_deepseek_api_key
# OR
# ANTHROPIC_API_KEY=your_anthropic_api_key
# OR
# GEMINI_API_KEY=your_gemini_api_key
# Optional: Specify which provider to use (defaults to first available)
AI_PROVIDER=openai
# Git Integration
GITHUB_TOKEN=your_github_token
GITHUB_REPOS=owner/repo1,owner/repo2
GITLAB_TOKEN=your_gitlab_token
GITLAB_PROJECTS=12345,67890
# JWT Secret (auto-generated if not set)
JWT_SECRET_KEY=your_jwt_secret-
advisory: Logs decisions but doesn't block changes (default)- Best for: Testing, gradual rollout, learning mode
- All decisions are logged and visible in dashboard
- No changes are blocked
-
enforce: Blocks high-risk changes (score โฅ 70)- Best for: Production environments
- High-risk changes are automatically blocked
- Requires manual approval for blocked changes
PatchPulse is 100% open source and supports bring your own LLM. You can use any of these providers:
| Provider | Cost | Quality | Setup |
|---|---|---|---|
| OpenAI | $$$ | โญโญโญโญโญ | OPENAI_API_KEY=sk-... |
| DeepSeek | $ | โญโญโญโญ | DEEPSEEK_API_KEY=sk-... |
| Claude | $$$ | โญโญโญโญโญ | ANTHROPIC_API_KEY=sk-ant-... |
| Gemini | $$ | โญโญโญโญ | GEMINI_API_KEY=... |
export OPENAI_API_KEY=sk-your-key-here
# Or in .env file:
echo "OPENAI_API_KEY=sk-your-key-here" >> .envModels: Uses gpt-4o-mini by default (cost-effective). You can modify ai_analyzer.py to use other models.
export DEEPSEEK_API_KEY=sk-your-key-here
# Or in .env file:
echo "DEEPSEEK_API_KEY=sk-your-key-here" >> .envModels: Uses deepseek-chat by default. OpenAI-compatible API.
# First install the package
pip install anthropic
export ANTHROPIC_API_KEY=sk-ant-your-key-here
# Or in .env file:
echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" >> .envModels: Uses claude-3-5-sonnet-20241022 by default.
# First install the package
pip install google-generativeai
export GEMINI_API_KEY=your-key-here
# Or in .env file:
echo "GEMINI_API_KEY=your-key-here" >> .envModels: Uses gemini-1.5-pro by default.
PatchPulse supports any OpenAI-compatible API endpoint (Ollama, LocalAI, vLLM, etc.):
# Set a dummy API key (not used for local endpoints)
export OPENAI_API_KEY=not-used
# Set your custom endpoint
export OPENAI_BASE_URL=http://localhost:11434/v1 # Ollama example
# Or
export OPENAI_BASE_URL=http://localhost:8080/v1 # LocalAI example
# Or in .env file:
echo "OPENAI_API_KEY=not-used" >> .env
echo "OPENAI_BASE_URL=http://localhost:11434/v1" >> .envExamples:
- Ollama:
OPENAI_BASE_URL=http://localhost:11434/v1 - LocalAI:
OPENAI_BASE_URL=http://localhost:8080/v1 - vLLM:
OPENAI_BASE_URL=http://localhost:8000/v1 - Any OpenAI-compatible service: Just set the base URL!
The system will automatically use your custom endpoint with the OpenAI client.
PatchPulse works perfectly without any LLM! If no API key is provided:
- โ All rule-based guardrails work
- โ Risk scoring works
- โ All integrations work
- โ Dashboard works
โ ๏ธ AI-powered features are disabled (security scanning, recommendations, predictions)
curl -X POST http://localhost:8000/api/v1/change-events \
-H "Content-Type: application/json" \
-d '{
"source": "github",
"repo": "org/repo",
"sha": "abc123",
"pr_number": 42,
"branch": "feature-branch",
"files": ["k8s/deployment.yaml"],
"diff_hunks": [{
"file": "k8s/deployment.yaml",
"hunk": "- limits:\n cpu: 500m"
}],
"timestamp": "2026-01-01T00:00:00Z"
}'curl http://localhost:8000/api/v1/decisions?limit=10curl http://localhost:8000/api/v1/analytics/summarycurl http://localhost:8000/api/v1/decisions/{decision_id}# Filter by risk score
curl "http://localhost:8000/api/v1/decisions?min_risk=50&max_risk=100"
# Filter by source
curl "http://localhost:8000/api/v1/decisions?source=github"
# Filter by date range
curl "http://localhost:8000/api/v1/decisions?start_date=2026-01-01&end_date=2026-01-31"See /docs for interactive API documentation.
docker compose up -dOption 1: Using your .env file (Recommended)
# Create a values file from your .env
# This reads your .env file and creates Helm values
cat > /tmp/patchpulse-values.yaml <<EOF
env:
DATABASE_URL: "postgresql://patchpulse:patchpulse@postgres:5432/patchpulse"
POLICY_MODE: "advisory"
LOG_LEVEL: "INFO"
OPENAI_API_KEY: "$(grep OPENAI_API_KEY .env | cut -d '=' -f2)"
DEEPSEEK_API_KEY: "$(grep DEEPSEEK_API_KEY .env | cut -d '=' -f2 || echo '')"
ANTHROPIC_API_KEY: "$(grep ANTHROPIC_API_KEY .env | cut -d '=' -f2 || echo '')"
GEMINI_API_KEY: "$(grep GEMINI_API_KEY .env | cut -d '=' -f2 || echo '')"
EOF
# Install backend using values from .env
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--create-namespace \
--values /tmp/patchpulse-values.yaml
# Install agent
helm install patchpulse-agent ./helm/agent \
--namespace patchpulse \
--set env.BACKEND_URL=http://patchpulse-backend:8000Option 2: Using --set-file (Alternative)
# Install backend with API key from .env file
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--create-namespace \
--set env.OPENAI_API_KEY="$(grep OPENAI_API_KEY .env | cut -d '=' -f2)" \
--set env.POLICY_MODE=advisory
# Install agent
helm install patchpulse-agent ./helm/agent \
--namespace patchpulse \
--set env.BACKEND_URL=http://patchpulse-backend:8000Option 3: Manual values override
Edit helm/backend/values.yaml and add your API keys to the env section, then install:
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--create-namespace- Use environment variables for secrets (never hardcode)
- Set up proper TLS/SSL certificates
- Configure database backups
- Set up monitoring and alerting
- Use a managed PostgreSQL database for production
- Configure rate limiting
- Set up log aggregation
- Enable audit logging
# Backend
cd app/backend
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload
# Agent
cd app/agent
go run cmd/agent/main.go
# Git Integration
cd app/integrations/git
python poller.py# Unit tests
cd app/backend
pytest tests/
# Integration tests
docker compose up -d
./test_api_endpoints.shpatchpulse/
โโโ app/ # Application code
โ โโโ backend/ # FastAPI backend service
โ โ โโโ main.py # Main application entry point
โ โ โโโ models.py # Pydantic models and SQLAlchemy ORM
โ โ โโโ database.py # Database connection and setup
โ โ โโโ policy_engine.py # Policy evaluation and guardrails
โ โ โโโ ai_analyzer.py # AI-powered risk analysis (BYO LLM!)
โ โ โโโ ai_features.py # Advanced AI features
โ โ โโโ auth.py # Authentication system
โ โ โโโ requirements.txt
โ โโโ agent/ # Kubernetes agent (Go)
โ โ โโโ cmd/agent/ # Agent main application
โ โ โโโ Dockerfile
โ โโโ integrations/ # External integrations
โ โ โโโ git/ # GitHub/GitLab integration
โ โ โโโ slack/ # Slack notifications
โ โ โโโ teams/ # Microsoft Teams integration
โ โ โโโ pagerduty/ # PagerDuty integration
โ โ โโโ email/ # Email notifications
โ โโโ ui/ # Dashboard UI (served at /dashboard)
โโโ docs/ # Technical documentation
โโโ helm/ # Kubernetes Helm charts
โโโ docker-compose.yml # Local development setup
โโโ README.md # This file
Integrate PatchPulse into your CI/CD pipeline to automatically analyze PRs:
# GitHub Actions example
- name: Analyze with PatchPulse
run: |
curl -X POST $PATCHPULSE_URL/api/v1/change-events \
-H "Content-Type: application/json" \
-d @change-event.jsonValidate Kubernetes manifests before deployment:
# Analyze deployment manifests
kubectl apply --dry-run=client -f deployment.yaml | \
patchpulse analyze --source=manualTrack compliance with Kubernetes best practices:
# Get compliance report
curl http://localhost:8000/api/v1/analytics/compliancePrevent production incidents by catching risky changes:
- Missing resource limits
- Security misconfigurations
- Image tag issues
- Network policy violations
Use PatchPulse to educate teams on Kubernetes best practices:
- Real-time feedback on PRs
- Detailed explanations of guardrail violations
- Historical analytics on common mistakes
- API keys never exposed in logs or responses
- Least-privilege RBAC for agent
- Encrypted database connections
- TLS for all API communications
- Audit logging for all decisions
- Rate limiting on API endpoints
- Self-hosted - your data stays on your infrastructure
See SECURITY.md for detailed security information.
Contributions are welcome! This is a solo project, so any help is genuinely appreciated.
- Fork the repo
- Create a branch (
git checkout -b feature/your-feature) - Make your changes
- Commit (
git commit -m 'Add your feature') - Push (
git push origin feature/your-feature) - Open a Pull Request
See CONTRIBUTING.md for more details.
What I'd love help with:
- ๐ Bug fixes (especially edge cases I haven't hit yet)
- โจ New features (if you have ideas, open an issue first to discuss)
- ๐ Documentation (I'm not great at writing docs, so improvements are welcome)
- ๐งช Tests (more test coverage is always good)
- ๐จ UI improvements (the dashboard could definitely be prettier)
- ๐ New integrations (want to add something? Let's talk)
This project is licensed under the PatchPulse Non-Commercial License - see the LICENSE file for details.
โ Permitted Uses:
- Personal use
- Educational use
- Research and development
- Internal use within non-profit organizations
- Contributing to the PatchPulse project
- Forking and modifying for personal/educational purposes
โ Prohibited Uses:
- Commercial use (selling, licensing, or providing as a service)
- Use in commercial products or services
- Reselling or redistributing for profit
- Use by for-profit companies without explicit written permission
๐ผ Commercial Licensing: For commercial use, please contact us to obtain a commercial license. Commercial licenses are available for:
- SaaS providers
- Enterprise deployments
- Commercial products incorporating PatchPulse
- Consulting services using PatchPulse
Contact: amarkdotdev@gmail.com
This license protects the open-source nature of PatchPulse while ensuring commercial use requires proper licensing.
Documentation: http://localhost:8000/docs (when running locally)
Website: https://patchpulse.dev
Issues: https://github.com/amarkdotdev/patchpulse/issues
Email: amarkdotdev@gmail.com
Ways to help:
- ๐ Found a bug? Open an issue - I'll try to fix it
- ๐ก Have an idea? Open a discussion or issue
- ๐ Docs unclear? Send a PR to improve them
If PatchPulse has saved you from a late-night incident or just made your life easier, consider buying me a coffee:
It's not required at all, but it's a nice way to say thanks and helps me justify spending more time on this project. Every bit helps! ๐
- Multi-tenant support (in progress)
- Custom guardrail DSL
- Integration with more Git providers (Bitbucket, Azure DevOps)
- Additional AI provider support
- Compliance reporting (SOC2, ISO27001)
- Enhanced documentation
- Local LLM support (Ollama, LocalAI)
- Webhook support for real-time PR analysis
- Custom risk scoring algorithms
- Policy templates library
I'm a DevOps engineer based in Israel ๐ฎ๐ฑ, and I built PatchPulse because I was tired of preventable production incidents.
You know those moments when you're debugging at 2am and think "we should've caught this earlier"? That's what PatchPulse is for. It's the tool I wish I had when I was managing Kubernetes clusters at scale.
I built this in my spare time, iterating based on real problems I've faced. It's not perfect, but it's useful, and I'm sharing it because I think other teams might find it helpful too.
Want to chat?
- ๐ง Email: amarkdotdev@gmail.com
- ๐ GitHub: @amarkdotdev
- โ Buy Me a Coffee: buymeacoffee.com/aaronmark (if PatchPulse saves you from a late-night incident, consider it ๐)
This project wouldn't exist without the open source community. Special shoutout to everyone who's contributed, reported bugs, or just used PatchPulse and gave feedback.
Built with:
- FastAPI - Because Python web frameworks don't have to be slow
- PostgreSQL - Reliable and battle-tested
- Go - For the Kubernetes agent (because sometimes you need speed)
- Docker - Makes deployment actually bearable
- Kubernetes - The thing we're all trying to make safer
๐ Open Source | ๐ค Bring Your Own LLM | ๐ Self-Hosted
Made with โค๏ธ in Israel for the Kubernetes community worldwide
โญ Star on GitHub โข ๐ Documentation โข โ Buy Me a Coffee โข ๐ Report Bug