Search docs
Search modules and symbols
Commands

Commands

Register console and chat commands with command / command.server / command.admin from the @s2script/sdk barrel — the spelling s2s create scaffolds:

import { command, ADMFLAG, HookResult } from '@s2script/sdk';
import type { Command, HookResultValue } from '@s2script/sdk';

export function OnPluginStart(): void {
  command('hello', (cmd) => {
    cmd.reply(`hi from slot ${cmd.callerSlot}`);
    return HookResult.Handled;
  });

  command.server('sm_reloadmap', (cmd) => {
    cmd.reply('reloading');
    return HookResult.Handled;
  });

  command.admin('sm_kick', ADMFLAG.KICK, kick);
}

function kick(cmd: Command): HookResultValue {
  if (cmd.argCount < 1) {
    cmd.reply('Usage: sm_kick <target>');
    return HookResult.Handled; // usage errors still consume the command
  }
  return HookResult.Handled;
}
  • command — anyone / console (SourceMod RegConsoleCmd)
  • command.server — server console only (callerSlot < 0; SourceMod RegServerCmd)
  • command.admin — flag-gated via the host admin cache (SourceMod RegAdminCmd)
  • command.onClientCommand — observe an existing CLIENT command by name (SourceMod AddCommandListener)

command is load-window only — it throws after settle. Call it from OnPluginStart. CS2 types stay on @s2script/cs2; @s2script/sdk/unsafe and @s2script/sdk/console stay subpaths (not re-exported on the barrel).

Return values

A command you own is a SourceMod Action callback; ours is HookResult. Return HookResult.Handled (Plugin_Handled) on every path, including usage errors — the command was still consumed. Omit the return (void) to continue — the same as returning HookResult.Continue.

Chat listeners that must pass through — basetriggers, or a bare rtv / nominate word — return HookResult.Continue so the player’s line still broadcasts:

export function OnClientSayCommand(slot: number, text: string, teamonly: boolean): HookResultValue {
  if (text.trim().toLowerCase() === 'rtv') {
    requestRtv(slot);
  }
  return HookResult.Continue; // never suppress — the trigger word still shows
}

The cmd invocation is engine-generic (callerSlot, args, argString, reply). Command on @s2script/sdk is an alias for CommandInvocation. Chat ! / / triggers reach the same registry. Player replies are deferred one frame so they land after the chat line (SourceMod parity).

cmd.replyT(key, …args) replies in the caller’s language (SourceMod’s %t). Load the phrase files first — see Translations. The key is checked at build against those files; a plugin that loads none widens it to string. A missing file or an unloaded @s2script/translations degrades to the raw key.

Cookbook recipes in the SDK repo are copy-pasteable named-public plugins: export function OnPluginStart plus any other publics they need (OnGameFrame, OnClientConnected, …).

See the commands module and admin module.

s2script — Source 2 plugin framework

GitHub