Chatty v3 is a ground-up rewrite built on Kyori's Adventure library. It is approaching its first stable release (
3.0.0); this branch holds its code.
- Stable builds — the Releases page (once
3.0.0is tagged).- Development builds — the latest artifact from the "Actions" tab (see the "Artifacts" section).
Chatty v2.* is deprecated and no longer maintained. Upgrading from v2? See MIGRATION.md — v3 migrates your old config automatically.
Chatty is the modern chat management system for Bukkit-compatible servers. It's based on-top of Kyori's Adventure library, that makes it so powerful and stable.
Key features:
- Chat channels ("local" and "global" by default)
- Private messaging
- Moderation (CAPS, advertisements, swears)
- Notifications (chat, action bar, title and advancement toasts)
- "Vanilla" messages configuring (join/quit/death)
- MiniMessage both legacy (&) styling format
chats.yml has two features that both change how a message looks, and they
answer different questions:
| Chosen by | Changes | |
|---|---|---|
styles |
the reader's permission chatty.style.<id> |
how the chat looks to that reader |
sender-formats |
the sender's permission chatty.sender-format.<id> or chatty.chat.<chat>.sender-format.<id> |
how that player's messages look to everybody |
So sender-formats is what gives a rank its own prefix in chat, and styles is
what lets one reader see the chat in a different colour. They compose: the
sender's rank is resolved first, and the reader's style is then taken from that
rank's own styles.
chats:
global:
format: '{prefix}{player}: {message}'
sender-formats:
vip:
priority: 10
format: '&6[VIP] &r{player}&8: &f{message}'
styles:
red: { format: '&6[VIP] &r&c{player}&8: &c{message}' }Highest priority wins when a sender qualifies for several. A rank that defines
no styles is shown the same way to every reader.
Caps, advertisement and swear filters, plus mute:
/mute <player> [10m|2h|3d|1w] [reason] # no duration means permanent
/unmute <player>
Mutes are stored with the player, so they survive a restart and apply on every
server sharing the database. A muted player cannot use public chats or private
messages. chatty.command.mute grants the commands, chatty.bypass.mute exempts
a player — operators hold both by default.
With PlaceholderAPI installed, Chatty exposes its own data so TAB, scoreboards, Discord bridges and anything else can read it:
| Placeholder | Value |
|---|---|
%chatty_chat% |
id of the chat the player currently writes to |
%chatty_chat_displayname% |
its display name |
%chatty_chat_range% |
its range in blocks (-3 cross-server, -2 server, -1 world) |
%chatty_chat_range_<id>% |
the range of a named chat, e.g. %chatty_chat_range_local% |
%chatty_chat_displayname_<id>% |
the display name of a named chat |
%chatty_prefix% / %chatty_suffix% |
the prefix and suffix Chatty resolves for the player |
%chatty_spy% |
whether spy mode is on |
%chatty_player_message% |
the last message the player sent through Chatty |
%chatty_targetname% |
who that message named, or the player themselves |
%rel_chatty_ignore% |
whether the first player ignores the second |
%chatty_prefix% is empty unless Vault or LuckPerms is installed, because that
is where the prefix comes from.
The last two describe the message a player just sent, so a command run afterwards can quote it — a Discord bridge, or a punishment naming what was said:
/discordsrv broadcast <channel> %chatty_targetname% » %chatty_player_message%
/cmi jail %player_name% said: %chatty_player_message% 2h
%chatty_targetname% is the first player mentioned in that message; with no
mention it is the sender, so it is never empty for an online player.
Add the API as a compileOnly dependency and declare Chatty as a plugin dependency — the classes come from the running plugin at runtime:
repositories { maven { url = 'https://jitpack.io' } }
dependencies { compileOnly 'ru.brikster:chatty-api:3.0.0' }depend: [ Chatty ]The published artifact carries Chatty's relocated Adventure, because the plugin
bundles its own copy to keep working on servers that have none. That is why it
must be compileOnly: a second copy on your own classpath would be a different
class to the JVM. Sources and javadoc jars are published alongside it.
Paper, Spigot and Purpur from 1.8.8 up to 26.x, and Folia. Folia support is verified by booting a real Folia server: the plugin schedules its own work and never touches the Bukkit scheduler, and the bundled bStats, which does, is skipped there.
Every spelling below is covered by ColourSpellingMatrixTest, so this table is
what the code does rather than what it intends to do. All of them work in chat
formats, in message-format, in lang/ files and in a prefix or suffix coming
from LuckPerms or Vault.
| Spelling | Example | Supported |
|---|---|---|
| Legacy colour | &c |
yes |
| Legacy decoration | &l &n &o &m &k &r |
yes |
| Section sign | §c |
yes |
| MiniMessage colour | <red> |
yes |
| MiniMessage hex | <#757575> |
yes |
| Ampersand hex | 򸽇 |
yes |
| Spigot spread hex | &x&7&5&7&5&7&5 |
yes |
| Gradient | <gradient:#ff0000:#00ff00> |
yes |
| Rainbow | <rainbow> |
yes |
| Bare hash | #757575 |
no, prints as text |
Writing colour codes in your own messages is a separate question — that needs
chatty.decoration.*, see the permissions section of the migration guide.
Chatty uses Gradle to handle dependencies & building. Building needs JDK 21; the jar it produces targets Java 11, so it runs on Java 11 and newer.
git clone https://github.com/Brikster/Chatty.git
cd Chatty/
./gradlew buildOutput jar will be placed into /build/libs directory.
Run the unit tests:
./gradlew testRun the end-to-end smoke test — it boots real Minecraft servers with the built plugin and verifies that it enables cleanly on a fresh install, processes live in-game chat, correctly migrates a legacy v2 configuration, still runs on a legacy server (1.8.8), and coexists with DiscordSRV:
./gradlew build
JAVA_HOME=/path/to/jdk-21 bash scripts/smoke-test.shJAVA_HOME must point at a JDK the target server accepts: 21 for 1.21.x, 11 for
1.16.5, 25 for 26.x. Pick the server version with MC_VERSION, and switch off
the parts a lane cannot run:
MC_VERSION=26.2 CHAT_TEST=0 JAVA_HOME=/path/to/jdk-25 bash scripts/smoke-test.shCHAT_TEST=0 skips the in-game bot, which cannot join a server newer than
protocol 1.21.9, and LEGACY_SCENARIO=0 skips the 1.8.8 lane. The legacy
scenario needs a Java 11 runtime; it is downloaded automatically, or point
LEGACY_JAVA_HOME at an existing one.
Both run automatically on every push via GitHub Actions, with the smoke test as a matrix over 1.21.11, 1.16.5 and 26.2.