Cursor often generates duplicate utility functions instead of importing existing shared ones from a monorepo's root packages. By creating .cursor/rules with explicit import paths, referencing shared packages with @file in prompts, and structuring your monorepo so Cursor can discover shared code, you eliminate duplication and keep your codebase DRY.
Making Cursor aware of shared utilities in a monorepo
In monorepo setups, shared utility functions live in a common package like packages/shared or libs/utils. Cursor often does not know these exist and generates duplicate implementations. This tutorial shows you how to configure Cursor rules, reference shared packages in prompts, and structure your project so the AI always imports from the right place.
Prerequisites
- Cursor installed with a monorepo project open
- A shared utilities package in your monorepo (e.g., packages/shared)
- Basic familiarity with Cursor Chat (Cmd+L) and Composer (Cmd+I)
- Understanding of your monorepo's import path aliases
Step-by-step guide
Create a shared utilities index file
Create a shared utilities index file
Ensure your shared package has a clean index file that re-exports all utilities. Cursor reads this file to understand what shared functions are available. A well-organized barrel export makes it easy for the AI to discover existing utilities.
1// packages/shared/src/index.ts23// String utilities4export { capitalize, slugify, truncate } from './string';56// Date utilities7export { formatDate, parseISO, daysBetween } from './date';89// Validation utilities10export { isEmail, isURL, isUUID } from './validation';1112// HTTP utilities13export { fetchWithRetry, buildQueryString } from './http';1415// Type guards16export { isNonNull, isString, isNumber } from './guards';Expected result: A single entry point that lists all available shared utilities for Cursor to reference.
Add monorepo-aware rules to .cursor/rules
Add monorepo-aware rules to .cursor/rules
Create a rule file in each sub-package that tells Cursor where shared utilities live and how to import them. This rule auto-attaches when Cursor works on files in that package.
1---2description: Import rules for apps/web package3globs: "apps/web/src/**/*.{ts,tsx}"4alwaysApply: true5---67## Shared Utilities8- ALWAYS check @packages/shared/src/index.ts before creating utility functions9- Import shared utilities with: import { fn } from '@myorg/shared'10- NEVER duplicate functions that already exist in packages/shared11- Available shared utilities: capitalize, slugify, truncate, formatDate,12 parseISO, daysBetween, isEmail, isURL, isUUID, fetchWithRetry,13 buildQueryString, isNonNull, isString, isNumber1415## Import Paths16- Shared package: @myorg/shared17- UI components: @myorg/ui18- Config: @myorg/configPro tip: List the most commonly used shared functions directly in the rule. This way Cursor knows what exists without needing to read the actual file every time.
Expected result: Cursor will check for existing shared utilities before generating new ones in any apps/web file.
Reference shared packages in your prompts
Reference shared packages in your prompts
When asking Cursor to generate code that might need utilities, explicitly reference the shared package using @file or @folder. This gives the AI direct visibility into what already exists. Open Cmd+L and include the reference before your request.
1// Cursor Chat prompt (Cmd+L):2// @packages/shared/src/index.ts3// @packages/shared/src/validation.ts4// Create a registration form handler in apps/web that5// validates email and URL inputs. Use the validation6// functions from our shared package instead of writing7// new ones.Expected result: Cursor generates a handler that imports isEmail and isURL from @myorg/shared instead of reimplementing them.
Configure .cursorignore for monorepo performance
Configure .cursorignore for monorepo performance
Large monorepos can overwhelm Cursor's indexing. Exclude build artifacts, node_modules, and unrelated packages from indexing while keeping shared packages visible. This improves performance and reduces noise in AI suggestions.
1# .cursorignore (project root)2node_modules/3dist/4build/5.next/6coverage/7*.log89# Exclude packages you never work on10# packages/legacy-api/11# packages/deprecated-ui/Pro tip: Do NOT add your shared packages to .cursorignore. Cursor needs to index them to suggest correct imports.
Expected result: Cursor indexes only relevant source code, with shared packages fully visible for import suggestions.
Test with a new feature generation prompt
Test with a new feature generation prompt
Verify the setup by asking Cursor to generate a new feature that would typically need utility functions. The AI should import from the shared package rather than creating local copies. Use Composer (Cmd+I) for a multi-file generation.
1// Composer prompt (Cmd+I):2// @packages/shared/src/index.ts Generate a new API route3// at apps/api/src/routes/users.ts that:4// 1. Validates email input using shared utilities5// 2. Slugifies the username using shared utilities6// 3. Formats dates using shared utilities7// Import all utilities from @myorg/shared. Do not create8// any new utility functions.Expected result: Cursor generates the route file with correct imports from @myorg/shared and zero duplicate utility code.
Complete working example
1---2description: Monorepo import rules and shared package awareness3globs: "apps/*/src/**/*.{ts,tsx},packages/*/src/**/*.{ts,tsx}"4alwaysApply: true5---67## Monorepo Structure8This is a monorepo using npm workspaces with the following packages:9- packages/shared — utility functions, type guards, validators10- packages/ui — shared React components (Button, Modal, Input)11- packages/config — shared configuration (ESLint, TypeScript, Tailwind)12- apps/web — Next.js frontend application13- apps/api — Express.js backend API1415## Import Rules16- ALWAYS check packages/shared before writing utility functions17- Import shared utils: import { fn } from '@myorg/shared'18- Import UI components: import { Component } from '@myorg/ui'19- NEVER create local utility files that duplicate shared functionality20- NEVER import directly from relative paths across packages21 (use package names: @myorg/shared, not ../../packages/shared)2223## Available Shared Utilities24- String: capitalize, slugify, truncate, camelCase, kebabCase25- Date: formatDate, parseISO, daysBetween, isExpired26- Validation: isEmail, isURL, isUUID, isPhoneNumber27- HTTP: fetchWithRetry, buildQueryString, parseSearchParams28- Guards: isNonNull, isString, isNumber, isDefined2930## Before Creating New Utilities311. Search @packages/shared for existing implementation322. If it does not exist, add it to packages/shared (not locally)333. Export from packages/shared/src/index.ts344. Import in consuming packages via @myorg/sharedCommon mistakes when reusing shared utilities with Cursor
Why it's a problem: Adding shared packages to .cursorignore
How to avoid: Only add build artifacts and node_modules to .cursorignore. Keep all source packages indexed.
Why it's a problem: Not listing available utilities in .cursor/rules
How to avoid: Add a bulleted list of available shared functions to your monorepo-imports.mdc rule file.
Why it's a problem: Using relative import paths across packages
How to avoid: Add a rule requiring package name imports (@myorg/shared) and never relative cross-package paths.
Best practices
- Maintain a barrel index.ts in every shared package that re-exports all public utilities
- List available shared functions directly in .cursor/rules files for quick AI reference
- Reference @packages/shared/src/index.ts in every prompt that may need utility functions
- Open separate Cursor windows for different packages in very large monorepos
- Use .cursorindexingignore for files that should not be indexed but can still be read when referenced
- Commit .cursor/rules/ to Git so all team members get the same monorepo-aware AI behavior
- Use Notepads to store frequently referenced shared package documentation
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I have a monorepo with packages/shared containing utility functions (capitalize, slugify, isEmail, formatDate, fetchWithRetry). Generate a new Express route handler that validates user input, formats dates, and slugifies usernames. Import all utilities from @myorg/shared. Do not create duplicate utility functions.
In Cursor Chat (Cmd+L): @packages/shared/src/index.ts @packages/shared/src/validation.ts Create a new form validation hook in apps/web/src/hooks/useFormValidation.ts that uses isEmail, isURL, and isUUID from @myorg/shared. Import from the package name, not relative paths.
Frequently asked questions
Why does Cursor keep creating duplicate utility functions?
Cursor generates duplicates when it cannot see the shared package. Reference @packages/shared/src/index.ts in your prompt and add an alwaysApply rule listing available utilities.
Should I open the whole monorepo or just one package in Cursor?
For daily work in a specific package, opening just that package is faster. For cross-package work or refactoring shared code, open the whole monorepo so Cursor can index all packages.
How do I handle tsconfig path aliases in Cursor?
Cursor reads your tsconfig.json paths. Ensure @myorg/shared is properly mapped in tsconfig.json. Reference the tsconfig in your .cursorrules if Cursor generates wrong import paths.
Can Cursor create new shared utilities automatically?
Yes. Use Composer (Cmd+I) with a prompt like: 'Add a new sanitizeHTML function to packages/shared/src/string.ts and export it from the index. Then use it in apps/web/src/components/RichText.tsx.'
What if my shared package is in a different repository?
Use @docs to index the shared package documentation. Alternatively, use a Notepad containing the shared package API surface and reference it with @notepad-name in your prompts.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation