What Is bootstrap.js in Desktop Commander and Why It Must Be Imported First

TLDR: bootstrap.js sets process.env.UV_THREADPOOL_SIZE to 16 before any I/O operations begin, preventing the application from hanging when multiple file-system operations saturate libuv's default 4-thread pool.

Desktop Commander (wonderwhy-er/DesktopCommanderMCP) performs intensive file-system operations that execute on libuv's thread pool. By default, this pool contains only four threads, which can become blocked during burst I/O workloads and cause multi-minute hangs. The bootstrap.js module (compiled from src/bootstrap.ts) ensures the pool is expanded to 16 threads before any thread-pool work is submitted, making it a critical first import in the application's entry point.

The Problem: libuv's Default Thread Pool

Desktop Commander relies on libuv for asynchronous file-system operations. By default, libuv initializes a thread pool containing only 4 threads (UV_THREADPOOL_SIZE=4). When the application encounters a burst of slow or parallel I/O operations—such as multiple agents reading and writing files on cloud-synced drives—these four threads can become fully occupied.

Once the pool saturates, subsequent operations queue indefinitely. This manifests as the entire application hanging for minutes, rendering Desktop Commander unresponsive during heavy workloads.

How bootstrap.js Solves the Bottleneck

The bootstrap.js module resolves this by configuring the environment variable before libuv initializes its thread pool. The code increases the default pool size from 4 to 16 threads unless the user has already specified a custom value.

The Implementation in src/bootstrap.ts

In src/bootstrap.ts, the logic is straightforward but timing-critical:

// src/bootstrap.ts
/** Thread‑pool bootstrap – MUST be the first import in index.ts. */
const DEFAULT_THREADPOOL_SIZE = 16;

if (!process.env.UV_THREADPOOL_SIZE) {
  process.env.UV_THREADPOOL_SIZE = String(DEFAULT_THREADPOOL_SIZE);
}

This assignment must occur before any asynchronous I/O module loads. Libuv reads UV_THREADPOOL_SIZE only once—when the thread pool is first created. If the variable changes after the pool initializes, the modification has no effect.

Why Import Order Matters

The environment variable must be set before any module submits work to the thread pool. Once a file-system operation or other libuv-backed task executes, the pool initializes with whatever UV_THREADPOOL_SIZE value existed at that moment.

The Entry Point Configuration

Desktop Commander enforces the correct initialization order in src/index.ts by importing bootstrap.js as the very first module:

// src/index.ts
import './bootstrap.js';      // ← must be first
import './config.js';
import './ui/...';

If bootstrap.js were imported after ./config.js or any other I/O-performing module, the thread pool would already be locked at 4 threads, and the subsequent environment variable change would be ignored.

Verifying the Thread Pool Size

You can confirm the configuration is active by logging the environment variable after imports complete:

console.log('Thread‑pool size:', process.env.UV_THREADPOOL_SIZE);
// Expected output: Thread‑pool size: 16

Without bootstrap.js, this would return undefined or 4, indicating the default (and potentially insufficient) pool size.

Summary

  • bootstrap.js is compiled from src/bootstrap.ts and sets UV_THREADPOOL_SIZE to prevent thread pool exhaustion.
  • Libuv's default thread pool contains only 4 threads, which can block during intensive I/O operations.
  • The module must be imported first in src/index.ts because libuv reads the environment variable only once at pool initialization.
  • Desktop Commander defaults to 16 threads, with user overrides respected via existing environment variables.
  • Failure to import bootstrap.js first can result in multi-minute application hangs during parallel file operations.

Frequently Asked Questions

What happens if I import bootstrap.js after other modules?

If bootstrap.js is imported after modules that perform I/O, libuv will have already initialized its thread pool with the default size of 4 threads. Changing process.env.UV_THREADPOOL_SIZE afterward has no effect, leaving the application vulnerable to hangs during heavy file operations.

Can I customize the thread pool size in Desktop Commander?

Yes. If you set UV_THREADPOOL_SIZE before running the application, bootstrap.js will detect the existing value and preserve it. The default of 16 only applies when no user-defined value exists.

Why does Desktop Commander need 16 threads instead of 4?

Desktop Commander executes multiple concurrent file-system operations across potentially slow or cloud-synced drives. The default 4-thread pool quickly saturates under parallel agent workloads, causing the entire Node.js process to stall until threads free up. Sixteen threads provide sufficient concurrency for typical usage patterns.

Does bootstrap.js do anything besides set the thread pool size?

No. According to the source code in src/bootstrap.ts, its sole purpose is to configure UV_THREADPOOL_SIZE before any other code executes. It contains no other runtime logic or side effects.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →