OnServerCommand
OnServerCommand is called by Oxide's command dispatcher before a console command is executed, giving plugins a chance to block it. Returning a non-null value stops the command from running.
object OnServerCommand(ConsoleSystem.Arg arg)Parameters
| Parameter | Type | Description |
|---|---|---|
arg | ConsoleSystem.Arg | The ConsoleSystem.Arg describing the queued console command: arg.cmd.FullName is the command string (e.g. 'global.kill'), arg.Connection identifies the calling client (null for server console/RCON), arg.Player() resolves the connected player, and arg.Args holds the raw string arguments. |
Return value
Return null (or nothing) to let the command run normally. Return any non-null object to block the command entirely; Oxide then reports the command as handled and the original command never executes. A returned value does not become the command's output, it only acts as a stop signal.
How it works
This hook is not a patched game method; Oxide calls it from its own IOnServerCommand gate before a player or server console command reaches the game. It runs for player-issued commands (arg.Connection is set) and for commands executed server-side or over RCON (arg.Connection is null). Three chat commands, chat.say, chat.teamsay and chat.localsay, are filtered out before the hook and never reach it, so use OnPlayerChat for chat. arg.cmd.FullName gives the command path, arg.Args the argument array, and arg.Player() the issuing player or null. The hook also has a second, covalence-style form OnServerCommand(string command, string[] args); Oxide calls both and prefers the Arg result when both return something. Declaring the parameter as ConsoleSystem.Arg keeps you on this overload. It fires for every command a client sends, which can be many per second, so keep the body cheap and avoid logging.
Example plugin: Block .kill and other commands for non-admins
using UnityEngine;
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Command Blocker", "RustPluginGenerator", "1.0.0")]
[Description("Blocks configured console commands unless the player has a bypass permission")]
public class CommandBlocker : RustPlugin
{
private const string PermBypass = "commandblocker.bypass";
private PluginConfig config;
private HashSet<string> blocked;
private class PluginConfig
{
[JsonProperty("Blocked commands")]
public List<string> BlockedCommands = new List<string>
{
"kill",
"respawn",
"global.kill",
"global.respawn"
};
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new Exception();
}
catch
{
PrintWarning("Configuration file is invalid, using defaults");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Blocked"] = "The command '{0}' is not allowed on this server."
}, this);
}
private string Msg(string key, string userId = null, params object[] args) =>
string.Format(lang.GetMessage(key, this, userId), args);
private void Init()
{
permission.RegisterPermission(PermBypass, this);
}
private void OnServerInitialized()
{
blocked = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string command in config.BlockedCommands)
{
if (!string.IsNullOrEmpty(command))
blocked.Add(command.Trim());
}
}
private object OnServerCommand(ConsoleSystem.Arg arg)
{
if (arg == null || arg.cmd == null || blocked == null || blocked.Count == 0)
return null;
string command = arg.cmd.FullName;
if (string.IsNullOrEmpty(command) || !blocked.Contains(command))
return null;
BasePlayer player = arg.Player();
if (player == null)
return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass))
return null;
player.ChatMessage(Msg("Blocked", player.UserIDString, command));
return false;
}
}
}The plugin stores a list of blocked console commands in its config and registers a permission that grants exemptions. In OnServerCommand it reads arg.cmd.FullName, ignores anything not on the list, and resolves the calling player through arg.Player(). Server console and RCON calls have no player and pass through untouched. If a player issues a blocked command without commandblocker.bypass, the plugin sends a localized chat reply and returns false to stop the command. Because the hook can fire rapidly, nothing is logged per call; the only output is the reply to the blocked player.
Common use cases
Block client console commands
Prevent players from running commands like
kill,respawnorglobal.inventoryoutside their intended context by returning a truthy value from the hook.Audit or gate admin tooling
Only allow a whitelist of commands to players in an admin group, blocking everything else and replying with a permission message.
Rate-limit spammy commands
Track per-player command timestamps and block a command when it arrives too frequently, reducing input flooding on the server.
Pitfalls
Chat commands are excluded
chat.say,chat.teamsayandchat.localsayare filtered out before this hook is called, so blocking them here silently fails. UseOnPlayerChatorOnUserChatinstead.Runs at high frequency
Any client can send commands repeatedly, so the hook body should be a fast string comparison against a small set. Avoid allocations, data file reads or logging inside it.
Two overloads are invoked
Oxide also calls
OnServerCommand(string, string[]). If you implement both, keep their return values consistent; theArgresult takes priority when it is non-null.
Plugin recipes that use OnServerCommand
Build a plugin with OnServerCommand
Describe what should happen and get a compiled plugin that uses this hook.
Edit the prompt on the next screen. 2 free plugins a month, no card.
Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.
Build a plugin with OnServerCommand
Generate