One Window, Many Packages: Use JetBrains Project Attach for Monorepos (works for separate repos too)

One Window, Many Packages: Use JetBrains Project Attach for Monorepos (works for separate repos too)

~ 5 min read

Monorepos let you keep multiple apps and packages in a single VCS root e.g. apps/web, apps/api, packages/ui, packages/config, with one or few lockfiles and first-class cross-package tooling (workspaces, Nx, Turborepo). The downside is that day‑to‑day work can involve jumping between different toolchains, interpreters, and run targets.

JetBrains IDEs (IntelliJ IDEA, WebStorm, PhpStorm, etc.) have a feature called Project Attach that makes monorepos feel snappier: you can attach specific apps/packages as separate roots inside one window so you get clear boundaries for interpreters, run/debug configs, and navigation. And yes, if you don’t use a monorepo, the same feature works great to attach completely separate repositories into one window.

Why Project Attach in a monorepo?

  • Focused context per app/package while keeping one window and unified navigation (Search Everywhere, Go to File/Symbol across attached roots).
  • Cleaner tooling boundaries: each attached root can have its own Node interpreter, SDK/JDK, and run/debug configs.
  • Works alongside your workspace tools (pnpm/yarn/npm workspaces, Nx, Turborepo); Attach is an IDE convenience, not a build‑system replacement.
  • If each project lives in a separate namespace it’s all handled.

Monorepo + Attached Roots: how they fit together

  • Monorepo: a single repository with shared tooling (often one lockfile) and cross‑package workflows.
  • Attached roots: in the IDE, treat apps/packages (and even tooling folders) as separate project roots for clarity and per‑root settings.
  • Also works for polyrepos: you can attach completely separate repositories to the same window; each retains its own VCS root and lockfile.

Attach apps/packages (quick path)

  1. Open your monorepo in a JetBrains IDE.
  2. File → Attach to Project… (or File → Open… and choose “Attach” in the dialog).
  3. Select the app/package directory (e.g., apps/web, apps/api, packages/ui). You can attach multiple.
  4. Each attached directory appears as a top‑level root in the Project view.
  5. To remove: right‑click the attached root → Remove from Project. Files on disk are untouched.

Node.js, workspaces, and keeping things separate

  • Node interpreter per root: Settings/Preferences → Languages & Frameworks → Node.js → Node interpreter. Choose “node from nvm/Volta/asdf” or a local binary for each attached root if versions differ.
  • Package manager: the monorepo may have a single lockfile, but run configurations should set the Working directory to the specific app/package so node_modules resolution is correct (especially with pnpm/yarn workspaces).
  • Corepack: enable to pin npm/pnpm/yarn versions; Attach respects per‑root working directories.

TypeScript

  • Use “TypeScript → Use TypeScript Service from” the app/package node_modules/typescript when versions differ across packages (common in large repos).

PHP (PhpStorm)

  • If your monorepo includes PHP and JS/TS together, configure a separate interpreter per attached PHP root (local, Docker, WSL, remote) and map paths for correct indexing and Xdebug.

JVM (IntelliJ IDEA)

  • Gradle/Maven modules in a monorepo often share a JDK, but you can still set per‑root Gradle JVM and user home ( GRADLE_USER_HOME) if isolation is required.

Run/Debug configurations that “just work”

  • Create configurations from package.json scripts (pnpm/yarn/npm), framework runners, or Docker/Compose at the app/package root.
  • Set the Working directory to the attached app/package.
  • Name configs with prefixes (web:dev, api:test, ui:build) for fast filtering.

VCS and Git operations

  • Monorepo: a single VCS root; commits are scoped by paths. Use changelists to keep work per app/package clean.
  • Polyrepo: when attaching separate repositories, JetBrains shows multiple VCS roots with separate logs.

Indexing and performance tips

  • Exclude heavy directories per root (node_modules, dist, .next, build, vendor) if not already excluded.
  • Disable language plugins you don’t need for this workspace.
  • Very large packages? Consider opening those in a new window and keeping only actively edited ones attached.

Monorepo example layout

  • apps/web (Astro/Solid, pnpm workspace)
  • apps/api (Laravel via Sail/Docker)
  • packages/ui (shared React/Solid UI library)
  • packages/config (shared ESLint/TS config)

Attach all four; configure Node/PHP interpreters and TS service per root. Run web dev server, API in Sail, and UI tests without switching windows.

Also works for separate repositories

  • frontend (Astro/Solid, pnpm)
  • api (Laravel)
  • shared-lib (TypeScript library)
  • infra (Terraform) Attach all of them to one window; each repo retains its own VCS root and lockfile.

Troubleshooting

  • Wrong Node version picked up
    • Set the Node interpreter per attached root, or use .nvmrc/.node-version/Volta and enable automatic detection.
  • Workspace scripts run in the wrong directory
    • Edit the Run Configuration → Working directory to the app/package path.
  • TypeScript errors show wrong lib definitions
    • Switch TS Service to “Use TypeScript from node_modules” of that app/package.
  • Gradle/Composer reuse global caches with unexpected versions
    • Pin tool versions and isolate caches if necessary (GRADLE_USER_HOME, Composer config).

FAQ

  • Does Attach change my monorepo layout? No, it’s purely an IDE/workspace feature.
  • Can I mix monorepo packages and external repos in the same window? Yes, attach both.
  • Is WSL/Remote supported? Yes, attach local or remotely mapped folders as usual and configure interpreters per root.

Key shortcuts (defaults vary by OS and keymap)

  • Search Everywhere: Shift Shift across all attached roots
  • Go to File: Cmd/Ctrl+Shift+O across roots
  • Go to Symbol: Cmd/Ctrl+Alt+Shift+N
  • Recent Files: Cmd/Ctrl+E
  • Run Anything: Ctrl twice, then type a script name from the current root

Wrap-up

Project Attach gives monorepos sharper boundaries and faster flow, and it works just as well for separate repositories. Keep tooling tidy per app/package while enjoying unified navigation, search, and run/debug in a single JetBrains window.

Starter checklist

  • Attach apps/packages you actively work on (and any sibling repos)
  • Configure per-root interpreters (Node, PHP, JDK)
  • Pin TS/ESLint/Prettier per app/package
  • Create named run configs with clear prefixes
  • Exclude heavy build artefacts per root
  • Use changelists and, for polyrepos, separate VCS roots

Happy shipping.

all posts →