DEV Community

Cover image for πŸ” Tracking Global Keyboard Shortcuts in Node.js (Windows)
Jigar Gosar
Jigar Gosar

Posted on

πŸ” Tracking Global Keyboard Shortcuts in Node.js (Windows)

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 CTRL β†’ Ctrl
  • βœ… 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.

Top comments (0)