Configure Forge for a Monorepo
import { Aside, Tabs, TabItem } from ‘@astrojs/starlight/components’;
Monorepos work with Forge out of the box — run forge index at the repo root and Forge indexes everything. The challenge is tuning configuration so Forge understands which packages are entry points, which paths to ignore, and how packages relate to each other.
Index the monorepo root
Section titled “Index the monorepo root”Run forge index from the monorepo root:
forge index /path/to/monorepo --with-search --with-gitForge walks the entire directory tree, parsing all supported source files. For a typical monorepo with 50–200 packages, initial indexing takes 30–120 seconds. Subsequent incremental runs are much faster.
Verify the index:
forge statsExpected output:
forge stats: /home/you/repos/monorepo
Files indexed: 8,432 Symbols extracted: 94,217 Packages found: 47 Languages: TypeScript (6,201), JavaScript (1,891), Python (340) Index size: 187 MB Last indexed: 2026-04-16 14:32:01 (2 minutes ago)Create a per-repo config
Section titled “Create a per-repo config”Create .forge/config.toml in the monorepo root:
[index]# Paths to skip during indexingignored_paths = [ "node_modules", "dist", "build", ".next", ".turbo", "coverage", "**/*.test.ts", "**/*.spec.ts",]
# Entry points for reachability analysis (forge_check_wiring)# These are the roots of the dependency graphentry_points = [ "apps/web/src/index.ts", "apps/api/src/main.ts", "apps/mobile/index.js",]
[search]# Max results per search querymax_results = 50
[health]# Minimum coverage threshold for P2 warning (0 = disabled)min_coverage = 0After creating or editing .forge/config.toml, re-run forge index to apply the new configuration.
Package manager workspace support
Section titled “Package manager workspace support”Forge recognizes workspace configurations automatically.
If package.json at the root defines a workspaces field, Forge uses it to identify package boundaries:
{ "workspaces": [ "packages/*", "apps/*" ]}Forge maps cross-package imports correctly — an import from @myorg/ui in apps/web resolves to packages/ui/src/index.ts, not an unresolved external.
Forge reads Cargo.toml at the repo root to identify workspace members:
[workspace]members = [ "crates/core", "crates/cli", "crates/server",]Cross-crate imports resolve within the workspace.
For Python monorepos using namespace packages or PEP 517 workspace tooling (Poetry workspaces, uv), add package roots to the config explicitly:
[index]entry_points = [ "services/api/main.py", "services/worker/main.py", "libs/core/__init__.py",]Forge follows relative imports and sys.path-style references within the indexed tree.
Path aliases
Section titled “Path aliases”If your monorepo uses TypeScript path aliases (e.g., @app/*, ~/*), Forge reads them from tsconfig.json automatically. For non-standard alias resolution, specify them in .forge/config.toml:
[resolve]aliases = [ { alias = "@app", target = "apps/web/src" }, { alias = "@shared", target = "packages/shared/src" }, { alias = "~", target = "src" },]Without this, imports using these aliases appear as unresolved and generate P0 broken_import findings.
Verify cross-package resolution
Section titled “Verify cross-package resolution”After indexing, verify that cross-package imports resolve correctly:
forge healthLook for broken_import findings. If you see many errors like:
P0 broken_import: apps/web/src/components/Button.tsx:3 cannot resolve '@shared/ui'This means path aliases or workspace config isn’t set up. Add the alias to .forge/config.toml and re-index.
You can also check a specific package’s wiring:
forge check-wiring apps/web/src/index.tsExpected output when correctly configured:
forge check-wiring: apps/web/src/index.ts
Reachable from entry points: YES Entry point: apps/web/src/index.ts (self) Path: (entry)
Outbound imports: 14 files All imports resolved: YESLarge monorepos
Section titled “Large monorepos”For monorepos with 500K+ files (large company repos), tune the ignored paths aggressively:
[index]ignored_paths = [ "node_modules", "dist", "build", ".cache", ".turbo", "storybook-static", "**/*.min.js", "**/*.bundle.js", "**/__mocks__", "vendor", "third_party",]
[index]# Limit file size (bytes) — skips generated files and large JSONmax_file_size_bytes = 512000Common pitfalls
Section titled “Common pitfalls”Duplicate symbol warnings after indexing
If the same package appears multiple times (e.g., packages/ui and node_modules/packages/ui), add the duplicate path to ignored_paths. node_modules is ignored by default; if you see duplicates, a symlink or unusual path is creating a second traversal.
Entry points show as “unreachable”
forge_check_wiring returns “unreachable” only when a file has no path from any declared entry point. If the file IS an entry point, add it to entry_points in .forge/config.toml.
Indexing takes over 5 minutes
Check forge stats for file count. If it’s unexpectedly high (>100K files), a large directory is being indexed that shouldn’t be. Run FORGE_LOG=debug forge index . to see which paths are taking the most time, then add them to ignored_paths.