Garry's Mod external console software.

- Download the latest release.
- Launch the gterm executable whenever Garry's Mod is running.
- Restart Garry's Mod to complete the installation.
- Enjoy!
- Download the latest release of
gterm. - Move the
.dll(even on macos/linux!) undersrcds/garrysmod/lua/bin(if thebinfolder doesnt exist, create it). - In
srcds/garrysmod/lua/includes/init.luaadd at the top of the filerequire("gterm"). - Restart the server.
- Launch the gterm executable.
- Enjoy!
IMPORTANT NOTE: GTerm communicates with the gmod module over a localhost TCP socket (127.0.0.1:27514), so GTerm must run on the same host as the server. If you run your server inside a docker container or any other sandbox, run GTerm inside that same sandbox (or otherwise share the loopback interface).
- Download the latest release of
gterm. - Move the
.dll(even on macos/linux!) underGarrysMod/garrysmod/lua/bin(if thebinfolder doesnt exist, create it). - In
GarrysMod/garrysmod/lua/menu/menu.luaadd at the bottom of the filerequire("gterm"). - Restart Garry's Mod.
- Voila!
GTerm includes a WebSocket server for console streaming and command execution.
Setup:
- Enable API in
Config.json:"API": true - Connect WebSocket clients to
ws://localhost:27512/ws/
Configuration Options:
{
"API": true,
"APIPort": 27512,
"APISecret": "your_secret_here"
}Example Payloads:
Sending commands (text message):
status
Receiving console output (JSON):
{
"Time": 1704123456,
"Data": [
{
"Color": { "R": 255, "G": 255, "B": 255, "A": 255 },
"Text": "hostname: My Server\n"
}
]
}GTerm includes an MCP (Model Context Protocol) server for AI agents such as Cursor, Vscode, Zed, Claude Code, etc..
Setup:
- Enable MCP in
Config.json:"MCP": true - (Optional) Set
"MCPSecret"for authentication - Configure your MCP client to connect to
http://localhost:27513(add?secret=...if using authentication)
Available Tools:
get_game_status- Report whether GMod is connected, in a session, and which Lua realms can run code right now (map, gamemode, players). Works even while GMod is closed. Agents should call this first.run_gmod_command- Execute a console command and capture its outputexecute_lua_code- Execute Lua in a required realm (serverorclient).validate_lua_syntax- Compile-check Lua with the game's ownCompileStringwithout executing itcheck_game_file- Ask the running game whether a path exists in its virtual filesystem (mounted addons/GMAs included), not just on diskcapture_console_output- Monitor console output for a durationlist_gmod_directory- Browse the Garry's Mod file structure on diskread_gmod_file- Read a text file from the installation on diskread_game_file- Read a file's contents from the running game's virtual filesystem (mounted addons, Workshop GMAs), which the on-disk reader can't seetake_screenshot_region- Capture one rectangle of the screen and return it enlarged, so a HUD element, viewmodel or panel is actually legible. Preferred over the full-screen shot for anything specifictake_screenshot- Capture the whole screen. Last resort: prove things with Lua state and arithmetic firstread_gmod_wiki- Fetch a page from the Garry's Mod wiki (wiki.facepunch.com/gmod) to check a function's real signature before using itlist_tool_packages- Lists all the third party tools provided by addons inlua/gterm_packages/*.lua(see below)request_tool_packages- Ask the user, in GTerm's own console, which packages to enable. The agent cannot choose by itselfcall_package_tool- Run one tool from an enabled package with a JSON args object
Every tool result is prefixed with a [GTerm] status line so the agent always knows the connection and realm state. When a precondition is not met (disconnected, wrong realm, no session), the tool returns an error explaining what to do rather than failing silently; pass force: true to attempt the call anyway.
Seeing what an agent is doing. MCP clients show the tool name but usually not the arguments, so GTerm surfaces them itself: every tool call prints a magenta [agent] line in GTerm's console before it runs. Lua is shown in full on its own lines with Monokai syntax highlighting, and console commands are highlighted inline.
Addons and servers can provide their own tools to the agent as Lua files at lua/gterm_packages/<package>.lua. GTerm discovers and loads packages with client-realm Lua (sv_allowcslua must be 1).
Enabling is done manually in GTerm's console using packages in GTerm, or when the agent calls request_tool_packages. Consent is stored in Config.json under ToolPackageConsent per scope (server IPv4, or local for listen servers and singleplayer).
The file returns a table: optional description, optional server (IPv4; only usable on that server), and tools. Each tool has name ([a-z][a-z0-9_]*), description, inputSchema (JSON schema, type = "object"), optional realm ("client", the default, or "server"), and run(args). Its return value (string or table) comes back as the result, capped at 4096 characters by print. Limits: 32 tools, 512-character descriptions, 8 KB input schema, 256 KB definition. Package names: [a-z0-9][a-z0-9_-]{0,63}.
Example lua/gterm_packages/my_addon.lua:
return {
description = "Helpers for my addon.",
tools = {
{
name = "find_entities",
description = "Lists entities of a class near the local player.",
inputSchema = {
type = "object",
properties = {
class = { type = "string", description = "Entity class, e.g. prop_physics" },
radius = { type = "number", description = "Search radius in units (default 512)" },
},
required = { "class" },
},
run = function(args)
local out = {}
for _, e in ipairs(ents.FindInSphere(LocalPlayer():GetPos(), args.radius or 512)) do
if e:GetClass() == args.class then out[#out + 1] = { id = e:EntIndex(), pos = tostring(e:GetPos()) } end
end
return out
end,
},
{
name = "count_props",
description = "Counts props on the server (listen server or singleplayer only).",
inputSchema = { type = "object" },
realm = "server",
run = function() return #ents.FindByClass("prop_physics") end,
},
},
}Configuration Options:
{
"MCP": true,
"MCPPort": 27513,
"MCPCollectionWindowMs": 1000,
"MCPSecret": "your_secret_here"
}MCP Client Example (with secret):
{
"mcpServers": {
"gterm": {
"url": "http://localhost:27513?secret=your_secret_here"
}
}
}