GitHub PyPI

AUTOPSY

AI-powered incident diagnosis · zero-trust
v0.3.0 MIT License Python 3.10+ Anthropic / OpenAI

AI-powered incident diagnosis for engineering teams. Pull production error logs and recent deploys, send them to an LLM, and get a structured root cause analysis in the terminal in under a minute. Zero-trust: your data never leaves your environment.

Install
pip install autopsy-cli

30-Second Diagnosis

Pull logs, correlate deploys, get a structured root cause with confidence score.

Zero-Trust

Your data stays in your environment. API keys in local .env, never committed.

Multi-Source

CloudWatch, Datadog, GitHub, GitLab. All collectors run in parallel.

Slack & Post-Mortem

Post to Slack or generate markdown post-mortems instantly.

Prerequisites

Area Requirement
AWS CloudWatch Logs access; credentials via aws configure or AWS_PROFILE; IAM: logs:DescribeLogGroups, logs:StartQuery, logs:GetQueryResults.
Datadog Optional. API key + Application key; site (e.g. datadoghq.com).
GitHub Personal Access Token with repo scope.
GitLab Optional. Personal Access Token with read_api scope. Supports self-hosted.
AI Provider OpenAI or Anthropic account + API key + credits.
Local Python 3.10+, pip, terminal, internet.
You do not need: a server, Docker, a separate cloud account, a database, or admin/root. No changes to your AWS or app code.

Installation

From PyPI

pip install autopsy-cli

From Source

git clone https://github.com/zaappy/autopsy.git && cd autopsy
pip install -e ".[dev]"

Verify Installation

autopsy --version
# autopsy  0.3.0
# prompt   v1
# python   3.12.x
Dependencies: click, boto3, PyGithub, python-gitlab, rich, anthropic, openai, pydantic, pyyaml, questionary, python-dotenv.

Quick Start

Three steps: install → init → diagnose.

1. Configure

autopsy init      # Interactive wizard — creates ~/.autopsy/config.yaml + .env

2. Diagnose

autopsy diagnose  # Run full pipeline: collect → reduce → AI → render

3. Or Use the TUI

autopsy           # Interactive menu: Diagnose, History, Setup, Validate, Config

TUI Shortcuts

Key Action
d Diagnose
i Init / Setup
v Validate
c Config
q Quit
Esc Back

Configuration

After autopsy init, edit ~/.autopsy/config.yaml or re-run the wizard. Credentials are stored in ~/.autopsy/.env.

Config Sections

Section Purpose
aws CloudWatch region, log groups, time window (minutes). Uses your AWS CLI credentials.
datadog Optional. Site, service/source filters, time window. Uses DD_API_KEY / DD_APP_KEY.
github Repo (owner/repo), branch, number of recent commits. Uses GITHUB_TOKEN.
gitlab Optional. URL, project ID, branch, deploy count. Uses GITLAB_TOKEN. Can coexist with GitHub.
ai Provider (anthropic or openai), model, API keys.
slack Optional. Webhook integration for posting diagnoses to Slack.

Managing Config

autopsy config show       # Print config (secrets masked)
autopsy config show --reveal  # Show secrets
autopsy config validate   # Check env vars and connectivity
Security: Add ~/.autopsy/.env to .gitignore. Never commit credentials.

How It Works

1
Collect

CloudWatch, Datadog, GitHub, GitLab — all in parallel

2
Reduce

Log dedup, token budget, diff filters

3
Diagnose

Single prompt to LLM → structured JSON

4
Render

Rich panels, JSON, post-mortem, or Slack

Pipeline Details

Step 1: Collect

All configured collectors run in parallel by default using asyncio.to_thread with a ThreadPoolExecutor fallback. Each collector creates its own API client instance (thread-safe). Partial failures are handled gracefully.

Step 2: Reduce

4-stage log reduction pipeline:

  1. Query filter — regex at query level (~90% reduction)
  2. Deduplication — hash message templates, keep 1 + count (~60%)
  3. Truncation — 500 char/entry, stack traces to top 5 frames (~40%)
  4. Token budget — hard cap at 6000 tokens, FIFO eviction

Step 3: Diagnose

The AI engine receives all collected data in a single prompt. Logs and deploys are grouped, and each collector is labeled in the prompt (e.g. per-source blocks) so the model can correlate across systems. When more than one collector runs, the prompt includes cross-source instructions. The LLM returns structured JSON with root cause, correlated deploy, suggested fix, timeline, and a sources array.

Step 4: Render

Output to Rich terminal panels (default), raw JSON (--json), markdown post-mortem (--postmortem), or Slack webhook (--slack).

CLI Reference

Command Description
autopsy Interactive TUI — menu with Diagnose, Setup, Validate, Config
autopsy init Interactive config wizard
autopsy init --slack Configure only Slack integration
autopsy diagnose Run full diagnosis pipeline
autopsy diagnose --source <name> Restrict to named collector(s); repeat flag for multiple.
autopsy diagnose --json Output raw JSON
autopsy diagnose --postmortem Generate markdown post-mortem
autopsy diagnose --slack Post diagnosis to Slack webhook
autopsy diagnose --time-window 15 Override log window (minutes)
autopsy diagnose --log-group /aws/lambda/foo Override log groups (repeatable)
autopsy diagnose --provider openai Use OpenAI instead of Anthropic
autopsy diagnose --sequential Run collectors sequentially (debugging)
autopsy history list List saved diagnoses (newest first)
autopsy history show <id> Show a saved diagnosis
autopsy history search "query" Search saved diagnoses
autopsy history stats Show history statistics
autopsy history export ./h.json Export history to JSON or CSV
autopsy config show Print config (secrets masked)
autopsy config validate Check credentials and connectivity
autopsy version CLI, prompt, and Python version

