DocsHound turns open issues and merged pull requests into grounded, reviewable documentation updates.
The project contains two independently deployable applications:
frontend/— React, TypeScript, and Vite static applicationbackend/— FastAPI JSON/SSE API and agent runtime
Credentials submitted through the local connection panels are sent directly to the backend, held only in process memory, and never returned by the API.
Repository activity
↓
Open gaps + shipped changes
↓
Search relevant first-party documentation
↓
Assess coverage: missing, partial, or documented
↓
Grounded Markdown draft for missing or partial coverage
↓
Human review and approval
↓
New-page or existing-page patch preview
↓
Documentation pull request
Requires Python 3.14 and Bun 1.3+. The original root setup commands remain supported:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
test -f .env || cp .env.example .env
# Add credentials to .env, then start the app:
./run.shOpen http://127.0.0.1:8000. run.sh builds the React
frontend and serves it with the API from one backend process. HOST and PORT
can override the default bind address and port. Keep an existing .env when
upgrading; replacing it would discard its credentials and settings.
For a frozen backend installation, use uv 0.12+ instead of the pip commands:
cd backend
uv sync --locked
cd ..
./run.shBackend dependencies are declared in backend/pyproject.toml and reproducibly
resolved by backend/uv.lock. Refresh them deliberately with
cd backend && uv lock --upgrade && uv sync.
For frontend hot reload, run each development server in its own terminal:
./backend/run.sh
bun run --cwd frontend devThe frontend development server runs at http://127.0.0.1:5173
and proxies /api to the backend at http://127.0.0.1:8000.
The repeatable stage setup, pinned live GitHub sources, read-only preflight, and
LangSmith trace configuration live in demo/. Start the
complete demo environment with:
./demo/run.sh opencodeAdd credentials to backend/.env (or a root .env for compatibility with
existing local installations):
APP_ENV=development # set to production to disable browser key entry
GITHUB_TOKEN= # optional server token for scans and documentation PRs
MERGE_GATEWAY_API_KEY= # recommended: model-based analysis through Gateway
MERGE_GATEWAY_PRIMARY_MODEL=google/gemini-3.7-flash
MERGE_GATEWAY_FALLBACK_MODEL=openai/gpt-5.6-luna
OPENAI_API_KEY= # optional legacy direct-provider fallback
OPENAI_MODEL=gpt-4o-mini
LANGSMITH_API_KEY= # default OTLP trace destination
LANGSMITH_PROJECT=docshound
ALLOWED_ORIGINS=http://localhost:5173
DOCSHOUND_DB_PATH= # optional: explicit shared SQLite path
For automatic forks of arbitrary public repositories, use a classic GitHub
token with the public_repo scope. GitHub requires Administration write access
to create a fork with a fine-grained token, so fine-grained tokens are best for
direct writes or reusing a fork you already created; give that fork Contents and
Pull requests read/write access.
VITE_API_BASE_URL is the only frontend environment variable. Set it to the
public backend origin for independent deployments:
VITE_API_BASE_URL=https://api.example.com
Values prefixed with VITE_ are public and embedded in the browser bundle.
Never place Merge Gateway, model-provider, or GitHub credentials in the
frontend environment.
In local development, a server-managed GITHUB_TOKEN is automatically verified
for the repository entered on the homepage without being sent to or displayed
in the browser. This is the recommended setup for repeatable demos. When no
server token is configured, the readiness checklist can accept one GitHub token
for repository research and documentation pull requests. The model connection
menu can similarly send a Merge Gateway key to the backend. Browser-provided
overrides are held only in backend process memory and cleared on restart. DocsHound
automatically resolves the official documentation repository and folder from
repository structure, README links, the GitHub homepage, and “Edit this page on
GitHub” links. The detected source is shown before each run and can be
overridden.
Pull-request previews always use that upstream documentation repository. Only after approval does DocsHound resolve a write destination: it writes directly when permitted, otherwise it reuses the connected account's fork or creates one, then opens the pull request against upstream. If GitHub permits the fork and commit but requires browser confirmation for the cross-fork pull request, DocsHound links directly to the prefilled upstream comparison page.
For a confirmed documentation root containing at most 100 Markdown or MDX
pages, an authenticated run reads the complete corpus before ranking the best
eight pages per finding. Larger roots use a bounded search of up to 100 pages.
When documentation lives in a separate repository, its issues and merged pull
requests can also be included as documentation-specific evidence. Browser
credential entry is disabled when APP_ENV is production; production
deployments should inject GITHUB_TOKEN and MERGE_GATEWAY_API_KEY through the
server's secret manager.
Public website fetches check URLs and DNS answers before each request, including redirect targets. They request uncompressed responses and treat replies that still advertise compression as unavailable. Documentation pages retain a prefix of up to 500,000 bytes before text extraction. Robots.txt, sitemap, and documentation-source homepage responses above 2,000,000 bytes are unavailable. The HTTP transport resolves hostnames separately from the DNS preflight, so deployments that require DNS rebinding protection should also enforce network egress restrictions.
DocsHound produces one vendor-neutral OpenTelemetry trace stream enriched with
OpenInference semantics. Each run is an OpenInference AGENT span, repository
operations are TOOL spans, and the LangChain, LangGraph, and OpenAI-compatible
Gateway calls beneath them are instrumented automatically. Model spans include
the requested provider/model, the model returned by Gateway, and whether
DocsHound used its fallback route.
Set a LangSmith API key to use LangSmith as the default OTLP destination:
LANGSMITH_API_KEY=lsv2_...
LANGSMITH_PROJECT=docshound
OTEL_SERVICE_NAME=docshound
The LangSmith SDK's native tracing switch is intentionally unnecessary: spans
go directly to LangSmith's OTLP endpoint, avoiding a duplicate trace tree.
Explicit OTEL_EXPORTER_OTLP_ENDPOINT or
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT configuration takes precedence, making it
possible to route the same spans to an OpenTelemetry Collector or a future
Google exporter without changing agent code. Standard options including
OTEL_EXPORTER_OTLP_HEADERS, OTEL_RESOURCE_ATTRIBUTES, and
OTEL_SDK_DISABLED are supported. Set OPENINFERENCE_HIDE_INPUTS=true and/or
OPENINFERENCE_HIDE_OUTPUTS=true when model content must not be captured by
automatic instrumentation. DocsHound's custom spans record repository identity,
the selected documentation repository and root, source references, and result
summaries—not credentials or issue, pull-request, and document bodies.
Build and run both applications locally:
docker compose up --buildOpen http://localhost:8080. The backend is available at
http://localhost:8000, with persistent SQLite data in a named Docker volume.
Each directory also has its own Dockerfile, so the frontend and backend can be
built, deployed, scaled, and rolled back separately. Configure the backend's
ALLOWED_ORIGINS with the deployed frontend origin.
The versioned backend API is under /api/v1. Interactive OpenAPI documentation
is available at http://127.0.0.1:8000/docs.
Start a run:
curl -sS -X POST http://127.0.0.1:8000/api/v1/runs \
-H 'Content-Type: application/json' \
-d '{"repo":"GoogleCloudPlatform/knowledge-catalog","limit":50}'Resolve and confirm documentation sources before a run:
curl -sS -X POST http://127.0.0.1:8000/api/v1/sources/resolve \
-H 'Content-Type: application/json' \
-d '{"repo":"kubernetes/kubernetes"}'Then fetch its state or subscribe to JSON server-sent events:
curl -sS http://127.0.0.1:8000/api/v1/runs/<RUN_ID>
curl -N http://127.0.0.1:8000/api/v1/runs/<RUN_ID>/eventsEach observer receives its own live event stream. New observers of an active run also receive up to its last 2,000 events. Slow observers retain a bounded recent window, so use the run state endpoint for a complete current snapshot. Completed streams are retained for at most 50 runs in process memory; persisted run state remains available after that event history expires.
Completed run responses and run_completed events include a user-facing
outcome and summary. Outcomes distinguish recommendations from
no_activity, no_recommendations, partial_failure, and failed, so clients
never have to infer an empty result from counters or mistake a recoverable tool
error for a successful run.
The API also exposes findings, approval/rejection, approved documents, repository patch previews, patch downloads, and pull-request creation. Each patch preview records the approved revision it was built from. Approving a changed document discards its unpublished preview, and publishing a preview for an earlier revision returns HTTP 409. To update an existing documentation pull request after editing, refresh the preview and publish again; DocsHound pushes the new revision to the same branch and pull request.
For compatibility with existing integrations, POST /runs,
GET /runs/{run_id}, and GET /runs/{run_id}/events.json remain available as
aliases for the original DocsHound API contract. New integrations should use
the versioned /api/v1 routes.
The backend stores new installations in backend/data/docshound.db. If that
file is absent, an existing root data/docshound.db is reused so an upgrade
keeps saved runs and documents visible. If both exist, the backend database
takes precedence. Set
DOCSHOUND_DB_PATH when a deployment needs an explicit shared location.
The database includes completed runs, findings, approved document revisions, prepared patches, and created pull-request metadata.
SQLite and the in-process event stream are appropriate for a single backend replica. A multi-replica deployment should use shared persistence and event delivery before scaling horizontally.
Run backend tests:
cd backend
uv lock --check
uv run ruff check app tests ../demo
PYTHONWARNINGS='error::ResourceWarning' \
uv run --locked python -m unittest discover -s tests -vRun frontend checks:
cd frontend
bun run format:check
bun run typecheck
bun run test
bun run buildGitHub Actions runs the same locked backend and frontend checks, then builds
both Docker images with docker compose build.
backend/
app/ FastAPI API, agent, persistence, and integrations
tests/ API and workflow tests
Dockerfile
frontend/
src/ React application and typed API client
public/ DocsHound assets
Dockerfile
docker-compose.yml Local production-style deployment
run.sh Starts both development servers