microsoft/rushstack
github.com/microsoft/rushstack ↗ · 3998 files · 21.6 MB · scan capped
https://rushstack.io/ The home for projects maintained by the Rush Stack community.
Overview
RushStack is a TypeScript monorepo of reusable developer tools for large JavaScript and TypeScript workspaces. Its inspected core combines Rush’s cross-project orchestration, Heft’s configurable task execution, API Extractor’s declaration analysis, and API Documenter’s documentation generation. It also includes dependency-inspection interfaces, opt-in daemon clients, MCP tooling, and a Playwright browser tunnel, with shared libraries and configuration rigs connecting these products.
System map
The repository packages several developer tools around shared command-line, filesystem, build, and configuration infrastructure. Rush owns cross-project orchestration, while Heft supplies configurable execution within projects. API analysis, documentation, browser interfaces, daemon IPC, and MCP each have separate runtime boundaries. The inspected manifests and CI define package builds and integration checks; this map is bounded rather than exhaustive.
- README describes reusable tooling for large TypeScript monorepos and identifies Rush, Heft, API Extractor, API Documenter, and Lockfile Explorer as distinct products.
- rush.json pins Rush 5.179.0 and PNPM 10.27.0, specifies supported Node ranges, and constrains project folders to exactly two levels.
- Rush’s executable checks Node compatibility, discovers MinimalRushConfiguration, selects RUSH_PREVIEW_VERSION or the repository’s Rush version, and passes launch options to launchRushFrontendAsync.
- Heft initializes project configuration and InternalHeftSession before registering clean, run, per-phase, watch, and alias actions; its package exposes both CommonJS and ESM library outputs.
- API Extractor exposes a CLI and library API with rollup declarations; API Documenter consumes its JSON models through a separate CLI and library package.
- Lockfile Explorer runs Express on port 8091 and serves a packaged React application; its Heft build copies frontend assets and shared graph declarations/JavaScript from the private web package.
- Daemon transport uses POSIX sockets and PID JSON records under /tmp/rushd-<uid> or an absolute RUSHD_RUNTIME_DIR override; Windows uses named pipes and temporary-directory lockfiles.
- Packages commonly build/test through Heft and pack through rush-pnpm; CI installs dependencies, runs production retest, checks package-manager integration, and exercises source-built Rush against a second checkout.
Feature catalog
The inspected user-facing surface is primarily command-line tooling, supplemented by React interfaces and integration APIs. Rush supports workspace maintenance and phased builds; Heft exposes project tasks and watch variants. API tools produce review, declaration, and documentation artifacts, while Lockfile Explorer supports dependency investigation and policy checks. Ancillary utilities and integrations are represented here without claiming an exhaustive catalog of every published package.
- Rush registers workspace actions including add/remove, install/update, link/unlink, change/check, publish/deploy, purge, scan, setup, version, autoinstaller management, and interactive upgrades.
- This repository defines build, incremental test, non-incremental retest, always-watching start, and pack commands; start initially builds and subsequently runs build/test phases for affected projects.
- Heft generates actions for configured phases and their watch variants, plus clean/run and aliases with default parameters; aliases cannot collide with existing actions or reference undefined targets.
- API Extractor offers init/run and produces API reports, doc models, and public/alpha/beta/internal declaration rollups; Documenter registers markdown, yaml, and generate actions.
- Lockfile Explorer displays dependency entries, package JSON, selected-entry details, and bookmarks, with back/forward selection history; lockfile-lint separately registers init/check for dependency policies.
- rush-client and rushx-client are opt-in daemon frontends; routing preserves in-process execution for help, --no-daemon, native reporter requests, terminal-based rushx scripts, and CI without explicit RUSH_DAEMON=1.
- Rush MCP registers conflict resolution, project migration, command validation, and workspace/project details tools; PlaywrightTunnel supports polling or incoming connections and launches headed Chromium, Firefox, or WebKit servers.
- Additional inspected surfaces include V8 CPU-profile analytics, require() load-regression reporting, VS Code Project Details/Versions tabs, and Webpack localization-aware asynchronous chunk URL handling.
Data flow
Configuration and filesystem inputs feed most tool flows, with CLI arguments determining selection and execution mode. API analysis transforms TypeScript declarations into structured models and generated files. Lockfile Explorer transfers a serialized dependency graph over HTTP into Redux, while bookmarks persist independently in browser storage. Daemon state combines workspace fingerprints with separately owned transport files and connection lifetimes.
- ExtractorConfig loads an extends chain, resolves relative or package-based references, normalizes file-relative paths before merging, applies defaults, and schema-validates the merged configuration.
- Extractor.invoke obtains CompilerState, sends its TypeScript program into Collector, then runs Collector.analyze, DocCommentEnhancer, ValidationEnhancer, and ApiModelGenerator before writing enabled outputs.
- API reports first persist to reportTempFolder, then compare against reportFolder; changed expected reports are rewritten during local builds, whereas production builds emit warnings instead.
- Documenter’s BaseAction loads matching .api.json files into ApiModel and applies inheritDoc resolution; MarkdownDocumenter emits TSDoc-derived text, lets a plugin alter pageContent, and writes files with configured line endings.
- GET /api/graph reads PNPM YAML, generates LfxGraph, and serializes JSON; readLockfileAsync fetches that endpoint, deserializes the graph, and returns entries for App’s loadEntries dispatch.
- lfxGraphLoader normalizes version-dependent dependency IDs, distinguishes regular/dev/peer dependencies, records transitive peers, and omits Rush’s synthetic '.' importer from workspace project entries.
- Redux owns entry filters and navigation stacks; bookmark mutations synchronously write rawEntryId keys under LOCKFILE_EXPLORER_BOOKMARKS, and loadEntries hydrates matching IDs from that storage.
- WorkspaceRequestLifecycle captures startup environment and workspace/runtime fingerprints in memory; DaemonFrameListener separately binds a socket, records PID/protocol/start-time metadata, and pins file identities for its lifetime owner.
Behavior traces
Source inspection followed API extraction, Markdown documentation generation, and Lockfile Explorer loading and bookmark persistence across their participating files. Additional traces expose Rush graph construction, Heft startup, build-cache lookup, and pnpmfile execution. These are execution-order descriptions derived from code, not runtime observations. Conditional branches materially change warnings, filesystem writes, process reuse, and lifecycle handling.
- API extraction startup constructs ApiExtractorCommandLine, registers InitAction/RunAction, and executes the parser; RunAction.onExecuteAsync loads an explicit config or discovers one from '.', then calls Extractor.invoke.
- Inside Extractor.invoke, Collector.analyze → DocCommentEnhancer.analyze → ValidationEnhancer.analyze → buildApiPackage precedes model/report/rollup output; success ignores warnings locally but includes them in production failure.
- Markdown CLI startup executes ApiDocumenterCommandLine → MarkdownAction.onExecuteAsync → buildApiModel → MarkdownDocumenter.generateFiles; generation optionally initializes a plugin, deletes old output, writes the model page, and invokes onFinished.
- Explorer startup constructs ExplorerCommandLineParser → onExecuteAsync → init before changing cwd; it registers static/API handlers and listens, while React App invokes readLockfileAsync → fetch /api/graph → deserializeFromJson → dispatch(loadEntries).
- Bookmark persistence follows addBookmark → saveBookmarkToLocalStorage → JSON parse/update/stringify/setItem; subsequent loadEntries reads stored IDs and attaches matching graph entries, while removeBookmark removes both Redux and stored entries.
- Rush phased execution applies graph/sharding/shell/validation plugins, fires session hooks, calls createOperationsAsync, captures input snapshots, constructs OperationGraph, fires onGraphCreatedAsync, then executes; watch mode creates ProjectWatcher and waits for abort.
- Heft startup constructs its parser; executeAsync normalizes cwd, initializes InternalHeftSession, registers phase/watch actions and validated aliases, and delegates argument execution to the shared parser.
- Cache lookup rejects missing IDs or disabled caching, queries the local provider, returns immediately for a matching output receipt, and queries cloud storage only on local miss; Explorer’s package-spec path loads JSON, invokes an optional pnpmfile worker, and disposes it in finally.
Testing signals
Tests and CI were inspected, not executed; test existence establishes neither passing results nor measured coverage. The inspected suite combines Jest tests over compiled JavaScript, snapshots, temporary-workspace subprocess fixtures, and Playwright demonstrations. CI specifies Linux/Windows and multiple Node versions, including cross-checkout cache exercises. Coverage observations are limited to the inspected files, and the inventory does not establish whole-repository coverage or absence.
- Shared Heft Jest configuration uses Node, clears mocks, matches compiled .test.js/.test.cjs files, and disables coverage collection by default; rush-lib overrides roots/testMatch to lib-intermediate-commonjs.
- ExtractorConfig-lookup tests verify <lookup> project-folder discovery for root, config/, and nested configuration locations; these cases test configuration resolution rather than complete extraction output.
- CustomMarkdownEmitter tests construct TSDoc headings, emphasis, links, and whitespace cases, then snapshot emitted text; that inspected test does not exercise MarkdownDocumenter’s output-folder deletion.
- Lockfile graph tests snapshot a PNPM v9 edge-case fixture; PnpmfileRunner tests assert transformed dependencies, forwarded logs, disposal, and rejection of calls after disposal.
- Heft CLI tests create temporary plugin/config fixtures and spawn the compiled executable; assertions cover task failure with zero/negative/positive prior exit codes, successful tasks, and alias-name collisions.
- Public-client IPC boundary tests cover changed direct/inherited/rig descriptors, generation changes and child replacement, native NoOp/missing-script/empty-selection behavior, preassigned shard runners, and --no-ipc.
- CI specifies Node 20/22/24/26 on Linux and Node 24/26 on Windows, production retest, package-manager integration tests, and repeated source-built test commands in a second checkout sharing the build cache; these steps were not run here.
- Browser-tunnel Playwright configuration selects five browser/channel projects, one worker, zero retries, and tracing; the inspected demo only navigates to about:blank and checks its URL, providing no assertion of launch-option rejection.
Risk map
These are source observations and explicitly labeled hypotheses, not confirmed vulnerabilities. Sensitive boundaries include generated-output deletion, request-derived filesystem access, installed-code execution, browser launch/install behavior, and daemon ownership. Native and hosted execution share orchestration code but differ in lifecycle capabilities. The reviewed sources also reveal dependency coupling that merits focused regression checks when changed.
- Documenter accepts an arbitrary --output-folder and MarkdownDocumenter.generateFiles calls ensureEmptyFolder on it before writing pages; a wrongly selected output path therefore has a concrete deletion blast radius.
- Explorer installs unrestricted cors() and calls app.listen(PORT) without a host argument; its registered graph and file-reading routes contain no authentication checks in the inspected parser.
- Hypothesis: Explorer’s package-json/package-spec endpoints may permit reads outside projectRoot through traversal because they interpolate request.body.projectPath without a containment check in these handlers; exploitability was not tested. (inferred)
- Explorer’s pnpmfile worker uses require(resolvedPath) and invokes hooks.readPackage; Documenter similarly requires resolved plugin entrypoints. Both execute workspace/installed JavaScript rather than merely parsing configuration.
- Daemon startup protects its POSIX runtime boundary by creating mode-0700 directories, verifying ownership and non-symlink identity, and checking socket-path length before binding; listener ownership is checked before socket/lockfile publication.
- Browser tunneling filters launch options through a per-user allowlist but also installs/imports handshake-selected Playwright versions; inspected handshake validation checks the version’s type, action, and browser name without semantic-version validation in that function.
- Webpack localization replaces GetChunkFilenameRuntimeModule.prototype.generate to capture chunk identity and relies on assetPath callback conventions; hypothesis: Webpack runtime changes or interactions with other prototype wrappers can affect this integration. (inferred)
- Native phased-command output closure stops new operations but lets started operations finish because native commands do not own their process groups; hosted-engine graph options separately enable termination support and alter runner closure.
Extension points
Extension mechanisms are explicit and operate at several layers: CLI commands, operation graphs, project tasks, generated documentation, and MCP tools. Configuration rigs supply reusable defaults, while public APIs support programmatic invocation. Hooks distinguish session registration from per-graph execution customization. Plugin mechanisms load executable code and therefore carry compatibility and trust requirements.
- Rush adds custom actions from CommandLineConfiguration.commands and plugin-supplied configurations; a plugin-provided build command suppresses automatic creation of the default build command.
- Rush session hooks runAnyPhasedCommand and runPhasedCommand[actionName] allow registration before createOperationsAsync receives the operation set and execution context.
- onGraphCreatedAsync exposes the constructed graph and initial snapshot; graph hooks can transform operation environments and observe request results, including native PATH augmentation and afterExecuteRequestAsync.
- Heft plugins implement apply(session, heftConfiguration, pluginOptions); task and lifecycle interfaces distinguish scope, and an optional accessor lets other plugins request access within the same phase.
- Heft configuration extends rig profiles and augments phasesByName/tasksByName with named task plugins, options, and dependencies; Explorer’s TypeScript task explicitly depends on pre-compile-copy.
- API Extractor supports loadConfigAndInvoke or invoke with prepared configuration; ExtractorConfig.prepare accepts runtime configuration objects, but requires extends expansion and an absolute configObjectFullPath when supplied.
- Documenter resolves config-listed plugin packages, requires apiDocumenterPluginManifest version 1000, selects named features, permits one MarkdownDocumenterFeature, and invokes initialization, pre-write, and finished callbacks.
- MCP loads schema-validated mcpPlugins from common/config/rush-mcp/rush-mcp.json, prepares their autoinstallers, reads rush-mcp-plugin.json manifests, and exposes registerTool with Zod schema shapes and bound executeAsync callbacks.
Contributor handoff
Begin at the owning package and follow its manifest, rig, source entrypoint, and relevant tests before widening scope. Shared Rush graph and daemon changes require attention to native execution, retained processes, ownership, and cancellation. Generated files and copied frontend/backend contracts introduce edit-order and build-order traps. Tests and CI were inspected, not executed; recommendations below identify existing checks for a separately authorized execution task.
- Use existing Heft build/test phase scripts for package validation and repository test/retest commands for broader integration when execution is authorized; this investigation inspected those scripts and CI without running them.
- Read rush.json before choosing tool versions or workspace layout: Rush and PNPM are pinned, Node ranges are constrained, and project folders must have depth two.
- For Rush lifecycle changes, read phased-commands.md together with PhasedScriptAction; operation creation precedes graph hooks, and watch sessions reuse graph objects rather than recreating operations each iteration.
- For API output changes, account for local versus production semantics: local builds can rewrite expected reports and tolerate warnings, while production warnings fail extraction; missing expected-report folders receive special handling.
- Edit Documenter’s generators and plugin callbacks rather than generated Markdown pages; emitted pages carry a generated-file notice, and every generation empties the configured output directory.
- For Explorer contract changes, read the web package alongside the backend: build/lfx-shared and dist are populated by copying frontend-package outputs, and TypeScript compilation depends on the shared-code copy task.
- Daemon dogfooding guidance requires a stable extracted client closure instead of mutable workspace outputs; preserve native fallback/routing behavior and consult descriptor-boundary tests when altering retained child reuse.
- Treat rushd-review-map.md as historical review context: it names an earlier frozen snapshot and explicitly requires additional review for later fixes, so it does not certify the inspected commit or bound its current risk.
Languages
| Language | Files | Share of source |
|---|---|---|
| TypeScript | 2804 | 87% |
| JSON | 1949 | docs/config |
| Markdown | 445 | docs/config |
| JavaScript | 362 | 11% |
| YAML | 68 | docs/config |
| Sass | 45 | 1% |
| CSS | 19 | docs/config |
| HTML | 10 | docs/config |
Start reading here
Probable source entrypoint: build-tests/ — inferred from the directory tree and manifest, not the upstream docs.
Source roots
build-tests/ (770 files) libraries/ (770 files) apps/ (703 files)
Source layout — apps/
| Path | Files |
|---|---|
apps/api-documenter/ | 55 |
apps/api-extractor/ | 112 |
apps/cpu-profile-summarizer/ | 15 |
apps/heft/ | 86 |
apps/lockfile-explorer-web/ | 15 |
Repository structure
| Top-level path | Files |
|---|---|
build-tests/ | 770 |
libraries/ | 770 |
apps/ | 703 |
heft-plugins/ | 357 |
webpack/ | 300 |
common/ | 221 |
rush-plugins/ | 210 |
rigs/ | 164 |
Docs found: README.mddocs/rush/dogfooding-rush-daemon.mddocs/rush/environment-variables.mddocs/rush/phased-commands.mddocs/rush/plugin-migration-guide.mddocs/rush/reporter.mddocs/rush/rushd-review-map.md
Package
apps/api-documenter/package.json — @microsoft/api-documenter v7.30.17, 12 declared dependencies.
@microsoft/api-extractor-model@microsoft/tsdoc@rushstack/heft@rushstack/node-core-library@rushstack/terminal@rushstack/ts-command-line@types/js-yaml@types/resolveeslintjs-yamllocal-node-rigresolve
CI & config entrypoints
README.md— Repository readme.github/workflows/ci.yml— GitHub Actions workflow.github/workflows/file-doc-tickets.yml— GitHub Actions workflowapps/lockfile-explorer-web/src/App.tsx— React rootapps/playwright-browser-tunnel/playwright.config.ts— Playwright e2e configvscode-extensions/rush-vscode-command-webview/src/App.tsx— React rootapps/api-documenter/package.json— npm scripts: _phase:build, _phase:pack, _phase:test, buildapps/api-extractor/package.json— npm scripts: _phase:build, _phase:pack, _phase:test, buildapps/cpu-profile-summarizer/package.json— npm scripts: _phase:build, _phase:pack, _phase:test, build, startapps/heft/package.json— npm scripts: _phase:build, _phase:pack, _phase:test, build, start
Structural health signals
Average score 6.6/10 across 96 analyzed source files; 47 hotspots surfaced.
common/scripts/install-run.js— 1110 lines, score 4.7 (Large file, Deep nesting)apps/api-documenter/src/documenters/MarkdownDocumenter.ts— 1309 lines, score 5 (Large file, Deep nesting)apps/api-documenter/src/documenters/YamlDocumenter.ts— 1084 lines, score 5 (Large file, Deep nesting)
These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.
Recent history
1e18b16f02922026-10-01 — [rush] Dogfood the Rush daemon in rushstack: allow command-scoped plugins, add snapshot workflow and guide (#6046)bc4c146892462026-09-30 — Applying package version bumps (#6101)f11aaa2e38be2026-09-29 — [rush-client-core] Bound the daemon startup reservation and surface startup errors (#6066)721461c89e4c2026-09-29 — Applying package version bumps (#6093)78d4687f48fe2026-09-28 — Applying package version bumps (#6044)