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
336 changes: 18 additions & 318 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions apps/web/PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ A local review workspace that combines a browser-based Git diff with comments th
- Comments can be copied as agent-ready XML. The same review comments are available to compatible coding agents through MCP and, in supported browsers, WebMCP.
- The CLI can also display a piped Git patch as a fixed review.
- A remote diffx server can collect from many agent sessions across many repositories. The Repos drawer keeps that work navigable: each repository lists only its current changed branches, newest first, and new arrivals are marked without replacing the review in progress.
- Review data is stored by the local diffx server, as documented in the README.
- Review data is stored by the local diffx server, as documented in `../../docs-website/src/pages/api.md`.

## Capabilities and Constraints

- The web UI uses the Pierre diff package extensively. Use its intended APIs and rendering model; never break its selection, annotations, sticky headers, context expansion, or virtual scrolling.

## Evidence on Hand

- Product usage and behavior: `../../README.md`.
- Product usage and behavior: `../../docs-website/src/pages/`.
- Architecture and frontend ownership: `../../docs/architecture.md` and `../../docs/development.md`.
- Agent integration: `../../docs/mcp.md` and `../../docs/webmcp.md`.
- Existing visual system and Pierre integration rules: `../../DESIGN.md` and `src/DiffWorkspace.tsx`.
Expand Down
3 changes: 1 addition & 2 deletions docs-website/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
/dist/
/resources/
/.hugo_build.lock
/src/pages.gen.ts
34 changes: 18 additions & 16 deletions docs-website/README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
# Docs website

