You want a custom /spawn command that plays a sound effect and shows a title. Or maybe a voting system that rewards players with diamonds. Or a death counter on the scoreboard. None of these exist as standalone plugins — at least not exactly how you want them.
The traditional answer is "learn Java and write a plugin." But that is a months-long detour if you just want your server to do one specific thing. Skript exists to bridge that gap. It is a scripting language designed for Minecraft server admins — English-like syntax, no compilation step, and instant reloads while the server runs.
This guide covers everything from installation to writing real scripts that solve real problems. By the end, you will have working examples for custom commands, cooldowns, economy hooks, and more — all without touching Java.
What Skript Is (and What It Isn't)
Skript is a Paper plugin that lets you write server logic in plain-English syntax. Instead of Java classes and event handlers, you write lines like:
on death of player:
send "You died at %location of victim%" to victim
The plugin parses your .sk files and registers them as event listeners, commands, and scheduled tasks. When an event fires, Skript executes the matching triggers.
Skript vs Traditional Plugins
| Aspect | Skript | Java Plugin |
|---|---|---|
| Learning curve | Hours to days | Weeks to months |
| Syntax | English-like, readable | Standard Java |
| Hot reload | Yes — /skript reload | Requires restart (usually) |
| Performance | Good for most use cases | Optimal for heavy logic |
| Ecosystem | Addons extend functionality | Full Bukkit/Paper API access |
Skript is not a replacement for compiled plugins. If you need to process thousands of entities per tick, intercept packets, or implement complex algorithms, Java is the right tool. But for event responses, custom commands, chat formatting, scoreboards, and minigame logic — Skript handles it cleanly.
When to Use Skript
Use Skript when:
- You want a quick custom feature without waiting for a plugin author.
- You need to glue existing plugins together (e.g., "when player joins, check LuckPerms group and send different welcome messages").
- You are iterating on game mechanics and want instant feedback.
- Your server's identity depends on unique features that no existing plugin provides.
Avoid Skript when:
- The feature requires extreme performance (anti-cheat tick loops, packet manipulation).
- A mature, well-maintained plugin already does what you need.
- You are comfortable with Java and want full API access.
Installing Skript on Paper or Purpur
Skript requires Paper or Purpur — it will not run on Vanilla or Spigot. The current stable release is Skript 2.15.0, which supports Minecraft versions from 1.21 through 26.1.
Step 1: Download Skript
Grab the latest .jar from the official sources:
- Modrinth: modrinth.com/plugin/skript
- PaperMC Hangar: hangar.papermc.io/SkriptLang/Skript
- GitHub Releases: github.com/SkriptLang/Skript/releases
Download the file that matches your Minecraft version. For most servers running 1.21 or later, the latest release works.
Step 2: Install
- Stop your server (or use a plugin manager that supports hot-loading).
- Upload
Skript-2.15.0.jarto your/pluginsfolder. - Start the server.
Skript creates its folder structure automatically:
plugins/
└── Skript/
├── config.sk
├── scripts/
│ └── (your .sk files go here)
└── variables.csv
Step 3: Verify Installation
Run /skript info in the console or as an op. You should see the version number and a list of enabled scripts. If Skript fails to load, check the console for errors — usually a version mismatch or missing dependency.
Essential Addons
Skript's core syntax covers the basics. Addons extend it with specialized features:
| Addon | Purpose |
|---|---|
| SkQuery | Extra expressions — scoreboards, holograms, NBT access |
| skript-reflect | Direct Java reflection — call any Bukkit method |
| SkBee | Recipes, advancements, structures, NBT compounds |
| Skellett | GUI menus, packets, boss bars, tab completion |
Install addons the same way: drop the .jar in /plugins and restart. Most addons are available on Modrinth or GitHub.
Writing Your First Script
Scripts live in plugins/Skript/scripts/. Each .sk file is parsed independently. Let's start with a simple example.
Example: Death Coordinates Message
Create a file called death-coords.sk:
on death of player:
set {_loc} to location of victim
send "&cYou died at &f%x of {_loc}%, %y of {_loc}%, %z of {_loc}%" to victim
Save the file, then run /skript reload death-coords in the console. Now when a player dies, they receive a message with their death coordinates — no server restart required.
Anatomy of a Script
Every Skript file contains one or more triggers. A trigger consists of:
- Event header — what activates the trigger (
on death of player:,on join:,every 5 minutes:). - Indented body — the effects and conditions that run when the event fires.
on break of diamond ore: # Event header
if player has permission "vip.bonus": # Condition
give player 1 diamond # Effect
send "&aBonus diamond!" to player # Effect
Variables
Skript has two variable types:
- Local variables (
{_name}) — exist only within the current trigger, discarded after. - Global variables (
{name}) — persist across triggers and server restarts (saved tovariables.csv).
on join:
add 1 to {joins::%uuid of player%}
send "Welcome! This is visit #%{joins::%uuid of player%}%"
List variables use :: notation. {joins::*} returns all values; {joins::%uuid%} returns a specific player's count.
The Reload Workflow
Skript's killer feature is instant reloading:
- Edit your
.skfile. - Run
/skript reload <scriptname>or/skript reload all. - Test immediately.
No compilation. No restart. If you make a syntax error, Skript tells you the line number and what it expected. Fix it and reload again.
Practical Patterns
Here are real-world scripts you can adapt for your server.
Custom Commands
command /spawn:
description: Teleport to spawn
permission: server.spawn
cooldown: 30 seconds
cooldown message: &cWait %remaining time% before teleporting again.
trigger:
teleport player to spawn of world "world"
send title "&aWelcome Home" with subtitle "&7You arrived at spawn" to player
play sound "entity.enderman.teleport" to player
This creates a /spawn command with a 30-second cooldown, permission check, title animation, and sound effect. The cooldown keyword is built-in — no separate cooldown tracking needed.
Kill Tracking with Scoreboards
on death of player:
if attacker is a player:
add 1 to {kills::%uuid of attacker%}
set score of attacker in sidebar to {kills::%uuid of attacker%}
For a deeper dive into scoreboard mechanics, see the scoreboard guide.
Economy Integration
If you use Vault (through EssentialsX or another economy plugin), Skript can hook into it:
command /sellhand:
trigger:
set {_item} to player's tool
if {_item} is air:
send "&cYou're not holding anything."
stop
set {_price} to 0
if {_item} is diamond:
set {_price} to 100 * (item amount of {_item})
else if {_item} is iron ingot:
set {_price} to 10 * (item amount of {_item})
if {_price} is 0:
send "&cThat item has no value."
stop
add {_price} to player's balance
remove {_item} from player
send "&aYou sold %{_item}% for $%{_price}%"
This requires the Vault dependency and SkQuery or a similar addon for balance expressions. For full economy setup, see the economy guide.
Kit System with Cooldowns
command /kit starter:
permission: kits.starter
cooldown: 24 hours
cooldown message: &cYou can claim this kit again in %remaining time%.
cooldown bypass: kits.bypass
trigger:
give player 16 cooked beef
give player iron sword
give player iron pickaxe
give player 32 torches
send "&aYou received the Starter Kit!"
The cooldown bypass permission lets VIPs skip the wait — useful for donor ranks configured in LuckPerms.
Scheduled Tasks
every 30 minutes:
broadcast "&6[TIP] &fVisit /rules to see server guidelines"
every 1 hour:
loop all players:
if {playtime::%uuid of loop-player%} is not set:
set {playtime::%uuid of loop-player%} to 0
add 1 to {playtime::%uuid of loop-player%}
Scheduled triggers run server-side, independent of player activity.
Debugging and Common Mistakes
Even simple scripts can break. Here is how to troubleshoot.
Reading Error Messages
When a script fails to parse, Skript prints the error to console:
[Skript] Line 4: Can't understand this condition: "if player have permission"
The fix: has, not have. Skript syntax is precise — read the error message and check documentation.
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Wrong indentation | Script does nothing or throws parse error | Use consistent tabs or spaces (not mixed) |
| Typo in event name | Trigger never fires | Check docs for exact event names |
| Missing colons | Parse error | Every header line ends with : |
Using {name} when you meant {_name} | Variable persists unexpectedly | Prefix with _ for local scope |
| Infinite loops | Server freeze | Add conditions or limits to while loops |
The /skript reload Trap
If you edit a script that defines a command and reload, the old command is unregistered and re-registered. This is usually fine. But if you have a syntax error, the command disappears until you fix and reload again.
Always test scripts on a development server first — or at minimum, reload during low-traffic hours.
Logging for Debugging
Add temporary broadcast or send to console lines to trace execution:
on right click on sign:
send "DEBUG: Player clicked sign at %location of event-block%" to console
# rest of your logic
Remove debug lines before going live.
Performance Considerations
Skript is interpreted, not compiled. For most servers, this is irrelevant — Skript triggers execute in microseconds. But if you loop through thousands of entities every tick, you will notice lag.
Rules of thumb:
- Avoid
every 1 ticktriggers unless absolutely necessary. - Use
loop all playersinstead ofloop all entitieswhen you only need players. - Store computed values in variables instead of recalculating.
- For heavy processing, consider a compiled plugin instead.
Quick Reference
| Concept | Syntax Example |
|---|---|
| Event trigger | on join:, on death of player:, on break of stone: |
| Command definition | command /name: with trigger: block |
| Local variable | {_temp} — discarded after trigger |
| Global variable | {data} — persists across restarts |
| List variable | {list::*}, {list::%key%} |
| Condition | if player has permission "x": |
| Loop | loop all players:, loop {list::*}: |
| Cooldown | cooldown: 30 seconds in command definition |
| Scheduled task | every 5 minutes: |
| Reload command | /skript reload <scriptname> |
| Documentation | docs.skriptlang.org |
Related Guides
- Best Minecraft Server Plugins 2026 — The essential plugins every server should have, including several that pair well with Skript.
- Paper, Purpur, Fabric, or Forge? — Understand why Skript requires Paper or Purpur and what each server software offers.
- How to Set Up Permissions with LuckPerms — Configure permission nodes that your Skript commands can check against.
- Minecraft Server Console Commands — The full command reference, including
/skriptsubcommands. - How to Set Up an Economy — Install Vault and an economy plugin so Skript can manage player balances.
- How to Use Scoreboards — Learn vanilla scoreboard mechanics that Skript can control.
If you want to focus on building your server instead of managing infrastructure, Swelis Hosting handles the Java runtime, file management, and backups — so you can focus on writing scripts that make your server unique.
