Files

1 line
47 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "bekirdag/docdex", "files": {"docs/usage.md": {"aa90e506a6652fd1d90e318d312e2221db7ca8de": {"t": 1785596014.346307, "n": 46312, "h": "6386a21cb9f7e5b3", "c": "# Docdex Usage Guide\n\nThis is the detailed, technical guide for Docdex. Use it for installation, setup, MCP wiring, HTTP usage, and configuration.\n\n## Contents\n- Install\n- First run\n- Operating modes\n- MCP integration\n- HTTP API\n- State, paths, and defaults\n- Configuration reference\n- Ops and safety\n- Troubleshooting\n- References\n\n## Install\n\n### npm (recommended)\n- Requires Node.js >= 18.\n- Install: `npm i -g docdex`\n- Verify: `docdex --version`\n- `docdex` (alias `docdexd`) downloads the matching platform binary from the GitHub release that matches the npm version.\n\nSupported published binaries:\n- macOS: arm64, x64\n- Linux glibc: arm64, x64\n- Linux musl: x64\n- Windows: x64\n\nInstaller notes:\n- Supported platforms and troubleshooting: `docs/ops/installer_supported_platforms.md`.\n- Release manifest schema: `docs/contracts/release_manifest_schema_v1.md`.\n- Forks: set `DOCDEX_DOWNLOAD_REPO=<owner/repo>` before install.\n- Mirrors: set `DOCDEX_DOWNLOAD_BASE=http://host/path` to redirect downloads.\n- Local dev fallback: if release assets are missing and a local `target/release/docdexd` (or `target/debug/docdexd`) exists, the installer can use it. Disable with `DOCDEX_LOCAL_FALLBACK=0` or override with `DOCDEX_LOCAL_BINARY=/path/to/docdexd`.\n- Platform diagnostics (no download): `docdex doctor` (alias `docdex diagnostics`).\n\nPostinstall behavior:\n- The installer downloads/repairs `docdexd` into the Docdex data directory (`DOCDEX_DIST_DIR` override).\n- It writes MCP client config pointing to `http://127.0.0.1:28491/v1/mcp/sse` (Codex uses `http://127.0.0.1:28491/v1/mcp` with `tool_timeout_sec = 300` and `startup_timeout_sec = 300`) and updates known client config files when present.\n- Auto-configured clients (when config files are present): Claude Desktop, Cursor, Windsurf, Cline, Roo Code, Continue, VS Code, PearAI, Void, Zed, Codex. Restart clients after install.\n- It registers OS startup (LaunchAgent/systemd user/Task Scheduler) so the daemon starts after reboot/login, and attempts to start it immediately when safe.\n- Startup registration now applies conservative FD-pressure controls by default: `DOCDEX_REPO_IDLE_SECONDS=300`, `DOCDEX_REPO_HIBERNATE_SECONDS=1800`, `DOCDEX_REPO_CLEANUP_INTERVAL_SECONDS=60`, `DOCDEX_WEB_MAX_CONCURRENT_BROWSER_FETCHES=1`, and `DOCDEX_WEB_MAX_CONCURRENT_LLM=1` (plus `DOCDEX_BROWSER_AUTO_INSTALL=0`).\n- On macOS, the generated LaunchAgent plist sets `SoftResourceLimits/NumberOfFiles=65536` and `HardResourceLimits/NumberOfFiles=200000` to reduce launchd `EMFILE` incidents under multi-repo load.\n- Start the daemon with `docdex start` (alias: `docdexd daemon`) or run the setup wizard (`docdex setup`) if startup registration fails. Windows uses `%LOCALAPPDATA%\\\\docdex\\\\run-daemon.cmd` for the scheduled task.\n- If no supported local LLM service is usable, the setup wizard can prompt to install the Ollama fallback and the default embedding model.\n- Skip prompts with `DOCDEX_OLLAMA_INSTALL=0` or `DOCDEX_OLLAMA_MODEL_PROMPT=0`.\n- Force with `DOCDEX_OLLAMA_INSTALL=1` or `DOCDEX_OLLAMA_MODEL=<model>`.\n\n### Build from source\n- Requires Rust (stable) and Cargo.\n- Build: `cargo build --release`\n- Install: `cargo install --path .`\n- MCP is served by the daemon over HTTP/SSE; no separate MCP server binary is required.\n\n### Uninstall\n- `npm uninstall -g docdex` stops the daemon, removes its startup registration, and deletes Docdex MCP entries from supported client config files.\n- The installer data dir (see below) is not removed automatically; delete it manually if you want a full cleanup.\n- Persistent `~/.docdex` data such as `config.toml`, repo indexes, logs, and delegation telemetry is preserved across uninstall/reinstall; remove it manually only when you intentionally want to reset local state.\n\n## First run\n\n```bash\n# index a repo\n\ndocdexd index --repo /path/to/repo\n\n# serve HTTP API with watcher (legacy; singleton lock enforced)\n\ndocdexd serve --repo /path/to/repo --host 127.0.0.1 --port 28491 --log warn --secure-mode=false\n\n# singleton daemon (shared MCP over /v1/mcp/sse; preferred)\n\ndocdex start --host 127.0.0.1 --port 28491 --log warn --secure-mode=false\n\n# ad-hoc query via CLI\n\ndocdexd chat --repo /path/to/repo --query \"otp flow\" --limit 5\n\n# interactive REPL\n\ndocdexd chat --repo /path/to/repo\n```\n\nNotes:\n- CLI commands default to the daemon HTTP base URL (from config). Use `DOCDEX_HTTP_BASE_URL` to override or `DOCDEX_CLI_LOCAL=1` to run in-process.\n- Add `.docdex/` to `.gitignore` if you store state under the repo.\n\n## Operating modes\n- `index`: builds the repo index and code intelligence artifacts.\n- `serve`: legacy per-repo HTTP API with watcher; a global singleton lock prevents multiple servers from starting.\n- `daemon`: singleton service that hosts shared MCP over HTTP/SSE (`/v1/mcp/sse`).\n\n## Repo scoping (multi-repo daemon)\nWhen a singleton daemon starts without a default repo or has more than one repo mounted, the daemon requires an explicit repo scope.\n\n- Mount a repo and get its `repo_id`:\n - `POST /v1/initialize` with `{ \"rootUri\": \"file:///path/to/repo\" }`\n- For HTTP calls, send `x-docdex-repo-id: <sha256>` or `repo_id` in query/body.\n- MCP SSE sessions bind to the repo in `initialize.rootUri` and reuse it automatically.\n- Per-request `project_root`/`repo_path` overrides the bound repo for MCP calls.\n\n## MCP integration\n\nSupported auto-detected MCP clients (installation adds config when the file exists):\n- Claude Desktop\n- Cursor\n- Windsurf\n- Cline\n- Roo Code\n- Continue\n- VS Code\n- PearAI\n- Void\n- Zed\n- Codex\n\n### Shared MCP (daemon, HTTP/SSE)\nStart the daemon (`docdex start`) and point clients at `http://127.0.0.1:28491/v1/mcp/sse`.\n\nJSON config example (Cursor, Continue, Cline, Claude Desktop devtools):\n```json\n{\n \"mcpServers\": {\n \"docdex\": {\n \"url\": \"http://127.0.0.1:28491/v1/mcp/sse\"\n }\n }\n}\n```\n\nClaude Code (CLI) config (user/local scope in `~/.claude.json`, project scope in `.mcp.json`):\n```json\n{\n \"mcpServers\": {\n \"docdex\": {\n \"type\": \"http\",\n \"url\": \"http://127.0.0.1:28491/v1/mcp\"\n }\n }\n}\n```\n\nCodex config example (TOML):\n```toml\n[mcp_servers.docdex]\nurl = \"http://127.0.0.1:28491/v1/mcp\"\ntool_timeout_sec = 300\nstartup_timeout_sec = 300\n```\n\nAfter changing Codex MCP config, restart Codex or open a new Codex session. Running Codex sessions do not hot-reload MCP server URLs.\n\n## HTTP API\n\nCore endpoints:\n- `GET /healthz`\n- `GET /search?q=...&limit=...`\n- `GET /snippet/:doc_id`\n- `GET /v1/capabilities`\n- `POST /v1/search/rerank`\n- `POST /v1/search/batch`\n- `POST /v1/delegate`\n- `POST /v1/chat/completions`\n- `POST /v1/conversations/import`, `GET /v1/conversations`, `GET /v1/conversations/search`\n- `GET /v1/conversations/:session_id/export`, `POST /v1/conversations/:session_id/redact`\n- `POST /v1/conversations/prune`, `POST /v1/diary/write`, `GET /v1/diary/read`, `POST /v1/hooks/conversation`\n- `POST /v1/wakeup`, `GET /v1/kg/query`, `GET /v1/kg/search/*`, `GET /v1/kg/timeline`\n- `GET /v1/kg/neighborhood`, `GET /v1/kg/entity-links`, `GET /v1/kg/episode`\n- `POST /v1/kg/edge/delete`, `POST /v1/kg/episode/delete`, `POST /v1/kg/rebuild`, `POST /v1/kg/clear`\n- `GET /v1/symbols`, `GET /v1/ast`, `GET /v1/graph/impact`\n- `GET /v1/impact/diagnostics`\n- `GET /v1/index/status`\n- `GET /v1/telemetry/delegation`\n- `GET /v1/llm/diagnostics`, `POST /v1/llm/diagnostics`\n\nRedaction note:\n- `POST /v1/conversations/:session_id/redact` removes transcript searchability and wake-up recall for that session, but `read` and `export` keep the original message slots with `[redacted]` placeholder content instead of dropping the array entirely.\n\nOptional retrieval feature negotiation:\n- HTTP: `GET /v1/capabilities`, `POST /v1/search/rerank`, `POST /v1/search/batch`\n- MCP: `docdex_capabilities`, `docdex_rerank`, `docdex_batch_search`\n- Read current runtime limits from `GET /v1/capabilities` (for example rerank candidate cap and batch query cap).\n\nReference: `docs/http_api.md`.\n\n## Code intelligence\nDocdex builds symbol, AST, and impact graph data during indexing so tools can reason about structure, not just text.\nSupported AST/symbols languages: Rust, Python, JavaScript, TypeScript, Go, Java, C#, C/C++, PHP, Kotlin, Swift, Ruby, Lua, Dart.\n\nExamples:\n```bash\ncurl \"http://127.0.0.1:28491/v1/symbols?file=src/app.ts\"\ncurl \"http://127.0.0.1:28491/v1/ast?path=src/app.ts\"\ncurl -X POST \"http://127.0.0.1:28491/v1/ast/query\" -H \"Content-Type: application/json\" \\\n -d '{\"kinds\":[\"function_item\"],\"name\":\"handleRequest\",\"pathPrefix\":\"src\",\"limit\":20}'\ncurl \"http://127.0.0.1:28491/v1/graph/impact?file=src/app.ts&maxDepth=3\"\n```\n\nNotes:\n- AST kinds are tree-sitter node kinds and are language-specific. Examples: Rust `function_item`/`struct_item`, JS/TS `function_declaration`/`class_declaration`, Python `function_definition`/`class_definition`.\n\n## Folder tree (filtered)\nUse the built-in tree renderer instead of running ad-hoc `rg --files`/`find`, which includes noisy folders.\n\nCLI:\n```bash\ndocdexd tree --repo /path/to/repo --max-depth 4 --dirs-only\ndocdexd tree --repo /path/to/repo src --include-hidden --extra-excludes \".direnv,.cache\"\n```\n\nMCP tool:\n```json\n{ \"tool\": \"docdex_tree\", \"args\": { \"path\": \"src\", \"max_depth\": 4, \"dirs_only\": true } }\n```\n\nNotes:\n- Default excludes cover common noisy folders: `.git`, `node_modules`, `dist`, `build`, `target`, etc.\n- `max_depth=0` returns only the root label.\n\n## Agent helper CLI commands\nThese commands are designed for agent workflows and scripted troubleshooting. They mirror HTTP/MCP behavior where possible.\n\nRepo helpers:\n```bash\ndocdexd repo init --repo /path/to/repo\ndocdexd repo id --repo /path/to/repo\ndocdexd repo status --repo /path/to/repo\ndocdexd repo dirty --repo /path/to/repo --exit-code\n```\n\nImpact + DAG helpers:\n```bash\ndocdexd impact-graph --repo /path/to/repo --file src/app.ts --max-depth 3\ndocdexd impact-diagnostics --repo /path/to/repo\ndocdexd impact-diagnostics --repo /path/to/repo --file src/app.ts\ndocdexd dag view --repo /path/to/repo <session_id> --format text\ndocdexd dag export --repo /path/to/repo <session_id> --format json\n```\nNotes:\n- Use the `dag_session_id` returned by `/search` (or MCP `docdex_search`/`docdex_web_research`) as the `<session_id>` for DAG view/export.\n\nSearch helpers:\n```bash\ndocdexd search --repo /path/to/repo --query \"auth flow\" --limit 8 --snippets false\ndocdexd search --repo /path/to/repo --query \"config\" --force-web --async-web=false\n```\n\nLibs ingestion helpers:\n```bash\ndocdexd libs discover --repo /path/to/repo\ndocdexd libs fetch --repo /path/to/repo --sources /path/to/libs_sources.json\ndocdexd search --repo /path/to/repo --query \"jwt decode\" --include-libs\n```\n\nDelegation helpers:\n```bash\ndocdexd delegation savings --repo /path/to/repo\ndocdexd delegation agents --json\n```\n\nFile helpers:\n```bash\ndocdexd open --repo /path/to/repo --file src/app.ts --head 20\ndocdexd open --repo /path/to/repo --file src/app.ts --start 10 --end 40 --clamp\ndocdexd file ensure-newline --repo /path/to/repo --file README.md\ndocdexd file write --repo /path/to/repo --file notes.txt --content \"hello\" --create\n```\nDirect HTTP file reads are available through `GET /v1/open` or `POST /v1/open` with `path`, `start_line`, `end_line`, `head`, `clamp`, and optional `repo_id`. Full-file open remains disabled by default for encrypted repos unless `repo_encryption.full_file_open_enabled` is explicitly enabled; use `/search` and `/snippet/:doc_id` for encrypted deployments by default.\n\n## Conversation memory\n\nConversation memory is repo-scoped by default and disabled automatically when `[memory].enabled = false`.\nRepo-less sessions must use an explicit `conversation_namespace`; they do not silently fall back to some repo archive.\nConversation state keeps imported sessions in `conversation.db`, derived knowledge facts in `knowledge.db`, and serves compact wake-up bundles instead of replaying full transcripts.\n\nThe `docdexd conversations`, `docdexd diary`, and `docdexd hook conversation` commands are HTTP-backed wrappers. Start `docdex start` or `docdexd daemon` first, and set `DOCDEX_HTTP_BASE_URL` when the daemon is not listening on `http://127.0.0.1:28491`.\n\nArchive and manage sessions:\n```bash\ndocdexd conversations import --repo /path/to/repo ./session.txt --format plain_text --agent-id codex\ndocdexd conversations list --repo /path/to/repo --agent-id codex\ndocdexd conversations search --repo /path/to/repo \"timeline_index\"\ndocdexd conversations read --repo /path/to/repo <session_id>\ndocdexd conversations export --repo /path/to/repo <session_id>\ndocdexd conversations redact --repo /path/to/repo <session_id>\ndocdexd conversations delete --repo /path/to/repo <session_id>\ndocdexd conversations prune --repo /path/to/repo --apply --manual-retention-days 30 --working-memory-retention-days 7\n\ndocdexd conversations import --conversation-namespace shared-team ./session.txt --format plain_text --agent-id codex\ndocdexd conversations search --conversation-namespace shared-team \"timeline_index\"\n```\n\nDiary and hook capture:\n```bash\ndocdexd diary write --repo /path/to/repo --agent-id codex \"Wake-up rollout validated for knowledge.db\"\ndocdexd diary read --repo /path/to/repo --agent-id codex --limit 10\n\ndocdexd hook conversation --repo /path/to/repo \\\n --action session_close_summarization \\\n --source codex \\\n --agent-id codex \\\n --transcript ./session.txt \\\n --format plain_text \\\n --wait-for-processing\n\ndocdexd hook conversation --conversation-namespace shared-team \\\n --action periodic_memory_save \\\n --source codex \\\n --agent-id codex \\\n --summary-text \"timeline_index moved into knowledge.db and needs follow-up tests\"\n```\n\nWake-up bundles and chat context:\n```bash\ncurl -X POST http://127.0.0.1:28491/v1/wakeup \\\n -H \"Content-Type: application/json\" \\\n -d '{\"agent_id\":\"codex\",\"query\":\"knowledge.db\",\"max_tokens\":96}'\n\ncurl -X POST http://127.0.0.1:28491/v1/wakeup \\\n -H \"Content-Type: application/json\" \\\n -H \"x-docdex-conversation-namespace: shared-team\" \\\n -d '{\"agent_id\":\"codex\",\"query\":\"timeline_index\",\"max_tokens\":96}'\n\ncurl -X POST http://127.0.0.1:28491/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"fake-model\",\n \"messages\": [{\"role\": \"user\", \"content\": \"What changed around knowledge.db?\"}],\n \"docdex\": {\n \"agent_id\": \"codex\",\n \"limit\": 6,\n \"include_libs\": true,\n \"dag_session_id\": \"session-123\"\n }\n }'\n```\n\nTemporal knowledge graph:\n```bash\ndocdexd conversations kg-query --repo /path/to/repo \"knowledge.db\"\ndocdexd conversations kg-search-nodes --repo /path/to/repo \"knowledge\"\ndocdexd conversations kg-search-edges --repo /path/to/repo \"timeline_index\"\ndocdexd conversations kg-search-episodes --repo /path/to/repo \"wake-up rollout\"\ndocdexd conversations kg-neighborhood --repo /path/to/repo \"knowledge.db\"\ndocdexd conversations kg-entity-links --repo /path/to/repo \"knowledge.db\"\ndocdexd conversations kg-episode --repo /path/to/repo <episode_id>\ndocdexd conversations kg-timeline --repo /path/to/repo \"knowledge.db\"\ndocdexd conversations kg-delete-edge --repo /path/to/repo <edge_id>\ndocdexd conversations kg-delete-episode --repo /path/to/repo <episode_id>\ndocdexd conversations kg-rebuild --repo /path/to/repo\ndocdexd conversations kg-clear --repo /path/to/repo\n```\n\nHTTP examples:\n```bash\ncurl -X POST http://127.0.0.1:28491/v1/conversations/import \\\n -H \"Content-Type: application/json\" \\\n -d '{\"source\":\"manual\",\"agent_id\":\"codex\",\"transcript_text\":\"user: Repo fact: knowledge.db uses timeline_index\"}'\n\ncurl -X POST http://127.0.0.1:28491/v1/diary/write \\\n -H \"Content-Type: application/json\" \\\n -d '{\"agent_id\":\"codex\",\"content\":\"Wake-up rollout validated for knowledge.db\",\"entry_type\":\"note\"}'\n\ncurl -X POST http://127.0.0.1:28491/v1/hooks/conversation \\\n -H \"Content-Type: application/json\" \\\n -d '{\"action\":\"session_close_summarization\",\"source\":\"codex\",\"agent_id\":\"codex\",\"transcript_text\":\"user: timeline_index now belongs to knowledge.db\",\"format\":\"plain_text\",\"wait_for_processing\":true}'\n\ncurl \"http://127.0.0.1:28491/v1/kg/search/nodes?q=knowledge&limit=10\"\ncurl \"http://127.0.0.1:28491/v1/kg/neighborhood?entity=knowledge.db&limit=10\"\ncurl \"http://127.0.0.1:28491/v1/kg/entity-links?entity=knowledge.db&limit=10\"\n```\n\nConfig example:\n```toml\n[memory.conversations]\nenabled = true\nauto_capture = true\narchive_raw_transcripts = false\nmax_wakeup_tokens = 192\nmax_episodic_summaries = 6\nmax_knowledge_facts = 3\nmax_transcript_snippets = 4\nmanual_retention_days = 30\nauto_capture_retention_days = 14\ndiary_retention_days = 30\nhook_event_retention_days = 7\nworking_memory_retention_days = 7\nepisodic_rollup_retention_days = 30\nsweeper_interval_seconds = 600\nsource_allowlist = []\nsource_denylist = [\"blocked-source\"]\n```\n\nNotes:\n- Wake-up retrieval order is working memory, episodic summaries, KG facts, then transcript snippets.\n- `/v1/chat/completions` can prepend wake-up context, profile truth, and cached `Project map:` context; non-streaming responses can include `reasoning_trace`.\n- `sweeper_interval_seconds` controls automatic prune-and-compact passes for conversation archives.\n- Prune and background sweeps also trim superseded working-memory rows and persist episodic rollups before removing expired sessions.\n- Hook payloads can import transcripts, persist diary entries, or do both depending on the action and supplied fields.\n- `conversation_namespace` and `repo_id` are mutually exclusive on the same HTTP request.\n- MCP exposes the same surfaces as `docdex_conversation_*`, `docdex_diary_*`, `docdex_conversation_hook`, `docdex_wakeup`, and `docdex_kg_*`.\n- MCP tools accept `conversation_namespace` for the same repo-less scope used by the CLI and HTTP API.\n\nTest helper:\n```bash\ndocdexd test run-node --repo /path/to/repo --file scripts/check.js --args \"foo bar\"\n```\n\nRun-tests helper:\n```bash\ndocdexd run-tests --repo /path/to/repo\ndocdexd run-tests --repo /path/to/repo --target src/lib.rs\n```\n\nHook helper:\n```bash\ndocdexd hook pre-commit --repo /path/to/repo\n```\n\nMCP registration helper:\n```bash\ndocdexd mcp add --agent codex --transport http\ndocdexd mcp add --all\ndocdexd mcp add --agent codex --remove\n```\n\nWhen `docdexd mcp add --agent codex ...` updates the Codex endpoint, restart Codex so the running MCP client reloads the new URL.\n\nTUI:\n```bash\ndocdexd tui --repo /path/to/repo\n```\n\nNotes:\n- `docdexd search` defaults to HTTP; set `DOCDEX_CLI_LOCAL=1` to run in-process.\n- `docdexd open`/`file`/`test` run locally and do not require the daemon.\n\n## Local LLM services\nDocdex detects supported local LLM services before it suggests installing anything. It can reuse Ollama, vLLM, llama.cpp-compatible OpenAI endpoints, LM Studio, LocalAI, SGLang, TGI-compatible deployments, and healthy local mcoda agents when they are already present. Ollama remains the recommended fallback because it is the easiest guided setup path. Use `docdexd llm-list` to see recommended Ollama fallback models for your hardware.\n\nFirst-time setup (recommended):\n```bash\ndocdex setup\n```\nThe wizard is interactive; run it from a terminal. The first screen lists detected local services, models, embedding candidates, chat/delegation candidates, and matching mcoda agents. If usable defaults exist, the wizard can write those defaults without installing anything. If no usable service/model exists, it offers the Ollama fallback. If Ollama is installed but not running and you choose the fallback path, the wizard will attempt to start it to pull models. When supported, the wizard also enables the Ollama service to run on restart.\n\nInspect what Docdex sees:\n```bash\ndocdexd llm detect --json\ndocdexd llm diagnostics --json\n```\n`llm detect` reports bounded read-only probes and model inventories. `llm diagnostics` explains selected, skipped, unavailable, and fallback decisions for embedding and delegation defaults.\n\nSkip auto-setup on install:\n```bash\nDOCDEX_SETUP_SKIP=1 npm i -g docdex\n```\nSetup markers are stored under `~/.docdex/state`: `setup_status.json`, `setup_pending.json`, and `setup_failed.json`.\nSetup overrides:\n- `DOCDEX_SETUP_FORCE=1`: re-run the wizard even if deferred/complete.\n- `DOCDEX_OLLAMA_INSTALL=1|0`: auto-accept or skip the Ollama install prompt.\n- `DOCDEX_OLLAMA_MODEL_PROMPT=1|0`: force model prompts on/off.\n- `DOCDEX_OLLAMA_MODEL_ASSUME_Y=1`: auto-accept recommended model installs.\n- `DOCDEX_LOCAL_SERVICE_PROBE_TIMEOUT_MS=<ms>`: bound local service probe latency for setup and diagnostics.\n- `DOCDEX_OPENAI_COMPATIBLE_BASE_URL` or `DOCDEX_LLM_BASE_URL`: point custom OpenAI-compatible local probes at a loopback HTTP URL.\n- `DOCDEX_BROWSER_INSTALL=chromium|skip`: auto-accept or skip the Chromium download prompt.\n- The wizard Web APIs section can also store an `mswarm` API key/base URL under `~/.docdex/config.toml` and optionally switch Docdex web discovery to `mswarm`.\n\nThe setup wizard can download Chromium into `~/.docdex/state/bin/chromium/`.\n\nManual Ollama fallback setup:\n```bash\nollama serve\nollama pull nomic-embed-text\n```\n\nChange local LLM defaults later:\n- Run the wizard again: `docdexd setup` (alias: `docdexd llm-setup`).\n- Inspect decisions first: `docdexd llm diagnostics --json`.\n- Or edit `~/.docdex/config.toml`:\n - `[llm].agent_id` (optional mcoda agent id/slug for main chat generation)\n - `[llm].default_model` (chat model)\n - `[llm].embedding_model`\n - `[llm].base_url` (service base URL)\n - `[llm].provider` (`ollama`, `vllm`, `llama-cpp`, `llama-cpp-python`, `lm-studio`, `localai`, `sglang`, `tgi`, or `custom-openai-compatible`)\nRestart the daemon after changing config so it reloads the new defaults.\n\nConfigure mswarm web search later:\n```bash\ndocdexd mswarm configure \\\n --api-key \"<mswarm-api-key>\" \\\n --enable-web-search\n```\nThis stores the key in `~/.docdex/config.toml` under `[integrations.mswarm]`, defaults `[integrations.mswarm].base_url` to `https://api.mswarm.org/`, and sets `[web].discovery_provider = \"mswarm\"` when `--enable-web-search` is used. Use `--base-url` only when pointing Docdex at a non-default mswarm gateway.\n\nInspect or manage consent later:\n```bash\ndocdexd mswarm status --json\ndocdexd mswarm request-deletion --reason \"privacy request\"\ndocdexd mswarm revoke --reason \"opt-out\"\n```\nNotes:\n- `request-deletion` submits the current Docdex identity to mswarm using the persisted consent token.\n- For free Docdex installs, request deletion before revoking consent, because the deletion flow uses the currently stored consent token as proof of ownership.\n\nMain LLM config example, using the Ollama fallback:\n```toml\n[llm]\nprovider = \"ollama\"\nbase_url = \"http://127.0.0.1:11434\"\ndefault_model = \"phi3.5:3.8b\"\nagent_id = \"\" # optional mcoda agent id/slug for main chat/search generation\nembedding_model = \"nomic-embed-text:latest\"\nmax_answer_tokens = 1024\n```\n\nOpenAI-compatible local service example:\n```toml\n[llm]\nprovider = \"llama-cpp\"\nbase_url = \"http://127.0.0.1:8080/v1\"\ndefault_model = \"qwen3.6-coder\"\nembedding_model = \"bge-m3\"\nmax_answer_tokens = 1024\n\n[llm.delegation]\nauto_enable = true\nlocal_agent_id = \"local-qwen\"\n```\n\nNotes:\n- When `[llm].agent_id` is set, Docdex tries that mcoda agent first for main LLM work.\n- If that mcoda agent is missing or cannot be resolved, Docdex falls back to `[llm].default_model`.\n- A per-request chat `agent` still overrides `[llm].agent_id`, and a per-request `model` overrides the configured fallback model.\n- Old configs that only contain generated Ollama defaults (`ollama`, `http://127.0.0.1:11434`, `phi3.5:3.8b`, `nomic-embed-text`) can be migrated by setup to a detected local service or mcoda agent. Explicit custom provider, base URL, embedding model, chat model, or delegation agent settings are preserved.\n\nEnable Ollama later (if skipped during install):\n- Install Ollama for your OS.\n- Run `docdexd setup` to validate the daemon and pull configured models.\n\nRun Docdex with Ollama:\n```bash\nDOCDEX_OLLAMA_BASE_URL=http://127.0.0.1:11434 docdex start --host 127.0.0.1 --port 28491\n```\n\n## Delegation (local-first plus cloud fallback)\nDocdex can offload small tasks to a local model, local service endpoint, or mcoda agent to reduce paid-token usage. When mswarm is configured, it can also materialize managed mcoda cloud agents and use them as cloud fallbacks for `/v1/delegate` and the MCP tool `docdex_local_completion`.\n\nConfig (`~/.docdex/config.toml`):\n```toml\n[llm.delegation]\nenabled = true\nauto_enable = true\nenforce_local = false\nallow_fallback_to_primary = false\nre_evaluate = true\nlocal_agent_id = \"\" # compatibility fallback when a lane-specific default is unset\ncloud_agent_id = \"\" # compatibility fallback when a lane-specific cloud fallback is unset\nprimary_agent_id = \"\" # compatibility fallback when a lane-specific primary is unset\nlocal_selection_policy = \"task_capability\" # or \"mcoda_zero_cost_most_capable\"\nuse_cached_local_decision = true\nmode = \"draft_only\" # or \"draft_then_refine\"\ntimeout_ms = 300000\nmax_tokens = 500000\nmax_context_chars = 250000\nprimary_usd_per_million_tokens = 0.0\nlocal_usd_per_million_tokens = 0.0\ntask_allowlist = [\"generate_tests\", \"write_docstring\", \"scaffold_boilerplate\", \"refactor_simple\", \"format_code\", \"general_question\"]\n\n[llm.delegation.code]\nlocal_agent_id = \"qwen3-coder\"\ncloud_agent_id = \"mswarm-cloud-openrouter-kwaipilot-kat-coder-pro\"\nprimary_agent_id = \"qwen3-coder\"\n\n[llm.delegation.general]\nlocal_agent_id = \"qwen-3.5-35b\"\ncloud_agent_id = \"mswarm-cloud-openrouter-qwen-qwen3-235b-a22b-thinking-2507\"\nprimary_agent_id = \"qwen-3.5-35b\"\n\n[llm.delegation.cloud]\nenabled = true\nprovider = \"openrouter\"\nlimit = 12\nsync_limit = 12\nsorted_by_catalog_rating = true\nmax_cost_per_million = 1.0\nmin_context = 128000\nmin_reasoning = 6.5\n```\n\nNotes:\n- `auto_enable` defaults to true; delegation auto-enables when local models or mcoda agents are present (opt out with `auto_enable = false`).\n- Task lanes: the code-oriented task types use `[llm.delegation.code]` first, while `general_question` uses `[llm.delegation.general]` first. The flat `local_agent_id` / `cloud_agent_id` / `primary_agent_id` remain compatibility fallbacks when the lane-specific values are empty.\n- If the effective local lane is empty, Docdex selects candidates from the library by task type. Healthy zero-cost local mcoda agents and healthy provider-neutral local service models are ranked ahead of managed cloud agents; if nothing local qualifies, Docdex can fall back to the configured cloud lane and then the configured fallback model.\n- If `[llm.delegation.cloud].enabled = true` and `[integrations.mswarm].api_key` is set, Docdex runs `mcoda cloud agent list --json` with the configured provider/price/context/reasoning filters, materializes the top `sync_limit` results as managed `mswarm-cloud-*` mcoda agents, and exposes them through `docdexd delegation agents`.\n- `cloud_agent_id` under `[llm.delegation.code]` or `[llm.delegation.general]` is the preferred cloud fallback for that lane. The flat `[llm.delegation].cloud_agent_id` is a compatibility fallback when the lane-specific cloud value is empty.\n- Automatic target selection excludes paid mcoda candidates unless they are cheaper than the effective caller/primary model. Explicit per-request `agent` overrides remain hard overrides, while lane-specific `local_agent_id` / `cloud_agent_id` are tried first within their local or cloud tier.\n- If the same family exists both locally and in the managed cloud catalog, the local target wins because local candidates are ranked ahead of cloud candidates.\n- Set `local_selection_policy = \"mcoda_zero_cost_most_capable\"` to prefer mcoda when it is installed, inspect the mcoda inventory, find healthy zero-cost agents, choose the most capable one by delegation capabilities plus `max_complexity`/`reasoning_rating`/`rating`, and delegate local jobs to that agent.\n- When `use_cached_local_decision = true`, Docdex stores the chosen zero-cost local mcoda agent in `~/.docdex/state/llm/local_model_library.json` and reuses it on later runs. If the cached agent disappears, becomes unhealthy, or is no longer zero-cost, Docdex refreshes the mcoda inventory and chooses a new one automatically. Managed cloud agents are not cached as zero-cost decisions.\n- If the effective `primary_agent_id` is empty, Docdex selects a primary model/agent from the local library by task type (preferring mcoda agents) for refinement/fallback.\n- To force an Ollama model, set a lane-specific or flat `*_agent_id` to `model:<name>` or `ollama:<name>`. To force a detected provider-neutral local service model, use the `service:<provider>:<model>@<base_url>` target shown by diagnostics. Per-request `agent` also accepts model names listed by `docdexd delegation agents`.\n- Use `docdexd delegation agents --json` to verify whether mcoda is installed, list local plus managed cloud mcoda agents, and inspect `cost_per_million` alongside `max_complexity`, `rating`, `usage`, `reasoning_rating`, `health_status`, and `source`.\n- Cloud catalog discovery mirrors mcoda’s filters: `provider`, `limit`, `max_cost_per_million`, `sorted_by_catalog_rating`, `min_context`, and `min_reasoning`. For setup/ops outside Docdex, the equivalent command is `mcoda cloud agent list --json --provider openrouter --limit ... --max-cost-per-1m-token ... --sorted-by-catalog-rating --min-context ... --min-reasoning ...`.\n- mcoda inventory refresh path: Docdex first runs `mcoda agent list --json --refresh-health` for fresh status and falls back to `mcoda agent list --json` for backward compatibility before DB fallback. For managed cloud agents, that refresh also updates `agent_usage_limits`; exhausted agents are marked `limited` and skipped until their reset window passes.\n- Supported local CLI adapters for mcoda agent resolution include `codex-cli`, `gemini-cli`, `openai-cli`, `ollama-cli`, and `claude-cli`.\n- Prefer agents whose `usage` matches the task, whose `reasoning_rating` is higher for complex work, and whose `health_status` is `healthy`.\n- Table output shows `USAGE`, `COMPLEXITY`, `RATING`, `REASON`, `COST/$1M`, and `HEALTH` for mcoda agents (`-` means unknown).\n- When `re_evaluate = true`, Docdex reviews successful mcoda outputs, including managed cloud delegations, using the primary agent when available and updates the mcoda ratings in `~/.mcoda/mcoda.db`. Review failures fall back to a heuristic score and never block delegation responses.\n- `task_allowlist` is optional; an empty list allows all task types, including `general_question`.\n- `draft_then_refine` returns a primary-agent refinement when available; otherwise returns the local draft with a warning.\n- If local delegation execution fails at runtime (for example missing local CLI binary), Docdex returns a warning and uses the configured/selected primary target when fallback is enabled.\n- Local delegation failures are also appended to `~/.docdex/state/logs/errors/delegation_local_failures.jsonl` with source, repo, task type, local target, recovery action, and error details. This dedicated failure history is written independently of `DOCDEX_LOG_TO_STATE`.\n- `enforce_local = true` requires a local agent/model to be available; if `allow_fallback_to_primary = false`, primary usage (fallback/refine) is disabled and the local draft is returned.\n- Local model library: `~/.docdex/state/llm/local_model_library.json` (or under `DOCDEX_STATE_DIR`).\n- Config compatibility: legacy config keys `primary_usd_per_1k_tokens` and `local_usd_per_1k_tokens` are still accepted on read, but Docdex now writes the canonical `*_usd_per_million_tokens` names.\n- Env overrides: `DOCDEX_DELEGATION_ENABLED`, `DOCDEX_DELEGATION_AUTO_ENABLE`, `DOCDEX_DELEGATION_ENFORCE_LOCAL`, `DOCDEX_DELEGATION_ALLOW_FALLBACK`, `DOCDEX_DELEGATION_REEVALUATE`, `DOCDEX_DELEGATION_LOCAL_AGENT`, `DOCDEX_DELEGATION_CLOUD_AGENT`, `DOCDEX_DELEGATION_PRIMARY_AGENT`, `DOCDEX_DELEGATION_CODE_LOCAL_AGENT`, `DOCDEX_DELEGATION_CODE_CLOUD_AGENT`, `DOCDEX_DELEGATION_CODE_PRIMARY_AGENT`, `DOCDEX_DELEGATION_GENERAL_LOCAL_AGENT`, `DOCDEX_DELEGATION_GENERAL_CLOUD_AGENT`, `DOCDEX_DELEGATION_GENERAL_PRIMARY_AGENT`, `DOCDEX_DELEGATION_LOCAL_SELECTION_POLICY`, `DOCDEX_DELEGATION_USE_CACHED_LOCAL_DECISION`, `DOCDEX_DELEGATION_MODE`, `DOCDEX_DELEGATION_TIMEOUT_MS`, `DOCDEX_DELEGATION_MAX_TOKENS`, `DOCDEX_DELEGATION_PRIMARY_USD_PER_MILLION_TOKENS`, `DOCDEX_DELEGATION_LOCAL_USD_PER_MILLION_TOKENS`, `DOCDEX_DELEGATION_CLOUD_ENABLED`, `DOCDEX_DELEGATION_CLOUD_PROVIDER`, `DOCDEX_DELEGATION_CLOUD_LIMIT`, `DOCDEX_DELEGATION_CLOUD_SYNC_LIMIT`, `DOCDEX_DELEGATION_CLOUD_SORTED_BY_CATALOG_RATING`, `DOCDEX_DELEGATION_CLOUD_MAX_COST_PER_MILLION`, `DOCDEX_DELEGATION_CLOUD_MIN_CONTEXT`, `DOCDEX_DELEGATION_CLOUD_MIN_REASONING`.\n- Env compatibility: legacy `DOCDEX_DELEGATION_PRIMARY_USD_PER_1K_TOKENS` and `DOCDEX_DELEGATION_LOCAL_USD_PER_1K_TOKENS` are still accepted as aliases. When both forms are set, the canonical per-million env vars win.\n- Expensive model library: `docs/expensive_models.json`. Agents should match `agent_id`, `agent_slug`, `model`, or adapter type (case-insensitive) to decide whether to delegate.\n- Delegation callers can supply `caller_agent_id`, `caller_model`, or `primary_cost_per_million` per request so avoided-cost telemetry is attributed to the actual expensive caller instead of the static delegation fallback target.\n- Telemetry: `GET /v1/telemetry/delegation` or `docdexd delegation savings --repo /path/to/repo`. The CLI renders a table by default; use `--json` for raw JSON. Savings are repo-scoped by default; when the daemon has multiple repos mounted, send `repo_id`/`x-docdex-repo-id` or the CLI `--repo` flag. Use `GET /v1/telemetry/delegation?all=true` or `docdexd delegation savings --all` for daemon-global cumulative totals. Docdex persists daemon-global totals under `~/.docdex/state/telemetry/delegation.json` and repo totals under `~/.docdex/state/repos/<state_key>/delegation_telemetry.json`, so reinstalling or restarting the daemon does not reset saved delegation savings. The response includes actual fallback spend, avoided primary cost, and effective per-1M rates derived from runtime caller attribution when available.\n\n## Repo memory\nRepo memory stores project facts (notes, decisions, edge cases) and is used during chat/context assembly. Memory is enabled by default; disable with `DOCDEX_ENABLE_MEMORY=0` or `[memory].enabled = false`.\n\nCLI:\n```bash\ndocdexd memory-store --repo /path/to/repo --text \"Payments retry up to 3 times with backoff.\"\ndocdexd memory-recall --repo /path/to/repo --query \"payments retry policy\" --top-k 5\n```\n\nHTTP:\n```bash\ncurl -X POST \"http://127.0.0.1:28491/v1/memory/store\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\\\"text\\\":\\\"Payments retry up to 3 times with backoff.\\\"}'\n\ncurl -X POST \"http://127.0.0.1:28491/v1/memory/recall\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\\\"query\\\":\\\"payments retry policy\\\",\\\"top_k\\\":5}'\n```\n\nNotes:\n- Memory uses the configured embedding target, preferring a detected local service/model before the Ollama fallback. If no embedding service is available, these calls fail with a structured error.\n- When the daemon has no default repo or more than one repo is mounted, `repo_id` is required (query/body or `x-docdex-repo-id`).\n\n## Agent memory (profile preferences)\nAgent memory stores long-lived preferences across repos (style, tooling, constraints, workflow). It lives in the global state dir and does not require a repo path.\n\nCLI:\n```bash\ndocdexd profile add --agent-id \"default\" --category style --content \"Use concise bullet points.\"\ndocdexd profile search --agent-id \"default\" --query \"style\" --top-k 5\n```\n\nHTTP:\n```bash\ncurl -X POST \"http://127.0.0.1:28491/v1/profile/add\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\\\"agent_id\\\":\\\"default\\\",\\\"content\\\":\\\"Use concise bullet points.\\\",\\\"category\\\":\\\"style\\\"}'\n```\n\nNotes:\n- Categories: `style`, `tooling`, `constraint`, `workflow`.\n- Set a default agent with `[server].default_agent_id` or `docdexd serve --agent-id` (`DOCDEX_AGENT_ID`).\n\n## Personal Preferences And Mind Clone\nPersonal preferences store conversation-derived behavior, routines, feedback, and clone context in the global state area. Server memory lanes, personal preferences, and mind-clone context are enabled by default so shared chat clients can write company-wide memory out of the box. Set the env values below to pin hosted storage and capture policy; set `DOCDEX_PERSONAL_PREFERENCES_ENABLED=false` to opt out of personal preferences specifically.\n\nServer env:\n```bash\nDOCDEX_PERSONAL_PREFERENCES_ENABLED=true\nDOCDEX_PERSONAL_PREFERENCES_STORAGE_ROOT=/mnt/docdex/personal_preferences\nDOCDEX_PERSONAL_PREFERENCES_CAPTURE_ENABLED=true\nDOCDEX_PERSONAL_PREFERENCES_CAPTURE_CHAT_COMPLETIONS=true\nDOCDEX_PERSONAL_PREFERENCES_DIGEST_ENABLED=true\nDOCDEX_PERSONAL_PREFERENCES_PROCESS_IN_BACKGROUND=true\nDOCDEX_PERSONAL_PREFERENCES_CONTEXT_INJECTION_ENABLED=true\nDOCDEX_PERSONAL_PREFERENCES_AUTO_PROJECT_SAFE_TO_PROFILE=true\nDOCDEX_PERSONAL_PREFERENCES_SECRET_SCRUBBER_ENABLED=true\n```\n\nUseful endpoints:\n```bash\ncurl \"http://127.0.0.1:28491/v1/personal-preferences/status\"\ncurl -X POST \"http://127.0.0.1:28491/v1/personal-preferences/write\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"source\":\"company-chat\",\"agent_id\":\"okacam\",\"messages\":[{\"role\":\"user\",\"content\":\"Prefer concise status summaries.\"}]}'\ncurl -X POST \"http://127.0.0.1:28491/v1/personal-preferences/clone/context\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"query\":\"deployment workflow\",\"agent_id\":\"okacam\"}'\n```\n\nNotes:\n- Set `DOCDEX_PERSONAL_PREFERENCES_CONTENT_ENCRYPTION_KEY_ENV=<ENV_NAME>` and provide that key env var if captures should be encrypted at rest.\n- The encrypted-search compatibility write endpoint uses the configured raw-archive, secret-scrubber, digest, and optional content-encryption settings.\n\n## Hardware-aware LLM guidance\nUse `docdexd llm-list` or `docdex setup` to print your host RAM + GPU summary together with entries from `docs/llm_list.json`. The commands highlight a recommended entry that satisfies `minRamGb` and `requiresGpu`.\n\n## State, paths, and defaults\n- State/index directory: `~/.docdex/state/repos/<fingerprint>/index` by default (override with `--state-dir` / `DOCDEX_STATE_DIR`).\n- HTTP API: defaults to `127.0.0.1:28491` when serving.\n- Docdex data stays local under `~/.docdex/state` unless overridden.\n- Installer dist directory (daemon binaries + metadata): `${DOCDEX_DIST_DIR:-<docdex data dir>/dist}/<platformKey>/`.\n - macOS: `~/Library/Application Support/docdex/dist/<platformKey>/`\n - Linux: `$XDG_DATA_HOME/docdex/dist/<platformKey>/` (fallback `~/.local/share/docdex/dist/<platformKey>/`)\n - Windows: `%LOCALAPPDATA%\\\\docdex\\\\dist\\\\<platformKey>\\\\`\n- Daemon lock: `~/.docdex/locks/daemon.lock` by default (override with `DOCDEX_DAEMON_LOCK_PATH`; falls back to OS temp dir when home is unavailable).\n- Logs: set `DOCDEX_LOG_TO_STATE=1` to also write `~/.docdex/state/logs/docdexd-<pid>.log`.\n\n## Configuration reference\n\n### Common flags and env vars\n- `--repo <path>`: repo root (defaults to `.`).\n- `--state-dir <path>` / `DOCDEX_STATE_DIR`: override state dir (relative paths resolve under `repo`).\n- `--exclude-prefix a,b,c` / `DOCDEX_EXCLUDE_PREFIXES`.\n- `--exclude-dir a,b,c` / `DOCDEX_EXCLUDE_DIRS`.\n- `DOCDEX_HTTP_BASE_URL`: override daemon base URL for CLI.\n- `DOCDEX_HTTP_TIMEOUT_MS`: override CLI HTTP timeout (default 30000).\n- `DOCDEX_CLI_LOCAL=1`: run CLI in-process.\n- `DOCDEX_DIST_DIR`: override the installer dist base directory used by the npm wrapper.\n- `DOCDEX_ENABLE_SYMBOL_EXTRACTION`: deprecated (no-op).\n\n### Security and serving\n- `--expose` / `DOCDEX_EXPOSE`: allow non-loopback binds (requires auth).\n- `--auth-token <token>` / `DOCDEX_AUTH_TOKEN`: required for non-loopback binds.\n- `--secure-mode <true|false>` / `DOCDEX_SECURE_MODE`: default true.\n- `--allow-ip a,b,c` / `DOCDEX_ALLOW_IPS`: allowlist for HTTP API (IPC requests bypass the allowlist and are treated as loopback).\n- `--tls-cert`, `--tls-key`, `--certbot-domain`, `--certbot-live-dir`.\n- `--require-tls <true|false>` / `DOCDEX_REQUIRE_TLS`.\n- `--insecure` / `DOCDEX_INSECURE_HTTP=true`.\n- `--preflight-check` / `DOCDEX_PREFLIGHT_CHECK`.\n\n### Limits and logging\n- `--max-limit <n>` / `DOCDEX_MAX_LIMIT`.\n- `--max-query-bytes <n>` / `DOCDEX_MAX_QUERY_BYTES`.\n- `--max-request-bytes <n>` / `DOCDEX_MAX_REQUEST_BYTES`.\n- `--rate-limit-per-min <n>` / `DOCDEX_RATE_LIMIT_PER_MIN`.\n- `--rate-limit-burst <n>` / `DOCDEX_RATE_LIMIT_BURST`.\n- `--audit-log-path`, `--audit-max-bytes`, `--audit-max-files`, `--audit-disable`.\n- `--strip-snippet-html` / `DOCDEX_STRIP_SNIPPET_HTML`.\n- `--disable-snippet-text` / `DOCDEX_DISABLE_SNIPPET_TEXT`.\n- `--access-log <true|false>` / `DOCDEX_ACCESS_LOG`.\n\n### MCP IPC transport\n- Defaults:\n - macOS/Linux: `$XDG_RUNTIME_DIR/docdex/mcp.sock` (fallback: `~/.docdex/run/mcp.sock`)\n - Windows: `\\\\\\\\.\\\\pipe\\\\docdex-mcp`\n- Enable/disable: `--mcp-ipc auto|off` or `DOCDEX_MCP_IPC=1|0`.\n- Override endpoints: `DOCDEX_MCP_SOCKET_PATH` (unix) or `DOCDEX_MCP_PIPE_NAME` (windows).\n- Codex config (IPC):\n\n```toml\n[mcp_servers.docdex]\ntransport = \"ipc\"\nsocket_path = \"/absolute/path/to/mcp.sock\"\ntool_timeout_sec = 300\nstartup_timeout_sec = 300\n# Windows: pipe_name = \"\\\\\\\\.\\\\pipe\\\\docdex-mcp\"\n```\n\n- HTTP/SSE remains the default for other MCP clients (`/v1/mcp/sse` or `/v1/mcp`).\n\n### FD Hardening And Lock Retry\n- Daemon startup checks runtime nofile soft limit and warns (non-fatal) when it is below `DOCDEX_MIN_NOFILE_SOFT` (default: `4096`).\n- Profile lock acquisition uses bounded retries for transient pressure conditions (`WouldBlock`, `Interrupted`, `EMFILE`, `ENFILE`).\n- Lock retry tuning:\n - `DOCDEX_PROFILE_LOCK_MAX_ATTEMPTS` (default `5`, clamped to `1..20`)\n - `DOCDEX_PROFILE_LOCK_RETRY_BASE_MS` (default `25`, clamped to `1..5000`)\n- Startup warning threshold tuning:\n - `DOCDEX_MIN_NOFILE_SOFT` (default `4096`, clamped to `256..1048576`)\n- Repo/watcher pressure controls used by installer startup registration:\n - `DOCDEX_REPO_IDLE_SECONDS` (default `300`)\n - `DOCDEX_REPO_HIBERNATE_SECONDS` (default `1800`)\n - `DOCDEX_REPO_CLEANUP_INTERVAL_SECONDS` (default `60`)\n - `DOCDEX_WEB_MAX_CONCURRENT_BROWSER_FETCHES` (default `1`)\n - `DOCDEX_WEB_MAX_CONCURRENT_LLM` (default `1`)\n- Incident response guide: `docs/ops/fd_exhaustion_playbook.md`.\n\n### Memory and LLM\n- `--enable-memory <true|false>` / `DOCDEX_ENABLE_MEMORY`.\n- `DOCDEX_CONVERSATION_MEMORY_ENABLED` and `DOCDEX_CONVERSATION_AUTO_CAPTURE` for conversation memory.\n- `DOCDEX_PERSONAL_PREFERENCES_ENABLED` (alias: `DOCDEX_ENABLE_PERSONAL_PREFERENCES` or `DOCDEX_MIND_CLONE_ENABLED`) for personal preferences and mind clone.\n- `DOCDEX_PERSONAL_PREFERENCES_STORAGE_ROOT` to choose the shared personal-preferences store path.\n- `--embedding-base-url` / `DOCDEX_EMBEDDING_BASE_URL`.\n- `--ollama-base-url` / `DOCDEX_OLLAMA_BASE_URL`.\n- `--embedding-model` / `DOCDEX_EMBEDDING_MODEL` (default `nomic-embed-text`).\n- `DOCDEX_LLM_AGENT` / `DOCDEX_AGENT` to override `[llm].agent_id` for the main chat agent.\n\n### Web discovery (Tier 2)\n- `DOCDEX_WEB_ENABLED=1` to enable (daemon sets this by default unless overridden).\n- `DOCDEX_OFFLINE=1` to force offline.\n- `DOCDEX_WEB_DISCOVERY_PROVIDER` or `[web].discovery_provider` to choose the discovery backend (`duckduckgo_lite` by default, `mswarm` when configured).\n- With the default `duckduckgo_lite` provider, discovery tries DuckDuckGo first,\n configured SearXNG JSON endpoints second, and paid/API providers afterward;\n Brave is the final fallback unless explicitly selected as the primary provider.\n- Configure SearXNG with a comma-separated `DOCDEX_WEB_SEARXNG_URLS` value\n (`DOCDEX_SEARXNG_URLS` remains a compatibility alias) or a typed list in\n `config.toml`. Bare instance URLs are normalized to `/search`:\n ```toml\n [web]\n searxng_urls = [\"https://se.overrid.com/search\"]\n ```\n Set `searxng_urls = []` (or an explicitly empty\n `DOCDEX_WEB_SEARXNG_URLS`) to disable this fallback. Invalid explicit values\n fail closed to an empty SearXNG list instead of silently sending queries to\n the default endpoint.\n- `DOCDEX_WEB_*` knobs for thresholds, timeouts, cache TTL, and backoff.\n- `DOCDEX_WEB_BROWSER` / `DOCDEX_CHROME_PATH` to set a Chromium binary.\n- `web.scraper.engine` in `config.toml` is `chromium` (only supported engine).\n- `DOCDEX_BROWSER_AUTO_INSTALL=0` to disable Chromium auto-install.\n- Encrypted repository mode blocks web discovery unless `[repo_encryption].web_discovery_enabled = true` or `DOCDEX_REPO_ENCRYPTION_WEB_DISCOVERY_ENABLED=true` is set.\n- `docdexd mswarm configure|status|request-deletion|revoke` manages `~/.docdex/config.toml` entries for `[integrations.mswarm]` and the local telemetry-consent workflow.\n- mswarm web search settings can also be set manually:\n - `[integrations.mswarm].base_url`\n - `[integrations.mswarm].api_key`\n - `DOCDEX_MSWARM_BASE_URL`\n - `DOCDEX_MSWARM_API_KEY`\n- Optional API providers (set in `config.toml` under `[web.providers]` or via env):\n - Brave: `DOCDEX_BRAVE_API_KEY`\n - Google CSE: `DOCDEX_GOOGLE_CSE_API_KEY` + `DOCDEX_GOOGLE_CSE_CX`\n - Bing: `DOCDEX_BING_API_KEY`\n - URL overrides: `DOCDEX_BRAVE_API_URL`, `DOCDEX_GOOGLE_CSE_API_URL`, `DOCDEX_BING_API_URL`\n\n## Ops and safety\n- Health check: `GET /healthz`.\n- Metrics: `GET /metrics`.\n- `docdexd check`: preflight validation for config, state, local LLM/Ollama fallback, browser, ports.\n- FD incident runbook: `docs/ops/fd_exhaustion_playbook.md`.\n- `docdexd self-check --repo <path>`: sensitive-term scan.\n\n## Troubleshooting\n- Browser path issues: `docdexd browser setup` or set `DOCDEX_WEB_BROWSER`/`DOCDEX_CHROME_PATH`.\n- Local LLM timeouts: ensure the configured local service is running, confirm the base URL with `docdexd llm diagnostics --json`, and tune `DOCDEX_EMBEDDING_TIMEOUT_MS`.\n- 429s in load tests: run with `--secure-mode=false` or raise rate limits.\n- `indexing_in_progress` (HTTP 202) on `/search`: call `/v1/index/status` and retry after `retry_after_ms`, or rebuild with `/v1/index/rebuild` if indexing is stuck.\n\n## References\n- HTTP API: `docs/http_api.md`\n- MCP errors: `docs/mcp/errors.md`\n- Quality gates: `docs/quality_gates.md`\n- Metrics dashboard: `docs/metrics_dashboard.md`\n- FD exhaustion playbook: `docs/ops/fd_exhaustion_playbook.md`\n"}}}}