Skip to Content
ScriptingKey Bindings

Add a key binding players can change

Register a client command, then connect it to RegisterKeyMapping. The mapping supplies an initial key; the player can change it in FiveM’s key-binding settings. Do not hardcode a control-number polling loop for a normal menu toggle or command.

This example prints your character’s coordinates in the F8 console. It is deliberately local: displaying coordinates is not permission to teleport, award items, or change server state.

Make a complete resource

Create resources/[local]/doc_keys/fxmanifest.lua:

fx_version 'cerulean' game 'gta5' client_script 'client.lua'

Create client.lua:

RegisterCommand('doccoords', function() if IsPauseMenuActive() then return end local position = GetEntityCoords(PlayerPedId()) print(('Position: %.2f, %.2f, %.2f'):format( position.x, position.y, position.z )) end, false) RegisterKeyMapping('doccoords', 'Docs: print coordinates', 'keyboard', 'F7')

Run refresh and ensure doc_keys in the server console. Join the server, close F8, and press F7. Open F8 again to see Position: .... You can also enter doccoords directly in F8 to test the command independently of its binding.

Press versus hold

A press action needs one command. A held action needs paired +command and -command handlers so release clears the state. Add this independent demonstration to client.lua:

local inspecting = false RegisterCommand('+docinspect', function() if inspecting then return end inspecting = true print('Inspect mode started') end, false) RegisterCommand('-docinspect', function() inspecting = false print('Inspect mode stopped') end, false) RegisterKeyMapping('+docinspect', 'Docs: hold inspect mode', 'keyboard', 'F6')

This example changes a local flag only. If an actual feature creates cameras, disables controls, or takes NUI focus, put the corresponding cleanup in its release/close path and its resource-stop handler. Input can be interrupted; a missing key-up event must not leave a player stuck.

For a HUD that must draw every frame, a rendering loop can still be necessary. That is a different job from detecting the key. See Lua threads and timers.

Test the player’s saved binding

Open settings and locate the FiveM key-bindings section. Search for the exact label Docs: print coordinates, assign another free key, close settings, and test again. The new key should work without modifying Lua.

Changing the default key in source is not a migration of existing player preferences. Keep command names stable between releases, and tell users how to rebind an existing command rather than deleting their configuration.

SymptomIsolate it
Typing doccoords in F8 works, but the key does notCheck the saved binding, key conflicts, and whether another UI owns focus
Command is unknownCheck client script loading and ensure doc_keys
Label is absent from settingsConfirm RegisterKeyMapping ran on the client, not the server
Hold action never stopsConfirm the matching -docinspect command exists and cleanup is not only in the key-down handler
Old key still works after updating the defaultInspect the saved user binding; do not assume source defaults overwrite it

Keep authorization on the server

The final false in these client commands is not an access-control policy. Never protect an administrative action by hiding its key binding. When a key requests a server action, use validated network events. For server commands use restricted commands and ACE permissions.

The Cfx.re key-binding example  explains the command/mapping pattern. It is an archived article; this guide does not carry forward its historical limitations as current guarantees. See also NUI focus and close behavior.