| name | cross-platform-paths |
| description | Critical patterns for cross-platform path handling in this VS Code extension. Windows vs POSIX path bugs are the #1 source of issues. Use this skill when reviewing or writing path-related code. |
| argument-hint | Review path handling in [file or component] |
| user-invocable | false |
Cross-Platform Path Handling
CRITICAL: This extension runs on Windows, macOS, and Linux. Path bugs are the #1 source of issues.
Core Rules
Rule 1: Never Concatenate Paths with /
const envPath = homeDir + '/.venv/bin/python';
const envPath = path.join(homeDir, '.venv', 'bin', 'python');
Rule 2: Use path.resolve() for Comparisons, Not path.normalize()
const normalized = path.normalize(fsPath);
const normalized = path.resolve(fsPath);
const pathA = path.resolve(fsPath);
const pathB = path.resolve(e.environmentPath.fsPath);
return pathA === pathB;
Rule 3: Use Uri.file().fsPath for VS Code Paths
if (filePath === otherPath) {
}
import { Uri } from 'vscode';
const fsPathA = Uri.file(pathA).fsPath;
const fsPathB = Uri.file(pathB).fsPath;
if (fsPathA === fsPathB) {
}
Platform-Specific Gotchas
Windows
| Issue | Details |
|---|
| Drive letters | Paths start with C:\, D:\, etc. |
| Backslashes | Separator is \, not / |
| Case insensitivity | C:\Test equals c:\test |
| Long paths | Paths >260 chars may fail |
| Mapped drives | Z:\ may not be accessible |
| pyenv-win | Uses pyenv.bat, not pyenv or pyenv.exe |
| Poetry cache | %LOCALAPPDATA%\pypoetry\Cache\virtualenvs |
| UNC paths | \\server\share\ format |
macOS
| Issue | Details |
|---|
| Case sensitivity | Depends on filesystem (usually insensitive) |
| Homebrew symlinks | Complex symlink chains in /opt/homebrew/ |
| Poetry cache | ~/Library/Caches/pypoetry/virtualenvs |
| XCode Python | Different from Command Line Tools Python |
Linux
| Issue | Details |
|---|
| Case sensitivity | Paths ARE case-sensitive |
| /bin symlinks | /bin may be symlink to /usr/bin |
| XDG directories | ~/.local/share/virtualenvs for pipenv |
| Poetry cache | ~/.cache/pypoetry/virtualenvs |
| Hidden files | Dot-prefixed files are hidden |
Common Patterns
Getting Platform-Specific Paths
import * as os from 'os';
import * as path from 'path';
const home = os.homedir();
const venvPath = path.join(home, '.venv', 'bin', 'python');
Environment-Specific Executable Names
const isWindows = process.platform === 'win32';
const pythonExe = isWindows ? 'python.exe' : 'python';
const activateScript = isWindows
? path.join(venvPath, 'Scripts', 'activate.bat')
: path.join(venvPath, 'bin', 'activate');
const pyenvCmd = isWindows ? 'pyenv.bat' : 'pyenv';
Normalizing Paths for Comparison
import { normalizePath } from './common/utils/pathUtils';
const key = normalizePath(filePath);
cache.set(key, value);
traceLog(`Discovered: ${filePath}`);
Handling Uri | string Union Types
function process(locator: Uri | string) {
const fsPath = locator.fsPath;
}
function process(locator: Uri | string) {
const fsPath = locator instanceof Uri ? locator.fsPath : locator;
const normalized = path.resolve(fsPath);
}
File Existence Checks
import * as fs from 'fs';
import * as path from 'path';
const configPath = path.join(projectRoot, 'pyproject.toml');
if (fs.existsSync(configPath)) {
}
import { promises as fsPromises } from 'fs';
try {
await fsPromises.access(configPath);
} catch {
}
Shell Path Escaping
terminal.sendText(`python ${filePath}`);
terminal.sendText(`python "${filePath}"`);
const shellPath = isGitBash ? filePath.replace(/\\/g, '/') : filePath;
Testing Cross-Platform Code
When testing path-related code:
- Test on Windows (cmd, PowerShell, Git Bash)
- Test on macOS (zsh, bash)
- Test on Linux (bash, fish)
Pay special attention to:
- Paths with spaces:
C:\Program Files\Python
- Paths with Unicode:
~/проекты/
- Very long paths (>260 chars on Windows)
- Paths with special characters:
$, &, (, )