Collectors

All collectors implement the BaseCollector ABC and run in parallel by default.

CloudWatch

Uses boto3 to run CloudWatch Logs Insights queries. Polls with backoff until results are ready. Applies the 4-stage log reduction pipeline.

Datadog

Optional. Uses the Datadog Logs Search API. Shares the same log reduction pipeline as CloudWatch.

GitHub

Uses PyGithub to fetch recent commits and diffs. Smart diff reduction: filter by file extension, exclude lockfiles/generated, cap per file and per commit.

GitLab

Optional. Uses python-gitlab to pull commits, diffs, merge requests, and deployment events. Supports self-hosted instances.

Parallel Execution

All active collectors run concurrently using asyncio.to_thread with asyncio.gather. Falls back to ThreadPoolExecutor if a running event loop is detected.

AI Engine

The orchestrator calls the AIEngine interface — never calls provider APIs directly.

Supported Providers

Provider Default Model API Key Env
Anthropic claude-sonnet-4-20250514 ANTHROPIC_API_KEY
OpenAI gpt-4o OPENAI_API_KEY

How It Works

  1. Build prompt: System prompt + user prompt from all collected data
  2. Call LLM: Single API call with structured JSON output instructions
  3. Parse response: Validate JSON against Pydantic models
  4. Retry: Once on malformed JSON. Falls back to raw text on second failure.

Output Structure

Interface Contracts

BaseCollector collectors/base.py

class CollectedData(BaseModel):
    source: str              # "cloudwatch", "github", "gitlab"
    data_type: str           # "logs" | "deploys" | "metrics"
    entries: list[dict]      # Normalized data entries
    time_range: tuple[datetime, datetime]
    raw_query: str           # The query used (for debugging)
    entry_count: int         # Total before dedup/truncation
    truncated: bool          # Whether data was reduced

class BaseCollector(ABC):
    @abstractmethod
    def validate_config(self, config: dict) -> bool: ...
    @abstractmethod
    def collect(self, config: dict) -> CollectedData: ...
    @property
    @abstractmethod
    def name(self) -> str: ...

AIEngine ai/engine.py

class AIEngine:
    def diagnose(self, collected_data: list[CollectedData]) -> DiagnosisResult:
        """Build prompt, call LLM, parse response.
        Retries once on malformed JSON."""
    def _build_prompt(self, collected_data) -> tuple[str, str]: ...
    def _parse_response(self, raw: str) -> DiagnosisResult: ...

DiagnosisOrchestrator diagnosis.py

class DiagnosisOrchestrator:
    def run(self, *, time_window=None, log_groups=None,
            provider=None, sequential=False) -> DiagnosisResult:
        """Full pipeline: validate → collect → diagnose → return"""

Data Models

All models are Pydantic BaseModel subclasses.

DiagnosisResult ai/models.py

class RootCause(BaseModel):
    summary: str
    category: str    # code_change | config_change | infra | dependency | traffic | unknown
    confidence: float  # 0.0 - 1.0
    evidence: list[str]

class CorrelatedDeploy(BaseModel):
    commit_sha: str | None = None
    author: str | None = None
    pr_title: str | None = None
    changed_files: list[str] = []

class SuggestedFix(BaseModel):
    immediate: str
    long_term: str

class TimelineEvent(BaseModel):
    time: str
    event: str

class DiagnosisResult(BaseModel):
    root_cause: RootCause
    correlated_deploy: CorrelatedDeploy
    suggested_fix: SuggestedFix
    timeline: list[TimelineEvent]
    prompt_version: str = "v1"
    raw_response: str | None = None

Error Hierarchy

All custom exceptions inherit from AutopsyError.

AutopsyError (base)
ConfigError
ConfigNotFoundError
ConfigValidationError
CollectorError
AWSAuthError
AWSPermissionError
GitHubAuthError
GitHubRateLimitError
GitLabAuthError
GitLabRateLimitError
NoDataError
AIError
AIAuthError
AIRateLimitError
AIResponseError
AITimeoutError
RenderError

Error Display

[ERROR] CloudWatch query timeout after 60s.
[FIX]   Check that the log group exists: aws logs describe-log-groups
[DOCS]  https://docs.aws.amazon.com/...

Changelog

Unreleased

Added

0.3.0 — 2026-03-11

Added

0.2.2 — 2026-03-10

Added

0.2.0

Added

Contributing

Development Setup

  1. Fork and clone
    git clone https://github.com/YOUR_USERNAME/autopsy.git && cd autopsy
  2. Virtual environment
    python -m venv .venv && source .venv/bin/activate
  3. Install with dev dependencies
    pip install -e ".[dev]"

Code Style

Tool Command Purpose
Ruff ruff check . Linting
mypy mypy autopsy Type checking (strict)
pytest pytest -v All tests must pass

Project Layout

Path Purpose
autopsy/cli.py CLI entrypoint; no business logic
autopsy/collectors/ CloudWatch, Datadog, GitHub, GitLab
autopsy/ai/ AI engine (prompts, models, diagnosis)
autopsy/renderers/ Terminal and JSON output
autopsy/config.py Config loading and validation
tests/ Pytest tests (including VCR for HTTP)
Separation of concerns: Collectors, AI, and renderers are independent of the CLI layer.

Submitting Changes

  1. Create a branch from main
  2. Make changes and add/update tests
  3. Run ruff check . and pytest locally
  4. Push to your fork and open a PR against main

Security Policy

Supported Versions

Version Supported
0.2.x+ Yes
< 0.2 No

Reporting a Vulnerability

Do not open a public GitHub issue for security-sensitive bugs.

Email: zaappy@users.noreply.github.com with a clear description, steps to reproduce, and impact.

What We Care About