diff --git a/src/equicordplugins/showRolesInChat/index.tsx b/src/equicordplugins/showRolesInChat/index.tsx
new file mode 100644
index 000000000..b7520178a
--- /dev/null
+++ b/src/equicordplugins/showRolesInChat/index.tsx
@@ -0,0 +1,156 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2026 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import "./styles.css";
+
+import { definePluginSettings } from "@api/Settings";
+import ErrorBoundary from "@components/ErrorBoundary";
+import { EyeIcon } from "@components/Icons";
+import { EquicordDevs } from "@utils/constants";
+import { classNameFactory } from "@utils/css";
+import { getCurrentGuild } from "@utils/discord";
+import definePlugin, { OptionType } from "@utils/types";
+import { User } from "@vencord/discord-types";
+import { ChannelStore, ContextMenuApi, GuildMemberStore, GuildRoleStore, Menu, useStateFromStores } from "@webpack/common";
+import type React from "react";
+
+const cl = classNameFactory("vc-sric-");
+
+const SETTINGS_KEYS: (keyof typeof settings.store)[] = ["showBots", "useRoleColor", "excludedRoles"];
+
+const settings = definePluginSettings({
+ showBots: {
+ type: OptionType.BOOLEAN,
+ description: "Whether to show the highest role on bots.",
+ default: false
+ },
+ useRoleColor: {
+ type: OptionType.BOOLEAN,
+ description: "Use the role's color for the icon.",
+ default: true
+ }
+}).withPrivateSettings<{ excludedRoles?: string[]; }>();
+
+function getHighestRole(guildId: string, userId: string, excludedRoles?: string[]) {
+ const roles = GuildMemberStore.getMember(guildId, userId)?.roles;
+ if (!roles?.length) return null;
+
+ return GuildRoleStore.getSortedRoles(guildId).find(r => roles.includes(r.id) && !excludedRoles?.includes(r.id));
+}
+
+function toggleRole(roleId: string) {
+ const excluded = settings.store.excludedRoles ?? [];
+ settings.store.excludedRoles = excluded.includes(roleId) ? excluded.filter(id => id !== roleId) : [...excluded, roleId];
+}
+
+function makeToggleRoleItem(roleId: string) {
+ const isExcluded = settings.store.excludedRoles?.includes(roleId);
+ return (
+
toggleRole(roleId)}
+ />
+ );
+}
+
+function EyeSlashIcon() {
+ return (
+
+ );
+}
+
+function ShieldUserIcon({ color }: { color: string; }) {
+ return (
+
+ );
+}
+
+const HighestRoleIndicator = ErrorBoundary.wrap(({ user, channelId }: { user: User; channelId: string; }) => {
+ const { showBots, useRoleColor, excludedRoles } = settings.use(SETTINGS_KEYS);
+
+ const guildId = (!user.bot || showBots) ? ChannelStore.getChannel(channelId)?.guild_id : null;
+ const role = useStateFromStores([GuildMemberStore, GuildRoleStore], () => guildId ? getHighestRole(guildId, user.id, excludedRoles) : null, [guildId, user.id, excludedRoles]);
+
+ if (!guildId || !role) return null;
+
+ const handleContextMenu = (e: React.MouseEvent) => {
+ ContextMenuApi.openContextMenu(e, () => {
+ const userRoles = GuildMemberStore.getMember(guildId, user.id)?.roles ?? [];
+ const excluded = excludedRoles ?? [];
+ const hiddenRoles = GuildRoleStore.getSortedRoles(guildId).filter(r => excluded.includes(r.id) && userRoles.includes(r.id));
+
+ return (
+
+
+ {makeToggleRoleItem(role.id)}
+
+ {hiddenRoles.length > 0 && (
+
+
+ );
+ });
+ };
+
+ return (
+
+
+
+ {role.name}
+
+
+ );
+}, { noop: true });
+
+export default definePlugin({
+ name: "ShowRolesInChat",
+ description: "Shows a user's highest role next to their name in chat messages. Hide/show specific roles in their context menu (right-click).",
+ tags: ["Appearance", "Chat", "Roles", "Servers"],
+ authors: [EquicordDevs.lucabeyer],
+ settings,
+ contextMenus: {
+ "dev-context"(children, { id }: { id: string; }) {
+ if (GuildRoleStore.getRole(getCurrentGuild()?.id ?? "", id)) {
+ children.push(
+
+ {makeToggleRoleItem(id)}
+
+ );
+ }
+ },
+ "guild-settings-role-context"(children, props: { role: { id: string; }; }) {
+ children.push(
+
+ {makeToggleRoleItem(props.role.id)}
+
+ );
+ }
+ },
+ renderMessageDecoration: ({ message }) => (
+
+ )
+});
diff --git a/src/equicordplugins/showRolesInChat/styles.css b/src/equicordplugins/showRolesInChat/styles.css
new file mode 100644
index 000000000..016d7361c
--- /dev/null
+++ b/src/equicordplugins/showRolesInChat/styles.css
@@ -0,0 +1,28 @@
+.vc-sric-indicator {
+ display: inline-flex;
+ align-items: center;
+ box-sizing: border-box;
+ height: 16px;
+ padding: 0 6px 0 4px;
+ background: var(--background-mod-strong);
+ border-radius: 4px;
+ font-size: .72rem;
+ font-weight: 600;
+ line-height: 16px;
+ color: var(--text-default);
+ cursor: default;
+}
+
+.vc-sric-icon {
+ width: 14px;
+ height: 14px;
+ margin-right: 4px;
+ flex-shrink: 0;
+}
+
+.vc-sric-name {
+ white-space: nowrap;
+ max-width: 120px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
\ No newline at end of file
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 17d82cf64..f1b28f5f5 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -1390,6 +1390,10 @@ export const EquicordDevs = Object.freeze({
name: "bastih18",
id: 273797150880563201n
},
+ lucabeyer: {
+ name: "luca.beyer",
+ id: 405090676771127317n
+ },
} satisfies Record);
// iife so #__PURE__ works correctly