Public user documentation built with Hugo and Hextra. Independent of the
application; existing `docs/` remains code and contributor documentation.
Public user documentation built with [Vocs](https://vocs.dev). Canonical source
for user-facing usage; the root README links here. Existing `docs/` remains code
and contributor documentation.

## Run locally

From the repository root, with mise installed and the project trusted:

```sh
pnpm install --frozen-lockfile
mise run docs:dev
```

Open <http://localhost:1313/>. Changes reload automatically; stop with `Ctrl+C`.
Mise installs the pinned Hugo extended binary when needed. The theme is pinned
in this directory's `go.mod` and `go.sum`; its first download needs network access.
The website needs Go and Git for Hugo modules, with no Node dependencies.
Open <http://localhost:5173/>. Changes reload automatically; stop with `Ctrl+C`.
The site pins React 19.3 directly, as Vocs requires; the web app keeps the
catalog React version.

## Build

```sh
mise run docs:build
```

Static HTML and assets go to `docs-website/dist/` (gitignored). Build warnings
fail the command. `mise run docs:check` runs the same validation.
Static HTML and assets go to `docs-website/dist/public/` (gitignored). Dead
links fail the build. `mise run docs:check` runs the same validation. Preview a
build with `pnpm --filter @diffx/docs preview`.

The pnpm workspace also exposes `pnpm --filter @diffx/docs dev`, `build`, and
`check` through mise. Application builds remain independent.
`preview`. Application builds remain independent.

## Edit

- Homepage: `content/_index.md`.
- Guides: Markdown files in `content/`; use `weight` to order the sidebar.
- Screenshots and other assets: add files under `static/`, then reference them
with paths such as `/images/review.png`.
- Site configuration: `hugo.yaml`.
- Pages: Markdown files in `src/pages/`. Keep them plain Markdown so GitHub
renders the files the README links to.
- Link pages with relative `page.md` paths; Vocs rewrites them to routes.
- Sidebar and site configuration: `vocs.config.ts`.
- Screenshots and other assets: add files under `public/`, then reference
them with paths such as `/images/review.png`.

Use Hextra's built-in docs layout, search, code blocks, and theme toggle. Keep
pages brief; no custom layout or deployment setup yet.
Keep pages brief; no custom layout or deployment setup yet.
17 changes: 0 additions & 17 deletions docs-website/content/_index.md

This file was deleted.

5 changes: 0 additions & 5 deletions docs-website/go.mod

This file was deleted.

2 changes: 0 additions & 2 deletions docs-website/go.sum

This file was deleted.

39 changes: 0 additions & 39 deletions docs-website/hugo.yaml

This file was deleted.

14 changes: 11 additions & 3 deletions docs-website/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
{
"name": "@diffx/docs",
"private": true,
"type": "module",
"scripts": {
"dev": "mise run docs:dev",
"build": "mise run docs:build",
"check": "mise run docs:check"
"dev": "vocs dev",
"build": "vocs build",
"preview": "vocs preview"
},
"dependencies": {
"react": "~19.3.1",
"react-dom": "~19.3.1",
"vite": "catalog:",
"vocs": "^2.10.3",
"waku": "1.0.0-rc.3"
}
}
140 changes: 140 additions & 0 deletions docs-website/src/pages/agent-hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
title: Agent hooks and remote ingestion
description: Run a remote diffx server and collect changes automatically after agent turns.
---

# Agent hooks and remote ingestion

Install Codex, Claude Code, OpenCode or Pi plugins to synchronize each
worktree automatically after agent completion:

```sh
codex plugin marketplace add flexdinesh/diffx
codex plugin add diffx@diffx
```

Configure a remote server and token first. Plugins are remote-only.
The plugin returns after scheduling; a detached Go worker collects only the
triggering checkout using the same branch comparison as manual review.
Non-Git directories are ignored. Child repositories and branches without live
checkouts are excluded; use `sync --branch` for explicit object-only recovery.
Persistent Git identities survive checkout moves and branch renames.
Initially clean automatic captures are skipped. Dirty-to-clean transitions and
new session associations are submitted. Unchanged uploads are skipped, overlapping requests
coalesce, and failures stay outside the agent conversation. See
[plugin setup](plugins.md) for native installation on all hosts,
configuration and removal. Plugins are ready to install from the repository;
the diffx executable is installed separately and must be available to the
harness through PATH or `DIFFX_BINARY`.

Inspect collection/delivery activity and retry waiting payloads:

```sh
diffx collector status
diffx collector retry
tail -n 50 ~/.local/state/diffx/hooks-v4/hooks.log
diffx sync --branch feature --base main --no-browser
```

Manually schedule the same detached collection used by harness plugins:

```sh
diffx hook --harness codex --path /path/to/repo
```

To collect synchronously with harness metadata:

```sh
diffx sync --trigger agent-hook --harness codex --run-id run-123 --session-name 'Feature work' --no-browser
```

Use `--source-id` to supply a stable source/container identity. Hostnames,
branches and source-local paths are searchable metadata, not global identities.
Different sources, checkouts, branches, HEADs, or diff contents remain
independently reviewable. Identical content from the same checkout reuses its
review context. Sessions associate with shared reviews; they do not own or
claim authorship of every worktree's edits. Harness, session ID and optional
session name remain searchable even when identical content reuses a review.

Build and run the container setup for server development:

```sh
mise run docker:up
mise run docker:down
```

Compose publishes HTTP on `127.0.0.1:7980`, outside the local 7981–7990 range,
and preserves the named SQLite volume when stopped or recreated. Set
`DIFFX_SERVER_PORT=7979` to publish another host port. The project is named
`diffx`, so its volume is shared by every checkout. Before first start, put
`DIFFX_SERVER_USERNAME=alice` and `DIFFX_SERVER_PASSWORD=…` in a git-ignored
`.env` beside `compose.yaml`. No default account/password is generated. These
bootstrap credentials create the first account once; restarts preserve password
changes. Signup is disabled by default. Compose explicitly enables insecure
cookies for loopback HTTP development; set `DIFFX_SERVER_INSECURE_COOKIES=false`
and deploy behind HTTPS for remote access.
See [server development](https://github.com/flexdinesh/diffx/blob/main/docs/development.md#server-development) for configuration
and persistence details. Deploy behind HTTPS when exposing the server remotely.

Or build and run the image directly:

```sh
mise run docker:build
docker run --name diffx-server --read-only -p 127.0.0.1:7980:7980 \
--env-file /path/to/private-server.env \
--mount source=diffx-data,target=/data diffx-server:local
```

The env file supplies bootstrap username/password; plain HTTP development also
requires `DIFFX_SERVER_INSECURE_COOKIES=true`. The volume contains observations,
jobs, accounts and credential hashes.
The image runs without Git or a repository mount, as an unprivileged user.
SIGTERM drains HTTP and stops the worker; durable unfinished jobs recover after
their leases expire. Back up the database while stopped.

Build/install the remote server with Go:

```sh
go install github.com/flexdinesh/diffx/cmd/diffx-server@edge
DIFFX_SERVER_USERNAME=alice DIFFX_SERVER_PASSWORD=… \
DIFFX_SERVER_INSECURE_COOKIES=true DIFFX_SERVER_STATE=./test-data/state.db diffx-server
```

Sign in with username/password, then open the top-right account settings to create
a named API token. `collector` tokens support sync and plugins; `api` tokens also
support the user's review REST/MCP APIs. Both expire after 90 days by default
(selectable 1–365 days), can be revoked, and show their secret only once. Browser
sessions use secure cookies; API/MCP and collectors use bearer tokens. Multiple
users share one SQLite database with private data per account. Local `diffx`
automatically supplies its owner and has no login or account settings.

Set `DIFFX_SERVER_SIGNUP_ENABLED=true` to allow signup; invitations are not yet
supported. For operator provisioning or password recovery, stop the server, run:

```sh
diffx-server user create --username bob --state /data/state.db --password-stdin < /path/to/private-password
diffx-server user reset-password --username alice --state /data/state.db --password-stdin < /path/to/private-password
```

Then restart the server. Password reset revokes browser sessions; API token
ownership is independent of passwords. Bootstrap requires both
`DIFFX_SERVER_USERNAME` and `DIFFX_SERVER_PASSWORD`; it never overwrites an existing
account's password. Deploy behind TLS with secure cookies.
Use `--retention-days 14` or config/environment to change server retention.
The server defaults to `127.0.0.1:7980` and `./data/state.db`, independent of
personal CLI settings. Its image defaults to `0.0.0.0:7980` and `/data/state.db`;
`DIFFX_SERVER_*` env vars override image defaults, and explicit flags override
env vars. The CLI never reads `DIFFX_SERVER_*`.

Collectors select that destination with config `remote.url`, `DIFFX_REMOTE_URL`
or `--server`, and authenticate with config `remote.token`, `DIFFX_REMOTE_TOKEN`
or `--token`:

```sh
diffx sync --server https://reviews.example.com
```

Remote submission does not start a local server. The remote server needs no Git
installation or repository mount: all queries read committed SQLite data.
Other producers can submit the same `POST /api/v2/ingestions` contract directly;
the bundled plugins invoke the Go collector.
42 changes: 42 additions & 0 deletions docs-website/src/pages/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: API and data
description: REST contract, ingestion protocol, storage and upgrades.
---

# API and data

The OpenAPI contract is served at `/openapi.yaml`. `POST /api/v2/ingestions`
validates and atomically commits an observation; acknowledgement means commit,
not collection scheduled. Replaying the same source/submission identity and
payload returns its original receipt. Reusing it with different payload fails.
Hooks persist bounded immutable payloads before delivery and retry after later
triggers or `diffx collector retry`. Their pending-data retention remains
seven days independently of server retention. Manual commands always submit and
report failures directly.

Collectors and servers require ingestion protocol 4; upgrade them together.
Public v1 routes and synchronous ingestion are removed.

`/api/v2/contexts` lists stored observations with `q`, `repository`, `branch`,
`worktree`, `hostname`, `sourceId`, `runId`, `harness`, `sessionId` and `sessionName`
filters; `latest=true` omits stale snapshots. Each context names its `streamId` and
the stream's current `latestContextId`. Session filters search submission associations. Scoped review operations
use `/api/v2/contexts/{id}/...`; `/api/v2/events` sends ingestion notifications.
Latest means the most recently collected submission for each source, repository,
checkout, branch and comparison policy; arrival order breaks ties. It does not guarantee current
filesystem state. Older snapshots stay stale when newer reviews expire.

Compatible coding agents can discover stored reviews through `/mcp` or use the
printed `/mcp/contexts/{id}` URL; see
[MCP](mcp.md). A compatible browser can expose the same tools through
WebMCP while the page is open; see [WebMCP](webmcp.md).

Local data lives in `$XDG_STATE_HOME/diffx/state.db`, or
`~/.local/state/diffx/state.db`. `--state memory` disables persistence.
Current schema 11 state persists across restarts. Older, newer or unrecognized
databases are refused without an automatic reset. To start fresh, stop the
server, back up its state directory, and explicitly choose a new database path.
Legacy commands and pending producer payloads are retired.
Stop older processes before upgrading. Local service lifecycle uses a private
authenticated loopback control listener; its token does not authenticate the
local public API.
Loading
Loading