Codebase health analysis powered by the GitLab Orbit Knowledge Graph
Orbit Recon reads the DuckDB property graph produced by GitLab Orbit and runs four automated health checks that most teams either do manually or don't do at all:
| Check | What it finds | Why it matters |
|---|---|---|
| Dead Code | Functions, classes, methods with zero references anywhere in the codebase | Bloated codebases, confused developers, dead public API surface |
| Circular Dependencies | A↔B and multi-module cycles (A→B→C→A) | Unpredictable changes, tangled modules, risky refactors |
| Module Coupling | High fan-out modules that depend on too many other modules | Change-prone code — any dependency change breaks them |
| Architectural Drift | Layer boundary violations (domain importing infrastructure) | Silent erosion of architecture over time |
It outputs structured reports in Markdown (developer review), JSON (CI/CD + GitLab Code Quality), or YAML (pipeline config). In CI mode, it exits with code 1 on critical findings — a merge request gate.
Orbit Recon is a showcase submission demonstrating how the Orbit Knowledge Graph can be consumed by custom tools and AI agents to deliver real developer value beyond code navigation. It includes both a Rust CLI binary and a GitLab Duo Agent Platform skill so AI agents can orchestrate health scans.
┌─────────────┐ orbit index ┌──────────────────┐
│ Repository │ ──────────────────> │ .orbit/ │
│ (source) │ │ orbit.duckdb │
└─────────────┘ └────────┬─────────┘
│
orbit-recon reads
DuckDB directly
(no server, no API)
│
┌────────▼─────────┐
│ Orbit Recon │
│ (Rust binary) │
│ │
│ ▸ Dead code │
│ ▸ Cycles (2+ mod)│
│ ▸ Coupling │
│ ▸ Drift │
└────────┬─────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌────────────┐ ┌───────────┐ ┌──────────┐
│ Markdown │ │ JSON │ │ YAML │
│ (review) │ │ (CI/CD) │ │ (config) │
└────────────┘ └───────────┘ └──────────┘
Key design decisions:
- Direct DuckDB access — no server, no API keys, no network. The
duckdbRust crate with thebundledfeature compiles DuckDB into the binary. Everything runs offline. - Rust — same language as Orbit itself. Single static binary, zero runtime dependencies, memory-safe, fast.
cargo install orbit-reconand go. - Agent Skills specification — the
SKILL.mdfollows the emerging standard so any compatible AI agent (Duo, Claude Code, Codex, Gemini CLI) can invoke it. - Schema discovery — Orbit's DuckDB schema is still evolving. Orbit Recon queries
information_schemaat runtime to adapt to whatever table/column names the graph uses.
- Rust toolchain (1.80+)
- GitLab CLI (
glab) with Orbit extension, or theorbitbinary directly
# From crates.io (when published)
cargo install orbit-recon
# Or build from source
git clone https://github.com/icohangar-ops/orbit-recon.git
cd orbit-recon
cargo build --release
# Binary at target/release/orbit-recon# 1. Index your repository with Orbit Local
cd /path/to/your/repo
orbit index .
# 2. Run the full analysis
orbit-recon
# 3. Get JSON output (for CI/CD)
orbit-recon --format json --output report.json
# 4. CI mode — exits with code 1 on critical findings
orbit-recon --format json --output report.json --ci# Install the skill into your project
glab skills install orbit-reconThen in GitLab Duo, just ask: "Run an Orbit Recon health scan on this codebase."
orbit-recon [OPTIONS]
Options:
-r, --repo <PATH> Repository path (contains .orbit/) [default: .]
-d, --db <PATH> DuckDB file path (overrides auto-detection)
-f, --format <FORMAT> Output format: json, markdown, yaml [default: markdown]
-o, --output <PATH> Output file path (stdout if omitted)
-c, --config <PATH> Config file path [default: .orbit-recon.yml]
--only <CHECKS> Only run specific checks (comma-separated)
Options: dead_code, circular_dependencies, coupling,
architectural_drift
-s, --severity <LEVEL> Minimum severity to report [default: info]
Options: info, warning, critical
--ci CI mode: exit code 1 if critical findings exist
-h, --help Show help
-V, --version Show version
# Full analysis, Markdown to stdout
orbit-recon --repo /path/to/project
# Only check for dead code and circular deps
orbit-recon --only dead_code,circular_dependencies
# Only critical findings, JSON output for CI
orbit-recon --severity critical --format json --output report.json --ci
# Custom config file
orbit-recon --config /path/to/custom-rules.yml
# Point to a specific DuckDB file
orbit-recon --db /custom/path/orbit.duckdbFinds definitions (functions, methods, classes, structs, enums, traits) that have zero incoming references in the entire codebase. These are nodes in the Orbit graph with no incoming REFERENCES edges.
Severity classification:
| Condition | Severity | Rationale |
|---|---|---|
| Public class/struct/enum with no references | CRITICAL | Dead public API surface — likely confuses consumers |
| Private function/method with no references | WARNING | Possibly dead, but may be used via reflection |
| Entry points, test functions, barrel files | INFO | Known false positives — suppressed by default |
False positive handling: Automatically skips index.ts, mod.rs, main.rs, lib.rs, and files matching test naming conventions. Additional ignore patterns can be configured in .orbit-recon.yml.
Builds a module-level dependency graph from the raw cross-file references in the Orbit graph, then runs cycle detection:
- Pairwise cycles (A↔B): Detects bidirectional module dependencies by checking if both A→B and B→A edges exist
- Multi-module cycles (A→B→C→A): Uses recursive DFS to find cycles involving 3+ modules
- Scoring: Each cycle is scored by the total number of cross-references, with high-volume cycles flagged as critical
Example output:
CRITICAL `auth` <-> `user` — 34 cross-references
Chain: auth/service.rs imports user/model.rs, user/repository.rs imports auth/token.rs
Suggestion: Extract shared code into a third module (dependency inversion principle)
Measures the fan-out metric for every module — the number of other modules it directly depends on.
Thresholds (configurable):
| Fan-out | Severity | Meaning |
|---|---|---|
| < 8 | ✅ Healthy | Normal dependency count |
| 8–14 | Moderate coupling, worth reviewing | |
| ≥ 15 | 🔴 Critical | Highly coupled, change-prone |
Lists every dependency for high-coupling modules so developers know exactly where to focus refactoring efforts.
Validates every cross-file reference against layer boundary rules defined in .orbit-recon.yml. Each rule specifies:
- A glob pattern matching files in a layer (e.g.,
src/domain/**) - A list of glob patterns the layer is allowed to import from
When a definition in a governed layer imports something outside its allowed scope, it's flagged as an architectural drift violation.
Default boundaries (for standard layered architectures):
| Layer | Allowed to Import |
|---|---|
src/domain/** |
src/domain/**, src/types/**, src/models/** |
src/application/** |
src/domain/**, src/application/**, src/types/**, src/models/** |
src/presentation/** |
src/application/**, src/domain/**, src/types/**, src/models/** |
Create .orbit-recon.yml in your repository root. A full example is at config/.orbit-recon.example.yml.
# Architecture boundary rules
boundaries:
- name: "Domain Layer"
pattern: "src/domain/**"
allowed_imports:
- "src/domain/**"
- "src/types/**"
- name: "Application Layer"
pattern: "src/application/**"
allowed_imports:
- "src/domain/**"
- "src/application/**"
- "src/types/**"
- name: "Presentation Layer"
pattern: "src/presentation/**"
allowed_imports:
- "src/application/**"
- "src/domain/**"
- "src/types/**"
# Severity thresholds
thresholds:
dead_code_warning: 20 # Total dead code count to escalate to warning
dead_code_critical: 50 # Total dead code count to escalate to critical
coupling_warning_fan_out: 8 # Module fan-out for warning
coupling_critical_fan_out: 15 # Module fan-out for critical
# Ignore patterns (glob syntax)
ignore:
dead_code:
- "test/**"
- "tests/**"
- "**/*.test.*"
- "**/*.spec.*"
drift:
- "src/generated/**"
- "**/*.generated.*"Add to your .gitlab-ci.yml:
orbit-recon-check:
stage: test
before_script:
- glab orbit setup
- orbit index .
- cargo install orbit-recon
script:
- orbit-recon --format json --output orbit-report.json --ci
artifacts:
reports:
codequality: orbit-report.json
paths:
- orbit-report.json
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"This runs Orbit Recon on every merge request, feeds results into GitLab Code Quality, and blocks the pipeline if critical findings exist.
- name: Orbit Recon
run: |
orbit index .
orbit-recon --format json --output report.json --ciOrbit Recon includes a skill that follows the Agent Skills specification. This means any compatible AI agent can invoke it.
| File | Purpose |
|---|---|
AGENTS.md |
Agent context: architecture, query patterns, setup, limitations |
.agents/skills/orbit-recon/SKILL.md |
Skill definition: triggers, prerequisites, step-by-step instructions, error handling |
- Install the skill:
glab skills install orbit-recon - The agent reads
SKILL.mdand learns the workflow - User asks: "Run an Orbit Recon health scan"
- Agent verifies prerequisites, runs
orbit-recon, presents findings
The skill is compatible with GitLab Duo Agent Platform, Claude Code, Codex, and Gemini CLI.
Beyond the CLI and the Duo skill, Orbit Recon exposes its four health checks as
Model Context Protocol tools through a
dedicated binary, orbit-recon-mcp. Any MCP client — Claude Desktop, Cursor,
GitLab Duo, or a custom agent — can call the checks directly as tools.
It is a thin wrapper: the server binary reuses the exact same orbit_recon
library the CLI does, so there is no duplicated analysis logic. The transport is
newline-delimited JSON-RPC 2.0 over stdio, implemented with only
serde_json (already a dependency) — no async runtime or extra crates were added.
# Build both binaries (orbit-recon and orbit-recon-mcp)
cargo build --release
# Run the MCP server (serves on stdio; a client spawns it)
./target/release/orbit-recon-mcp
# Or during development
cargo run --bin orbit-recon-mcp| Tool | Purpose |
|---|---|
analyze_dead_code |
Definitions with zero incoming references (dead code). |
detect_circular_dependencies |
A↔B and multi-module (A→B→C→A) dependency cycles. |
analyze_coupling |
Per-module fan-out; flags modules over the configured thresholds. |
detect_architectural_drift |
Imports that cross configured layer boundaries. |
health_scan |
All four checks + graph stats as one structured report (json or markdown). |
Common inputs (all optional): repo (path to a repo with .orbit/, default .),
db (explicit DuckDB path), severity (info | warning | critical).
health_scan also accepts format (json | markdown).
{
"mcpServers": {
"orbit-recon": {
"command": "orbit-recon-mcp",
"args": []
}
}
}cargo test # includes tools/list + a no-network tools/call over a temp DuckDB graphOrbit Recon follows the same publishing path as the author's other MCP servers
(codehealth-mcp, codesentinel) under the io.github.Cubiczan namespace. The
server.json manifest declares the server for the
MCP Registry; publish it with the
mcp-publisher CLI (not a PR):
# Package/publish the binary crate so `orbit-recon-mcp` is installable
cargo publish
# Then register the MCP server manifest
mcp-publisher login github
mcp-publisher publish # reads ./server.json (io.github.Cubiczan/orbit-recon)orbit-recon/
├── .agents/
│ └── skills/
│ └── orbit-recon/
│ └── SKILL.md # Duo Agent Platform skill definition
├── config/
│ └── .orbit-recon.example.yml # Example configuration
├── src/
│ ├── lib.rs # Shared core library (checks driver, graph open, scan_repo)
│ ├── main.rs # CLI entry point, argument parsing, orchestration
│ ├── bin/
│ │ └── mcp_server.rs # MCP server binary (stdio JSON-RPC, wraps the library)
│ ├── config.rs # YAML config loader, boundary matching, ignore patterns
│ ├── findings.rs # Finding, Severity, Category, Location types
│ ├── report.rs # Markdown/JSON/YAML report generation
│ └── queries/
│ ├── mod.rs # Module aggregator, graph stats, schema discovery
│ ├── dead_code.rs # Zero in-degree definition detection
│ ├── circular_deps.rs # Module cycle detection (pair + multi-module DFS)
│ ├── coupling.rs # Fan-out metric per module
│ └── drift.rs # Boundary rule violation detection
├── AGENTS.md # Agent platform documentation
├── server.json # MCP Registry manifest (io.github.Cubiczan/orbit-recon)
├── Cargo.toml # Rust dependencies
├── devpost-submission.md # Devpost hackathon submission content
├── video-script.md # 3-minute demo video script
├── .gitlab-ci.yml # CI/CD pipeline template
├── .gitignore
├── orbit-recon-icon-512.png # Project icon
├── devpost-thumbnail.png # Devpost submission thumbnail
└── README.md # This file
| Dependency | Purpose |
|---|---|
| duckdb (bundled) | Reads Orbit Knowledge Graph, no system dependency |
| clap v4 | CLI argument parsing with derive macros |
| serde + serde_json + serde_yaml | JSON/YAML report serialization |
| glob | Boundary rule pattern matching |
| chrono | Timestamp formatting in reports |
| colored | Terminal severity colors (future) |
| anyhow + thiserror | Error handling |
| uuid | Unique finding IDs |
| log + env_logger | Structured logging |
- Orbit Remote adapter — Query Orbit Remote via gRPC/HTTP for GitLab-hosted repos
- Historical tracking — Track finding counts over time, plot trends
- Diff mode — Compare two graph snapshots, report only new findings per MR
- VS Code extension — Inline annotations for drift and dead code
- Web dashboard — Interactive dependency graph visualization (D3.js / vis.js)
- Multi-language tuning — Optimized defaults for Python, Go, Java, Ruby
- AI Catalog — Submit to GitLab AI Catalog for one-click install
MIT — see LICENSE.
- GitHub: https://github.com/icohangar-ops/orbit-recon
- Codeberg: https://codeberg.org/cubiczan/orbit-recon
- Hackathon: https://gitlab-transcend.devpost.com
- Orbit Docs: https://docs.gitlab.com/orbit
- Agent Skills Spec: https://docs.gitlab.com/user/duo_agent_platform/customize/agent_skills