cross-platform-paths
Best practices for writing platform-agnostic file path code in TypeScript.
Install
mkdir -p .claude/skills/cross-platform-paths && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15874" && unzip -o skill.zip -d .claude/skills/cross-platform-paths && rm skill.zipInstalls to .claude/skills/cross-platform-paths
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
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.Key capabilities
- →Concatenate paths using `path.join()`
- →Resolve paths for comparison with `path.resolve()`
- →Use `Uri.file().fsPath` for VS Code paths
- →Get platform-specific home directory
- →Quote paths for shell commands
How it works
The skill provides rules and examples for handling file paths to ensure compatibility across Windows, macOS, and Linux environments.
Inputs & outputs
When to use cross-platform-paths
- →Review path logic
- →Fix Windows path bugs
- →Compare file system paths
About this skill
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 /
// ❌ WRONG: POSIX-style path concatenation
const envPath = homeDir + '/.venv/bin/python';
// ✅ RIGHT: Use path.join()
const envPath = path.join(homeDir, '.venv', 'bin', 'python');
Rule 2: Use path.resolve() for Comparisons, Not path.normalize()
// ❌ WRONG: path.normalize keeps relative paths relative on Windows
const normalized = path.normalize(fsPath);
// path.normalize('\test') → '\test' (still relative!)
// ✅ RIGHT: path.resolve adds drive letter on Windows
const normalized = path.resolve(fsPath);
// path.resolve('\test') → 'C:\test' (absolute!)
// When comparing paths, use resolve() on BOTH sides:
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
// ❌ WRONG: Raw string comparison
if (filePath === otherPath) {
}
// ✅ RIGHT: Compare fsPath to fsPath
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';
// Home directory
const home = os.homedir(); // Works cross-platform
// Construct paths correctly
const venvPath = path.join(home, '.venv', 'bin', 'python');
// Windows: C:\Users\name\.venv\bin\python
// macOS: /Users/name/.venv/bin/python
// Linux: /home/name/.venv/bin/python
Environment-Specific Executable Names
const isWindows = process.platform === 'win32';
// Python executable
const pythonExe = isWindows ? 'python.exe' : 'python';
// Activate script
const activateScript = isWindows
? path.join(venvPath, 'Scripts', 'activate.bat')
: path.join(venvPath, 'bin', 'activate');
// pyenv command
const pyenvCmd = isWindows ? 'pyenv.bat' : 'pyenv';
Normalizing Paths for Comparison
import { normalizePath } from './common/utils/pathUtils';
// Use normalizePath() for map keys and comparisons
const key = normalizePath(filePath);
cache.set(key, value);
// But preserve original for user display
traceLog(`Discovered: ${filePath}`); // Keep original
Handling Uri | string Union Types
// ❌ WRONG: Assuming Uri
function process(locator: Uri | string) {
const fsPath = locator.fsPath; // Crashes if string!
}
// ✅ RIGHT: Handle both types
function process(locator: Uri | string) {
const fsPath = locator instanceof Uri ? locator.fsPath : locator;
// Now normalize for comparisons
const normalized = path.resolve(fsPath);
}
File Existence Checks
import * as fs from 'fs';
import * as path from 'path';
// Check file exists (cross-platform)
const configPath = path.join(projectRoot, 'pyproject.toml');
if (fs.existsSync(configPath)) {
// File exists
}
// Use async version when possible
import { promises as fsPromises } from 'fs';
try {
await fsPromises.access(configPath);
// File exists
} catch {
// File does not exist
}
Shell Path Escaping
// ❌ WRONG: Unescaped paths in shell commands
terminal.sendText(`python ${filePath}`);
// D:\path\file.py becomes "D:pathfile.py" in some shells!
// ✅ RIGHT: Quote paths
terminal.sendText(`python "${filePath}"`);
// For Git Bash on Windows, escape backslashes
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:
$,&,(,)
When not to use it
- →When concatenating paths with `/`
- →When using `path.normalize()` for comparisons
- →When comparing raw string paths directly
Limitations
- →Prohibits concatenating paths with `/`
- →Requires `path.resolve()` for path comparisons
- →Requires `Uri.file().fsPath` for VS Code path comparisons
How it compares
This skill enforces specific path manipulation functions and patterns to avoid common cross-platform path bugs, unlike generic string operations.
Compared to similar skills
cross-platform-paths side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| cross-platform-paths (this skill) | 0 | 6mo | No flags | Beginner |
| effect-patterns-error-handling | 1 | 7mo | No flags | Advanced |
| effect-patterns-scheduling | 1 | 7mo | No flags | Beginner |
| nextjs-server-side-error-debugging | 1 | 7mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by microsoft
View all by microsoft →You might also like
effect-patterns-error-handling
PaulJPhilp
Effect-TS patterns for Error Handling. Use when working with error handling in Effect-TS applications.
effect-patterns-scheduling
PaulJPhilp
Effect-TS patterns for Scheduling. Use when working with scheduling in Effect-TS applications.
nextjs-server-side-error-debugging
blader
Debug getServerSideProps and getStaticProps errors in Next.js. Use when: (1) Page shows generic error but browser console is empty, (2) API routes return 500 with no details, (3) Server-side code fails silently, (4) Error only occurs on refresh not client navigation. Check terminal/server logs instead of browser for actual error messages.
typescript-node-esm-compiler-runtime
GonkaGate
Own TypeScript plus Node.js ESM compiler/runtime correctness. Use whenever the real question is why TypeScript compiles but Node fails, how `tsconfig`/`package.json`/entrypoint/runtime mode must align, whether relative imports should use `.js` or `.ts`, how `nodenext`/`node20`/`verbatimModuleSyntax`
supabase-developer
daffy0208
Build full-stack applications with Supabase (PostgreSQL, Auth, Storage, Real-time, Edge Functions). Use when implementing authentication, database design with RLS, file storage, real-time features, or serverless functions.
payload
payloadcms
Use when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.