Setting Up a Development Environment
This guide will walk you through setting up a development environment for DocsGPT. This setup allows you to modify and test the applicationβs backend and frontend components.
1. Spin Up Postgres and Redis
For development purposes, you can quickly start Postgres and Redis containers. Postgres is the user-data store for DocsGPT (conversations, agents, prompts, sources, attachments, workflows, logs, and token usage), and Redis is used as the cache and Celery broker. We provide a dedicated Docker Compose file, docker-compose-dev.yaml, located in the deployment directory, that includes only these essential services. Once POSTGRES_URI points at it (step 1 of section 2 below), the backend applies the Alembic schema automatically on first boot (AUTO_MIGRATE=true / AUTO_CREATE_DB=true ship enabled), so no separate migration step is required. You can still run python scripts/db/init_postgres.py or docsgpt migrate (python -m docsgpt migrate without installing) explicitly if you prefer.
You can find the docker-compose-dev.yaml file hereΒ .
Steps to start Postgres and Redis:
-
Navigate to the root directory of your DocsGPT repository in your terminal.
-
Run the following command to start the containers defined in
docker-compose-dev.yaml:docker compose -f deployment/docker-compose-dev.yaml up -dThis starts Postgres and Redis in detached mode, running in the background. When the API boots against the fresh Postgres instance, it will automatically create the database (if missing) and apply the current Alembic schema.
MongoDB is not needed for a default DocsGPT install. The MongoDB vector store (VECTOR_STORE=mongodb)
runs its searches with Atlas $vectorSearch, so MONGO_URI must point at MongoDB Atlas (or a local
Atlas deployment with search); a plain mongo container does not provide it. The client library is not
part of the dependencies: install it with pip install 'pymongo>=4.6' (uv pip install in a uv
environment, where a later uv sync removes it again). For migrating an existing
Mongo-based install to Postgres, see PostgreSQL for User Data.
2. Run the Backend
To run the DocsGPT backend locally, youβll need to set up a Python environment and install the necessary dependencies.
Prerequisites:
- Python 3.12:
pyproject.tomlrequires 3.12 or newer, and CI tests on 3.12. Check your version withpython --versionorpython3 --version. - uvΒ (recommended): it installs the locked dependencies and the
docsgptcommand in one step. Plain pip works too.
Steps to run the backend:
-
Configure Environment Variables:
DocsGPT reads its settings from environment variables and from a
.envfile in the repository root. Start from the template:cp .env-template .envThen edit
.envand set the two values a development setup needs:# The Postgres started in section 1 (credentials from deployment/docker-compose-dev.yaml) POSTGRES_URI=postgresql://docsgpt:docsgpt@localhost:5432/docsgpt # Any random string; generate one with: openssl rand -hex 32 INTERNAL_KEY=<paste the generated value>POSTGRES_URIis commented out in the template, and without it the backend skips its database setup.INTERNAL_KEYis how the worker hands a finished index back to the API, so without it every upload fails after parsing. The API and the worker read the same.env, so they share the key.To pick a model provider, set
LLM_PROVIDERandAPI_KEYas described in Cloud providers or Local inference. To work without any provider or key, run the backend withdocsgpt dev --mock-llm(step 4), which answers from a local mock.You can also export any setting in your shell instead of writing it to
.env. The App Configuration guide explains the common settings, and the Settings Reference lists every one, generated from the definitions indocsgpt/core/settings/. -
Install the Backend:
From the repository root, with uv:
uv syncThis creates
.venv, installs the dependencies pinned inuv.locktogether with the test tools, and installs DocsGPT itself in editable mode, which puts thedocsgptcommand in.venv/bin. Activate the environment (source .venv/bin/activate, or.venv\Scripts\activateon Windows) or prefix commands withuv run, as inuv run docsgpt dev. uv uses a Python 3.12 or newer that it finds on your system, or downloads one;uv sync --python 3.12pins the version CI uses.With pip instead, create a virtual environment, install the exported requirements, then install the checkout itself so the
docsgptcommand exists:python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r docsgpt/requirements.txt pip install -e .Without the last line, run the commands in this guide as
python -m docsgpt β¦(for examplepython -m docsgpt dev).Optional extras are not installed by default. Add them when you need the feature (each file is the core set plus the extra):
uv sync --extra docling --extra milvus # name every extra you want: uv sync removes the others # or with pip: pip install -r docsgpt/requirements-docling.txt # docling parser engine: OCR backend, read_document structured output pip install -r docsgpt/requirements-milvus.txt # VECTOR_STORE=milvusThe docling file adds the PyTorch CPU index; pip handles that as-is, while
uv pip install -rneedsUV_INDEX_STRATEGY=unsafe-best-match(or useuv sync --extra docling, which reads the lock).A feature whose extra is missing fails with the exact command to run. Dependencies are declared in
pyproject.tomland locked inuv.lock, and therequirements*.txtfiles are exported from that lock. After changingpyproject.toml, runuv lockandbash scripts/export_requirements.shso the exported files stay in sync (CI checks this).With Postgres and Redis running, check the setup:
docsgpt doctorIt reports whether PostgreSQL and Redis answer, whether a model provider is configured, and whether the API port is free. A missing
POSTGRES_URIshows up here as a failure. -
Embedding Model (no action needed):
The embedding model is downloaded automatically the first time you ingest a document, and cached for subsequent runs under
models/in the data home: the repository root, unlessDOCSGPT_HOMEpoints elsewhere. SetEMBEDDINGS_CACHE_DIRto use another directory.For an offline or air-gapped machine, fetch it ahead of time instead:
docsgpt prefetch-models -
Run the Backend:
One command runs the API and the worker from this checkout, each restarting when you save a file:
docsgpt devBoth run as children of that terminal, with their output interleaved and labelled, and Ctrl-C stops them together. Useful flags:
Flag What it does --uialso start the Vite dev server, so the whole app runs from one command --mock-llmrun scripts/mock_llm.pyand point DocsGPT at it, so no API key is needed--no-workerleave the worker to you, for instance when debugging it in your editor; start one as in step 5, or searches and scheduled tasks stop working --no-reloaddo not restart anything on save --portserve the API somewhere other than 7091 docsgpt devis for a checkout.docsgpt up --native, by contrast, installs supervised services that outlive the shell β see Run it as services.docsgpt doctorchecks the things that usually break a new setup: whether PostgreSQL answers and its schema matches this version, whether Redis answers, whether a model provider is configured, and whether the port is free. Run it first when something does not start.To run the two processes yourself instead, start the ASGI composition under uvicorn. It serves the whole application, hot-reloads on source changes, and matches the production runtime:
uvicorn docsgpt.asgi:asgi_app --host 0.0.0.0 --port 7091 --reloadThis makes the backend accessible on
http://localhost:7091. Production usesgunicorn -k docsgpt.gunicorn_worker.BoundedDrainUvicornWorkeragainst the samedocsgpt.asgi:asgi_apptarget;docsgpt/Dockerfilehas the full command.A plain Flask run is a faster inner loop (quick startup, the Werkzeug interactive debugger):
flask --app docsgpt/app.py run --host=0.0.0.0 --port=7091But it serves only the WSGI Flask app, so the ASGI-only features return 404 under it. Chat still works (
POST /streamis a Flask route). Useflask runonly when you donβt need those features. -
Start the Celery Worker (not needed if you used
docsgpt dev):Open a new terminal window (and activate your virtual environment if you used one), then start the worker from the repository root:
docsgpt workerUse
python -m docsgpt workerif thedocsgptcommand is not on yourPATH. The worker parses and embeds uploaded documents, embeds every search query for the API, and runs background agent tasks. It also embeds the Celery beat scheduler (-B).Chat retrieval needs a running worker. The API sends each query embedding to it (
EMBEDDINGS_DELEGATE_TO_WORKER, on by default). Without a worker, the first search waits up toEMBEDDINGS_DELEGATE_TIMEOUT(60 seconds), searches in the next 30 seconds fail at once, and every answer comes back with no retrieved context, without an error. To run the API alone, setEMBEDDINGS_DELEGATE_TO_WORKER=falseto load the model in the API process, or pointEMBEDDINGS_BASE_URLat an embeddings service.The beat scheduler fires scheduled agent runs, source syncs, the reconciliation of stuck tasks, the background job sweeps, retention cleanups and the version check. If no scheduler runs, none of these happen and nothing reports it. At least one scheduler must run. Running more than one is safe, because a lock in Redis lets only one of them schedule at a time.
docsgpt worker --no-beatleaves the scheduler out, anddocsgpt beatruns it on its own. On Windows the scheduler cannot run inside the worker, so rundocsgpt beatin a third terminal. Background jobs lists every periodic task and what it trims.To run Celery directly, add
-Byourself:celery -A docsgpt.app.celery worker -l INFO -BCelery rejects
-Bon Windows. There, drop it and run the scheduler in a separate terminal withcelery -A docsgpt.app.celery beat -l INFO(ordocsgpt beat).macOS note: due to a threading issue with the default prefork pool, use the solo pool on macOS.
docsgpt workerpicks it automatically on macOS and Windows. With raw Celery, pass it yourself:python -m celery -A docsgpt.app.celery worker -l INFO -B --pool=soloThe solo pool makes each query embedding take roughly 350 ms instead of about 55 ms on prefork, almost all of it spent waiting for the worker to pick up the message. That only affects local development; production runs prefork.
Running in Debugger (VSCode):
For easier debugging, you can launch the API and the Celery worker directly from VSCodeβs debugger.
- Press Shift + Cmd + D (macOS) or Shift + Windows + D (Windows) to open the Run and Debug view.
- You should see configurations named βAPI (uvicorn)β and βCelery workerβ, and a compound βDocsGPT: Full Stackβ that starts them with the frontend. Select one and click the βStart Debuggingβ button (green play icon).
The API configuration runs the same ASGI app as production, so the ASGI-only features
work under the debugger. It deliberately runs without --reload: the reloader restarts the server in a child
process, which your breakpoints would not be attached to. The worker configuration uses the solo pool and
embeds the beat scheduler (-B), except on Windows, where it leaves -B out; start docsgpt beat there.
3. Start the Frontend
To run the DocsGPT frontend locally, youβll need Node.js and npm (Node Package Manager). docsgpt dev --ui starts
the frontend dev server together with the backend once its dependencies are installed (steps 1 and 2 below).
Prerequisites:
- Node.js 22: the frontend declares
node >=22 <23and pins 22 infrontend/.nvmrc, so with nvmΒ you can runnvm useinfrontend/. Check your version withnode -v. npm is bundled with Node.js.
Steps to start the frontend:
-
Navigate to the Frontend Directory:
In your terminal, change the current directory to the
frontendfolder within your DocsGPT repository:cd frontend -
Install Frontend Dependencies:
Install the projectβs frontend dependencies using npm:
npm install --include=devThis installs everything in
package.json, development dependencies included. Vite runs from this local install, and the install also sets up the Husky pre-commit hook, so neither needs a global install. -
Run the Frontend App:
Start the frontend development server:
npm run devThis command will start the Vite development server. The frontend application will typically be accessible at http://localhost:5173/Β . The terminal will display the exact URL where the frontend is running.
With both the backend and frontend running, you should now have a fully functional DocsGPT development environment. You can access the application in your browser at http://localhost:5173/Β and start developing!
ASGI-only features
A few routes hold a response open for a long time, so they are native-async routes mounted only on the ASGI app,
docsgpt.asgi:asgi_app, and not on the Flask app:
| Route | Feature |
|---|---|
/mcp | DocsGPTβs own MCP server |
GET /api/events | Live notifications |
GET /api/messages/<id>/events | Resuming a chat answer after the connection drops |
GET /api/devices/sessions/<id>/events | The command stream of a paired remote device |
GET /api/artifacts/<id>/download | Artifact downloads |
docsgpt api, docsgpt dev, uvicorn docsgpt.asgi:asgi_app, gunicorn with a uvicorn worker and the Docker
images all serve the ASGI app. flask --app docsgpt/app.py run serves only the Flask app, so these routes
return 404 under it.
Working on two branches at once
Each install keeps its own directory and its own services, so a second branch can run beside the first as long as it gets its own port:
docsgpt dev --port 7092 # a second checkout, second terminal
docsgpt up --native --dir ~/.docsgpt/review --port 7092 # or a second installed copyA native install in another directory gets its own service names, so the two never write over each
otherβs units. docsgpt status --dir ~/.docsgpt/review reports on that one alone.
Troubleshooting
Run docsgpt doctor first. It checks PostgreSQL, Redis, the model provider and the API port.
- Searches hang for up to a minute or fail at once, and answers ignore your documents. No worker is consuming the
embeddingsqueue. Start one as in step 5. A worker started with an explicit-Qmust listembeddings. - Scheduled agent runs and source syncs never fire. No beat scheduler is running. Start the worker with
docsgpt workeror add-Bto thecelerycommand. On Windows, also rundocsgpt beat. - Notifications never appear, a dropped answer doesnβt resume, a paired device never receives commands, or
artifact downloads return 404. The API is running under
flask run. Serve it through the ASGI app instead; see ASGI-only features.