DeepSource: How to Configure .deepsource.toml for Accurate, Low‑Noise Multi‑Language Analysis
A practical guide to configuring DeepSource with .deepsource.toml: set analyzers, transformers, exclude and test patterns, and dependency paths to reduce noise.
DeepSource’s analysis pipeline starts with a single file at the repository root—the .deepsource.toml configuration—and getting that file right determines whether the platform delivers useful insights or a flood of irrelevant findings. This article explains why the .deepsource.toml matters, how to author it for single- and multi-language projects, and how to avoid common pitfalls that cause analyzers to miss code or report false positives. Whether you’re enabling Python checks, adding JavaScript/TypeScript rules, or tuning transformers for automatic formatting, the choices in this file shape the developer experience, CI feedback, and security posture of your codebase.
Why the .deepsource.toml File Is the Gatekeeper for DeepSource Analysis
Every run of DeepSource reads a single canonical configuration to decide which analyzers and formatters to run and which files to ignore. That small TOML file controls language versions, test detection, exclude patterns, and auto-fix behavior. If the file is missing, malformed, or misconfigured, DeepSource either won’t run or will analyze the wrong set of files with the wrong assumptions—leading to missed issues or noisy dashboards filled with generated-code warnings. Treating .deepsource.toml as part of your code hygiene and review process prevents configuration drift that erodes trust in the tooling.
Basic .deepsource.toml Structure and Required Keys
At minimum, a valid .deepsource.toml declares a version and at least one analyzer. The file uses TOML syntax: top-level arrays of tables (for example, [[analyzers]] and [[transformers]]), plus top-level arrays for global patterns like exclude_patterns and test_patterns. The only required primitive key is version = 1; omitting or changing that value causes a parsing error and disables analysis. From there, the configuration typically includes:
- exclude_patterns — globs for files/directories to ignore
- test_patterns — globs identifying test code
- [[analyzers]] blocks — one per language, each with name, enabled, and an optional [analyzers.meta] table
- [[transformers]] blocks — one per formatter to enable auto-fix PRs
Think of the minimal valid file as a switch to enable DeepSource; everything else refines how it interprets your repository.
The Version Key: Why version = 1 Must Be Present
The top-line version declaration is a small but critical detail: DeepSource currently expects version = 1. If that key is missing or set to any other number, the platform will not parse the file correctly, and you will see no analyzer output. Always confirm this line is present before troubleshooting other behaviors.
How Exclude Patterns Reduce Noise (and How to Write Them Carefully)
Exclude patterns tell DeepSource to ignore files entirely. Use them for generated code, vendored libraries, build artifacts, and assets that don’t need static analysis. Patterns use shell-style globs:
-
- matches characters in a single path segment
- ** matches directories recursively
- ? matches a single character
- character classes like [abc] match a set
Typical excludes include node_modules/, vendor/, dist/, compiled assets like *.min.js, protobuf outputs (e.g., */.pb.go), and framework artifacts such as .next/ or coverage/. Be conservative: overly broad exclusions such as src/ or */.py can hide source files you intended to analyze. Prefer directory-level exclusions that target generated or third-party code (for example, /generated/) and scope monorepo patterns to service directories when necessary.
Why You Should Use test_patterns Rather Than exclude_patterns for Tests
Tests should usually be analyzed, but with relaxed rules. test_patterns marks files as test code so DeepSource applies test-appropriate rules—permitting hardcoded test data, relaxing complexity thresholds, and preventing tests from skewing documentation coverage. Common test patterns include tests/, /*_test.py, /*_test.go, */.test.js, and /*.spec.ts. Excluding test files entirely with exclude_patterns prevents DeepSource from calculating coverage and leaves a blind spot in your repository’s quality metrics.
Configuring Analyzers: How Each Language Block Shapes Analysis
Each [[analyzers]] block defines a language engine. You can enable multiple analyzers in the same repository, but each analyzer needs exact names (for example, python, javascript, go, java, ruby, rust). Names are case‑sensitive—using Python instead of python or golang instead of go will silently fail and the analyzer won’t appear in the dashboard.
-
Python: The python analyzer has a rich [analyzers.meta] table. Common keys include runtime_version (for example 3.10, 3.11, or 3.12), max_line_length to set line-length checks, skip_doc_coverage to exempt module-level docstrings or dunder methods from coverage requirements, and dependency_file_paths to point DeepSource at requirements.txt, pyproject.toml, or Pipfile. Specifying runtime_version ensures newer syntax (match/case, union types) is interpreted correctly.
-
JavaScript / TypeScript: The javascript analyzer auto-detects .js, .jsx, .ts, and .tsx files. The meta section supports plugins (react, vue, angular) and environment (browser, node) arrays. If you use Flow, dialect can be set accordingly. In monorepos with multiple package.json files, explicitly listing dependency manifests helps correct resolution.
-
Go: The go analyzer accepts import_root to match the module path from go.mod, skip_generated to ignore files that contain a generated header (// Code generated …), and cgo_enabled to toggle CGO-dependent analysis. Correct import_root helps DeepSource resolve first-party versus third-party packages.
-
Java: Java configuration often focuses on runtime_version (8, 11, 17, 21). Providing the correct value ensures recognition of language features like records, sealed classes, and newer pattern matching.
- Ruby and Rust: ruby and rust analyzers require minimal top-level configuration. DeepSource infers Ruby versions from Gemfile or .ruby-version and focuses on RuboCop-style issues. Rust analysis emphasizes clippy-style lints, unsafe usage, and idiomatic patterns that compiler checks do not enforce.
Transformers: Automated Formatting and Safe Auto‑Fixes
Transformers are the automatic formatters that DeepSource can run and, when enabled, will surface fixes as pull requests. Common transformers include:
- black, isort, autopep8, yapf (Python)
- prettier (JavaScript/TypeScript, JSON, CSS, Markdown)
- gofmt, gofumpt (Go)
- rustfmt (Rust)
- rubocop (Ruby)
Transformers don’t conflict with analyzers in principle: analyzers detect issues and transformers propose fixes for formatting-related ones. But you must align transformer defaults with analyzer settings. For example, Black uses an 88-character default; if your python analyzer uses max_line_length = 120 you’ll have mixed signals about line length. Where needed, configure the formatter’s own config file (pyproject.toml for Black, .prettierrc for Prettier, rustfmt.toml, .rubocop.yml) so the auto-fixes match your team’s conventions.
Transformer and Analyzer Interaction: Avoiding Conflicting Signals
The pipeline typically runs analyzers first, then transformers propose fixes for formatting violations. Conflicts arise when analyzer thresholds differ from transformer defaults. To prevent churn, make transformer behavior explicit in project config files rather than relying on transformer defaults. That way, transform PRs and analyzer guidance will converge instead of producing contradictory feedback to developers.
Dependency File Paths: Why DeepSource Needs to Know Your Dependency Manifests
Specifying dependency_file_paths helps DeepSource build an accurate dependency graph and avoid false positives when a module import comes from third-party code. For Python, list requirements.txt, requirements-dev.txt, setup.py, Pipfile or pyproject.toml as appropriate. For JavaScript, package.json is typically auto-detected, but in multi-package repositories or when multiple package.json files exist at different levels, listing them removes ambiguity.
Multi‑Analyzer Setups for Polyglot Repositories and Monorepos
Modern applications commonly span multiple languages—backend services in Python or Go, front-end bundles in JS/TS, and infrastructure code in Terraform or Helm. Use multiple [[analyzers]] blocks in the same .deepsource.toml to enable each language’s checks. Global exclude and test patterns apply across analyzers, but you can scope patterns to service directories in a monorepo to keep configurations precise. For example: services/api/vendor/, services/web/node_modules/, services/web/dist/**. Scoped patterns reduce accidental exclusions and make the configuration easier to audit as the repository grows.
Real‑World Configuration Patterns by Project Type
Project archetypes have recurring configuration needs:
-
Python web app (Django/Flask): Exclude migrations, collected static files, media uploads, and coverage reports; set runtime_version to the appropriate Python 3.x release; use black and isort as transformers; add dependency paths to requirements*.txt or pyproject.toml.
-
Go microservice with protobufs: Exclude pb.go and pb.gw.go generated files and vendor directories; set import_root to the module path in go.mod; consider cgo_enabled = false if your CI lacks a C toolchain.
-
React + TypeScript front end: Exclude node_modules, build artifacts, declaration files (*.d.ts), and Jest snapshot directories; enable prettier and the javascript analyzer with the react plugin and browser environment.
- Ruby on Rails: Exclude vendor, db/schema.rb and migrations, logs and tmp, and compiled assets; enable rubocop transformer and rely on Gemfile or .ruby-version for Ruby version inference.
Those patterns reflect commonly repeated choices; adapt them to your repository’s structure and the conventions your team follows.
Common .deepsource.toml Mistakes and How to Avoid Them
Several recurring errors cause prolonged troubleshooting:
- Missing version = 1: analysis fails silently—always include this line.
- Wrong analyzer names: analyzer identifiers are exact and case-sensitive; check names (python, javascript, go, java, ruby, rust).
- Overly broad exclude patterns: avoid excluding whole source directories accidentally; prefer precise generated-code patterns.
- Missing test_patterns: without explicit test patterns, tests are treated as production code and generate noisy findings.
- Transformer/analyzer mismatch: make formatting settings explicit in project config files to avoid conflicting advice.
- Not excluding generated code: generated files produce findings that you can’t fix; exclude them.
- Using exclude_patterns for tests: tests should be analyzed with test rules, not hidden, so use test_patterns.
Document these checks in your team’s onboarding or a repository CONTRIBUTING.md to reduce repeated misconfiguration.
Validating and Troubleshooting Your DeepSource Configuration
After editing .deepsource.toml:
- Validate TOML syntax locally with a validator—TOML has specific rules for arrays, tables, and quoting that differ from JSON or YAML.
- Commit the file to the repository root on the default branch (main or master). DeepSource reads config from the repository’s default branch; placing the file on a feature branch won’t take effect until merged.
- Check the DeepSource dashboard for configuration errors and analyzer status. The dashboard surface shows whether analyzers are enabled and highlights syntax or semantic errors in the configuration.
- Trigger a manual analysis if you need immediate feedback. This forces the platform to re-read the file without waiting for the next commit.
- Inspect early results: large numbers of findings in generated folders indicate exclude_patterns need adjustment; test-related false positives point to missing test_patterns; syntax errors in otherwise valid code usually mean runtime_version is misconfigured.
Treat changes to .deepsource.toml as part of code review. Changes to the file can add new analyzers or expose previously ignored issues, and they should be evaluated for developer workflow impact.
Alternatives and When to Choose Zero‑Config Tools
Some teams prefer a zero-config approach. Tools like CodeAnt AI advertise automatic language detection and analysis without a configuration file—this eliminates a class of configuration mistakes and lowers onboarding friction. The trade-off is control: a committed .deepsource.toml gives teams explicit, auditable control over excludes, language versions, and transformer behavior. Organizations with strict security scanning requirements, mixed-language monorepos, or tightly enforced style rules often prefer the predictability of an explicit config file, while small teams or single-language projects might favor zero-config convenience.
Industry Implications: What Analyzer Configuration Means for Teams and Security
Configuration of static analysis tools has downstream effects on developer productivity, incident response, and compliance. Well-scoped analysis reduces noisy alerts so teams can focus on genuine risks and technical debt; misconfigured analysis erodes confidence and encourages developers to ignore alerts. For security teams, accurate dependency resolution (via dependency_file_paths) and precise exclude patterns matter—excluding vendor code indiscriminately can hide vulnerable transitive dependencies, while failing to exclude generated code can waste triage resources. For engineering leadership, making analyzer config part of CI governance and quarterly review cycles helps keep checks aligned with evolving code structures and third-party tool updates.
Operationalizing .deepsource.toml Across Teams and Repositories
To keep configuration consistent:
- Store a canonical template in a central repo or in a developer handbook.
- Include .deepsource.toml edits in code review and require a brief justification for non-trivial changes.
- Schedule a short quarterly review to reconcile exclude and test patterns with changes in build tooling, generated-code locations, or new frameworks.
- Use CI jobs or local pre-commit hooks to validate TOML syntax before commits.
These practices prevent gradual configuration rot and ensure that analysis remains a productive part of the development lifecycle.
A forward-looking perspective: as language ecosystems and build systems evolve, configuration files like .deepsource.toml will need to grow more expressive—supporting fine-grained scope per subproject, conditional analyzer options, and richer integration with dependency graphs. Teams that treat analyzer configuration as part of their codebase’s living documentation will be better placed to extract consistent value from automated analysis—keeping false positives low, surfacing real security issues, and maintaining a frictionless developer experience across multi-language stacks.
















