Updating modifier key mappings through defaults command tool
It's important for the defaults command to use the correct "keyboard ID" in the key, it seems to be: com.apple.keyboard.modifiermapping.$VendorID-$ProductID-0

For example the internal keyboard for my MacBook Air uses: com.apple.keyboard.modifiermapping.1452-579-0, while the external keyboard on my iMac uses com.apple.keyboard.modifiermapping.1118-219-0

How to get the correct "keyboard ID"? On the command line you can use:

ioreg -p IOUSB -c IOUSBDevice | grep -e class -e idVendor -e idProduct


to get a list of your USB devices with the relevant parameters:

  [...]
  +-o Natural® Ergonomic Keyboard 4000@fa140000  &lt;class IOUSBDevice, id 0x100000452, registered, matched, active, busy 0 (115 ms), retain 12&gt;
        "idProduct" = 219
        "idVendor" = 1118


My guess is that the third parameter (the "-0" part) is a "counter", in case you have more than one keyboard of the same type.

So, to switch off the CapsLock key on my external keyboard I can now use:

defaults -currentHost write -g com.apple.keyboard.modifiermapping.1118-219-0 -array-add '&lt;dict&gt;&lt;key&gt;HIDKeyboardModifierMappingDst&lt;/key&gt;&lt;integer&gt;-1&lt;/integer&gt;&lt;key&gt;HIDKeyboardModifierMappingSrc&lt;/key&gt;&lt;integer&gt;0&lt;/integer&gt;&lt;/dict&gt;'




And, for completeness' sake, here's a list of possible key codes to use (from Mac OS X Hints):


None — –1
Caps Lock — 0
Shift (Left) — 1
Control (Left) — 2
Option (Left) — 3
Command (Left) — 4
Keypad 0 — 5
Help — 6
Shift (Right) — 9
Control (Right) — 10
Option (Right) — 11
Command (Right) — 12




Update: thanks to Lauri Ranta here's a command that works for Bluetooth &amp; USB keyboards:

ioreg -n IOHIDKeyboard -r | grep -e 'class IOHIDKeyboard' -e VendorID\" -e Product


which gives you slightly different output:

+-o IOHIDKeyboard  &lt;class IOHIDKeyboard, id 0x100000489, registered, matched, active, busy 0 (0 ms), retain 8&gt;
  |   "Product" = "Apple Wireless Keyboard"
  |   "VendorID" = 1452
  |   "ProductID" = 570