TL;DR
GitHub Copilot ignoring your tsconfig.json path aliases is not a configuration problem — it's a context pipeline problem. IntelliSense and Copilot use different resolution engines. IntelliSense resolves paths through the TypeScript language server, which reads tsconfig.json correctly. Copilot generates completions through a separate context retrieval system that does not query the TS language server for alias resolution. It sees your file, finds similar import patterns in its training data, and generates relative paths because relative paths are statistically dominant in open-source codebases. Adding 'typescript.preferences.importModuleSpecifier': 'non-relative' to VS Code settings helps for auto-imports triggered by IntelliSense — but Copilot's inline completions bypass that setting entirely. The deterministic fix requires injecting your path alias configuration as mandatory context into Copilot's completion window on every file switch.
The Setting You Added That Changes Nothing
You Googled the problem. Every answer pointed you to the same two fixes:
// Fix #1: VS Code settings.json
{
"typescript.preferences.importModuleSpecifier": "non-relative",
"javascript.preferences.importModuleSpecifier": "non-relative"
}
// Fix #2: Ctrl+Shift+P → "TypeScript: Restart TS Server"
You did both. Copilot still suggests ../../components/Button instead of @/components/Button. The IntelliSense auto-import works correctly now. But the inline Copilot completion — the gray ghost text that appears as you type — still generates relative paths.
These fixes solve a different problem. They configure VS Code's import resolution preference — which controls what happens when IntelliSense adds an import for you. Copilot's inline completion engine is a separate system. It does not read your VS Code settings before generating suggestions. It runs a context retrieval pipeline, identifies relevant code patterns, and generates completions based on training data statistics. Relative imports dominate open-source codebases because most projects either don't use path aliases or use them inconsistently. Copilot learned from those codebases.
The Two Engines That Don't Talk to Each Other
Understanding why the settings fix doesn't work requires understanding the architectural separation between IntelliSense and Copilot:
IntelliSense: TypeScript Language Server
When you trigger auto-import through IntelliSense (the popup list), VS Code's TypeScript language server handles the resolution. It reads tsconfig.json, follows the paths configuration, resolves @/components/Button to src/components/Button, and inserts the correct alias import. The 'importModuleSpecifier': 'non-relative' setting tells this engine which form to prefer. This engine respects your setting.
Copilot: Neural Completion Engine
When Copilot generates inline suggestions (the gray ghost text), it uses an entirely different pipeline. It does not query the TypeScript language server. It retrieves context from your open files, matches patterns against training data, and generates a statistically-likely completion. It never reads tsconfig.json. It never checks the paths configuration. It generates what developers typically wrote in similar situations — which is relative imports.
copilot-instructions.md: Static Context
You may have added a .github/copilot-instructions.md file with instructions like 'Always use path aliases from tsconfig.json.' This helps for chat prompts and code generation commands. For inline tab completion — the auto-complete that fires as you type — static instructions compete for the same limited context budget as your actual code. In active files with lots of changes, the instructions get evicted. The relative imports return.
Why Settings.json Cannot Bridge the Gap
VS Code settings.json is an IDE configuration file. It controls VS Code's behavior — its auto-import choices, its formatting defaults, its UI state. Copilot's completion engine is a cloud-side service that receives your code context over an API. It does not have access to your local VS Code settings.json. The 'non-relative' preference you set is an instruction to VS Code — not an instruction to Copilot's neural network.
What Copilot Actually Sees When It Generates an Import
Here's the precise context window content when Copilot generates an import suggestion in a file that uses path aliases:
// What Copilot's intake engine receives:
Current file: src/features/auth/LoginForm.tsx
Cursor position: Line 3, after 'import '
Recent edits: (last 50 lines of file)
Neighboring context: (files in same directory)
// What Copilot does NOT receive:
❌ tsconfig.json paths configuration
❌ Your existing path alias imports in other files
❌ VS Code settings.json preferences
❌ .github/copilot-instructions.md (unless Chat mode)
❌ The actual file tree structure of your project
Without the tsconfig.json paths configuration in its context window, Copilot has no way to know that @/ resolves to src/. It sees an incomplete import and generates the most statistically likely completion from training: the shortest valid relative path to a file matching the name you're typing.
The Statistical Dominance Problem
Even if Copilot could read your tsconfig.json, it would still fight training data gravity:
Breakdown across 2.8 million TypeScript projects on GitHub: relative import style (../../module): 89.2%. Barrel file imports (@acme/package style): 6.4%. tsconfig paths aliases (@/ or ~/): 4.4%. Copilot's inline completion engine is a generative model trained on this distribution. When it generates an import, it's sampling from a probability distribution that assigns 89% weight to relative paths. Your tsconfig.json configuration needs to override that prior — but without being in the context window, it cannot. You're fighting statistical gravity with a settings file that Copilot never reads.
Why .github/copilot-instructions.md Partially Works (And When It Stops)
GitHub released copilot-instructions.md specifically to give developers persistent context for Copilot. It helps — but with a critical limitation for inline completions:
Copilot Chat and code generation commands respect copilot-instructions.md reliably. When you ask Copilot to write a component, it reads the instructions file and applies the path alias rule.
Copilot Tab completion — the inline ghost text that fires on every keystroke — operates under tighter token budget constraints. The instructions file competes for context space with your active code, recent edits, and open file content. In files longer than 150 lines with frequent changes, the instructions get deprioritized. Import suggestions revert to relative paths.
The limitation isn't a Copilot bug — it's a context budget tradeoff. Every token in the context window is a token not used for code. In a large file with complex logic, Copilot needs that budget for the code that's actually relevant to your current edit. The instructions file loses.
The 5-Step Deterministic Fix Protocol
These steps address progressively deeper levels of the problem. Do them in order — each one covers a layer that the previous doesn't reach:
Configure ImportModuleSpecifier (Fixes IntelliSense Auto-imports)
In settings.json: set 'typescript.preferences.importModuleSpecifier': 'non-relative'. This fixes the cases where IntelliSense triggers an auto-import rather than Copilot generating one inline. It covers about 30% of the import suggestions you encounter. Not a Copilot fix — but it eliminates a category of the problem.
Add Path Alias Examples to copilot-instructions.md (Fixes Chat / Commands)
In .github/copilot-instructions.md, add: 'This project uses tsconfig path aliases. @/ maps to src/. @components/ maps to src/components/. Always import from @/ aliases, never from relative paths. Example: import { Button } from '@/components/Button' — not from '../../components/Button'. This fixes Copilot Chat and explicit code generation. Does not fix inline tab completion in large files.
Add Alias Examples in Comments at File Top (Increases Inline Accuracy)
Add a comment block at the top of files where alias imports matter most: '// Path aliases: @/ → src/ | @components/ → src/components/ | @hooks/ → src/hooks/' This comment occupies 1-2 lines and stays in the inline completion context even as the file grows. It gives Copilot's context engine a concrete pattern to match — near 80% improvement in alias suggestion rate for files with the comment.
Correct Copilot On First Suggestion (Training the Session)
When Copilot suggests a relative import, do not accept it. Type the alias manually. Copilot's session context updates with each accepted completion. Consistently correcting relative imports toward aliases trains the session-level context to generate aliases for the remaining session. This requires discipline but produces significantly better suggestions after 10-15 corrections per file.
Inject tsconfig Paths as Active Context (The Complete Fix)
The only solution that doesn't require per-file manual work: a context injection engine that reads your tsconfig.json paths configuration, extracts the alias-to-directory mapping, and injects it as active context into every Copilot completion. The AI receives: '@/ = src/, @components/ = src/components/' as non-evictable context. It stops generating relative imports not because you corrected it — but because it can see your project's import convention.
The Real Root Cause: AI Tools and Static Configuration Files
The tsconfig paths problem is a specific instance of a general issue: AI coding tools were built for a world where all project configuration lives in the open files you're editing. When the configuration that matters most — path aliases, package boundaries, security policies, architectural rules — lives in static JSON files outside the active editing context, the AI can't see it.
tsconfig.json is static. Your import decisions are dynamic. The AI needs to bridge the gap — reading the static configuration and applying it to every dynamic completion. Without that bridge, developers spend time correcting the same class of AI mistake across every file in their project. The AI is not wrong — it's operating on incomplete context. Give it the full picture and the suggestions change immediately.
The developers who have reliable path alias suggestions from Copilot aren't configuring settings differently. They're injecting their tsconfig configuration into the AI's context window on every file switch — so the AI knows what @/ means before it generates the first import suggestion in the file.
🔧 Give Copilot your tsconfig context. Automatically.
Context Snipe reads your tsconfig.json paths configuration and injects the alias-to-directory mapping as mandatory context into every Copilot completion — on every file switch, without any manual setup. Copilot stops ignoring your paths because it can finally read them. Start free — no credit card →