Deriva reads a software repository, builds a graph of what is in it, and derives an ArchiMate enterprise architecture model you can open in Archi.
Deriva brings determinism to AI-assisted architecture model derivation. From repository to intermediate graph to output graph to the final ArchiMate model. Parsing and graph algorithms find the structure; an LLM reads what needs reading. Every prompt is versioned configuration you can open and change.
- Repository (clone): the code as it is, a Git repository cloned locally. Deriva classifies every file by type, from source and config to docs, tests and build files.
- Intermediate graph (extract): parsing (tree-sitter for most languages) turns the code into a graph of directories, files, types, methods, dependencies, technologies and business concepts. Graph metrics (PageRank, Louvain communities, k-core) then rank what matters.
- Output graph (derive): graph structure picks the candidates; an LLM classifies and names them within ArchiMate's rules, then refine steps tidy the result. The studio shows both graphs side by side.
- ArchiMate model (export): the output graph exports in the Open Group ArchiMate exchange format, ready to open in Archi.
Deriva runs on your own machine: Deriva Studio in your browser, the pipeline and its embedded databases locally. Nothing is sent anywhere except the prompts to the LLM you choose.
- uv, the Python package manager (below). It downloads Python 3.14 for you.
- Git, to clone the repositories you analyse.
- An LLM: an API key for Azure OpenAI, OpenAI, Anthropic or Mistral, or a local model in Ollama or LM Studio.
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | shuv tool install --python 3.14 deriva-studio
derivaderiva starts the studio and opens it in your browser at http://127.0.0.1:8765. It listens on this machine only; --port picks another port, --no-browser leaves the browser closed, and the API documentation is at /docs.
To try Deriva without installing it:
uvx --python 3.14 deriva-studio--python 3.14 matters: Deriva needs Python 3.14, and without it uv may pick an older Python and refuse the install.
On its first start the studio shows a banner until an LLM model is configured. Open General, add a model under Models and save; Set Up an LLM explains the fields. Structural steps run without a model, so Structural steps only (without LLM) in the Workspace gives a first look right away.
| Package | Gives you | Commands |
|---|---|---|
deriva-studio |
the studio and the command line | deriva, deriva-studio, deriva-cli |
deriva-cli |
the command line only, for scripts, CI and servers | deriva-cli |
deriva-dev |
everything, plus benchmarking | deriva, deriva-dev, deriva-cli |
All three release together with the same version number.
An installed Deriva keeps everything in one folder, ~/.deriva (on Windows %USERPROFILE%\.deriva):
| In the home folder | Holds |
|---|---|
.env |
your settings and model configs; the studio writes it when you save the first model |
sql.db |
the step configurations with their versions, file types, name patterns and settings; created from the defaults on first start |
workspace/ |
cloned repositories, the graphs, caches, runs, benchmark sessions and exports |
The environment variable DERIVA_HOME moves this folder, for example to keep projects apart or to try something in a sandbox. deriva-cli status shows which home folder is in use. Relative paths in .env are read from the home folder, so Deriva finds the same files from any working directory.
uv tool upgrade deriva-studio
uv tool uninstall deriva-studioAn upgrade keeps your work: the configuration database only gets the schema changes a new version needs, and your own step versions stay as they are. Uninstalling leaves the home folder in place; delete ~/.deriva to remove your data too.
The packages share the deriva and deriva-cli commands, so install one of them. To switch, for example to get benchmarking, uninstall the other first; your home folder stays:
uv tool uninstall deriva-studio
uv tool install --python 3.14 deriva-devEvery GitHub release has a constraints.txt with the exact version of every dependency. Download it from the release's assets into the current folder, then install against it:
uv tool install --python 3.14 deriva-dev==0.8.0 -c constraints.txtDeriva's Python package is named deriva, like the client of ISI's DERIVA platform (deriva-py, on PyPI as deriva). The two cannot share one Python environment. Install Deriva as a tool, as above, or in a virtual environment of its own.
For development, or to follow the latest changes:
git clone https://github.com/StevenBtw/Deriva.git
cd Deriva
uv sync
cd studio && npm install && npm run build && cd ..
uv run derivauv sync installs all three packages from the checkout, with the development tools. The checkout is its own home folder: .env and workspace/ sit in the repository root, and the configuration database in deriva/adapters/database/sql.db. Building the front end needs Node 22; build again after you pull changes to studio/. CONTRIBUTING.md has the details.
Each model gets a block of LLM_{NAME}_* settings in .env in your home folder (the studio's General page writes them for you), and LLM_DEFAULT_MODEL picks the one Deriva uses. The default model is the name in lowercase with hyphens: LLM_MISTRAL_SMALL_* becomes mistral-small.
# .env: a cloud model
LLM_DEFAULT_MODEL=mistral-small
LLM_MISTRAL_SMALL_PROVIDER=mistral
LLM_MISTRAL_SMALL_MODEL=mistral-small-2603
LLM_MISTRAL_SMALL_KEY=your-mistral-api-keyName a dated model version (mistral-small-2603) rather than a -latest alias, so a run says which model answered; each LLM call also records the model the provider reports. Some models need two more settings:
# .env: models without a temperature, or with reasoning to switch off
LLM_ANTHROPIC_HAIKU_PROVIDER=anthropic
LLM_ANTHROPIC_HAIKU_MODEL=claude-haiku-5-5
LLM_ANTHROPIC_HAIKU_SAMPLING=false # takes no temperature: Deriva leaves it out
LLM_ANTHROPIC_HAIKU_REASONING=none # thinking off
LLM_OPENAI_LUNA_PROVIDER=openai
LLM_OPENAI_LUNA_MODEL=gpt-6-luna
LLM_OPENAI_LUNA_REASONING=none # reasoning off, so the step temperatures applyREASONING is a level (none, low, medium, high) for OpenAI, Azure and Anthropic models. A model with SAMPLING=false runs at its provider's default sampling, so its answers can vary more than those of a model at temperature 0. deriva-cli config model set <name> --provider <provider> --model <model id> --sampling false --reasoning none writes both.
A local model needs no key:
# .env: a local model in Ollama
LLM_DEFAULT_MODEL=ollama-devstral
LLM_OLLAMA_DEVSTRAL_PROVIDER=ollama
LLM_OLLAMA_DEVSTRAL_MODEL=devstral-small-2
LLM_OLLAMA_DEVSTRAL_URL=http://localhost:11434/api/chat| Provider | For |
|---|---|
azure |
Azure OpenAI |
openai |
OpenAI |
anthropic |
Anthropic |
mistral |
Mistral |
ollama |
Ollama, local |
lmstudio |
LM Studio, local |
Rate limits, retries and the response cache have defaults; .env.example lists every setting.
- Open Repositories in the studio's menu and choose + Clone repository. Enter the Git URL; a name and a branch are optional.
- Open the Workspace, pick the repository and a scope, and press Run. Structural steps only (without LLM) gives a first look without any LLM calls.
- Follow the run in the tabs at the bottom: Live, Trace, Prompts and Errors. The intermediate graph and the output graph fill in side by side.
- View model, on the right edge, opens the output graph as an ArchiMate diagram; click an element for its details.
Deriva writes the model in the Open Group ArchiMate exchange format. From the studio: open View model and press Export XML; it writes workspace/output/model.xml on the machine that runs the studio. Or from the command line:
uv run deriva-cli export -o workspace/output/model.xml --repo my-repoIn Archi, choose File, Import, Open Exchange XML Model and pick the file.
- Open Extraction config or Derivation config in the menu.
- Pick a step and edit its instruction or example. Every LLM step follows the same pattern: input, instruction, example.
- Press Save as new version. Earlier versions stay in the history, and each step can be switched on or off.
Run the repository again to see the effect.
All configuration lives in .env in your home folder; a variable set in the environment wins over the file. Key settings:
# Graph database (grafeo embedded)
GRAFEO_DB_DIR=workspace/graphs # Default: one <repo>.grafeo database per repository in the home folder; empty = in-memory
# LLM Provider (mistral, openai, azure, anthropic, ollama, lmstudio)
LLM_MISTRAL_SMALL_PROVIDER=mistral
LLM_MISTRAL_SMALL_MODEL=mistral-small-2603
LLM_MISTRAL_SMALL_KEY=your-mistral-api-key
# Namespaces
GRAPH_NAMESPACE=Graph
ARCHIMATE_NAMESPACE=Model
# NLP translation models for business concepts (default shown)
DERIVA_NLP_MODELS_DIR=workspace/cache/nlpSee .env.example for all available options.
The LLM adapter includes built-in rate limiting to prevent API throttling:
# Requests per minute (0 = use provider default: 60 RPM for cloud, unlimited for local)
LLM_RATE_LIMIT_RPM=0
# Minimum delay between requests in seconds
LLM_RATE_LIMIT_DELAY=0.0
# Max retries on rate limit (429) errors
LLM_RATE_LIMIT_RETRIES=3
# Adaptive throttling (reduces RPM when hitting rate limits)
LLM_THROTTLE_ENABLED=true
LLM_THROTTLE_MIN_FACTOR=0.25 # Minimum 25% of configured RPM
LLM_THROTTLE_RECOVERY_TIME=60 # Seconds before trying to increase RPM
# Circuit breaker (stops requests when provider is failing)
LLM_CIRCUIT_BREAKER_ENABLED=true
LLM_CIRCUIT_FAILURE_THRESHOLD=5 # Consecutive failures to open circuit
LLM_CIRCUIT_RECOVERY_TIME=30 # Seconds before testing recoveryDefault rate limits by provider:
| Provider | Default RPM |
|---|---|
| OpenAI | 30 |
| Anthropic | 30 |
| Mistral | 60 |
| Ollama | Unlimited |
| LM Studio | Unlimited |
The rate limiter automatically:
- Throttles requests to stay within limits
- Applies exponential backoff on rate limit errors (HTTP 429)
- Respects Retry-After headers from providers
- Adaptively reduces RPM when hitting rate limits (recovers over time)
- Opens circuit breaker after consecutive failures to prevent cascading errors
If you encounter undefined extensions during extraction:
Via the studio:
- Open General & file types in the menu
- Add them to the registry:
- Extension (e.g.,
.tsx,Dockerfile) - Type (source, config, docs, test, build, asset, data, exclude)
- Subtype (e.g.,
typescript,docker)
- Extension (e.g.,
Via CLI:
# List all registered file types
uv run deriva-cli config filetype list
# Add a new file type
uv run deriva-cli config filetype add ".tsx" source typescript
# Delete a file type
uv run deriva-cli config filetype delete ".tsx"
# Show file type statistics by category
uv run deriva-cli config filetype statsNote: Files with unrecognized extensions are automatically classified as
file_type="unknown"with their extension as the subtype. This ensures all files get proper classification even without explicit registry entries.
Excluded directories: dependency and tool directories are skipped by every repository walk (no Directory or File nodes, no LLM calls), matched as whole path segments. The list is the excluded_directories system setting (JSON list); by default .git, __pycache__, node_modules, bower_components, vendor, .venv, venv and site-packages. Changing it triggers re-extraction.
uv run deriva-cli config setting show excluded_directories
uv run deriva-cli config setting set excluded_directories '[".git", "node_modules", "third_party"]'Derivation name patterns: some derivation steps use include and exclude patterns on the names of their code candidates; business concepts are already classified and skip them. Most of these steps reject a name that contains an exclude pattern and keep one that contains an include pattern, and a name that matches neither follows the step's default (rejected by most steps, kept by BusinessFunction, ApplicationInterface, SystemSoftware and TechnologyService). BusinessObject (type definitions) and BusinessEvent (methods) use the patterns to rank candidates instead, and fill their remaining slots with names that did not match. A step that uses the default candidate filter (ApplicationComponent, ApplicationInterface, BusinessFunction, DataObject, Device, Node, SystemSoftware, TechnologyService) can limit the patterns to candidates with given graph labels with its pattern_labels param, and set a k-core threshold with graph_filter. Patterns are stored per step, type and category.
uv run deriva-cli config pattern list Node
uv run deriva-cli config pattern add Node include deployment helm
uv run deriva-cli config pattern delete Node include --category deployment helm # a category left empty is deactivatedFull derivation runs start from an empty model: a derivation run skips every candidate the model already has, so a run on top of an earlier model derives less than a run from scratch. A full run (run derivation or run all without --phase or --only-step, and the studio's run scopes) therefore clears the model first, as benchmarks do. Runs of one phase or one step keep the model. The derivation_clear_model system setting (default true) switches this off; with benchmarking installed, the studio shows it as a switch in General.
uv run deriva-cli config setting set derivation_clear_model falseDeriva uses a versioning system for configurations. When you update a config, a new version is created while preserving previous versions for rollback.
Correct ways to update configs:
- Via the studio: open Extraction config or Derivation config, edit the instruction or example, and click "Save as new version"
- Via CLI: Use the
config updatecommand
# Update extraction config instruction
uv run deriva-cli config update extraction BusinessConcept \
-i "New instruction text..."
# Update extraction config with batch size for multi-file LLM calls
uv run deriva-cli config update extraction BusinessConcept \
--batch-size 5
# Update derivation config from file
uv run deriva-cli config update derivation ApplicationComponent \
--instruction-file prompts/app_component.txt
# View all versions
uv run deriva-cli config versionsDo NOT use JSON import/export for config updates. The db_tool import command is only for backup restoration or migration - it overwrites version history. See docs/benchmarks.md for the optimization workflow.
For LLM-assisted extraction steps:
- Open Extraction config in the studio's menu and pick a step (e.g., BusinessConcept)
- Edit its input sources, instruction, example or params
- Press Save as new version; earlier versions stay in the history
All prompts follow the Input + Instruction + Example pattern.
The studio is Deriva's local web UI (uv run deriva): a FastAPI backend over PipelineSession and a React front end.
| Area | Purpose |
|---|---|
| Workspace | Run the pipeline (repository, scope, structural steps only), follow it live, see the repository, the intermediate graph and the output graph linked live in one canvas (or separately), open the ArchiMate model |
| Repositories | Clone, inspect and delete repositories |
| General & file types | System settings (excluded directories) and the file type registry |
| Extraction / Derivation config | Step tables with versions; edit instructions and examples, save as a new version, switch steps on or off |
The graphs use anywidget-graph (its query bar runs read-only Cypher against the embedded databases) and the model uses anywidget-archimate. While a CLI run holds the databases, the studio says so and shows what it can.
For front-end development, run uv run deriva and, in studio/, npm run dev (Vite forwards the API to port 8765, or to DERIVA_STUDIO_API for a studio on another port); npm test, npm run lint and npm run typecheck check it.
- Grafeo (embedded graph database):
- Graph namespace: the intermediate graph (directories, files, types, methods, dependencies, technologies, business concepts)
- Model namespace: the output graph (ArchiMate elements and relationships)
- DuckDB (
sql.dbin your home folder; in a source checkoutderiva/adapters/database/sql.db): step configurations with their versions, file types, name patterns and settings; created on first use from the shipped defaults
Via the API (DELETE /api/graph, DELETE /api/model) or the CLI (deriva-cli clear graph|model):
- Clear Graph: Removes all nodes/edges from Graph namespace
- Clear Model: Removes all ArchiMate elements and relationships
In the Workspace's Separate view, each graph panel has a query bar that runs read-only Cypher against the embedded Grafeo database. A few to start with:
// All repositories
MATCH (r:Graph:Repository) RETURN r.repoName, r.url
// The files of one repository, with their type
MATCH (repo:Graph:Repository)-[:`Graph:CONTAINS`*]->(f:Graph:File)
WHERE repo.repoName = 'my-repo'
RETURN f.filePath, f.fileType
// Type definitions
MATCH (td:Graph:TypeDefinition) RETURN td.typeName, td.category, td.filePathuv run deriva starts the studio; uv run deriva-cli runs the same pipeline without it, for scripts and automation. Installed as a tool, the commands run without uv run (deriva-cli run all --repo my-repo -v); the examples here are for a source checkout.
uv run deriva-cli repo clone https://github.com/user/my-repo.git
uv run deriva-cli repo list
uv run deriva-cli run all --repo my-repo -v
uv run deriva-cli run extraction --repo my-repo --no-llm
uv run deriva-cli status
uv run deriva-cli export -o workspace/output/model.xml --repo my-repo
uv run deriva-cli --help| Option | Does |
|---|---|
--repo NAME |
Runs one repository (default: all) |
--phase PHASE |
Runs one phase: classify or parse (extraction), prep, generate or refine (derivation) |
--only-step STEP |
Runs a single step |
--no-llm |
Makes no LLM call: extraction runs its parsers, derivation only its prep phase (graph metrics), and the model is kept |
-v |
Prints detailed progress |
-o PATH |
Where export writes the model |
Configuration from the command line:
# View configuration
uv run deriva-cli config list extraction
uv run deriva-cli config show extraction BusinessConcept
# Add a derivation step (created disabled, then enable it); a refine step
# must also be implemented and registered in code under the same name
uv run deriva-cli config add derivation my_refine_step --phase refine --sequence 4 --params '{"dry_run": true}'
uv run deriva-cli config enable derivation my_refine_step
# Manage file types
uv run deriva-cli config filetype list
uv run deriva-cli config filetype add ".lock" dependency lock
uv run deriva-cli config filetype stats
# System settings (e.g. directories skipped during extraction)
uv run deriva-cli config setting show excluded_directories
# Derivation name patterns (include and exclude, per step and category)
uv run deriva-cli config pattern list SystemSoftwareBenchmarking comes with the deriva-dev package (uv tool install --python 3.14 deriva-dev); in a source checkout it is always there.
Deriva includes a multi-model benchmarking system for comparing LLM performance across different providers and models. See docs/benchmarks.md for the full guide and docs/optimization.md for detailed case studies.
# List available benchmark models
uv run deriva-cli benchmark models
# Run a benchmark with specific models
uv run deriva-cli benchmark run \
--repos flask_invoice_generator \
--models openai-gptx,ollama-devstral \
-n 3 \
-d "Comparing gptx with devstral" \
-v
# List benchmark sessions
uv run deriva-cli benchmark list
# Analyze a benchmark session
uv run deriva-cli benchmark analyze bench_20260101_150724The benchmark models are the models from Set Up an LLM: each LLM_{NAME}_* block in .env is one. Every session writes its models, LLM calls and event logs for process mining (OCEL 2.0, and a log with one case per run as CSV and XES) into workspace/benchmarks/<session_id>/; docs/benchmarks.md lists the files, and deriva-cli benchmark ocel exports the logs of several sessions together.
The front end is missing (source checkouts only; the installed studio ships its front end): build it (from source) and start the studio again (it looks for the front end when it starts).
A command line run, for example a benchmark, has the databases open. The studio shows what it can and carries on when that run finishes.
An installed tool:
uv tool install --reinstall --python 3.14 deriva-studioA source checkout:
uv run python --version # 3.14 or newer
uv sync --reinstallOn its first run this step downloads its language models (the spaCy pipelines and the translation models) into workspace/cache/nlp in your home folder and checks them by SHA-256. Check that the machine can reach the model hosts and run the step again. DERIVA_NLP_MODELS_DIR in .env moves the folder.
For development setup, architecture details, and contribution guidelines, see CONTRIBUTING.md.
This project is licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).
This means you can freely use, modify, and distribute this software, but if you run a modified version as a network service, you must make the source code available to users of that service.
See LICENSE for the full license text.
- FastAPI and React - The studio
- anywidget-graph and anywidget-archimate - Graph and model views
- Grafeo - Embedded graph database
- ArchiMate - Enterprise architecture standard
- Archi - Open source ArchiMate modeling tool
- Tree-sitter - Multi-language AST parsing
Status: Active Development