Cfx Lua IntelliSenseA Visual Studio Code extension that brings full IntelliSense, auto-completion, diagnostics, and type annotations to the Lua scripting environment used by FiveM and RedM. Built on top of the Lua Language Server by sumneko, this extension automatically configures your workspace with the correct runtime definitions, native function signatures, and LuaGLM type information so you can write Cfx.re Lua scripts with confidence.
Table of Contents
What It DoesWhen you open a Lua file in VS Code with this extension active, it will:
Supported Platforms
Prerequisites
InstallationFrom the VS Code Marketplace
Getting StartedOnce installed, the extension activates when you open a Configuration is applied only to workspaces that contain an By default, GTA V (FiveM) natives are loaded. To switch to RedM natives, click the
Your selection is persisted in your VS Code settings, and you can switch at any time — nothing is inferred from your manifest. CommandsAll commands are available from the Command Palette under the CfxLua category.
Configuration
You can change this in your VS Code
Or use the provided commands from the Command Palette (also available via the status bar toggle):
When switching games, the extension will remove the previous game's native library and add the new one, keeping CFX shared natives always active. Multi-root workspaces
DiagnosticsTwo checks run on top of whatever the Lua Language Server reports. Both can be turned off individually. Wrong-side native callsEvery native is visible in every file, which makes calling a client-only native
from a server script easy to do and impossible to notice until it fails at
runtime. This check reads your manifest's
It is deliberately conservative, and stays silent unless it is certain:
Set Misspelled manifest keysA manifest may carry arbitrary metadata keys, which is why unknown globals aren't
reported there — and why
Custom metadata keys such as Manifest Support
Type SnippetsAvailable in any Lua file:
Sharing Configuration With a TeamEverything above is written to your personal VS Code settings, which a team can't
commit and Paths are written relative to Native LibrariesNative function definitions are organized into three sets: CFX Shared Natives (
|
| Type | Fields | Description |
|---|---|---|
vector2 |
x, y (aliases: r, g) |
2D vector with arithmetic operator overloads |
vector3 |
x, y, z (aliases: r, g, b) |
3D vector extending vector2 |
vector4 |
x, y, z, w (aliases: r, g, b, a) |
4D vector extending vector3 |
quat |
x, y, z, w |
Quaternion type extending vector4 |
All vector types support:
- Arithmetic operators:
+,-,*,/, unary- - Length operator:
# - Swizzle access:
.xy,.xyz, etc. - Indexed access:
[1],[2],[3],[4]
Nonstandard Operators
The extension configures the Lua Language Server to recognize these Cfx-specific operators:
+= -= *= /= <<= >>= &= |= ^=
`template strings`
/**/ (block comments)
[!CAUTION] Some of these "power patches" have been known to cause instability. Use extended syntax features with caution in production scripts.
The Plugin System
The extension installs a Lua Language Server plugin (plugin.lua) that preprocesses Lua files before the language server analyzes them. This plugin handles several Cfx-specific quirks:
Safe Navigation Operator
Cfx Lua supports foo?.bar and foo?[index] syntax, which standard Lua does not. The plugin strips the ? character from these expressions to prevent parse errors, and rewrites usage to suppress need-check-nil diagnostics.
Manifest File Support
Files named fxmanifest.lua and __resource.lua use globals like fx_version, game, client_script, etc., that aren't defined anywhere in user code. The plugin injects ---@diagnostic disable: undefined-global at the top of these files to prevent false positive warnings.
FX Asset Protection
Files beginning with the FXAP header (FiveM asset protection) are encrypted and not valid Lua — the plugin returns an empty string for these files so the language server skips them gracefully.
.vscode and @meta Filtering
The plugin ignores files inside .vscode directories and files starting with ---@meta (such as the native definition files themselves) to avoid unnecessary processing.
How It Works Under the Hood
When the extension activates (triggered by opening a .lua file, or by a resource manifest in the workspace):
Workspace Detection — Unless
cfxlua.autoConfiguresays otherwise, the extension looks for anfxmanifest.luaor__resource.luain the open folders. If it finds none, it registers its commands and stops there, leaving unrelated Lua projects untouched. A manifest appearing later, or a folder being added to a multi-root workspace, triggers configuration then.File Migration — The bundled
plugin.luaandlibrary/directory are copied from the extension's install location to VS Code's global storage for the extension. This ensures a stable path that persists across extension updates. The copy is versioned: a.versionmarker in global storage records which extension version last populated it, so the ~150-file library is only recopied after an extension update — not on every VS Code launch.Plugin Registration — The path to
plugin.luais written to theLua.runtime.pluginsetting, telling the Lua Language Server to load it.Library Injection — The paths to the appropriate definition folders (
runtime/,manifest/,natives/CFX-NATIVE/, and eithernatives/GTAV/ornatives/RDR3/) are appended toLua.workspace.library, making all type information available to the language server.Runtime Configuration — The Lua runtime version is set to
5.4, nonstandard symbols are registered, and workspace ignore directories are configured to improve performance.Native Data, On Demand — Two compressed data files ship with the definition library. The small one (which sides each native supports) is read the first time a script is actually checked; the large one (hashes, signatures) only when you search the natives or hover a hash. Nothing is read during activation, so a window that never needs them never pays for them, and if either is missing the features using it stay quiet while everything else works as normal.
Settings are left in place when VS Code closes. Earlier versions removed them on deactivation and rewrote them on the next launch, which meant two settings.json writes and two language server reloads per session, a spurious diff in any tracked .code-workspace, and no guarantee the removal completed — VS Code does not wait for asynchronous work during shutdown. Use CfxLua: Remove configuration to undo everything deliberately.
All paths written to settings are stored ~-relative on every platform, so they stay portable across machines (e.g. via Settings Sync). Stale entries in older formats — including leftovers from the archived Overextended extension — are cleaned up automatically. Settings only get written when their value actually changes, so activation doesn't touch your settings.json or restart the language server unnecessarily.
Settings are applied at the workspace level when a .code-workspace file is present, or at the global (user) level otherwise. In multi-root workspaces, game-specific settings (cfxlua.game and the corresponding Lua.workspace.library entries) are written at the workspace folder level for the folder of the active editor.
Project Structure
cfxlua-vscode/
├── src/ # Extension source code (TypeScript)
│ ├── extension.ts # Entry point — activation, command registration
│ ├── isCfxWorkspace.ts # Manifest-based detection of a Cfx project
│ ├── ensureStorage.ts # Version-gated copy of bundled files to global storage
│ ├── getLuaConfig.ts # Helper to access the Lua Language Server configuration
│ ├── getSettingsScope.ts # Determines folder vs. workspace vs. global settings scope
│ ├── libraryUtils.ts # Pure helpers for library-entry cleanup and comparison
│ ├── logger.ts # "CfxLua" output channel logging
│ ├── lua.ts # Minimal Lua tokenizer — tells code from strings and comments
│ ├── manifest.ts # Manifest parsing, script globs, key suggestions
│ ├── nativeCatalog.ts # Queries over the native index (pure)
│ ├── nativesIndex.ts # Loads the compressed native index
│ ├── nativeScope.ts # Finds natives called from the wrong side (pure)
│ ├── diagnostics.ts # Publishes the diagnostics to VS Code
│ ├── findNative.ts # "Find Native" quick pick
│ ├── nativeHover.ts # Resolves a native hash on hover
│ ├── newResource.ts # "New Resource" scaffold
│ ├── writeLuarc.ts # ".luarc.json" export
│ ├── setLibrary.ts # Manages Lua.workspace.library entries
│ ├── setNativeLibrary.ts # Handles game-specific native library switching
│ ├── setPlugin.ts # Configures Lua.runtime.plugin and related settings
│ ├── toTildePath.ts # Rewrites home-relative paths to portable ~ form
│ └── test/unit/ # Unit tests for the pure modules
│
├── snippets/cfxlua.json # Lua snippets for common Cfx patterns
│
├── plugin/ # Git submodule (ihyajb/fivem-lls-addon) — plugin and library definitions
│ ├── plugin.lua # Lua Language Server plugin for Cfx-specific preprocessing
│ ├── config.json # Default Lua Language Server addon configuration
│ ├── native-scopes.json.gz # Which sides each native supports
│ ├── natives-index.json.gz # Every native as data, for search and hovers
│ └── library/
│ ├── manifest/ # fxmanifest.lua / __resource.lua definitions
│ ├── runtime/ # Cfx runtime type definitions
│ │ ├── citizen.lua # Citizen API (CreateThread, Wait, etc.)
│ │ ├── env.lua # Environment globals (events, HTTP, statebags)
│ │ ├── event.lua # Event handling types
│ │ ├── json.lua # JSON encode/decode types
│ │ ├── luaglm.lua # Vector, quaternion, matrix types
│ │ ├── msgpack.lua # MessagePack types
│ │ └── promise.lua # Promise library types
│ └── natives/
│ ├── CFX-NATIVE/ # CFX shared natives (always loaded)
│ │ └── CFX.lua
│ ├── GTAV/ # GTA V natives (43 category files)
│ │ ├── VEHICLE.lua
│ │ ├── PED.lua
│ │ └── ...
│ └── RDR3/ # RDR3 natives (60+ category files)
│ ├── PED.lua
│ ├── ENTITY.lua
│ └── ...
│
├── package.json # Extension manifest and bun scripts
├── tsconfig.json # TypeScript configuration (typecheck only)
└── biome.json # Linting and formatting configuration
Troubleshooting
IntelliSense isn't working
- Ensure the Lua Language Server extension is installed and enabled.
- Check that the workspace contains an
fxmanifest.luaor__resource.lua. Without one, the extension configures nothing — setcfxlua.autoConfiguretoalways, or run any CfxLua command to configure the workspace anyway. - Run CfxLua: Show Log to see what happened on activation.
- Run CfxLua: Repair configuration to recopy the definition library and reapply every setting.
- Check that
cfxlua.gameis set to a valid value ("gtav"or"rdr3").
Natives from the old Overextended extension are duplicating
This extension includes migration logic that automatically removes library paths from the original overextended.cfxlua-vscode extension. If you still see duplicates, manually check your Lua.workspace.library setting and remove any paths containing overextended.cfxlua-vscode.
Diagnostics appear in fxmanifest.lua
The extension's plugin suppresses undefined-global warnings in manifest files. If you're still seeing them, verify that Lua.runtime.plugin points to the correct plugin.lua path in your settings.
Safe navigation (?.) shows errors
The plugin rewrites safe navigation syntax to prevent parse errors. If it's not working, ensure the plugin is correctly loaded by checking Lua.runtime.plugin in your settings.
Extension settings aren't applying
The extension applies settings at the workspace level if a .code-workspace file is open, otherwise at the user (global) level. In multi-root workspaces, game-specific settings are written per workspace folder (for the folder of the active editor). Check the appropriate settings scope for your configuration — folder settings override workspace settings, which override user settings.
A wrong-side warning is wrong
Open an issue with the native's name and the manifest entry that loads the file — the check reads client_scripts, server_scripts and shared_scripts globs, so an unusual glob is the likeliest cause. In the meantime, set cfxlua.diagnostics.nativeScope to false.
Native search says the index is unavailable
The data files ship in the plugin submodule. In a development checkout, run git submodule update --init --recursive. Everything except native search, hash hover and the wrong-side check works without them.
Natives seem out of date
Native definitions are pulled weekly from the fivem-lls-addon repository and shipped in extension updates, so make sure the extension is up to date. The definition files in global storage are refreshed automatically the first time a new extension version activates.
Contributing
- Clone the repository including the
pluginsubmodule (without it, the extension has no native definitions to load):
If you already cloned without submodules, rungit clone --recurse-submodules https://github.com/ihyajb/cfxlua-vscode.gitgit submodule update --init --recursive. - Install Bun, then install dependencies:
cd cfxlua-vscode bun install - Open the project in VS Code and press
F5to launch the Extension Development Host. - The default build task runs
bun run watch, which rebuilds the bundle on change.
Building
Bun is the whole toolchain — package manager, bundler and test runner. There is no
webpack, no tsc build step, and no node_modules in the published extension.
bun run build # Development build, with a source map
bun run package # Production build, minified
bun run vsix # Build and package a .vsix
bun build targets Node and emits CommonJS, which is what the VS Code extension
host loads, with vscode left external.
Testing
bun test src # Run the unit tests
bun run typecheck # Typecheck (Bun does not typecheck on its own)
Tests cover the pure modules: the tokenizer, manifest parsing and glob matching, the native catalog, and the wrong-side check — including cases asserted against the index that actually ships, so a data regression fails the build rather than reaching users as a false warning.
Linting & Formatting
bun run lint # Lint, format and organise imports, with fixes applied
bun run check # Report without fixing, as CI does
Credits
This project builds upon the work of many contributors to the Cfx.re ecosystem:
- Overextended — creators of the original cfxlua-vscode extension
- CitizenFX Collective — developers of FiveM, RedM, and the LuaGLM runtime
- sumneko — author of the Lua Language Server
- gottfriedleibniz — LuaGLM implementation
- alloc8or, iTexZoz, TasoOneAsia — community contributions to native definitions and tooling
License
This project is licensed under the MIT License.