How Desktop Commander MCP Normalizes Line Endings Across Operating Systems
Desktop Commander MCP uses a dedicated line ending handler in src/utils/lineEndingHandler.ts to detect, normalize, and analyze line endings, ensuring consistent file operations across Windows, macOS, and Linux.
When working with files across different operating systems, inconsistent line endings can cause rendering issues and version control conflicts. Desktop Commander MCP solves this through a robust normalization system that processes text files during read and write operations.
Detecting the Current Line Ending Style
The detectLineEnding(content) function scans file content character-by-character to identify the first line ending sequence it encounters. According to the source code in src/utils/lineEndingHandler.ts, this function checks for '\r\n' (CRLF), '\n' (LF), or '\r' (CR) sequentially.
If the function finds no line endings in the content, it falls back to the host operating system's default: returning '\r\n' on Windows platforms and '\n' on all other systems. This detection provides the baseline for deciding whether normalization is required.
Normalizing to a Target Style
The normalizeLineEndings(text, targetLineEnding) function implements a two-stage normalization process. First, it collapses all existing line ending variants into a unified LF representation using regex replacements:
text.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
Once the content uses single '\n' characters consistently, the function translates to the requested target format:
'\r\n'(Windows): Replaces every'\n'with'\r\n''\r'(Classic Mac): Replaces every'\n'with'\r''\n'(Unix/Linux): Returns the LF-only string unchanged
This approach ensures that mixed line endings within a single file are eliminated before applying the target style.
Analyzing Mixed Line Endings
The analyzeLineEndings(content) function provides diagnostic capabilities by counting occurrences of CRLF, LF, and lone CR sequences within a file. It determines the predominant style and sets a hasMixed boolean flag when multiple styles are detected.
This analysis helps the UI layer—specifically src/ui/file-preview/src/file-type-handlers.ts—decide whether to display warnings or prompt users for automatic conversion before editing.
Integration with File System Operations
The line ending handler integrates into the application's file system layer through src/tools/filesystem.ts and src/handlers/filesystem-handlers.ts. When reading files, these modules call detectLineEnding() to preserve the original style, and when writing, they invoke normalizeLineEndings() to ensure the output matches the target platform or user preference.
Practical Implementation Examples
Here is how to use the line ending utilities in your own implementations:
import {
detectLineEnding,
normalizeLineEndings,
analyzeLineEndings,
} from './utils/lineEndingHandler';
// Detect the line ending used in a file
const raw = await fs.promises.readFile('example.txt', 'utf8');
const currentEnding = detectLineEnding(raw); // → '\r\n' | '\n' | '\r'
// Normalize the content to the OS default (e.g., Windows)
const normalized = normalizeLineEndings(
raw,
process.platform === 'win32' ? '\r\n' : '\n'
);
await fs.promises.writeFile('example.txt', normalized, 'utf8');
// Analyze a file for mixed line endings
const analysis = analyzeLineEndings(raw);
console.log({
predominant: analysis.style,
totalLines: analysis.count,
hasMixed: analysis.hasMixed,
});
When you run this code, all line endings become '\r\n' on Windows or '\n' on Unix-like systems, while mixed-ending files trigger the hasMixed flag for UI warnings.
Summary
- Detection:
detectLineEnding()scans character-by-character and falls back to OS defaults when no endings are found. - Normalization:
normalizeLineEndings()first collapses all variants to LF, then converts to the target style using regex replacements. - Analysis:
analyzeLineEndings()counts CRLF, LF, and CR occurrences to identify mixed files and predominant styles. - Integration: The handler connects to file operations via
src/tools/filesystem.tsand UI components insrc/ui/file-preview/src/file-type-handlers.ts.
Frequently Asked Questions
How does Desktop Commander MCP detect line endings in a file?
Desktop Commander MCP uses the detectLineEnding() function in src/utils/lineEndingHandler.ts to scan text content character-by-character until it encounters the first line ending sequence ('\r\n', '\n', or '\r'). If no line endings exist, it returns the platform default: '\r\n' for Windows and '\n' for macOS and Linux.
What happens when a file contains mixed line endings?
The analyzeLineEndings() function counts each type of line ending (CRLF, LF, and CR) separately. When multiple types are present, it sets hasMixed to true and identifies the predominant style. This allows the application to warn users through the UI components in src/ui/file-preview/src/file-type-handlers.ts before performing operations that might corrupt the file's consistency.
Which source files utilize the line ending handler?
The primary implementation lives in src/utils/lineEndingHandler.ts. The filesystem tools in src/tools/filesystem.ts call these utilities during read and write operations, while src/handlers/filesystem-handlers.ts integrates the normalized content into command handlers. The file preview UI uses analysis results from src/ui/file-preview/src/file-type-handlers.ts to display warnings.
Can I customize the target line ending style?
Yes. The normalizeLineEndings(text, targetLineEnding) function accepts any of the three standard line ending strings as the second parameter. You can pass '\r\n' for Windows-style, '\n' for Unix-style, or '\r' for legacy Mac-style endings, regardless of the current operating system.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →