# How the Audit Logging System in DesktopCommander Tracks and Rotates Tool Usage Logs

> DesktopCommander's audit logging system tracks tool usage via trackTools, automatically rotating logs at 10 MiB with timestamps. Learn how it manages your usage data efficiently.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-07-11

---

**DesktopCommander records every tool invocation via the `trackTools` utility in [`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts), automatically rotating logs when they reach 10 MiB by renaming them with timestamps and creating fresh log files.**

The audit logging system in DesktopCommander provides a complete forensic trail of tool executions for debugging and security auditing. Implemented in the **wonderwhy-er/DesktopCommanderMCP** repository, this lightweight mechanism captures metadata for every search, file edit, and PDF generation while preventing disk space exhaustion through automatic size-based rotation.

## How DesktopCommander Records Tool Invocations

### The trackTools Utility

The core implementation lives in [`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts), which exports the **`trackToolCall()`** function. This utility is invoked from [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) and other entry points immediately when a tool begins execution. Before writing any entry, the module checks log file size against the **`LOG_MAX_SIZE`** constant (10 MiB) to determine if rotation is required.

### Audit Entry Structure

Each log entry is a JSON object containing:

- **Tool name** – identifies which command was invoked (e.g., `search`, `edit`)
- **Request ID** – a unique UUID generated via `crypto.randomUUID()`
- **Start timestamp** – ISO 8601 timestamp from `new Date().toISOString()`
- **Invoking user** – user context when available
- **Description** – human-readable summary of the operation

These entries append to a plain-text log file located at `${HOME}/.desktop-commander/logs/desktop-commander-tools.log`.

## Automatic Log Rotation at 10 MiB

### Size-Based Rotation Logic

The rotation algorithm runs synchronously before every write operation. Inside [`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts), the system calls `fs.promises.stat()` to check the current file size. When the log exceeds **10 MiB** (`10 * 1024 * 1024` bytes), the module executes `maybeRotateLog()`:

```typescript
// Simplified logic from src/utils/trackTools.ts
const LOG_MAX_SIZE = 10 * 1024 * 1024; // 10 MiB

async function maybeRotateLog(filePath: string) {
  const { size } = await fs.promises.stat(filePath);
  if (size < LOG_MAX_SIZE) return;

  const date = new Date();
  const rotateTimestamp = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}_${String(date.getHours()).padStart(2, '0')}-${String(date.getMinutes()).padStart(2, '0')}-${String(date.getSeconds()).padStart(2, '0')}`;
  
  const { dir, name, ext } = path.parse(filePath);
  const newFileName = path.join(dir, `${name}_${rotateTimestamp}${ext}`);
  
  await fs.promises.rename(filePath, newFileName);
  await fs.promises.writeFile(filePath, ''); // start fresh
}

```

This synchronous-before-write approach guarantees that no audit entry is lost during rotation.

### Rotation File Naming Convention

Rotated archives retain the original base name with an appended timestamp suffix. For example, a rotation occurring on August 15, 2024 at 14:30:02 produces `desktop-commander-tools_2024-08-15_14-30-02.log`. The `path.parse()` method ensures the extension and directory structure remain consistent.

## Implementation Details and Code Examples

**Logging a tool call from your implementation:**

```typescript
import { trackToolCall } from './utils/trackTools.js';

async function runSearch(query: string) {
  const requestId = crypto.randomUUID();
  await trackToolCall({
    requestId,
    tool: 'search',
    description: `User search for "${query}"`,
    startTime: new Date().toISOString(),
  });
  // … perform the actual search …
}

```

**Inspecting logs manually:**

```bash

# Show the most recent 20 entries

tail -n 20 ~/.desktop-commander/logs/desktop-commander-tools.log

# List rotated archives (older than the active file)

ls -1 ~/.desktop-commander/logs/desktop-commander-tools_*.log

```

**Triggering rotation for testing:**

```typescript
import { writeFile } from 'fs/promises';

const LOG_PATH = `${process.env.HOME}/.desktop-commander/logs/desktop-commander-tools.log`;

// Fill the log file to exceed 10 MiB threshold
await writeFile(LOG_PATH, 'x'.repeat(10 * 1024 * 1024 + 1));

```

## Integration with the Logger Module

The audit system complements the **`logger`** module defined in [`src/utils/logger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/logger.ts). While `trackTools` handles structured tool-invocation audits, the logger provides general application logging and a **`logToStderr`** fallback for critical errors. The [`src/index.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/index.ts) file initializes global error handlers that route uncaught exceptions through this logger, ensuring that catastrophic failures are captured even if the audit stream is unavailable.

Key files in the audit pipeline:
- **[`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts)** – Core audit-logging implementation; writes entries and rotates logs at 10 MiB
- **[`src/utils/logger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/logger.ts)** – Provides the `logger` object and `logToStderr` fallback for critical errors
- **[`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts)** – Imports `trackToolCall` and forwards metadata from the HTTP server layer
- **[`src/index.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/index.ts)** – Sets up global error handlers that route exceptions through the logger

## Summary

- DesktopCommander writes JSON audit entries via `trackToolCall()` in [`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts) every time a tool executes.
- Log files reside at `${HOME}/.desktop-commander/logs/desktop-commander-tools.log` and store tool names, request IDs, timestamps, and operation descriptions.
- **Automatic rotation** occurs when the log reaches **10 MiB**, renaming the file with a `YYYY-MM-DD_HH-MM-SS` timestamp suffix and creating a fresh log.
- The rotation logic runs synchronously before each write, preventing data loss during file rollover.
- The separate `logger` module in [`src/utils/logger.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/logger.ts) handles general application errors and stderr fallback.

## Frequently Asked Questions

### Where are audit logs stored in DesktopCommander?

Audit logs are stored in the user's home directory at `${HOME}/.desktop-commander/logs/desktop-commander-tools.log`. Rotated archives remain in the same directory with timestamped suffixes (e.g., `desktop-commander-tools_2024-08-15_14-30-02.log`).

### What triggers automatic log rotation?

Rotation triggers when the active log file reaches **10 MiB** (10,485,760 bytes). The system checks file size before every write operation using `fs.promises.stat()`, ensuring that logs rotate immediately upon hitting the threshold without losing the triggering entry.

### How can I parse audit logs programmatically?

Since entries are plain JSON lines, you can parse them using standard streaming JSON parsers. Each line represents a separate tool invocation object containing `tool`, `requestId`, `startTime`, and `description` fields. For example, use `readline` in Node.js to stream the file line-by-line and `JSON.parse()` each entry.

### Is the audit logging system configurable?

The current implementation in `wonderwhy-er/DesktopCommanderMCP` uses hardcoded constants for the log path (`desktop-commander-tools.log`) and rotation size (10 MiB). To modify these behaviors, you must edit the `LOG_MAX_SIZE` constant and path variables directly in [`src/utils/trackTools.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/trackTools.ts) before building the application.