Skip to main content
The IChatGui service allows you to interact with the game’s chat system, including sending messages and handling incoming chat events.

Getting Started

Inject the service into your plugin:
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using Dalamud.Game.Text;

public class MyPlugin : IDalamudPlugin
{
    private readonly IChatGui chatGui;

    public MyPlugin(IChatGui chatGui)
    {
        this.chatGui = chatGui;
        
        // Subscribe to chat events
        this.chatGui.ChatMessage += OnChatMessage;
    }

    private void OnChatMessage(
        XivChatType type,
        int timestamp,
        ref SeString sender,
        ref SeString message,
        ref bool isHandled)
    {
        // Process incoming chat messages
    }

    public void Dispose()
    {
        this.chatGui.ChatMessage -= OnChatMessage;
    }
}

Sending Messages

Queue a chat message. Dalamud will send queued messages on the next framework event.
void Print(string message, string? messageTag = null, ushort? tagColor = null)
message
string
required
The message to send
messageTag
string
String to prepend message with “[messageTag] ”
tagColor
ushort
Color to display the message tag with
Example:
chatGui.Print("Hello, world!");
chatGui.Print("Plugin message", "MyPlugin", 575);
Queue a chat message with SeString formatting.
void Print(SeString message, string? messageTag = null, ushort? tagColor = null)
Example:
var builder = new SeStringBuilder()
    .AddUiForeground("Colored text", 500)
    .AddText(" normal text");

chatGui.Print(builder.Build(), "MyPlugin");
Queue a full chat entry with all properties.
void Print(XivChatEntry chat)
Example:
var entry = new XivChatEntry
{
    Type = XivChatType.Echo,
    Message = "Custom message",
    Name = "System"
};

chatGui.Print(entry);

PrintError

Queue an error message. Appears in error chat style.
void PrintError(string message, string? messageTag = null, ushort? tagColor = null)
void PrintError(SeString message, string? messageTag = null, ushort? tagColor = null)
Example:
chatGui.PrintError("Something went wrong!");
chatGui.PrintError("Failed to load data", "MyPlugin");
Create clickable links in chat that trigger custom actions.

AddChatLinkHandler

Register a chat link handler.
DalamudLinkPayload AddChatLinkHandler(uint commandId, Action<uint, SeString> commandAction)
commandId
uint
required
The ID of the command (unique to your plugin)
commandAction
Action<uint, SeString>
required
The action to execute when the link is clicked
Returns: An SeString payload for the link. Example:
var linkPayload = chatGui.AddChatLinkHandler(1, (id, payload) =>
{
    chatGui.Print("Link clicked!");
});

var message = new SeStringBuilder()
    .AddText("Click ")
    .Add(linkPayload)
    .AddUiForeground("[here]", 500)
    .Add(RawPayload.LinkTerminator)
    .AddText(" for more info");

chatGui.Print(message.Build());

RemoveChatLinkHandler

Remove a specific chat link handler or all handlers registered by the plugin.
void RemoveChatLinkHandler(uint commandId)
void RemoveChatLinkHandler()
Example:
// Remove specific handler
chatGui.RemoveChatLinkHandler(1);

// Remove all handlers (typically in Dispose)
chatGui.RemoveChatLinkHandler();

RegisteredLinkHandlers

Gets the dictionary of Dalamud link handlers.
IReadOnlyDictionary<(string PluginName, uint CommandId), Action<uint, SeString>> RegisteredLinkHandlers { get; }

Events

ChatMessage

Event that fires when a chat message is sent to chat by the game.
event OnMessageDelegate ChatMessage
Delegate signature:
public delegate void OnMessageDelegate(
    XivChatType type,
    int timestamp,
    ref SeString sender,
    ref SeString message,
    ref bool isHandled)
type
XivChatType
The type of chat
timestamp
int
The timestamp of when the message was sent
sender
SeString
The sender name (modifiable)
message
SeString
The message sent (modifiable)
isHandled
bool
Set to true to mark the message as handled
Example:
chatGui.ChatMessage += (type, timestamp, ref sender, ref message, ref isHandled) =>
{
    if (type == XivChatType.Say)
    {
        // Process say messages
        var text = message.TextValue;
        if (text.Contains("secret"))
        {
            message = new SeString(new TextPayload("[REDACTED]"));
        }
    }
};

