{
  "markdown": "# diffgrab\n\n[![PyPI](https://img.shields.io/pypi/v/diffgrab)](https://pypi.org/project/diffgrab/)\n[![Python](https://img.shields.io/pypi/pyversions/diffgrab)](https://pypi.org/project/diffgrab/)\n[![License](https://img.shields.io/github/license/QuartzUnit/diffgrab)](https://github.com/QuartzUnit/diffgrab/blob/main/LICENSE)\n\n> [한국어 문서](README.ko.md) · [llms.txt](llms.txt)\n\n> Web page change tracking with structured diffs. markgrab + snapgrab integration, MCP native.\n\n```python\nfrom diffgrab import DiffTracker\n\ntracker = DiffTracker()\nawait tracker.track(\"https://example.com\")\nchanges = await tracker.check()\nfor c in changes:\n    if c.changed:\n        print(c.summary)     # \"3 lines added, 1 lines removed in sections: Introduction.\"\n        print(c.unified_diff) # Standard unified diff output\nawait tracker.close()\n```\n\n## Features\n\n- **Change detection** — track any URL, detect content changes via content hashing\n- **Structured diffs** — unified diff + section-level analysis (which headings changed)\n- **Human-readable summaries** — \"5 lines added, 2 removed in sections: Intro, Methods\"\n- **Snapshot history** — SQLite storage, browse past versions of any page\n- **markgrab powered** — HTML/YouTube/PDF/DOCX extraction via [markgrab](https://github.com/QuartzUnit/markgrab)\n- **Visual diff** — optional screenshot comparison via [snapgrab](https://github.com/QuartzUnit/snapgrab)\n- **MCP server** — 5 tools for Claude Code / MCP clients\n- **CLI included** — `diffgrab track`, `check`, `diff`, `history`, `untrack`\n\n## How It Works\n\n```mermaid\nflowchart TD\n    A[\"diffgrab track URL\"] --> B[\"Fetch initial snapshot\\n(markgrab + snapgrab)\"]\n    B --> C[\"Store baseline\"]\n    C --> D[\"diffgrab check\"]\n    D --> E[\"Fetch current page\"]\n    E --> F{\"Content\\nhash match?\"}\n    F -->|\"changed\"| G[\"Compute structured diff\\n+ section analysis\"]\n    F -->|\"unchanged\"| H[\"No changes\"]\n    G --> I[\"📊 DiffResult\\nadded / removed / modified\"]\n```\n\n## Install\n\n```bash\npip install diffgrab\n```\n\nOptional extras:\n\n```bash\npip install 'diffgrab[cli]'      # CLI with click + rich\npip install 'diffgrab[visual]'   # Visual diff with snapgrab\npip install 'diffgrab[mcp]'      # MCP server with fastmcp\npip install 'diffgrab[all]'      # Everything\n```\n\n## Usage\n\n### Python API\n\n```python\nimport asyncio\nfrom diffgrab import DiffTracker\n\nasync def main():\n    tracker = DiffTracker()\n\n    # Track a URL (takes initial snapshot)\n    await tracker.track(\"https://example.com\", interval_hours=12)\n\n    # Check for changes\n    changes = await tracker.check()\n    for change in changes:\n        if change.changed:\n            print(change.summary)\n            print(change.unified_diff)\n\n    # Get diff between specific snapshots\n    result = await tracker.diff(\"https://example.com\", before_id=1, after_id=2)\n\n    # Browse snapshot history\n    history = await tracker.history(\"https://example.com\", count=20)\n\n    # Stop tracking\n    await tracker.untrack(\"https://example.com\")\n\n    await tracker.close()\n\nasyncio.run(main())\n```\n\n### Convenience Functions\n\n```python\nfrom diffgrab import track, check, diff, history, untrack\n\nawait track(\"https://example.com\")\nchanges = await check()\nresult = await diff(\"https://example.com\")\nsnaps = await history(\"https://example.com\")\nawait untrack(\"https://example.com\")\n```\n\n### CLI\n\n```bash\n# Track a URL\ndiffgrab track https://example.com --interval 12\n\n# Check all tracked URLs for changes\ndiffgrab check\n\n# Check a specific URL\ndiffgrab check https://example.com\n\n# Show diff between snapshots\ndiffgrab diff https://example.com\ndiffgrab diff https://example.com --before 1 --after 3\n\n# View snapshot history\ndiffgrab history https://example.com --count 20\n\n# Stop tracking\ndiffgrab untrack https://example.com\n```\n\n### MCP Server\n\nAdd to your Claude Code MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"diffgrab\": {\n      \"command\": \"diffgrab-mcp\",\n      \"args\": []\n    }\n  }\n}\n```\n\nOr with uvx:\n\n```json\n{\n  \"mcpServers\": {\n    \"diffgrab\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"diffgrab[mcp]\", \"diffgrab-mcp\"]\n    }\n  }\n}\n```\n\n**MCP Tools:**\n\n| Tool | Description |\n|------|-------------|\n| `track_url` | Register a URL for change tracking |\n| `check_changes` | Check tracked URLs for changes |\n| `get_diff` | Get structured diff between snapshots |\n| `get_history` | Browse snapshot history |\n| `untrack_url` | Stop tracking a URL |\n\n## DiffResult\n\nEvery diff operation returns a `DiffResult`:\n\n```python\n@dataclass\nclass DiffResult:\n    url: str                           # The tracked URL\n    changed: bool                      # Whether content changed\n    added_lines: int                   # Lines added\n    removed_lines: int                 # Lines removed\n    changed_sections: list[str]        # Markdown headings with changes\n    unified_diff: str                  # Standard unified diff\n    summary: str                       # Human-readable summary\n    before_snapshot_id: int | None     # DB ID of older snapshot\n    after_snapshot_id: int | None      # DB ID of newer snapshot\n    before_timestamp: str              # When older snapshot was taken\n    after_timestamp: str               # When newer snapshot was taken\n```\n\n## Storage\n\nSnapshots are stored in SQLite at `~/.local/share/diffgrab/diffgrab.db` (auto-created). Custom path:\n\n```python\ntracker = DiffTracker(db_path=\"/path/to/custom.db\")\n```\n\n## QuartzUnit Ecosystem\n\n| Package | Role | PyPI |\n|---------|------|------|\n| [markgrab](https://github.com/QuartzUnit/markgrab) | HTML/YouTube/PDF/DOCX to markdown | `pip install markgrab` |\n| [snapgrab](https://github.com/QuartzUnit/snapgrab) | URL to screenshot + metadata | `pip install snapgrab` |\n| [docpick](https://github.com/QuartzUnit/docpick) | OCR + LLM document extraction | `pip install docpick` |\n| [feedkit](https://github.com/QuartzUnit/feedkit) | RSS feed collection | `pip install feedkit` |\n| **diffgrab** | **Web page change tracking** | `pip install diffgrab` |\n| [browsegrab](https://github.com/QuartzUnit/browsegrab) | Browser agent for LLMs | Coming soon |\n\n## Used in\n\n- [newswatch](https://github.com/QuartzUnit/newswatch) — RSS news monitoring pipeline (feedkit → markgrab → embgrep → diffgrab)\n- [watchdeck](https://github.com/QuartzUnit/watchdeck) — Web page monitoring with visual diffs and safety guards\n\n## License\n\n[MIT](LICENSE)\n\n<!-- mcp-name: io.github.QuartzUnit/diffgrab -->\n\n\n---\n\n<sub>Part of the [QuartzUnit](https://github.com/QuartzUnit) ecosystem — composable Python libraries for data collection, extraction, search, and AI agent safety.</sub>\n",
  "bytes": 6569,
  "sha": "01bfa8887c9d117063a0976b578d8868cde5f720c798377bd5c8aa4af0c19f81",
  "repo_slug": "quartzunit/diffgrab",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_arknill_diffgrab_75d4d865/readme"
}