Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: docs

# Builds the Material for MkDocs site and deploys it to GitHub Pages.
# Pages "Source" must be set to "GitHub Actions" once in repo Settings.
on:
push:
branches: [main]
paths: # only rebuild when docs inputs change
- docs/**
- mkdocs.yml
- .github/workflows/docs.yml
- pyproject.toml
workflow_dispatch: # allow manual rebuilds

permissions:
contents: read
pages: write
id-token: write

concurrency: # never run two deploys at once
group: pages
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history → correct "last updated" dates
- name: Install Cairo/Pango for social cards
run: |
sudo apt-get update
sudo apt-get install -y libcairo2-dev libfreetype6-dev libffi-dev \
libjpeg-dev libpng-dev libz-dev libpango-1.0-0 libpangocairo-1.0-0
- uses: astral-sh/setup-uv@v5
with: { enable-cache: true }
- run: uv sync --group docs
- run: uv run mkdocs build --strict # CI=true ⇒ social cards generate; --strict fails on broken links
- uses: actions/upload-pages-artifact@v3
with: { path: site }

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ whygraph.toml

# Local scratch space for in-progress plan markdown (not version-controlled).
plans/

# MkDocs build output (the site is built and deployed by CI, never committed).
site/

# Material social-plugin font/image cache.
.cache/
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ IMAGE ?= whygraph:dev
# Name of the long-running container started by `make image-debug`.
DEBUG_NAME ?= whygraph-debug

.PHONY: help sync test scan db db-down inspect image image-test image-inspect image-debug image-debug-down
.PHONY: help sync test scan docs docs-build db db-down inspect image image-test image-inspect image-debug image-debug-down

help: ## List available targets
@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | sort | awk 'BEGIN{FS=":.*?## "}{printf " %-10s %s\n", $$1, $$2}'
Expand All @@ -27,6 +27,12 @@ test: ## Run the test suite
scan: ## Re-scan this repo so WhyGraph is tested against itself
uv run whygraph scan

docs: ## Serve the docs site locally with live reload (social cards skipped — no Cairo needed)
uv run mkdocs serve

docs-build: ## Build the static docs site into ./site (strict; cards skipped unless CI=true)
uv run mkdocs build --strict

db: ## Start the DBGate database viewer (http://localhost:8081)
@test -f docker-compose.yml || { echo "error: docker-compose.yml missing - run: cp docker-compose.example.yml docker-compose.yml"; exit 1; }
@test -f .whygraph/whygraph.db || echo "warning: .whygraph/whygraph.db missing - run 'make scan' first"
Expand Down
328 changes: 13 additions & 315 deletions README.md

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions docs/deploy/docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Run with Docker

Don't want Python, Node, `gh`, and CodeGraph on your machine? WhyGraph ships as a self-contained
image. Your host needs **only Docker**. Install a tiny shim, then it's the same `init` and `scan` as a
native install.

```bash
curl -fsSL https://raw.githubusercontent.com/mtrdesign/whygraph/main/scripts/install.sh | sh

cd your-repo
whygraph init # bootstrap the WhyGraph DB + write config
whygraph scan # crawl history + refresh CodeGraph + LLM descriptions
```

## How the shim works

`install.sh` drops `whygraph` and `whygraph-mcp` shims on your `PATH`. Each one runs the published
image against the current directory:

```bash
docker run --rm -v "$PWD:/workspace" -w /workspace ghcr.io/mtrdesign/whygraph whygraph "$@"
```

The container is **ephemeral per command** - no compose, no `docker exec`, nothing to start or stop.
Each invocation is a fresh process against the repo you're standing in.

- **Everything's in the image** - Python and WhyGraph, `git`, the GitHub CLI, and Node with the
CodeGraph CLI. CodeGraph indexes from the in-image binary, so there's no docker-in-docker.
- **Per-project config just works.** Each command reads the current repo's own `whygraph.toml`,
`.whygraph/`, and `.codegraph/`.
- **Files come back as yours.** The shim runs as your host user, so generated files aren't
root-owned and git sees matching ownership.

## Credentials

The shim passes your environment through. A GitHub token goes in `[scan].token` of the repo's
`whygraph.toml` (gitignored), and the shim also forwards `GH_TOKEN` / `GITHUB_TOKEN` plus
`ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `DEEPSEEK_API_KEY` from your environment.

!!! warning "Never bake a token into the image"
Pass credentials at run time, never at build time. The repo's gitignored `whygraph.toml` is the
right home for a pinned token.

## Wire your editor, still only Docker

The MCP server is containerized too. `install.sh` drops a `whygraph-mcp` shim alongside `whygraph`, so
there's nothing extra to install. Wire your editor from inside the repo:

```bash
whygraph init --agent claude # writes .mcp.json (also: --agent cursor / vscode / codex)
```

The generated config launches `whygraph-mcp` by bare command name. Your editor resolves it to the
shim, which starts a per-session container speaking MCP over stdio. It reads the repo's `.whygraph/`
and `.codegraph/` over the same `/workspace` mount the scan writes to - so the editor and the scan
share one source of truth on disk.

## Build the image yourself

Building locally instead of pulling - say, while developing:

```bash
docker build -f docker/whygraph/Dockerfile -t whygraph:latest .
WHYGRAPH_IMAGE=whygraph:latest whygraph scan
```

`WHYGRAPH_IMAGE` overrides the image the shim runs, so you can test a local build without touching the
install.
30 changes: 30 additions & 0 deletions docs/deploy/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Docker & Self-Hosting

WhyGraph ships as a self-contained image, so there are two ways to run it. Both use the same image;
they differ in who's driving.

<div class="grid cards" markdown>

- :material-laptop:{ .lg .middle } __As a local dev tool__

---

Install the Docker shim, then `init` and `scan` your repos and wire your editor - no Python or
Node on the host. This is the default install.

[:octicons-arrow-right-24: Run with Docker](docker.md)

- :material-server-network:{ .lg .middle } __As a service__

---

A containerized `whygraph-mcp` endpoint that real applications - not just editors - connect to
for git-based analysis of a target repo.

[:octicons-arrow-right-24: WhyGraph as a service](service.md)

</div>

Most people start with the local tool. Reach for the service model when you're building an
application that needs the *why* behind code - a review bot, an onboarding assistant, an internal
portal.
89 changes: 89 additions & 0 deletions docs/deploy/service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# WhyGraph as a service

Editors aren't the only thing that can talk to WhyGraph. The MCP server is a plain stdio program, so
any application that speaks MCP can connect to it for git-based analysis of a target repo. Think of a
review bot, an onboarding assistant, or an internal dev portal that needs the *why* behind a chunk of
code - not just the code.

This page covers that model: a containerized `whygraph-mcp` endpoint a third-party app drives over
MCP, reading the same on-disk data your scan produces.

## The shape of it

A consuming app launches the WhyGraph image, mounts the target repo at `/workspace`, and speaks MCP
over stdio. The scan **writes** the databases; the MCP server **reads** them. One repo on disk is the
single source of truth.

```mermaid
flowchart LR
app["Consuming app<br/>(bot · portal · assistant)"]
mcp["whygraph-mcp<br/>(container)"]
repo[("/workspace mount<br/>.whygraph + .codegraph")]

app -- "MCP over stdio" --> mcp
mcp -- "reads cached evidence + rationale" --> repo
scan["whygraph scan"] -- "writes" --> repo
```

The consuming app gets the full read surface over MCP:

- **Evidence** - `whygraph_evidence_for` and `whygraph_area_history` for the commits, PRs, and issues
behind a path or symbol.
- **Rationale** - `whygraph_rationale_brief` for a structured why-this-exists card.
- **Resources** - `whygraph://commit/{sha}`, `whygraph://pr/{number}`, `whygraph://issue/{number}`,
and `whygraph://repo/overview`.

See the [MCP surface reference](../reference/mcp.md) for exact signatures.

## Scan first

The server reads cached data - it doesn't crawl on demand. So the target repo must be scanned before
an app connects, or the tools have nothing to return.

```bash
cd /path/to/target-repo
whygraph scan
```

!!! warning "An unscanned repo returns nothing"
`whygraph_rationale_brief` raises an error when a target maps to no scanned commit, and the
evidence tools come back empty. Run `whygraph scan` (and keep it fresh with
[git hooks](../guide/scanning.md#keep-it-fresh)) before pointing an app at the server.

## Launch the endpoint

The MCP server runs from the same image as everything else. Mount the target repo and run
`whygraph-mcp`:

```bash
docker run --rm -i \
-v "/path/to/target-repo:/workspace" -w /workspace \
ghcr.io/mtrdesign/whygraph whygraph-mcp
```

The `-i` flag keeps stdin open for the MCP stdio transport. Your app spawns this command and talks
JSON-RPC to it, exactly as an editor would. The [`install.sh` shim](docker.md) wraps the same call as
a bare `whygraph-mcp` on `PATH`.

## Credentials

What the app needs depends on what it asks for:

- **Reading cached evidence and rationale needs no credentials.** It's all in the mounted databases.
- **Generating a *new* rationale card needs an LLM key.** `whygraph_rationale_brief` calls the
configured provider on a cache miss. Supply the key through the environment
(`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `DEEPSEEK_API_KEY`) or the repo's `whygraph.toml`
`[llm.*]` table.

!!! info "Tokens never live in the image"
Pass credentials at run time via env or the gitignored `whygraph.toml` - never bake them into a
built image. This matches WhyGraph's own invariant for the Docker shim.

## Current scope

Today the server speaks MCP over **stdio, one session per process**. There's no long-running HTTP
endpoint yet - each connection is its own `docker run`. A persistent server mode with an HTTP MCP
transport is on the [roadmap](../roadmap.md), not built.

For now, model your integration as "spawn a session, run the tools you need, let it exit" - the same
lifecycle an editor uses, driven by your app instead.
61 changes: 61 additions & 0 deletions docs/getting-started/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Getting Started

WhyGraph is a rationale layer over [CodeGraph](https://github.com/colbymchenry/codegraph). CodeGraph
maps what your code *is* - symbols, callers, callees. WhyGraph adds *why* it exists, drawn from the
history around it.

For each chunk of code, it collects evidence from git and GitHub - commits, blame, pull requests, the
issues those PRs closed - and links it together. Then it exposes that evidence to your AI editor over
MCP, plus an on-demand rationale card (purpose, why, constraints, tradeoffs, risks) that it caches.

You install WhyGraph once, then wire it into each repo you want it to analyze. It speaks MCP, so any
editor that does too can use it.

## CodeGraph vs WhyGraph

The two tools stay in their lanes:

| Layer | Answers | Examples |
|---|---|---|
| **CodeGraph** | "What's connected to what?" | callers, callees, symbol resolution, type hierarchy |
| **WhyGraph** | "Why does this exist, and when did it change?" | evidence, rationale cards, area history |

Run both. WhyGraph reads CodeGraph's index to resolve a symbol to a file and line range, then layers
its own history on top.

## Prerequisites

You don't need all of these - most are optional, and the phases that depend on them skip cleanly when
they're missing.

- **[uv](https://docs.astral.sh/uv/)** *or* **Docker** - uv for a native install, or Docker alone for
the [container install](installation.md). With Docker, you need nothing else on your host.
- **git** - your repo history is the primary evidence source.
- **Docker** *(native installs only)* - when no `codegraph` binary is on `PATH`, `whygraph scan` runs
CodeGraph inside the WhyGraph image to index the repo.
- **[`gh` CLI](https://cli.github.com/)**, authenticated - only for GitHub repos, and only if you
enable the remote crawl. Without it, the GitHub phase is skipped.
- **`claude` CLI** *or* an LLM API key - for per-commit descriptions and rationale cards. Both phases
skip cleanly if neither is available.

Ready to install?

<div class="grid cards" markdown>

- :material-download:{ .lg .middle } __Installation__

---

Docker, PyPI, GitHub, or a local checkout - pick the path that fits.

[:octicons-arrow-right-24: Install WhyGraph](installation.md)

- :material-rocket-launch:{ .lg .middle } __Quickstart__

---

Init, scan, wire an editor - the happy path in four commands.

[:octicons-arrow-right-24: Quickstart](quickstart.md)

</div>
Loading
Loading