Codebase map, dependency graph analyzer, and cleanup-confidence engine.
Project description
Orbits
Orbits is a map for codebases: it shows the main routes through a repo, what actually ran, what changed, and what looks safe to clean up.
It analyzes a source tree, resolves project-local dependencies, merges optional runtime traces, scores dead-code confidence with git/runtime evidence, writes a graph.json, and serves a bundled visualizer for exploring the result.
The current stack is:
- Python backend analyzer
- D3 + canvas visualizer
- browser-side worker analysis for folder loading in supported browsers
- local HTTP serving through
orbits scan . --open - first-class HTML/CSS/static-asset graph extraction for web projects
- optional Python and Node.js runtime tracing with merged dynamic-edge overlays
- codebase-map intelligence for regions, entrypoints, core hubs, impact, framework signals, and runtime command discovery
- Phase 6 language coverage with deep/partial/unknown confidence per file, named partial support, production glue files, and unknown-file mapping
Quick Start
From the repo root:
- Create and activate a local venv.
- Install frontend dependencies once.
- Run the analyzer with
scan . --open.
Windows PowerShell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
npm install
python analyzer.py scan . --open
Then open the URL printed by the server, typically:
http://127.0.0.1:8765/visualizer.html
If You Only Want a Graph File
python analyzer.py scan .
That writes graph.json in the repo root by default.
If You Already Have a Venv
.\.venv\Scripts\python.exe analyzer.py scan . --open
Installable CLI
Orbits can be installed as a normal Python CLI:
python -m pip install -e .
orbits scan . -o graph.json
orbits scan . --open
orbits cleanup-plan .
orbits scale-proof .
orbits language-coverage .
orbits --diff C:/temp/old-graph.json C:/temp/new-graph.json
python -m orbits scan . --open
The console script maps to the existing analyzer:main entry point, and the packaged wheel includes the visualizer assets used by --open. The legacy orbits . --serve / python analyzer.py . --serve forms still work.
For npm-based toolchains, Orbits also has a scoped wrapper that installs the PyPI package and exposes the same CLI:
npm install -g @yumekaz/orbits
orbits scan . --open
What It Does
- Crawls a project tree while skipping common noise
- Extracts imports/includes for multiple languages
- Extracts HTML links/scripts/forms/media references and CSS
@import/url(...)assets - Resolves project-local dependencies
- Computes cycles, islands, orphans, depth, health, and summary stats
- Detects common project entrypoints so launch files are not reported as dead just because nothing imports them
- Adds a higher-level codebase map with regions, core hubs, isolated areas, framework signals, runtime command suggestions, and per-file impact metrics
- Adds per-file language coverage confidence so unsupported files remain visible instead of disappearing from the map
- Scores dead-code confidence from structure, git age/churn, and runtime touch evidence
- Produces PR-friendly architecture diffs, including coupling, cycle, dead-file, classification, confidence, health, and runtime-edge changes
- Writes cleanup plans and scale-proof reports for CI, demos, and review
- Serves an interactive visualizer for the generated graph
Product Commands
orbits scan . --open
orbits cleanup-plan . --cleanup-plan-md cleanup-plan.md
orbits scale-proof . --scale-proof-md scale-proof.md
orbits language-coverage . --language-coverage-md language-coverage.md
orbits --diff old-graph.json new-graph.json --diff-json
scan writes the graph and opens the guided map UI. cleanup-plan groups dead-code candidates into safe, risky, and manual-review buckets with evidence. scale-proof summarizes repo size, language mix, edge counts, largest files, and scan metadata. language-coverage reports how much of the repo is deep, partial, or unknown analysis.
Entrypoint Detection
Orbits marks detected launch files as ENTRY even when they have no outbound imports. Detection currently uses package.json fields/scripts, Python project script metadata, setup.cfg / setup.py console scripts, Dockerfile CMD / ENTRYPOINT hints, common Makefile run targets, and conventional names such as main.py, app.py, server.py, manage.py, index.js / index.ts, and Go main.go.
Detected entries are stored in meta.entrypoints, and each matching node gets entrypoint: true plus entrypoint_reasons for future UI/report use.
Supported Languages
First-class extraction and resolution:
- Python
- JavaScript / TypeScript / TSX
- Go
- C / C++
- Java
- Kotlin
- HTML
- CSS / SCSS / Sass / Less
- referenced static assets such as images, fonts, JSON, PDFs, media, and Wasm
Named partial extraction and mapping:
- Rust
- C#
- PHP
- Ruby
- JSON
- YAML
- TOML
- Dockerfile
- Docker Compose
- Makefile
- Shell scripts
- SQL
- GitHub Actions workflows
Fallback:
- Unknown-language files remain visible in the map with
analysis_confidence: "unknown" - Generic regex-based extraction is used where a safe import-like pattern is available
Every node includes:
analysis_confidence:deep,partial, orunknownlanguage_role: source, config, build, ci, script, data, asset, or unknownanalysis_note: the honest reason for that confidence level
The graph metadata includes meta.language_coverage, including file counts and percentages for deep, partial, and unknown coverage.
Pipeline
- Crawl the project tree.
- Extract raw import/include statements.
- Resolve local edges against project files and referenced web assets.
- Build graph metadata and summary metrics.
- Optionally trace a Python or Node.js entrypoint at runtime and write
runtime_trace.json. - Merge dynamic runtime edges into the served/exported graph overlay.
- Attach codebase-map intelligence for the UI and reports.
- Write
graph.json. - Optionally serve the visualizer and graph assets.
Current Frontend Architecture
The active visualizer is not Cytoscape.
It currently uses:
- D3 for zoom, motion, and interaction
canvasfor graph rendering- DOM panels for controls, codebase map, impact, inspector, waste, cycles, and search
visualizer_worker.jsfor browser-side folder analysis
This preserves the older 3.5f visual feel while keeping the later browser-side workflow and performance work.
Phase 4 Status
Implemented in the current UI:
- Cluster view
- Filter panel
- File sidebar / inspector
- Waste panel
- Cycles panel
- Search with dependency-tree highlighting
- Minimap
- Language multi-select
- Unsupported-language warning banner
- Folder loading via File System Access API in Chromium-based browsers
- Browser-side worker analysis
- Large-graph performance modes and auto-degradation
Not implemented as originally claimed in older docs:
- Cytoscape.js / react-force-graph as the active renderer
Visual Baselines
Stage 2 visual regression is opt-in and does not run in the default test:e2e path.
Generate or refresh baselines:
npm run test:e2e:visual:update
Compare against existing baselines:
npm run test:e2e:visual
Baseline screenshots live in e2e/visual.spec.ts-snapshots/ and are committed once approved.
The dedicated Playwright screenshot script at scripts/visual-baselines.mjs keeps visual regression opt-in and out of the default test:e2e run.
Phase 5 Status
Implemented now:
- Python runtime tracing in a separate subprocess
- Node.js runtime tracing in a separate subprocess
- scoped C / C++ runtime tracing for local native binaries and libraries
- separate
runtime_trace.jsonartifact - merged runtime edge overlay in
graph.jsonviadynamic_edges - multi-session runtime metadata via
meta.runtime.sessions[] - runtime-aware
viewmenu edge modes:static,runtime,combined - runtime edge styling in the D3 + canvas visualizer
- stale runtime overlay preservation across static reanalysis paths
Current scope and honest boundary:
- runtime tracing is shipped for Python, Node.js, and scoped C / C++ overlays today
- multiple runtime artifacts can be merged into one graph as separate runtime sessions
- static graph metrics like cycles, depth, waste, and health remain static-analysis-based
- runtime edges are an overlay, not a replacement for the static graph
- reanalysis preserves prior runtime overlay, but marks it stale after source-changing actions until you retrace
- Node traces are best for
.js/.cjs/.mjsentrypoints; direct TypeScript runtime execution is still not claimed - runtime-to-static remapping for transpiled
dist/*.jstosrc/*.tsnow uses source maps, inline maps, customsourceMappingURLfiles, indexed source-map sections, source roots, and common bundler path forms when available, but is still not compiler-perfect - C / C++ tracing is still intentionally scoped: Linux captures loader edges plus local symbol bindings, macOS stays loader-oriented, and Windows captures local PE import-table DLL dependencies
- static C / C++ analysis also recognizes literal
dlopen(...),LoadLibrary(...), andLoadLibraryEx(...)calls when the referenced local library exists
Performance Reality
The visualizer is now much safer on large graphs than the old SVG version, but this is the honest boundary:
500+files is a reasonable target- large graphs degrade by reducing labels, limiting visible nodes/edges, sampling the minimap, and disabling live motion when needed
- very dense multi-thousand-node graphs can still be heavy depending on browser and machine
- this is engineered to degrade gracefully, not a promise that every arbitrarily huge graph can never slow down
Performance Modes
The visualizer has three modes in the view menu:
perf auto: chooses safer defaults automatically for large graphsperf full: favors richer motion and higher draw limitsperf safe: favors stability and stricter draw limits
On very large graphs, Orbits may automatically start with:
- cluster layout
- labels off
- full graph off
Browser Features
The visualizer supports two data sources:
- Backend-generated
graph.json - Browser-side folder analysis from the
folderbutton
Browser folder analysis:
- uses a Web Worker so analysis does not block the UI thread
- requires a Chromium-based browser for
showDirectoryPicker() - produces the same top-level graph shape as the backend visualizer expects
- is heuristic and not guaranteed to match backend analysis exactly on every repo
Runtime Requirements
Python
Recommended: use the workspace venv.
The repo expects local Python dependencies in .venv/.
Optional parser support depends on installed tree-sitter language packages.
If grammars are missing, Orbits reports unsupported languages in CLI output and graph metadata instead of silently pretending those files had no imports.
Node runtime tracing uses the same overlay contract as Python:
orbits scan /path/to/project --trace-node app.js
orbits scan /path/to/project --trace-node-module myapp.cli --trace-arg=--mode --trace-arg=dev
It writes a separate runtime artifact and merges into dynamic_edges exactly like Python.
You can also merge existing runtime artifacts back into a fresh static analysis:
orbits scan /path/to/project --runtime-input C:/tmp/python_runtime.json --runtime-input C:/tmp/node_runtime.json
Scoped native tracing is also available for local C / C++ binaries on supported platforms:
orbits scan /path/to/project --trace-cpp build/my_binary
On Linux this captures local loader edges and symbol bindings via loader diagnostics. On macOS it captures local loader edges. On Windows it executes the entry binary normally and adds scoped local DLL dependency edges from the executable's PE import table. Windows tracing is loader/dependency oriented; it does not claim deep native tracing, syscall tracing, or universal LoadLibrary discovery.
Static C / C++ extraction also adds graph edges for literal local dlopen(...), LoadLibrary(...), and LoadLibraryEx(...) library paths when the target file exists in the repo.
Frontend
Install frontend dependencies once:
npm install
The active frontend uses D3. Cytoscape is not the active renderer path.
Usage
Analyze a project:
orbits scan /path/to/project
Analyze and serve the visualizer:
orbits scan /path/to/project --open
Trace a Python script at runtime and merge dynamic edges:
orbits scan /path/to/project --trace-python app.py --open
Trace a Python module with arguments:
orbits scan /path/to/project --trace-module myapp.cli --trace-arg=--mode --trace-arg=dev
Trace a Node.js script or module with the same argument style:
orbits scan /path/to/project --trace-node app.js
orbits scan /path/to/project --trace-node-module myapp.cli --trace-arg=--mode --trace-arg=dev
Write the runtime artifact somewhere else:
orbits scan /path/to/project --trace-python app.py --runtime-output C:/temp/runtime_trace.json
Merge one or more existing runtime artifacts into a fresh graph:
orbits scan /path/to/project --runtime-input C:/temp/python_runtime.json --runtime-input C:/temp/node_runtime.json
Write output somewhere else and still serve correctly:
orbits scan /path/to/project -o C:/temp/my-graph.json --open
Compare two graph snapshots:
python analyzer.py --diff C:/temp/old-graph.json C:/temp/new-graph.json
python analyzer.py --diff C:/temp/old-graph.json C:/temp/new-graph.json --diff-json
The diff reports added and removed nodes, static and runtime dependency edges, dead-file changes, classification changes, and confidence-score changes. Edge comparison uses source -> target, so line-number-only import churn does not count as a dependency change.
Demo Evidence
The examples/ directory contains lightweight, deterministic material for a judge or reviewer:
examples/orbits-demo.png: screenshot of the visualizerexamples/demo-pr-comment.md: sample PR comment showing confidence evidence and graph-diff impactexamples/orbits.config.example.json: sample.orbits.jsonconfig shapeexamples/README.md: install, analyze, check, reports, diff, and runtime-boundary command transcriptexamples/fixtures/*.json: tiny graph snapshots fororbits --diff
Config, Reports, and Check Mode
Orbits reads optional project-root config from codegraph.config.json and .orbits.json.
If both exist, codegraph.config.json is loaded first and .orbits.json can extend or override it.
{
"ignore": {
"dirs": ["legacy/**", "generated/**"],
"files": ["*.snapshot.py", "fixtures/*.js"]
},
"intentional_files": ["scripts/manual_migration.py"],
"check": {
"max_orphans": 0,
"max_islands": 0,
"min_health": 85
},
"resolvers": {
"python": {
"src_dirs": ["src"],
"third_party": ["requests"]
},
"javascript": {
"base_url": "src",
"aliases": {
"@/*": "src/*"
}
},
"c_family": {
"include_dirs": ["include"]
},
"jvm": {
"src_roots": ["src/main/java", "src/main/kotlin"]
}
}
}
Write explicit dead-file reports:
orbits scan /path/to/project --dead-report-md dead-files.md --dead-report-csv dead-files.csv
orbits cleanup-plan /path/to/project --cleanup-plan-md cleanup-plan.md
orbits scale-proof /path/to/project --scale-proof-md scale-proof.md
orbits language-coverage /path/to/project --language-coverage-md language-coverage.md
When the analyzed root is inside a Git worktree, each dead-file item is also annotated with cheap history context: last touch age/timestamp, commit count, line churn, top authors, and a deterministic confidence score with reasons. Runtime overlays are folded into that score when present, so a fresh runtime touch lowers confidence while an untouched fresh trace raises it.
The cleanup plan is intentionally not a delete button. It separates safe, risky, and manual-review candidates, then records the blockers and evidence a developer should check before removing anything. The scale proof is demo/CI evidence: file counts, edge counts, language mix, byte buckets, largest files, and scan metadata.
Run a deterministic CI-style check:
orbits scan /path/to/project --check
orbits scan /path/to/project --check --max-orphans 0 --max-islands 1 --min-health 90
GitHub Actions and Thresholds
The included Orbits workflow runs the same CLI check on pushes and pull requests:
orbits scan . -o orbits-artifacts/graph.json --dead-report-md orbits-artifacts/dead-files.md --dead-report-csv orbits-artifacts/dead-files.csv --cleanup-plan-md orbits-artifacts/cleanup-plan.md --scale-proof-md orbits-artifacts/scale-proof.md --language-coverage-md orbits-artifacts/language-coverage.md --check
It uploads graph.json, reports, check logs, and the generated PR comment body as the orbits-report artifact. On pull requests, it also tries to build a base-branch architecture diff and update a sticky PR comment. Comment posting is best-effort; the check artifacts are still produced when the token cannot write comments.
Configure thresholds in codegraph.config.json or .orbits.json:
{
"check": {
"max_orphans": 0,
"max_islands": 1,
"min_health": 90
}
}
For repository-specific CI overrides without changing config files, set a GitHub Actions repository variable named ORBITS_CHECK_ARGS, for example:
--max-orphans 0 --max-islands 1 --min-health 90
--check exits with code 2 when a configured or flag-provided threshold is exceeded.
Orphan and island thresholds use actionable dead files after intentional_files suppressions.
Health uses the graph summary score.
PyPI Release Readiness
The repository includes .github/workflows/publish.yml for Python packaging:
workflow_dispatchbuilds the source distribution and wheel, then runstwine check- GitHub Release publishing uploads to PyPI through Trusted Publishing
- the PyPI project target is
orbits-codebase, which installs theorbitsCLI command
Before the first real release, configure a PyPI Trusted Publisher for this GitHub repository and the pypi environment. No API token is required when Trusted Publishing is configured correctly.
Load a graph directly in the browser UI:
- open the served visualizer
- use
OPEN GRAPH FILE - or drag and drop a
graph.json
If runtime data is present, the view menu lets you switch between:
staticedges onlyruntimeedges onlycombinedstatic + runtime edges
Behavior Guarantees
- Analysis does not edit the target repository's
.gitignore - Cache writes stay in Orbits-owned files
--servedoes not depend on changing the process working directory- Missing parser support is surfaced in metadata and UI/CLI messaging
- Runtime tracing writes to a separate artifact instead of mutating static cache files
- Source-changing reanalysis preserves runtime overlay but marks it stale until you rerun tracing
- Multiple runtime traces are preserved as individual sessions and also aggregated into one runtime overlay
Visualizer Features
Inspector shows:
- file path
- classification
- inbound/outbound references
- runtime edge markers (
dynorrt) when present - depth
- island
- cycle membership
- modified time
- git blame summary when available
Waste panel supports:
openkeepto mark a file as intentional wastedel
Intentional suppressions are stored in:
.orbits_intentional.jsonintentional_filesincodegraph.config.jsonor.orbits.json
Key Files
analyzer.py: CLI entry point, HTTP serving, file actions, metadata APIsruntime_trace.py: Python + Node runtime trace orchestration, artifact writer, runtime merge helpersnode_runtime_trace.cjs: Node.js runtime tracer child process and artifact writerentrypoints.py: manifest and conventional entrypoint detectionlang_dispatch.py: crawl orchestration, worker dispatch, language support metadataworker.py: per-language extraction and resolution executionextractors/: tree-sitter, web, and fallback extractorsresolvers/: language-specific resolution logicorbits_assets/: packaged visualizer assets for installed CLI servinggraph_engine.py: enrichment, waste detection, summary metricsgraph_diff.py: graph snapshot comparison helper and standalone diff CLIvisualizer.html: bundled shell/UIvisualizer_app.js: active D3 + canvas visualizer logicvisualizer_worker.js: browser-side worker analysis and layoutbenchmark_graph.py: deterministic large-graph benchmark fixture generator
Benchmarking
Generate a large synthetic graph fixture:
python benchmark_graph.py --nodes 1200 --seed 7 --output large_graph.json
This is useful for testing:
- render stability
- minimap behavior
- perf mode changes
- large-graph regressions
Verification
The repo currently includes regression coverage for:
- non-mutating analysis behavior
- serving behavior
- unsupported parser metadata
- Python import-from resolution
- Python runtime trace capture and merge behavior
- Node runtime trace capture and merge behavior
- multi-session runtime merge behavior and Node source-map remapping
- TypeScript alias resolution
- Go module resolution
- C / C++ include resolution
- Java and Kotlin package resolution
- HTML/CSS/static asset graph extraction
- end-to-end graph shape
- graph dependency diff summaries
- installable CLI metadata and packaged visualizer assets
- synthetic benchmark graph generation
- Playwright Stage 1 browser coverage for the visualizer, including runtime edge mode switching
Run backend tests:
python -m unittest discover -s tests -v
Run browser tests:
npm run test:e2e -- --reporter=line
Limitations
- Dynamic imports, reflection, generated code, and macro-heavy systems remain hard limits for static analysis alone
- Python runtime tracing only sees code paths that actually execute
- Python runtime tracing is time-bounded; timed-out sessions produce partial traces
- Node runtime tracing is shipped as a backend tracer for JavaScript entrypoints
- HTML/CSS analysis resolves static references, but it does not execute browser JavaScript or infer DOM nodes created at runtime
- Browser-side worker analysis is not guaranteed to match backend analysis exactly
- Large graphs are handled more safely now, but browser and machine limits still matter
- Git blame and file actions depend on local environment support and repository state
- Runtime edges are an overlay today; they do not currently rewrite static health, cycle, depth, or waste calculations
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file orbits_codebase-0.1.3.tar.gz.
File metadata
- Download URL: orbits_codebase-0.1.3.tar.gz
- Upload date:
- Size: 165.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee94b0ef0a2e3fb9391f039d116e3ccfcf3c9e6db1cf5b1a2369c83449a5058a
|
|
| MD5 |
f4a0ae6a10a1b09f1c8d02688d41c011
|
|
| BLAKE2b-256 |
181dc1e66598c30b2bee0250b99306f46c4bbf5017161d542329c94300fee7a6
|
Provenance
The following attestation bundles were made for orbits_codebase-0.1.3.tar.gz:
Publisher:
publish.yml on Yumekaz/Orbits
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
orbits_codebase-0.1.3.tar.gz -
Subject digest:
ee94b0ef0a2e3fb9391f039d116e3ccfcf3c9e6db1cf5b1a2369c83449a5058a - Sigstore transparency entry: 1402882413
- Sigstore integration time:
-
Permalink:
Yumekaz/Orbits@9e0125e3ef2e22139314e250ca0c39aba2a4952a -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/Yumekaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9e0125e3ef2e22139314e250ca0c39aba2a4952a -
Trigger Event:
release
-
Statement type:
File details
Details for the file orbits_codebase-0.1.3-py3-none-any.whl.
File metadata
- Download URL: orbits_codebase-0.1.3-py3-none-any.whl
- Upload date:
- Size: 153.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fea3154eef952f16ad4ef229e7402db1d01fab0bc6c314102aa1f1c45006e8cb
|
|
| MD5 |
13caa5f9d3250c591870526fcf21e5e8
|
|
| BLAKE2b-256 |
5957b34694d5c57a84b2a6cf5812bbb7e9f425da6845bc105aa99d4813f0b435
|
Provenance
The following attestation bundles were made for orbits_codebase-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on Yumekaz/Orbits
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
orbits_codebase-0.1.3-py3-none-any.whl -
Subject digest:
fea3154eef952f16ad4ef229e7402db1d01fab0bc6c314102aa1f1c45006e8cb - Sigstore transparency entry: 1402882475
- Sigstore integration time:
-
Permalink:
Yumekaz/Orbits@9e0125e3ef2e22139314e250ca0c39aba2a4952a -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/Yumekaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9e0125e3ef2e22139314e250ca0c39aba2a4952a -
Trigger Event:
release
-
Statement type: