Skip to content

Commit f0030f5

Browse files
authored
Merge pull request #24 from mtrdesign/feature/remove-codegraph-image
Drop standalone codegraph image, consolidate on one container
2 parents ea9e166 + 7f4a57e commit f0030f5

14 files changed

Lines changed: 77 additions & 317 deletions

File tree

.github/workflows/publish-codegraph-image.yml

Lines changed: 0 additions & 69 deletions
This file was deleted.

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Invariants that keep the shim correct — preserve them:
7373
- **Host-user file ownership.** The shim runs `--user "$(id -u):$(id -g)" -e HOME=/tmp` so `.whygraph/` and `.codegraph/` come back owned by the host user and git sees matching ownership (no "dubious ownership"). Keep these when editing the shim.
7474
- **GitHub token is per-project.** `[scan].token` in each repo's `whygraph.toml` (gitignored, never committed) is exported as `GH_TOKEN` for that scan's `gh` calls (`cli/commands/scan.py:_apply_github_token`), falling back to ambient `GH_TOKEN` / `GITHUB_TOKEN` (the shim passes those through). Do **not** bake a token into the image or assume a container-wide token.
7575

76-
CodeGraph runs from the **in-image `codegraph` binary** (no docker-in-docker, no host socket): `bootstrap.py` prefers the local binary and only falls back to `docker run` on hosts without it. `whygraph scan` refreshes the index each run `codegraph sync -q` when an index exists, `codegraph init -i` on first run — gated by `--codegraph/--no-codegraph`.
76+
CodeGraph indexing belongs to **`whygraph scan`, not `whygraph init`**`init` only bootstraps the WhyGraph DB / config / agent wiring (and its preflight no longer requires `docker`). `whygraph scan` builds or refreshes the index each run — `codegraph init -i` on first run, `codegraph sync -q` thereafter — gated by `--codegraph/--no-codegraph`. CodeGraph runs from the **in-image `codegraph` binary** (no docker-in-docker, no host socket): `bootstrap.py` (`services/codegraph/`) prefers the local binary and only falls back to `docker run` on native (`uv`/`pipx`) hosts without it. There is a **single image** `ghcr.io/mtrdesign/whygraph` — and that fallback runs `codegraph` inside it (`docker run … whygraph codegraph …`); there is no separate codegraph image.
7777

