output/PlaceholderAPI/SKILL.md
PlaceholderAPI - Minecraft plugin expansion system for placeholder text replacement
npx skillsauth add Kling0012/MCRPG PlaceholderAPIInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
PlaceholderAPI is a plugin for Spigot servers that allows server owners to display information from various plugins with a uniform format. It enables dynamic text replacement through expansions, allowing plugins to provide and consume placeholder values like %player_name% or %server_online%.
PlaceholderAPI has been downloaded over 1,700,000 times on Spigot and has been used concurrently on over 45,000 servers, making it a must-have for servers of any type or scale. With over 240+ expansions, it supports a wide variety of plugins including Essentials, Factions, LuckPerms, and Vault.
Trigger this skill when:
NoClassDefFoundError, expansion loading failures, or registration issues<repositories>
<repository>
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/releases/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
repositories {
maven { url 'https://repo.extendedclip.com/releases/' }
}
dependencies {
compileOnly 'me.clip:placeholderapi:2.11.6'
}
package at.helpch.placeholderapi.example.expansion;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
public class SomeExpansion extends PlaceholderExpansion {
@Override
@NotNull
public String getAuthor() {
return "Author"; // Required: Expansion author name
}
@Override
@NotNull
public String getIdentifier() {
return "example"; // Required: Used as %example_param%
}
@Override
@NotNull
public String getVersion() {
return "1.0.0"; // Required: Expansion version
}
@Override
public String onRequest(OfflinePlayer player, @NotNull String params) {
if (params.equalsIgnoreCase("placeholder1")) {
return "text1";
}
return null; // Return null for invalid placeholders
}
}
package at.helpch.placeholderapi.example.expansion;
import at.helpch.placeholderapi.example.SomePlugin;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
public class SomeExpansion extends PlaceholderExpansion {
private final SomePlugin plugin;
public SomeExpansion(SomePlugin plugin) {
this.plugin = plugin;
}
@Override
@NotNull
public String getAuthor() {
return String.join(", ", plugin.getDescription().getAuthors());
}
@Override
@NotNull
public String getIdentifier() {
return "example";
}
@Override
@NotNull
public String getVersion() {
return plugin.getDescription().getVersion();
}
@Override
public boolean persist() {
return true; // Keep expansion loaded on reload
}
@Override
public String onRequest(OfflinePlayer player, @NotNull String params) {
if (params.equalsIgnoreCase("config_value")) {
return plugin.getConfig().getString("path.value", "default");
}
return null;
}
}
package at.helpch.placeholderapi.example;
import at.helpch.placeholderapi.example.expansion.SomeExpansion;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
public class SomePlugin extends JavaPlugin {
@Override
public void onEnable() {
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
new SomeExpansion(this).register();
}
}
}
import me.clip.placeholderapi.PlaceholderAPI;
// Parse with player context
String parsed = PlaceholderAPI.setPlaceholders(player, "Hello %player_name%!");
player.sendMessage(parsed);
// Parse without player (server-level placeholders only)
String serverInfo = PlaceholderAPI.setPlaceholders(null, "Online: %server_online%");
name: MyPlugin
version: 1.0.0
main: com.example.MyPlugin
author: Author
softdepend:
- PlaceholderAPI
@Override
public String onRequest(OfflinePlayer player, @NotNull String params) {
// %example_param1% -> params = "param1"
// %example_section_value% -> params = "section_value"
if (params.startsWith("info_")) {
String type = params.substring(5); // Remove "info_" prefix
return getInfo(type);
}
switch (params.toLowerCase()) {
case "name":
return player != null ? player.getName() : "None";
case "uuid":
return player != null ? player.getUniqueId().toString() : "None";
default:
return null;
}
}
This skill includes comprehensive documentation in references/:
| File | Description | |------|-------------| | api.md | API documentation including common issues (NoClassDefFoundError, expansion loading failures) and troubleshooting | | developers.md | Complete developer guide: using PlaceholderAPI in plugins, creating expansions (internal/external/relational), eCloud submission | | users.md | User-facing documentation with complete placeholder list (300+ expansions), command reference, and usage examples | | index.md | Main wiki index with navigation to all sections |
| Format | Usage | Example |
|--------|-------|---------|
| %identifier_param% | Standard format | %player_name%, %server_online% |
| {identifier_param} | Bracket format (used within certain expansions like Animations) | {player_name} inside animation tags |
Important: When using placeholders within the Animations expansion text, you must use the bracket variant {player_name} instead of %player_name%.
| Type | Description | Registration |
|------|-------------|--------------|
| Internal | Built into your plugin's JAR | Manual registration required (recommended) |
| External | Separate JAR in plugins/PlaceholderAPI/expansions/ | Auto-loaded by PlaceholderAPI |
| Relational | Compares values between two players | Prefix: %rel_<identifier>_% |
"param" in %example_param%)null → Placeholder is invalid"" (empty string) → Valid placeholder with no value/papi reloadtrue: Required for internal expansions to prevent unregistrationfalse: Expansion will be unregistered on reload (default for external)| Command | Description |
|---------|-------------|
| /papi parse me <text> | Parse placeholders for yourself |
| /papi parse <player> <text> | Parse placeholders for specific player |
| /papi parse --null <text> | Parse server-level placeholders only |
| /papi bcparse <player> <text> | Parse and broadcast to all players |
| /papi cmdparse <player> <command> | Parse and execute as command |
| /papi parserel <p1> <p2> <text> | Parse relational placeholders |
| Command | Description |
|---------|-------------|
| /papi ecloud download <expansion> | Download expansion from eCloud |
| /papi ecloud download <expansion> <version> | Download specific version |
| /papi ecloud list all | List all available expansions |
| /papi ecloud list installed | List installed expansions |
| /papi ecloud info <expansion> | View expansion information |
| /papi ecloud placeholders <expansion> | Show expansion's placeholders |
| /papi ecloud status | Check eCloud connection status |
| Command | Description |
|---------|-------------|
| /papi list | List all installed expansions |
| /papi info <expansion> | View expansion details |
| /papi reload | Reload PlaceholderAPI configuration |
| /papi dump | Generate debug dump for pastebin |
| /papi version | Show PlaceholderAPI version |
| Resource | URL | |----------|-----| | Wiki | https://wiki.placeholderapi.com/ | | Spigot Resource | https://www.spigotmc.org/resources/6245/ | | Hangar Page | https://hangar.papermc.io/HelpChat/PlaceholderAPI | | Modrinth Page | https://modrinth.com/plugin/placeholderapi | | GitHub Repository | https://github.com/PlaceholderAPI/PlaceholderAPI | | CI Server | http://ci.extendedclip.com/job/PlaceholderAPI/ | | Discord Community | https://helpch.at/discord | | eCloud | https://api.extendedclip.com/home | | Placeholder List | https://helpch.at/placeholders | | Plugin Statistics | https://bstats.org/plugin/bukkit/PlaceholderAPI |
Download from eCloud using /papi ecloud download <name>:
| Expansion | Purpose | |-----------|---------| | Player | Basic player information (name, UUID, location, health) | | Server | Server information (TPS, online count, version) | | Bungee | Network-wide player counts for BungeeCord | | Vault | Economy, permission, and chat integration | | LuckPerms | Permission and prefix/suffix support |
[PlaceholderAPI] Failed to load Expansion class <expansion> (Is a dependency missing?)
[PlaceholderAPI] Cause: NoClassDefFoundError <path>
Cause: Server running Minecraft 1.8 or older without Gson included.
Solution: Use at least Minecraft 1.8.8 which includes the required Gson dependency, or manually add Gson to your classpath.
Cause: Internal expansion missing persist() = true override.
Solution: Add the following to your expansion class:
@Override
public boolean persist() {
return true;
}
provided/compileOnly scope - Never shade PlaceholderAPI into your plugin JARnull for invalid placeholders - Let PlaceholderAPI handle unknown identifiersOfflinePlayer instead of Player - Works for offline players and avoids NPEsBukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")onRequest()If you would like to contribute towards PlaceholderAPI, take a look at the Contributing file for the ins and outs on how you can do that and what you need to keep in mind.
If you would like to create your own Placeholder Expansion for PlaceholderAPI, take a look at the Wiki which contains a detailed tutorial on how you can achieve this.
tools
Skript-reflect addon for Skript - powerful reflection and element manipulation capabilities
tools
LuckPerms - Minecraft permission plugin for managing permissions, groups, and user access
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------