monoripple
monoripple finds JavaScript and TypeScript applications affected by a change at symbol precision. It uses Oxc for parsing and semantic binding analysis instead of treating every declared package dependency as a runtime dependency.
Features
- JavaScript, JSX, TypeScript, and TSX
- npm-compatible workspace package manifests and package exports
- named, default, namespace, and re-exported bindings
- static namespace-member narrowing
- separate runtime and type dependency graphs
- base/current graph union for deletions, renames, and removed exports
- deploy and typecheck affected queries
- runtime module and workspace package cycle detection
- structured diagnostics with warning policies
- local content-addressed parse cache
- external target-discovery plugins
- dependency-path explanations
Install
Usage
By default monoripple reports packages with a deploy script. Use --target <script> to select another package script, or --target all to include every package with an inferred entrypoint.
Task runners
Run a Turbo or Vite+ task only for affected packages:
auto selects Vite+ when the root package declares vite-plus or contains node_modules/.bin/vp; otherwise it uses Turbo through the detected package manager. Use --runner to override this with vite-plus, pnpm, npx, bun, yarn, or a direct turbo binary. Use --print to inspect the command without executing it, and repeat --runner-arg for task-runner options:
The wrapper exits successfully without invoking a runner when no packages are affected. For shell composition, both output formats emit repeated pnpm-style filter arguments:
When the affected set is empty, the composed form emits an impossible package filter instead of running every package. Turbo fails safely; Vite+ warns and exits successfully without running a task.
graph serves an interactive dependency-graph visualization over http://127.0.0.1 and opens it in your browser:
Use --port to pin a port (default picks a free one), --no-open to skip launching the browser, and --output file.html to also save the page. The default affected scope shows the symbol-level subgraph from changed declarations to deployment targets; all shows the whole repository at module granularity. Changed nodes, affected nodes, and targets are color-coded. Selecting a node highlights its reason path and lists the ordered “why it deploys” chain, including manifest changes on directly affected packages. When targets add the same workspace dependency, the view adds shared export nodes and shows exactly which runtime and type exports each target uses. The panel also lists affected targets so you can jump straight to any deployment reason.
why --ui opens an interactive terminal dependency-path viewer. Use arrow keys or j/k to navigate and q or Escape to exit. Directly affected packages list the exact changed build inputs in both text and UI modes.
Warnings can be hidden or promoted to errors:
The local cache defaults to $XDG_CACHE_HOME/monoripple or ~/.cache/monoripple. Disable it with --no-cache, inspect it with --cache-report, or override it with MONORIPPLE_CACHE_DIR.
Plugins
A repository may configure explicit external plugins in monoripple.json:
monoripple sends a versioned JSON request on stdin. Plugins return target roots and optional diagnostics:
Plugins are never auto-loaded from dependencies. A plugin failure is a graph error.
How it works
monoripple creates declaration nodes for each module using oxc_semantic. References inside a declaration become edges to the exact local or imported symbols they consume. Runtime and type-only edges are retained separately. Package exports and re-exports link those symbols across files.
Affected traversal reverses the dependency graph:
changed declaration
-> local consumer
-> imported binding
-> application target
The base and current graphs are combined before traversal so removed declarations retain their previous consumer edges. Cycles terminate through visited sets and are reported as strongly connected components rather than rejected by default.
Current boundaries
- external dependency and lockfile changes are diagnosed but not yet linked to exact consumers
- virtual and generated entrypoints need explicit plugin roots for complete precision
- Rust source changes affect their owning target, but Cargo dependency graphs are not yet modeled
- non-literal dynamic imports are diagnosed and should be promoted to errors for deployment planning
- deploy queries model source/configuration reachability, not final artifact hashes