npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@derived-modular/cli

v1.2.2

Published

Derived Modular Architecture checker and doctor CLI

Downloads

858

Readme

@derived-modular/cli

CLI and analyzer for Derived Modular Architecture (DMA) — hard boundary checks for CI, plus soft evolution signals for local use.

Architecture: DMA spec.

Zero-config for a single app root:

src/
├── app/        # composition root (DMA)
├── pages/      # also composition root (Astro / Next pages / …)
├── routes/     # also composition root (TanStack / SvelteKit / …)
├── features/
├── services/   # optional until the first promotion
└── shared/

Any of app/, pages/, and routes/ under src/ is a composition root (same layer rules as DMA app/): may mount modules; does not promote features. Keep route files as thin shells over */public/*.

Install

npm install -D @derived-modular/cli

Requires Node.js >=18.

npx @derived-modular/cli init
npx @derived-modular/cli check
npx @derived-modular/cli doctor
npx @derived-modular/cli promote features/cart --apply

Commands

npx @derived-modular/cli init [path]           # scaffold dirs/config/AGENTS (strict skip)
npx @derived-modular/cli check [path]          # hard rules (fails CI on errors)
npx @derived-modular/cli check --suggest       # print safe fix plan (no writes)
npx @derived-modular/cli check --fix          # apply safe fixes, then re-check
npx @derived-modular/cli doctor [path]         # evolution signals (exit 0 by default)
npx @derived-modular/cli doctor --suggest|--fix  # orphan-public delete plan / apply
npx @derived-modular/cli promote <module> [path] [--apply]  # feature → services (dry-run default)
npx @derived-modular/cli check --format json
npx @derived-modular/cli doctor --format sarif
npx @derived-modular/cli check .               # multi-root if path has no src/
npx @derived-modular/cli check --roots apps/web,apps/admin
npx @derived-modular/cli check . --include-packages
npx @derived-modular/cli check --config ./dma.config.ts

init

Bootstraps a single package: missing src/ layout (app unless pages/routes exist, plus features/shared), create-if-missing dma.config.ts, optional scripts.dma, append-only AGENTS.md DMA block. Never overwrites existing files. Does not wire linters (prints install hints). In a monorepo, run inside the app package. See docs: tooling → dma init.

promote

Moves a folder feature (features/<name>/ with public/) to services/<name>/ and rewrites imports that resolve into that module. Dry-run by default; --apply writes, then re-runs check and rolls back if new errors appear. Stage-0 file modules are rejected. See docs: tooling → dma promote.

--suggest / --fix (check & doctor)

Safe mechanical remediations only (single project root):

| Command | What it can change | | --- | --- | | check --suggest\|--fix | no-barrel importer → unique public path; public-api deep import → existing mirrored public/<rel> | | doctor --suggest\|--fix | delete orphan-public files with no importers at all |

--suggest prints the plan; --fix writes then re-runs the command. Mutually exclusive. Does not create public files, delete barrels, or run promote.

Invoke only via the package name — do not rely on a short global binary.

path defaults to the current working directory. If path contains the configured source root (default src/), that single tree is analyzed. If not, the CLI discovers DMA app packages (workspaces first, directory walk fallback). Use --roots or dma.config roots for an explicit list; --include-packages / config includePackages also includes library packages with layer dirs but no composition root.

Optional project config: dma.config.ts | .mts | .mjs | .js | .json (upward lookup). Fields: srcRoot, compositionRoots, roots, includePackages, thresholds. See docs: tooling → dma.config. Helper: defineConfig from @derived-modular/cli.

Exit codes

| Code | Meaning | | --- | --- | | 0 | OK — check found no errors; doctor / init / dry-run promote return 0 unless the tool itself fails | | 1 | check found architectural errors | | 2 | Environment failure (missing src/ for check/doctor, unreadable tree, invalid tsconfig, bad args, promote preflight/rollback) |

Output formats

  • human (default) — colored TTY diagnostics + summary
  • json — stable version: 1 report for CI/agents
  • sarif — GitHub Code Scanning–friendly SARIF 2.1.0

Disable ANSI colors with NO_COLOR=1.

Linter companions

File-scoped rules in the editor / lint script — not a full substitute for npx @derived-modular/cli check:

| Package | Notes | | --- | --- | | @derived-modular/eslint-plugin | Recommended for ESLint flat config | | @derived-modular/oxlint-plugin | Same rules via Oxlint JS plugins (alpha) | | @derived-modular/biome-plugin | Best-effort GritQL heuristics |

Graph rules (no-cycle, inbound predicates) and doctor signals exist only here.

What check enforces

| Rule | Meaning | | --- | --- | | layer-direction | Imports only downward: app → features → services → shared | | feature-to-feature | Features must not import other features — tip suggests dma promote on the imported module | | public-api | Cross-module imports must hit */public/* (stage-0 file modules are entirely public) | | no-barrel | No barrel index re-export surfaces inside modules | | no-cycle | No cycles in the module graph | | feature-has-inbound | A feature with inbound module edges must live in services/ — tip: dma promote <name> | | service-no-inbound | A service without inbound module edges violates its predicate |

Inbound edges are counted from other modules only (features/*, services/*). Mounts from composition roots (app/, pages/, routes/) do not promote a feature.

What doctor reports

| Signal | Meaning | | --- | --- | | shared-candidate | A module file is imported by 2+ other modules — on a feature, help suggests dma promote | | stage-growth | Module structure lags measured size — help points at folder/public/ or ui/model/api colocation | | dense-services | services subgraph looks dense/deep enough to suggest a split | | orphan-public | A public/ file has no external importers |

doctor does not re-emit hard check rule IDs. Placement wording follows the algorithm in the docs site (concepts/placement); no URLs are printed.

Supported sources

  • Scripts: .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts
  • UI: .vue, .svelte, .astro
  • Docs components: .md, .mdx
  • Edges include static import / export … from, import type, dynamic import(), and require() (covers next/dynamic / React.lazy targets)

Path aliases are loaded from tsconfig.json (comments / trailing commas supported; one-level extends when local paths are empty).

Path classification is shared with @derived-modular/boundaries.

Programmatic API

import { analyze, DEFAULT_THRESHOLDS } from "@derived-modular/cli";

const { diagnostics, srcRoot } = analyze(process.cwd(), "check");

The core never writes to stdout/stderr or calls process.exit — that stays in the CLI.

Local development (this monorepo)

# from repo root
npx @derived-modular/cli check packages/cli/tests/fixtures/clean
bun run dma:build
node packages/cli/dist/cli.js check .
cd packages/cli
bun test
bun run build

Out of scope

Autofix/codemods beyond promote / check --fix / ESLint no-barrel, LSP, domains/* layout, cross-package graph merge, watch mode. Biome does not read dma.config yet.

License

MIT