CheckMessageHandled

Event that allows you to stop messages from appearing in chat by setting the isHandled parameter to true.
event OnCheckMessageHandledDelegate CheckMessageHandled
Example:
chatGui.CheckMessageHandled += (type, timestamp, ref sender, ref message, ref isHandled) =>
{
    if (message.TextValue.Contains("spam"))
    {
        isHandled = true; // Block this message
    }
};

ChatMessageHandled

Event that fires when a chat message is handled by Dalamud or a plugin.
event OnMessageHandledDelegate ChatMessageHandled
Delegate signature:
public delegate void OnMessageHandledDelegate(
    XivChatType type,
    int timestamp,
    SeString sender,
    SeString message)

ChatMessageUnhandled

Event that fires when a chat message is not handled by Dalamud or a plugin.
event OnMessageUnhandledDelegate ChatMessageUnhandled

LogMessage

Event that fires when a log message (chat message based on entries in the LogMessage sheet) is sent.
event OnLogMessageDelegate LogMessage
Delegate signature:
public delegate void OnLogMessageDelegate(ILogMessage message)

Properties

LastLinkedItemId

Gets the ID of the last linked item.
uint LastLinkedItemId { get; }

LastLinkedItemFlags

Gets the flags of the last linked item.
byte LastLinkedItemFlags { get; }

Common Use Cases

Chat Command Response

private void OnCommand(string command, string args)
{
    if (args == "help")
    {
        chatGui.Print("Available commands:", "MyPlugin", 575);
        chatGui.Print("  /myplugin help - Show this help");
        chatGui.Print("  /myplugin status - Show status");
    }
    else if (args == "status")
    {
        var message = new SeStringBuilder()
            .AddUiForeground("[Status]", 500)
            .AddText(" Everything is working!")
            .Build();
        
        chatGui.Print(message);
    }
}

Filtering Chat Messages

private void Initialize()
{
    chatGui.CheckMessageHandled += (type, timestamp, ref sender, ref message, ref isHandled) =>
    {
        // Block specific message types
        if (type == XivChatType.Shout && config.BlockShout)
        {
            isHandled = true;
            return;
        }
        
        // Block messages containing certain words
        var text = message.TextValue.ToLower();
        if (config.BlockedWords.Any(word => text.Contains(word)))
        {
            isHandled = true;
        }
    };
}

Chat Logger

private void SetupChatLogger()
{
    chatGui.ChatMessage += (type, timestamp, ref sender, ref message, ref isHandled) =>
    {
        var logEntry = new ChatLogEntry
        {
            Type = type,
            Timestamp = DateTimeOffset.FromUnixTimeSeconds(timestamp),
            Sender = sender.TextValue,
            Message = message.TextValue
        };
        
        SaveToLog(logEntry);
    };
}

Interactive Help System

private void ShowInteractiveHelp()
{
    var teleportLink = chatGui.AddChatLinkHandler(1, (id, payload) =>
    {
        // Open teleport window
        OpenTeleportWindow();
    });
    
    var settingsLink = chatGui.AddChatLinkHandler(2, (id, payload) =>
    {
        // Open settings
        OpenSettings();
    });
    
    var message = new SeStringBuilder()
        .AddText("Click ")
        .Add(teleportLink)
        .AddUiForeground("[Teleport]", 500)
        .Add(RawPayload.LinkTerminator)
        .AddText(" or ")
        .Add(settingsLink)
        .AddUiForeground("[Settings]", 575)
        .Add(RawPayload.LinkTerminator)
        .Build();
    
    chatGui.Print(message, "MyPlugin");
}
Messages sent via Print are queued and sent on the next framework event, not immediately.
Remember to remove all chat link handlers in your plugin’s Dispose method to prevent memory leaks.

Build docs developers (and LLMs) love