Migration Guide
Migration Guide
Section titled “Migration Guide”This guide helps you migrate from other architecture analysis tools to Arxo, with side-by-side comparisons and practical examples.
Why Migrate to Arxo?
Section titled “Why Migrate to Arxo?”- Multi-language support - TypeScript, JavaScript, Python, Rust, Java, Kotlin, Go
- 50+ metrics - Beyond cycle detection: coupling, centrality, hotspots, evolution
- Policy enforcement - Define and enforce architectural rules in CI
- Built-in presets - Quick, CI, risk, security, AI/LLM analysis
- Performance - Written in Rust, optimized for large codebases
- Rich output - Console, JSON, HTML, SARIF, MessagePack formats
From Madge
Section titled “From Madge”Madge is popular for detecting circular dependencies in JavaScript/TypeScript projects.
Feature Comparison
Section titled “Feature Comparison”| Feature | Madge | Arxo |
|---|---|---|
| Cycle detection | ✅ Yes | ✅ Yes (SCC metric) |
| Dependency graph | ✅ Yes | ✅ Yes (import + call graphs) |
| Visualization | ✅ Graphviz | ✅ HTML interactive |
| Orphan detection | ✅ Yes | ⚠️ Partial (use centrality tables / graph views) |
| Policy enforcement | ❌ No | ✅ Yes |
| Multi-language | ❌ No | ✅ Yes (7 languages) |
| Performance metrics | ❌ No | ✅ Yes (50+ metrics) |
| CI/CD integration | ⚠️ Manual | ✅ Built-in |
Migration Steps
Section titled “Migration Steps”1. Basic Cycle Detection
Section titled “1. Basic Cycle Detection”Madge:
madge --circular src/Arxo:
arxo analyze --metric scc2. Generate Dependency Graph
Section titled “2. Generate Dependency Graph”Madge:
madge --image graph.png src/Arxo:
arxo analyze --format html --output report.html# Open report.html for interactive graph3. Find Orphan-Like Modules
Section titled “3. Find Orphan-Like Modules”Madge:
madge --orphans src/Arxo (closest equivalent):
arxo analyze --metric centrality --format html --output report.html# In the centrality module table, inspect modules with fan_in = 04. Exclude Directories
Section titled “4. Exclude Directories”Madge:
madge --circular --exclude '^(node_modules|test)' src/Arxo (.arxo.yaml):
data: import_graph: exclude: - "**/node_modules/**" - "**/test/**" - "**/*.test.ts"Then run:
arxo analyze --metric scc5. Custom Extensions
Section titled “5. Custom Extensions”Madge:
madge --circular --extensions ts,tsx src/Arxo (auto-detects all TypeScript files):
arxo analyze --metric scc6. CI Integration
Section titled “6. CI Integration”Madge (manual exit code check):
#!/bin/bashif madge --circular src/ | grep -q "Circular"; then echo "Cycles detected!" exit 1fiArxo (built-in CI preset):
arxo analyze --preset ci --fail-fastConfiguration Migration
Section titled “Configuration Migration”If you have a madge.json:
{ "detectiveOptions": { "ts": { "skipTypeImports": true } }, "fileExtensions": ["ts", "tsx"], "excludeRegExp": ["node_modules", "test"]}Equivalent .arxo.yaml:
data: import_graph: exclude: - "**/node_modules/**" - "**/test/**" languages: - typescript
metrics: - id: scc
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 0 message: "No circular dependencies allowed"From dependency-cruiser
Section titled “From dependency-cruiser”dependency-cruiser is a comprehensive dependency validation tool for JavaScript/TypeScript.
Feature Comparison
Section titled “Feature Comparison”| Feature | dependency-cruiser | Arxo |
|---|---|---|
| Dependency rules | ✅ Yes | ✅ Yes (policy invariants) |
| Cycle detection | ✅ Yes | ✅ Yes |
| Path validation | ✅ Yes | ✅ Yes (layer violations) |
| TypeScript support | ✅ Yes | ✅ Yes |
| Workspace support | ✅ Yes | ✅ Yes (monorepo) |
| Multi-language | ❌ No | ✅ Yes |
| Evolution metrics | ❌ No | ✅ Yes (git-based) |
| Performance | ⚠️ Slow on large repos | ✅ Fast (Rust) |
Migration Steps
Section titled “Migration Steps”1. Basic Validation
Section titled “1. Basic Validation”dependency-cruiser:
depcruise --validate .dependency-cruiser.js srcArxo:
arxo analyze --preset ci2. Cycle Detection
Section titled “2. Cycle Detection”dependency-cruiser (.dependency-cruiser.js):
module.exports = { forbidden: [ { name: 'no-circular', severity: 'error', from: {}, to: { circular: true } } ]};Arxo (.arxo.yaml):
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 0 message: "No circular dependencies allowed"3. Layer Enforcement
Section titled “3. Layer Enforcement”dependency-cruiser:
module.exports = { forbidden: [ { name: 'no-ui-to-data', from: { path: '^src/ui' }, to: { path: '^src/data' } } ]};Arxo (.arxo.yaml):
architecture: layers: - name: ui paths: ["src/ui/**"] allowed_effects: [] can_depend_on: ["services"]
- name: services paths: ["src/services/**"] allowed_effects: [] can_depend_on: ["data"]
- name: data paths: ["src/data/**"] allowed_effects: [] can_depend_on: []
metrics: - id: layer_violations
policy: invariants: - metric: layer_violations.violations_count op: "==" value: 0 message: "Layer violations detected"4. Monorepo Boundaries
Section titled “4. Monorepo Boundaries”dependency-cruiser:
module.exports = { forbidden: [ { name: 'no-inter-app', from: { path: '^apps/app1' }, to: { path: '^apps/app2' } } ]};Arxo (.arxo.yaml):
data: import_graph: group_by: folder group_depth: 2 # apps/app-name
policy: invariants: - metric: smells.cycles.count op: "==" value: 0 message: "Apps should not depend on each other"5. External Dependencies
Section titled “5. External Dependencies”dependency-cruiser:
module.exports = { forbidden: [ { name: 'no-deprecated', to: { dependencyTypes: ['deprecated'] } } ]};Arxo (uses OSV integration):
metrics: - id: security
policy: invariants: - metric: security.vulnerability_count op: "==" value: 0 message: "No known vulnerabilities allowed"Rule Migration Reference
Section titled “Rule Migration Reference”| dependency-cruiser rule | Arxo equivalent |
|---|---|
circular: true | scc.max_cycle_size == 0 |
path restrictions | layer_violations metric |
dependencyTypes: ['deprecated'] | security metric |
orphan: true | No direct invariant; inspect centrality.module.nodes_table (fan_in == 0) |
reachable: false | runtime_drift metric (dead code) |
From eslint-plugin-import
Section titled “From eslint-plugin-import”eslint-plugin-import catches import issues in JavaScript/TypeScript.
Feature Comparison
Section titled “Feature Comparison”| Feature | eslint-plugin-import | Arxo |
|---|---|---|
| No unresolved imports | ✅ Yes | ✅ Yes (parsing) |
| No cycles | ✅ Yes | ✅ Yes (SCC) |
| Import order | ✅ Yes | ❌ No (use prettier) |
| Path validation | ⚠️ Limited | ✅ Yes (layers) |
| Multi-file analysis | ⚠️ Slow | ✅ Fast |
| Architecture metrics | ❌ No | ✅ Yes |
Migration Steps
Section titled “Migration Steps”1. No Unresolved Imports
Section titled “1. No Unresolved Imports”ESLint:
{ "rules": { "import/no-unresolved": "error" }}Arxo (automatic):
arxo analyze# Parsing errors shown automatically2. No Circular Dependencies
Section titled “2. No Circular Dependencies”ESLint:
{ "rules": { "import/no-cycle": "error" }}Arxo:
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 03. No Restricted Paths
Section titled “3. No Restricted Paths”ESLint:
{ "rules": { "import/no-restricted-paths": ["error", { "zones": [ { "target": "./src/ui", "from": "./src/data" } ] }] }}Arxo:
architecture: layers: - name: ui paths: ["src/ui/**"] allowed_effects: [] can_depend_on: ["services"]
- name: services paths: ["src/services/**"] allowed_effects: [] can_depend_on: ["data"]
- name: data paths: ["src/data/**"] allowed_effects: [] can_depend_on: []
metrics: - id: layer_violations
policy: invariants: - metric: layer_violations.violations_count op: "==" value: 0From Other Tools
Section titled “From Other Tools”Architecture Decision Records (ADRs)
Section titled “Architecture Decision Records (ADRs)”If you use ADRs for documenting architecture, Arxo policies can enforce those decisions:
ADR: “We decided to keep services decoupled (propagation cost < 0.15)”
Arxo:
policy: invariants: - metric: propagation_cost.system.ratio op: "<=" value: 0.15 message: "Services should be loosely coupled (ADR-001)"Nx Enforce Module Boundaries
Section titled “Nx Enforce Module Boundaries”If you use Nx @nrwl/nx/enforce-module-boundaries:
Nx (.eslintrc.json):
{ "rules": { "@nrwl/nx/enforce-module-boundaries": ["error", { "depConstraints": [ { "sourceTag": "scope:app1", "onlyDependOnLibsWithTags": ["scope:shared"] } ] }] }}Arxo (.arxo.yaml):
data: import_graph: group_by: folder group_depth: 2
metrics: - id: monorepo
policy: invariants: - metric: monorepo.policy.edge_violations_count op: "==" value: 0General Migration Strategy
Section titled “General Migration Strategy”Step 1: Audit Current Setup
Section titled “Step 1: Audit Current Setup”Document what your current tool checks:
# Example: List all madge/depcruise rulesgrep -r "circular\|orphan\|forbidden" .Step 2: Run Initial Arxo Analysis
Section titled “Step 2: Run Initial Arxo Analysis”arxo initarxo analyze --preset quickReview the output to understand your architecture’s current state.
Step 3: Define Policies
Section titled “Step 3: Define Policies”Start with loose policies, then tighten:
# Week 1: Baselinepolicy: invariants: - metric: scc.max_cycle_size op: "<=" value: 10 # Allow small cycles initially
# Week 4: Tightenpolicy: invariants: - metric: scc.max_cycle_size op: "==" value: 0 # Zero cyclesStep 4: Integrate into CI
Section titled “Step 4: Integrate into CI”- name: Run Architecture Analysis run: arxo analyze --preset ci --fail-fastStep 5: Deprecate Old Tool
Section titled “Step 5: Deprecate Old Tool”Once Arxo is stable in CI:
- Remove old tool from
package.json - Delete old config files (
.dependency-cruiser.js, etc.) - Update documentation
Side-by-Side Workflows
Section titled “Side-by-Side Workflows”Detect and Fix Cycles
Section titled “Detect and Fix Cycles”| Task | Madge | Arxo |
|---|---|---|
| Find cycles | madge --circular src/ | arxo analyze --metric scc |
| Get details | madge --circular --json src/ | arxo analyze --format json |
| Visualize | madge --image graph.png src/ | arxo analyze --format html |
| Fix guidance | ❌ Manual | ✅ Breaking Cycles Guide |
CI Integration
Section titled “CI Integration”| Task | dependency-cruiser | Arxo |
|---|---|---|
| Run check | depcruise --validate | arxo analyze --preset ci |
| Fail on error | Exit code 1 | --fail-fast |
| Cache results | ❌ Manual | ✅ Built-in |
| Generate report | --output-type html | --format html |
Configuration Comparison
Section titled “Configuration Comparison”Madge → Arxo
Section titled “Madge → Arxo”madge.json:
{ "exclude": "node_modules|test", "circular": true, "detectiveOptions": { "ts": { "skipTypeImports": true } }}arxo.yaml:
data: import_graph: exclude: - "**/node_modules/**" - "**/test/**"
metrics: - id: scc
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 0dependency-cruiser → Arxo
Section titled “dependency-cruiser → Arxo”.dependency-cruiser.js:
module.exports = { forbidden: [ { name: 'no-circular', to: { circular: true } }, { name: 'no-orphans', from: { orphan: true } } ], options: { exclude: 'node_modules' }};arxo.yaml:
data: import_graph: exclude: - "**/node_modules/**"
metrics: - id: scc - id: centrality
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 0Then review centrality.module.nodes_table and check modules with fan_in = 0 for orphan-like patterns.
Flow Analysis Key Migration (v1 -> v2)
Section titled “Flow Analysis Key Migration (v1 -> v2)”If you previously used flat flow_analysis.* keys, migrate to domain-scoped keys:
| v1 key | v2 key |
|---|---|
flow_analysis.nodes | flow_analysis.graph.node_count |
flow_analysis.links | flow_analysis.graph.edge_count |
flow_analysis.total_flow | flow_analysis.graph.total_weight |
flow_analysis.avg_degree | flow_analysis.graph.avg_out_weight |
flow_analysis.max_fan_in | flow_analysis.graph.max_fan_in_weight |
flow_analysis.max_fan_out | flow_analysis.graph.max_fan_out_weight |
flow_analysis.gini_fan_in | flow_analysis.graph.gini_fan_in |
flow_analysis.gini_fan_out | flow_analysis.graph.gini_fan_out |
flow_analysis.density | flow_analysis.graph.density |
Flow Analysis now also includes dedicated domains:
flow_analysis.bow_tie.*flow_analysis.bottleneck.*flow_analysis.logical.*flow_analysis.runtime.*
See Flow Analysis for the full key contract and profile behavior.
Performance Comparison
Section titled “Performance Comparison”Based on a typical TypeScript monorepo (500 files, 3 apps):
| Tool | Initial Run | Cached Run | Memory |
|---|---|---|---|
| madge | ~8s | ~8s (no cache) | 150MB |
| dependency-cruiser | ~25s | ~20s | 300MB |
| Arxo | ~3s | ~0.5s | 80MB |
Arxo is faster due to:
- Rust implementation
- Parallel metric computation
- Incremental analysis cache
- Optimized graph algorithms
Migration Checklist
Section titled “Migration Checklist”- Install Arxo (pre-built binary from Releases or Installation)
- Create config:
arxo init - Run initial analysis:
arxo analyze --preset quick - Review current architecture state
- Define policies in
.arxo.yaml - Add to CI pipeline
- Test CI integration on a branch
- Document policies for team
- Remove old tool from
package.json - Delete old config files
- Update team documentation
Troubleshooting
Section titled “Troubleshooting””More violations than my old tool”
Section titled “”More violations than my old tool””Cause: Arxo is more comprehensive. Old tools may have missed issues.
Solution: Start with loose policies, review each violation, tighten gradually.
”Different cycle count”
Section titled “”Different cycle count””Cause: Grouping strategy. File-level vs folder-level grouping affects counts.
Solution: Adjust group_by and group_depth:
data: import_graph: group_by: file # or folder group_depth: 2“Old tool was faster”
Section titled ““Old tool was faster””Cause: Running too many metrics.
Solution: Use presets or limit metrics:
arxo analyze --quick # Fast checkarxo analyze --metric scc # Just cyclesGetting Help
Section titled “Getting Help”- Configuration Guide - Full config reference
- Policy Examples - Real-world policies
- Breaking Cycles - Fix circular dependencies
- CI Integration - Set up pipelines
- Troubleshooting - Common issues
Next Steps
Section titled “Next Steps”After migrating, explore advanced features:
- Evolution metrics - Track code churn with
--metric msr - Coupling analysis - Find tight coupling with
--preset coupling - Refactoring suggestions - Get automated suggestions with
--metric refactoring_recommendations - Baseline tracking - Compare against main with
--baseline origin/main - AI analysis - Check LLM integration health with
--preset ai