# sopaco/deepwiki-rs

> Rust CLI (Litho) that runs a fixed chain of LLM agents over a local repo and writes C4-style Markdown docs with Mermaid diagrams.

- Category: [Open-source DeepWiki](https://llms-technical-reviews.com/open-source-deepwiki/)
- Repository: https://github.com/sopaco/deepwiki-rs (reviewed at commit `27dbd3ed74535213e7c40be8abcdcec4145bebf2`, 2026-09-14)
- Stars: 3109 · Language: Rust · License: MIT
- Canonical page: https://llms-technical-reviews.com/p/deepwiki-rs/

## Overview

deepwiki-rs, which calls itself Litho, is a single Rust binary. You point it at a local checkout and it writes a folder of Markdown architecture documents. The output has a fixed shape: an overview, an architecture page, a workflow page, a boundary-interfaces page, an optional database page, and one "deep exploration" page per domain module that the LLM finds. The documents follow the C4 levels (context, container, component) and contain Mermaid diagrams.

The tool is a batch generator. It has no server, no web UI, no vector store and no chat. Every stage is a call to a "`StepForwardAgent`" that packs earlier results into one prompt and gets back either typed JSON or Markdown. The results live in an in-process key-value `Memory` for the length of one run. The only state that survives between runs is an on-disk LLM response cache keyed by an MD5 hash of the full prompt.

It is aimed at teams that want a one-command architecture write-up of a repo in one of eight output languages, and that can run a hosted or local LLM. It is not aimed at people who want to ask questions about a codebase.

## Architecture

```mermaid
flowchart TD
  CLI["cli.rs: Args -> Config"] --> L["workflow::launch"]
  L --> KS["KnowledgeSyncer (optional local docs)"]
  L --> P["PreProcessAgent"]
  P --> SE["StructureExtractor (walk + git ls-files)"]
  P --> DS["DirectorySummarizer (LLM per directory)"]
  P --> RA["RelationshipsAnalyze (LLM)"]
  P --> M[("Memory (in-process)")]
  L --> R["ResearchOrchestrator: 6-7 research agents"]
  R --> M
  L --> C["DocumentationComposer: 6 editors"]
  C --> M
  R --> LLM["LLMClient (rig providers)"]
  C --> LLM
  DS --> LLM
  LLM --> CACHE[("CacheManager: .litho/cache")]
  LLM --> TOOLS["file_explorer / file_reader tools"]
  L --> O["DiskOutlet -> output dir"]
  O --> MF["mermaid-fixer (external binary)"]
```

| Component | Path | Role |
|---|---|---|
| CLI and config | `src/cli.rs`, `src/config.rs` | Parse flags, load `litho.toml`, apply overrides and defaults |
| Pipeline driver | `src/generator/workflow.rs` | `launch`: preprocess, research, compose, save, summary |
| Preprocessing | `src/generator/preprocess/` | File walk, README extraction, per-directory LLM dossiers, relationship analysis |
| Language processors | `src/generator/preprocess/extractors/language_processors/` | Regex extractors for 12 languages that pre-list interfaces and imports for the prompt |
| Research agents | `src/generator/research/agents/` | System context, domain modules, architecture, workflow, key modules, boundary, database |
| Editors | `src/generator/compose/agents/` | Turn research results into the final Markdown pages |
| Agent framework | `src/generator/step_forward_agent.rs`, `agent_executor.rs` | Data-source declaration, prompt assembly, compression, cached LLM calls |
| LLM client | `src/llm/client/` | rig provider clients, model choice, retries, tool-using agents |
| Agent tools | `src/llm/tools/` | `file_explorer`, `file_reader`, `time` |
| Output | `src/generator/outlet/` | `DocTree`, `DiskOutlet`, `SummaryOutlet`, `MermaidFixer` |
| External knowledge | `src/integrations/` | Optional ingestion of local PDFs, Markdown, SQL and similar files by category |

## How a request flows

Take `deepwiki-rs -p ./my-repo -o ./litho.docs`:

1. **Configure.** `Args::to_config` loads `litho.toml` from the working directory or `--config`, then lets CLI flags override provider, models, base URL, key, language and stage-skip flags ([cli.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/cli.rs#L130-L257)).
2. **Startup checks.** `launch` optionally wipes the cache (`--force-regenerate`). It then refuses to run if the `mermaid-fixer` binary is not on `PATH`, builds the `LLMClient`, `CacheManager` and an empty `Memory`, and syncs external knowledge if configured ([workflow.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/workflow.rs#L45-L102)).
3. **Preprocess.** `PreProcessAgent::execute` reads the README, walks the tree with `StructureExtractor` (honouring `git ls-files` by default), asks the LLM for a `DirectoryDossier` per directory, and then runs `RelationshipsAnalyze`. All four results are stored in `Memory` under the `PREPROCESS` scope ([preprocess/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/mod.rs#L44-L128)).
4. **Research.** `ResearchOrchestrator` runs the agents in a fixed order: `SystemContextResearcher` (C1), `DomainModulesDetector`, `ArchitectureResearcher` and `WorkflowResearcher` (C2), `KeyModulesInsight` (C3-C4), `BoundaryAnalyzer`, and `DatabaseOverviewAnalyzer` only when a directory or file looks database-related ([orchestrator.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/research/orchestrator.rs#L22-L74)).
5. **Per-agent call.** Each agent's `execute` checks that its required sources exist in `Memory`, builds a prompt from them, appends a target-language instruction, and calls `extract` (typed JSON), `prompt` (text) or `prompt_with_tools` (tool-using agent) depending on `LLMCallMode`. The result is written back to `Memory` ([step_forward_agent.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/step_forward_agent.rs#L618-L725)).
6. **Compose.** `DocumentationComposer::execute` runs the overview, architecture, workflow, key-modules, boundary and (optional) database editors in sequence ([compose/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/mod.rs#L24-L52)). `KeyModulesInsightEditor` fans out one editor per domain report, bounded by `max_parallels`, and registers each page under `deep_exploration/<domain>.md` ([key_modules_insight_editor.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/agents/key_modules_insight_editor.rs#L16-L64)).
7. **Write.** `DiskOutlet::save` deletes the output directory, writes every `DocTree` entry it finds in `Memory`, and then shells out to `mermaid-fixer` over the folder ([outlet/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/outlet/mod.rs#L74-L119)). `SummaryOutlet` adds a run report.

## Key components

### Directory dossiers

Preprocessing is directory-first. `generate_directory_dossiers` reads each directory's files, sorts them by name, and splits them into batches of at most 256 KB of raw content ([preprocess/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/mod.rs#L130-L212)). The 256 KB limit does not mean the model sees 256 KB. `build_summary_prompt` sends only the first 500 characters of each file. Next to them it sends a list of up to 20 interfaces and 15 imports that the regex-based language processors extracted, plus line, function and class counts ([directory_summary.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/agents/directory_summary.rs#L374-L464)). The model returns a summary, an importance score, key files and per-file insights. If a call fails, the directory gets an empty fallback dossier and the run continues.

The 12 language processors (Rust, JS, TS, React, Vue, Svelte, PHP, Kotlin, Python, Java, C#, Swift) are line-regex extractors. There is no tree-sitter or compiler-grade parsing ([language_processors/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/extractors/language_processors/mod.rs#L41-L59)).

### StepForwardAgent

Agents declare `required_sources` and `optional_sources` (memory keys, other agents' results, or external-knowledge categories). `GeneratorPromptBuilder` formats each source, runs `PromptCompressor` on it when it is too large, then compresses the assembled prompt once more ([step_forward_agent.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/step_forward_agent.rs#L448-L576)). The default formatter keeps 25 code insights, omits source code, and lists only directories when there are more than 100 files ([L111-L123](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/step_forward_agent.rs#L111-L123)). Editors put `__CURRENT_UTC_TIME__` placeholders in the prompt, not the real time, and substitute the time after generation. That keeps the prompt stable, so the cache can hit.

### LLM client and model choice

`ProviderClient::new` maps eight providers to rig clients: OpenAI-compatible, Moonshot, DeepSeek, Mistral, OpenRouter, Anthropic, Gemini and Ollama ([providers.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/providers.rs#L35-L103)). Model choice is a size rule: if the system and user prompts together are at most 32 KB, the run uses `model_efficient` with `model_powerful` as fallback; otherwise it uses `model_powerful` only ([utils.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/utils.rs#L9-L21)). On a failed extraction, the fallback call repeats the prompt with the previous error appended ([client/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/mod.rs#L76-L123)). For the OpenAI variant, a response-parsing error falls back to a raw `/chat/completions` POST ([providers.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/providers.rs#L537-L590)).

### Tool-using agents

Three kinds of stage run as tool-using agents: `ArchitectureResearcher`, `WorkflowEditor`, and the per-domain key-module editors. `AgentBuilder` attaches `file_explorer` and `file_reader` and adds "Do not fabricate non-existent code" to the system prompt ([agent_builder.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/agent_builder.rs#L22-L44)). rig runs the tool loop with `max_turns` (default 100). `file_reader` refuses paths outside the project root and returns at most 200 lines unless asked for a range ([file_reader.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/tools/file_reader.rs#L43-L113)). `ReActExecutor` always reports success without a max-depth flag ([react_executor.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/react_executor.rs#L15-L43)), so the `SummaryReasoner` fallback in `prompt_with_react` never runs at this SHA.

### Cache

`CacheManager` stores each reply as JSON under `<cache_dir>/<scope>/<md5(prompt)>.json` with a timestamp and token estimate. Entries expire after `expire_hours`, which defaults to 8760 (one year) ([cache/mod.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/cache/mod.rs#L42-L124)). Re-runs on an unchanged repo are almost free. Any change to an upstream summary changes every downstream prompt, so those stages miss the cache.

## Extending it

- **New provider.** Add an `LLMProvider` variant and the matching arms in `ProviderClient`/`ProviderAgent`. The `match` blocks repeat for every provider, so this is a mechanical but wide change.
- **New page.** Implement `StepForwardAgent` for a research agent and an editor, add both to the orchestrator and composer, and give the editor a `DocTree` slot. The page list is code, not config.
- **New language.** Implement `LanguageProcessor` (dependencies and interfaces) and register it in `LanguageProcessorManager::new`.
- **External knowledge.** `[knowledge.local_docs]` in `litho.toml` lets you feed PDFs, Markdown, SQL, YAML or JSON by category to chosen agents. `sync-knowledge` chunks and caches them.

## Running it

- **Install.** `cargo install deepwiki-rs`, plus `cargo install mermaid-fixer`. The run aborts at startup without mermaid-fixer ([workflow.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/workflow.rs#L72-L75)).
- **Configure.** Out of the box the provider is "openai" pointed at an OpenAI-compatible ModelScope endpoint with Qwen models, `max_tokens` 131072, `max_parallels` 3, and the key from `LITHO_LLM_API_KEY` ([config.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/config.rs#L749-L778)). Override with `--llm-provider`, `--model-efficient`, `--model-powerful`, `--llm-api-base-url` and `--llm-api-key`. Ollama defaults to `localhost:11434`.
- **Scope.** By default only git-tracked files are read. `*.md`, `*.txt`, lock files and `.env` are excluded, and test files are skipped.
- **Output.** `./litho.docs` by default, with file names localised for the target language (zh, en, ja, ko, de, fr, ru, vi).

## Strengths and caveats

- **Strength: predictable structure.** The page list and agent order are fixed in code, so two runs on similar repos give documents with the same layout.
- **Strength: wide provider reach.** Eight providers through rig, a two-model size rule with fallback, and an OpenAI HTTP fallback for picky compatible endpoints.
- **Strength: grounded deep pages.** The tool-using editors can open real files inside the project root, and they are told not to invent code.
- **Strength: cheap re-runs.** The prompt-hash cache plus placeholder timestamps make repeated runs on the same tree hit the cache.
- **Caveat: shallow first pass.** Directory dossiers see 500 characters per file plus regex-extracted signatures. Everything later builds on these summaries, so anything missed here is missed in the final pages unless a tool-using agent looks it up.
- **Caveat: hard external dependency.** `mermaid-fixer` must be installed, and it is called with the API key as a command-line argument ([fixer.rs](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/outlet/fixer.rs#L37-L94)). Other users on the machine can see that argument in the process list.
- **Caveat: destructive output.** `DiskOutlet` runs `remove_dir_all` on the output path before writing. Point `-o` at a dedicated folder.
- **Caveat: no incremental model.** `Memory` is per-process, so `--skip-preprocessing` only works when the cache can rebuild the earlier stages. There is no diff-based update of single pages.
- **Caveat: crude heuristics.** The database stage triggers on any directory whose name contains "db", and backend directories are explicitly rated above frontend ones in the dossier prompt.

*Sources: code at 27dbd3e, verified Q&A.*

## How sopaco/deepwiki-rs answers the Open-source DeepWiki questions

### How is a repository ingested and chunked? (answered)

Repository ingestion is a multi-step process orchestrated by `PreProcessAgent.execute()` in `src/generator/preprocess/mod.rs`. First, `StructureExtractor.extract_structure()` (`src/generator/preprocess/extractors/structure_extractor.rs`) scans the project directory recursively using `tokio::fs::read_dir`, respecting configurable filters: `excluded_dirs`, `excluded_files`, `excluded_extensions`, `included_extensions`, `max_file_size` (default 512KB), `max_depth` (default 10), `include_hidden`, and `include_tests`. When `git_tracked_only` is true, it runs `git ls-files` and skips untracked files. Binary files are detected by extension. Each file gets a heuristic importance score based on path, extension, and size. Directories also receive an LLM-boosted score via `DirectoryScorer`. The structure is cached under key `structure_<path>`.

Second, `original_document_extractor.extract()` (`src/generator/preprocess/extractors/original_document_extractor.rs`) reads `README.md` from the project root, stripping markdown headers and code fences, keeping the first 500 lines as a plain-text description.

Third, `generate_directory_dossiers()` reads each directory's files from disk (respecting all the same exclusions), batches them at 256KB total content per LLM call, and sends them to `DirectorySummarizer` which produces a `DirectoryDossier` (purpose, importance score, summary, key files). If a single batch call fails, a fallback dossier with empty summary is used. Larger directories are split into multiple lexicographically-sorted batches and merged via `summarize_batch()`.

Finally, `RelationshipsAnalyze` analyzes inter-directory relationships from the dossiers. All results are stored in `Memory` under `MemoryScope::PREPROCESS`. There is no cloning step — the tool operates on a local path. Supported hosts are all filesystem directories. Large repos are handled via the 256KB batch limit, importance-based file filtering, and `max_file_size` truncation.

> **Editor's note.** Correction: the 256 KB batch limit is measured on raw file size, but the dossier prompt contains only the first 500 characters of each file plus regex-extracted interfaces, imports and line/function counts (directory_summary.rs build_summary_prompt), so the LLM never sees whole files at this stage.

Citations: [src/generator/preprocess/mod.rs:44-128](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/mod.rs#L44-L128) · [src/generator/preprocess/extractors/structure_extractor.rs:45-106](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/extractors/structure_extractor.rs#L45-L106) · [src/generator/preprocess/extractors/original_document_extractor.rs:1-33](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/extractors/original_document_extractor.rs#L1-L33) · [src/generator/preprocess/mod.rs:130-210](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/mod.rs#L130-L210) · [src/generator/preprocess/extractors/structure_extractor.rs:139-240](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/preprocess/extractors/structure_extractor.rs#L139-L240) · [src/config.rs:72-158](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/config.rs#L72-L158)

### How is retrieval (RAG) implemented? (not applicable)

DeepWiki-rs does not implement RAG or vector retrieval. There is no embedding model, vector store, or similarity search. Instead, it uses a **Memory-based data access pattern** where all preprocessing and research results are stored in an in-memory `Memory` store (key-value with scopes) and retrieved by key lookup. Agents declare their required data sources via `AgentDataConfig` — e.g. `DataSource::MemoryData`, `DataSource::ResearchResult`, or `DataSource::ExternalKnowledgeByCategory` — and the `StepForwardAgent` framework assembles them into a prompt via `GeneratorPromptBuilder.build_standard_user_prompt()`. This is not retrieval-augmented generation in the embedding sense: the system gathers all relevant context (project structure, code insights, relationship analysis, research reports, external knowledge) and packs it directly into the LLM prompt as formatted text. Large content is compressed via `PromptCompressor` or emergency-truncated.


Citations: [src/generator/step_forward_agent.rs:33-69](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/step_forward_agent.rs#L33-L69) · [src/generator/step_forward_agent.rs:446-577](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/step_forward_agent.rs#L446-L577) · [src/generator/context.rs:38-44](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/context.rs#L38-L44)

### How is the wiki structure (table of contents) determined? (answered)

The document structure is **hardcoded, not LLM-proposed**. The `DocTree` in `src/generator/outlet/mod.rs` defines five fixed document slots matching the six `compose` agents: Overview, Architecture, Workflow, Boundary, and Database (plus dynamic Key Modules Insight entries). The `DocTree::new()` constructor creates entries mapping each `AgentType` to a localized filename via `target_language.get_doc_filename()`. The `DocumentationComposer.execute()` method (`src/generator/compose/mod.rs`) runs six editors in a fixed sequence: `OverviewEditor`, `ArchitectureEditor`, `WorkflowEditor`, `KeyModulesInsightEditor`, `BoundaryEditor`, and optionally `DatabaseEditor`.

The `KeyModulesInsightEditor` is the only dynamic case: it reads the `KeyModulesInsight` research output (a list of `KeyModuleReport` objects, one per domain), spawns one `KeyModuleInsightEditor` per domain, runs them concurrently (bounded by `max_parallels`), and inserts each result into the `DocTree` under `deep_exploration/<domain_name>.md`.

Research agents (system context, domain modules, architecture, workflow, boundary, database) also produce structured output with agent-defined schemas like `DomainModulesReport`, `SystemContextReport`, `BoundaryAnalysisReport`, etc. These feed into the document editors but do not control the TOC structure.

The output format is Markdown with Mermaid diagrams (system context diagrams, flowcharts, sequence diagrams). Editors emit instructions in their system prompts about ASCII-only node IDs and standard diagram headers.


Citations: [src/generator/outlet/mod.rs:19-62](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/outlet/mod.rs#L19-L62) · [src/generator/compose/mod.rs:24-52](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/mod.rs#L24-L52) · [src/generator/compose/types.rs:5-25](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/types.rs#L5-L25) · [src/generator/compose/agents/key_modules_insight_editor.rs:16-65](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/agents/key_modules_insight_editor.rs#L16-L65) · [src/generator/compose/agents/overview_editor.rs:12-39](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/agents/overview_editor.rs#L12-L39)

### How are individual pages generated? (answered)

Each page is generated by a dedicated **editor agent** implementing the `StepForwardAgent` trait. The six editors (`OverviewEditor`, `ArchitectureEditor`, `WorkflowEditor`, `KeyModulesInsightEditor`, `BoundaryEditor`, `DatabaseEditor`) each define their own `PromptTemplate` with system prompt, opening instruction, closing instruction, and `LLMCallMode`. Most editors use `LLMCallMode::Prompt` (plain text generation) — only `KeyModuleInsightEditor` uses `PromptWithTools` (ReAct mode with file_explorer and file_reader tools). Per the agent prompt guidelines in `overview_editor.rs`, editors are instructed to include Mermaid diagrams with restrictions: ASCII-only node IDs, no zero-width characters, standard diagram headers. After generation, `MermaidFixer` (`src/generator/outlet/fixer.rs`) runs `mermaid-fixer` as an external program on the output directory to auto-fix any syntax issues.

Parallelism is implemented in `KeyModulesInsightEditor.execute()`: it creates one `KeyModuleInsightEditor` per domain report and runs them concurrently using `do_parallel_with_limit()` from `src/utils/threads.rs` (a semaphore-bounded concurrent executor). The concurrency limit is `config.llm.max_parallels` (default 3).

Caching is performed at the LLM call level in `agent_executor.rs` (`extract()`, `prompt()`, `prompt_with_tools()` functions). Each function computes a cache key from the system+user prompt, checks the `CacheManager`, and stores results with token usage estimates. Cache scope is the agent type key, so re-running with identical prompts hits the cache. `--force-regenerate` clears the cache before starting. Output is written by `DiskOutlet.save()` which iterates the `DocTree`, retrieves each document from `Memory` by its scoped key, and writes it to `output_path`. Source file citations come from the research data fed into each editor's prompt.

> **Editor's note.** Correction: `WorkflowEditor` also runs in `PromptWithTools` mode alongside the per-domain `KeyModuleInsightEditor`; the other editors (overview, architecture, boundary, database) use plain `Prompt`.

Citations: [src/generator/agent_executor.rs:1-180](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/agent_executor.rs#L1-L180) · [src/generator/compose/agents/key_modules_insight_editor.rs:16-65](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/agents/key_modules_insight_editor.rs#L16-L65) · [src/generator/compose/agents/overview_editor.rs:40-141](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/compose/agents/overview_editor.rs#L40-L141) · [src/generator/outlet/fixer.rs:1-109](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/outlet/fixer.rs#L1-L109) · [src/generator/outlet/mod.rs:74-119](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/generator/outlet/mod.rs#L74-L119)

### How are model providers configured? (answered)

Model providers are configured through the `LLMConfig` struct in `src/config.rs`. The `LLMProvider` enum supports 8 providers: OpenAI, Moonshot, DeepSeek, Mistral, OpenRouter, Anthropic, Gemini, and Ollama. Each is mapped to a `rig` provider client in `src/llm/client/providers.rs` via the `ProviderClient` enum. The `ProviderClient::new()` factory method creates the appropriate rig client, using builder patterns for custom base URLs. The only hardcoded URL check is for Anthropic: custom URLs are only used if they contain "anthropic" — otherwise it defaults to `https://api.anthropic.com` to avoid accidentally routing through a non-Anthropic endpoint when a global default URL is set.

**Per-stage model selection** is governed by `evaluate_befitting_model()` in `src/llm/client/utils.rs`: if combined system+user prompt is ≤32KB, it uses `model_efficient` with `model_powerful` as fallback; beyond 32KB, it uses `model_powerful` with no fallback. Both models come from config (`model_efficient`, `model_powerful`).

**OpenAI-compatible endpoints** are supported generically: OpenAI, Moonshot, and DeepSeek clients all accept custom `base_url`. For the OpenAI provider specifically, `ProviderAgent::prompt()` has an HTTP fallback path (`prompt_via_http`): when the rig agent fails with an API response parsing error, it retries via a raw reqwest POST to `{base_url}/chat/completions` with the same system/user messages, max_tokens, and temperature.

**Ollama** is supported with a dedicated `ollama_extractor_wrapper` that wraps the rig agent for structured extraction. Local models use `api_base_url` defaulting to `http://localhost:11434` when provider is Ollama (set in `cli.rs` line 193-195). All providers support configurable `max_tokens`, `temperature` (optional), `retry_attempts` (default 3), `retry_delay_ms` (default 5000), and `timeout_seconds` (default 300).


Citations: [src/config.rs:10-28](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/config.rs#L10-L28) · [src/config.rs:162-213](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/config.rs#L162-L213) · [src/llm/client/providers.rs:24-103](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/providers.rs#L24-L103) · [src/llm/client/providers.rs:537-662](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/providers.rs#L537-L662) · [src/llm/client/utils.rs:9-21](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/utils.rs#L9-L21) · [src/cli.rs:189-196](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/cli.rs#L189-L196)

### How is interactive Q&A / chat implemented? (not applicable)

DeepWiki-rs does not implement interactive Q&A, chat, or conversational features. There is no streaming endpoint, no MCP server, no conversation memory for user interaction, and no deep-research chat mode. The `ReAct` executor in `src/llm/client/react.rs` uses chat history internally for multi-turn tool-calling within a single agent call (tracking tool call→response cycles), but this is an internal mechanism for the LLM to use file_explorer/file_reader tools during generation — not exposed to users. The `SummaryReasoner` similarly replays the ReAct chat history to produce a final summary when the agent hits its max turn limit. These are internal implementation details, not interactive chat features. The tool is a batch documentation generator only.


Citations: [src/llm/client/react.rs:1-80](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/react.rs#L1-L80) · [src/llm/client/summary_reasoner.rs:1-70](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/summary_reasoner.rs#L1-L70) · [src/llm/client/mod.rs:138-229](https://github.com/sopaco/deepwiki-rs/blob/27dbd3ed74535213e7c40be8abcdcec4145bebf2/src/llm/client/mod.rs#L138-L229)
