🔍 Tracking Global Keyboard Shortcuts in Node.js (Windows)
Jigar Gosar

Jigar Gosar @jigargosar

About: elm programmer

Joined:
May 12, 2025

🔍 Tracking Global Keyboard Shortcuts in Node.js (Windows)

Publish Date: Jul 6
0 0

Capturing global keyboard shortcuts like Ctrl + C or Shift + Alt + S can be incredibly useful for building productivity tools, real-time overlays, or accessibility utilities. But doing it cleanly — without logging noisy or repeated key events — requires careful handling of modifier keys and key state.

This post walks through how to build a global key combo tracker in Node.js on Windows, and explains the logic behind each part of the implementation.


🧩 The Challenge

Most global key listeners log every key event — including repeated Ctrl, Shift, or Alt presses — which leads to noisy, unreadable logs like:

LEFT CTRL
LEFT CTRL
LEFT CTRL
A
Enter fullscreen mode Exit fullscreen mode

To build a clean and useful tracker, we need to:

  • ❌ Ignore modifier keys when pressed alone
  • ✅ Log only meaningful combinations (e.g. Ctrl + A)
  • ✅ Normalize key names like LEFT CTRLCtrl
  • ✅ Prevent repeated logs while keys are held
  • ✅ Support global tracking, even when the app is not focused

⚙️ Implementation

1. Install the Listener

We use node-global-key-listener, a native module that captures global key events across the OS.

npm install node-global-key-listener
Enter fullscreen mode Exit fullscreen mode

2. Core Logic

const { GlobalKeyboardListener } = require("node-global-key-listener");

const keyboard = new GlobalKeyboardListener();
const heldModifiers = new Set();
const loggedCombos = new Set();

const MODIFIERS = new Set([
  "LEFT CTRL", "RIGHT CTRL",
  "LEFT SHIFT", "RIGHT SHIFT",
  "LEFT ALT", "RIGHT ALT",
  "LEFT META", "RIGHT META"
]);

keyboard.addListener((e) => {
  const key = e.name.toUpperCase();

  if (e.state === "DOWN") {
    if (MODIFIERS.has(key)) {
      heldModifiers.add(normalizeModifier(key));
    } else {
      const combo = heldModifiers.size > 0
        ? [...heldModifiers, key].join(" + ")
        : key;

      if (!loggedCombos.has(combo)) {
        loggedCombos.add(combo);
        console.log(combo);
      }
    }
  } else if (e.state === "UP") {
    if (MODIFIERS.has(key)) {
      heldModifiers.delete(normalizeModifier(key));
    } else {
      loggedCombos.clear();
    }
  }
});

function normalizeModifier(key) {
  if (key.includes("CTRL")) return "Ctrl";
  if (key.includes("SHIFT")) return "Shift";
  if (key.includes("ALT")) return "Alt";
  if (key.includes("META")) return "Meta";
  return key;
}
Enter fullscreen mode Exit fullscreen mode

🧠 Why This Works

🔹 Modifier Filtering

We define a set of known modifier keys (LEFT CTRL, RIGHT SHIFT, etc.) and track them in heldModifiers. These keys are ignored when pressed alone — they only contribute to a combo.

🔹 Normalization

The OS reports keys like LEFT CTRL and RIGHT CTRL separately. For clarity and consistency, we normalize them to a single label (Ctrl, Shift, etc.) using the normalizeModifier() function.

This ensures that:

  • LEFT CTRL + A and RIGHT CTRL + A both log as Ctrl + A
  • The output is clean and human-readable

🔹 Combo Construction

When a non-modifier key is pressed:

  • If modifiers are held → log the full combo (e.g. Ctrl + A)
  • If no modifiers are held → log the key alone (e.g. A)

🔹 Duplicate Prevention

We use a loggedCombos set to ensure each combo is logged only once per press. This avoids repeated logs when holding keys.

🔹 Reset on Key Release

When a non-modifier key is released, we clear the loggedCombos set so the next press can be logged again.


🧪 Example Output

Ctrl + C
Shift + Alt + S
Escape
A
Enter fullscreen mode Exit fullscreen mode
  • Ctrl alone → ignored
  • A → logged
  • Ctrl + A → logged once
  • ✅ Holding keys → no spam

🚀 What’s Next?

This Node.js core is a clean foundation for more advanced tools. You could extend it by:

  • 🖼️ Wrapping it in an Electron app with a floating overlay
  • 💾 Logging combos to a file or clipboard
  • 🎨 Styling the UI with themes and transparency
  • 📦 Packaging it as a cross-platform desktop utility

🧠 Conclusion

This project demonstrates how to:

  • Handle global keyboard input in Node.js
  • Filter and normalize noisy key events
  • Design a clean shortcut-tracking system

It’s a great one-day build with real-world utility — and a perfect launchpad for more advanced desktop tools.


You can find the full source code on GitHub: global-key-logger.

Comments 0 total

    Add comment