7878
### Auto-rescan git hooks
7979

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ For each symbol, WhyGraph collects evidence from git history and GitHub (commits
1010

1111
- **[uv](https://docs.astral.sh/uv/)** — Python toolchain. Installs Python 3.11+ automatically.
1212
- **git** — repo history is the primary evidence source.
13-
- **Docker** `whygraph init` runs a vendored container image to bootstrap CodeGraph in the current repo. No host Node install needed.
13+
- **Docker** *(native installs only)* — when no `codegraph` binary is on PATH, `whygraph scan` runs CodeGraph inside the WhyGraph image to index the repo. No host Node install needed. The pure-Docker install (below) already runs everything in that image.
1414
- **[`gh` CLI](https://cli.github.com/)**, authenticated (`gh auth login`) — required only if your repo is on GitHub. Without it, the GitHub crawl phase is skipped silently.
1515
- **`claude` CLI** *or* `ANTHROPIC_API_KEY` — needed for the LLM diff-description phase of `whygraph scan` and for `whygraph_rationale_brief`. Both phases skip cleanly if neither is available. The `claude` CLI defaults to your Claude.ai subscription billing.
1616

@@ -117,9 +117,7 @@ WhyGraph's MCP server (`whygraph-mcp`) is a standalone console script, so any LL
117117
Run from the repo you want WhyGraph to analyse:
118118

119119
```bash
120-
whygraph init # preflight + WhyGraph DB + CodeGraph via Docker (no agent wiring)
121-
whygraph init --no-codegraph # skip the CodeGraph bootstrap step
122-
whygraph init --codegraph-image TAG # pin a specific whygraph-codegraph image
120+
whygraph init # preflight + WhyGraph DB + example config (no agent wiring)
123121
whygraph init --skip-preflight # skip the host-tool diagnostics (CI escape hatch)
124122
whygraph init --agent claude # all of the above + writes .mcp.json + populates .claude/
125123
whygraph init --agent cursor # writes .cursor/mcp.json
@@ -143,8 +141,8 @@ Don't want Python, Node, `gh`, and CodeGraph on your machine? WhyGraph ships as
143141
curl -fsSL https://raw.githubusercontent.com/mtrdesign/whygraph/main/scripts/install.sh | sh
144142

145143
cd your-repo
146-
whygraph init # bootstrap WhyGraph DB + CodeGraph index
147-
whygraph scan # crawl history + refresh index + LLM descriptions
144+
whygraph init # bootstrap WhyGraph DB + write config (+ optional --agent wiring)
145+
whygraph scan # crawl history + build/refresh CodeGraph index + LLM descriptions
148146
```
149147

150148
`install.sh` drops a `whygraph` (and `whygraph-mcp`) shim on your `PATH` that runs the published image (`ghcr.io/mtrdesign/whygraph`) against the current directory — `docker run --rm -v "$PWD:/workspace" … whygraph "$@"`. The container is ephemeral per command: no compose, no `docker exec`, nothing to start or stop.
@@ -173,8 +171,8 @@ The generated `.mcp.json` launches `whygraph-mcp` by bare command name; your edi
173171
| Command | Purpose |
174172
|---|---|
175173
| `whygraph version` | Print installed package version. |
176-
| `whygraph init [--no-codegraph]` | Run preflight diagnostics (git / docker / gh / LLM credential), bootstrap the WhyGraph DB, and pull the vendored Docker image to populate `.codegraph/codegraph.db`. Pass `--agent <name>` to also wire MCP for an editor. Idempotent. |
177-
| `whygraph scan` | Walk first-parent history and populate `.whygraph/whygraph.db`: commits + GitHub PRs/issues + TF-IDF scoring + per-commit LLM diff descriptions. Idempotent. `--no-remote` skips the PR/issue crawl for a fast, offline, git-only scan. |
174+
| `whygraph init` | Run preflight diagnostics (git / gh / LLM credential), bootstrap the WhyGraph DB, and write the example config + `.gitignore` entries. Pass `--agent <name>` to also wire MCP for an editor. Idempotent. Does not index CodeGraph — that happens on `scan`. |
175+
| `whygraph scan` | Build or refresh the CodeGraph index (`.codegraph/codegraph.db`), then walk first-parent history and populate `.whygraph/whygraph.db`: commits + GitHub PRs/issues + TF-IDF scoring + per-commit LLM diff descriptions. Idempotent. `--no-codegraph` skips the index refresh; `--no-remote` skips the PR/issue crawl for a fast, offline, git-only scan. |
178176
| `whygraph hooks install / uninstall / status` | Opt-in git hooks (`post-commit` / `post-merge` / `post-rewrite`) that keep WhyGraph current as you commit — see [Keep it fresh automatically](#keep-it-fresh-automatically). |
179177
| `whygraph render [--out PATH] [--open] [--depth N]` | Render a self-contained HTML viewer of the CodeGraph + WhyGraph data. Single file, vendored Cytoscape, opens with double-click. Cached rationale only. `--depth N` (1–4, default 1) caps which nodes get a populated detail block — fast first paint at default 1 (modules only); pass `--depth 4` for full data. |
180178
| `whygraph serve [--port 8765] [--open]` | Long-running localhost viewer with on-demand rationale generation. Same UI as `render`, plus a "Generate rationale" button on uncached nodes. |
@@ -292,7 +290,7 @@ whygraph serve --open # localhost viewer with on-demand rationale
292290
│ │ ├── agents/ # planner / researcher / synthesizer / implementor
293291
│ │ ├── commands/ # /rationale, /whygraph-plan, /whygraph-implement
294292
│ │ └── skills/ # ask-why / plan-change / pre-edit / implement-plan
295-
│ ├── init.py # CodeGraph bootstrap (nvm + codegraph init -i)
293+
│ ├── init.py # WhyGraph DB + config + agent MCP wiring
296294
│ ├── mcp_server.py # FastMCP stdio server (resources/tools/prompts)
297295
│ ├── mcp_queries.py # composite SQL for the MCP layer
298296
│ ├── backend.py # GraphBackend Protocol + SqliteCodegraphBackend

docker/codegraph/Dockerfile

Lines changed: 0 additions & 36 deletions
This file was deleted.

docker/codegraph/README.md

Lines changed: 0 additions & 48 deletions
This file was deleted.

docker/whygraph/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919

2020
FROM python:3.12-slim
2121

22-
# Pinned the same way as docker/codegraph/Dockerfile so the version can be
23-
# advanced without editing the body. Defaults to `latest` for local
24-
# convenience; CI/publish should pass an explicit pin.
22+
# Pinned via build arg so the version can be advanced without editing the
23+
# body. Defaults to `latest` for local convenience; CI/publish should pass
24+
# an explicit pin.
2525
ARG CODEGRAPH_VERSION=latest
2626
ARG NODE_MAJOR=22
2727

scripts/install.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
# the WhyGraph container against the current directory, then pulls the
66
# image. After this, the whole workflow is just:
77
#
8-
# whygraph init # in a repo: bootstrap DB + CodeGraph index
9-
# whygraph scan # crawl history + refresh index + LLM descriptions
8+
# whygraph init # in a repo: bootstrap DB + config (+ optional --agent wiring)
9+
# whygraph scan # crawl history + build/refresh CodeGraph index + LLM descriptions
1010
#
1111
# Usage:
1212
# curl -fsSL https://raw.githubusercontent.com/mtrdesign/whygraph/main/scripts/install.sh | sh

src/whygraph/cli/commands/init.py

Lines changed: 6 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,6 @@
4040
" Default: enabled. No-op for agents that ship no asset tree."
4141
),
4242
)
43-
@click.option(
44-
"--codegraph/--no-codegraph",
45-
"install_codegraph",
46-
default=True,
47-
help=(
48-
"Bootstrap CodeGraph via the vendored Docker image so the project"
49-
" ends up with a populated `.codegraph/codegraph.db`. Default:"
50-
" enabled. Idempotent — a re-run with the DB already present is"
51-
" a no-op."
52-
),
53-
)
54-
@click.option(
55-
"--codegraph-image",
56-
"codegraph_image",
57-
default=None,
58-
help=(
59-
"Override the Docker image used for the CodeGraph bootstrap."
60-
" Defaults to the pinned ghcr.io/mtrdesign/whygraph-codegraph tag."
61-
),
62-
)
6343
@click.option(
6444
"--skip-preflight",
6545
"skip_preflight",
@@ -85,8 +65,6 @@ def init_cmd(
8565
print_only: bool,
8666
list_agents: bool,
8767
install_assets: bool,
88-
install_codegraph: bool,
89-
codegraph_image: str | None,
9068
skip_preflight: bool,
9169
force: bool,
9270
) -> None:
@@ -98,9 +76,9 @@ def init_cmd(
9876
``.gitignore`` keeps the user-owned config and generated caches out of
9977
git (``whygraph.toml``, ``.whygraph/``, ``.codegraph/``).
10078
101-
Also bootstraps CodeGraph by default — runs the vendored Docker image
102-
to populate ``.codegraph/codegraph.db`` in the current repo. Pass
103-
``--no-codegraph`` to skip that step.
79+
Does **not** index CodeGraph — that happens on ``whygraph scan``,
80+
which populates ``.codegraph/codegraph.db`` (and refreshes it on every
81+
subsequent run).
10482
10583
With ``--agent X``, registers the WhyGraph MCP server with the named
10684
agent. All supported agents are project-scoped — their MCP config
@@ -123,23 +101,14 @@ def init_cmd(
123101
project_root = Path.cwd()
124102

125103
if not skip_preflight:
126-
_run_preflight(project_root, with_codegraph=install_codegraph)
104+
_run_preflight(project_root)
127105

128106
db_path = _ensure_db_initialized()
129107
click.echo(f"Initialized WhyGraph database at {db_path}")
130108

131109
_scaffold_example_config(project_root)
132110
_ensure_gitignore(project_root)
133111

134-
if install_codegraph:
135-
_ensure_codegraph_bootstrapped(project_root, image=codegraph_image)
136-
else:
137-
click.echo(
138-
"Skipped CodeGraph bootstrap. Re-run without `--no-codegraph`"
139-
" — or run `codegraph init -i` against the repo by hand —"
140-
" before using WhyGraph's rationale or evidence tools."
141-
)
142-
143112
if agent_name is None:
144113
click.echo(
145114
"Tip: run `whygraph init --list-agents` to see supported agents,"
@@ -161,7 +130,7 @@ def init_cmd(
161130
_print_install_summary(target, project_root, result, force=force)
162131

163132

164-
def _run_preflight(project_root: Path, *, with_codegraph: bool) -> None:
133+
def _run_preflight(project_root: Path) -> None:
165134
"""Echo the diagnostics block; ``fail`` with a clean error on missing tools.
166135
167136
Imported here (not at module top) so ``--list-agents`` and ``--help``
@@ -170,40 +139,11 @@ def _run_preflight(project_root: Path, *, with_codegraph: bool) -> None:
170139
from whygraph.cli.preflight import PreflightError, run_preflight
171140

172141
try:
173-
run_preflight(project_root, with_codegraph=with_codegraph)
142+
run_preflight(project_root)
174143
except PreflightError as exc:
175144
fail(str(exc))
176145

177146

178-
def _ensure_codegraph_bootstrapped(project_root: Path, *, image: str | None) -> None:
179-
"""Idempotently materialise ``.codegraph/codegraph.db`` via Docker.
180-
181-
Echoes a one-line status for both the "already initialized" and
182-
"bootstrapping now" cases, and ``fail``s with a clean message if the
183-
container run blows up. Lazy import keeps lightweight CLI surfaces
184-
fast (mirrors :func:`_ensure_db_initialized`).
185-
"""
186-
from whygraph.services.codegraph import (
187-
CODEGRAPH_DB_RELPATH,
188-
DEFAULT_CODEGRAPH_IMAGE,
189-
CodeGraphBootstrapError,
190-
ensure_codegraph_db,
191-
)
192-
193-
db_path = project_root / CODEGRAPH_DB_RELPATH
194-
if db_path.exists():
195-
click.echo(f"CodeGraph already initialized at {db_path}")
196-
return
197-
198-
img = image or DEFAULT_CODEGRAPH_IMAGE
199-
click.echo(f"Bootstrapping CodeGraph via Docker (image: {img})...")
200-
try:
201-
result_path = ensure_codegraph_db(project_root, image=image)
202-
except CodeGraphBootstrapError as exc:
203-
fail(f"CodeGraph bootstrap failed: {exc}")
204-
click.echo(f"Initialized CodeGraph database at {result_path}")
205-
206-
207147
def _scaffold_example_config(project_root: Path) -> None:
208148
"""Write the committable ``whygraph.example.toml`` at the project root.
209149

src/whygraph/cli/commands/scan.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@
4646
help=(
4747
"Refresh the CodeGraph index before crawling — `codegraph sync` when "
4848
"an index exists, `codegraph init -i` on first run. Uses the local "
49-
"`codegraph` binary if present, else the vendored Docker image. The "
50-
"crawl itself doesn't need CodeGraph (only the MCP rationale/evidence "
51-
"tools do), so a failure here warns rather than aborting. Default: on."
49+
"`codegraph` binary if present, else runs it inside the WhyGraph "
50+
"Docker image. The crawl itself doesn't need CodeGraph (only the MCP "
51+
"rationale/evidence tools do), so a failure here warns rather than "
52+
"aborting. Default: on."
5253
),
5354
)
5455
@click.option(
@@ -57,7 +58,8 @@
5758
default=None,
5859
help=(
5960
"Override the Docker image used for the CodeGraph refresh fallback "
60-
"(ignored when a local `codegraph` binary is found)."
61+
"(defaults to the pinned ghcr.io/mtrdesign/whygraph tag; ignored "
62+
"when a local `codegraph` binary is found)."
6163
),
6264
)
6365
@click.option(

0 commit comments

Comments
 (0)