The Basics

In Sandstone, all commands can directly be imported from sandstone:
import { advancement, execute, kill, say, scoreboard } from 'sandstone'
When typing a command or a subcommand, there are two possibilities:
  • The command/subcommand has several subcommands, like effect give|clear. To access a subcommand, access it as a property: effect.give or effect.clear
  • The command/subcommand has no subcommands. It directly has argument, like enchant. To specify the arguments, call it as a normal function: enchant("@a", "minecraft:sharpness")
A command can have multiple subcommands, which all have arguments: effect.give('@a', 'minecraft:speed', 30, 2) or effect.clear('@a', 'minecraft:night_vision').
A command is only written to the data pack if it has been called. For example, some commands do not have any arguments, like /reload. In Sandstone, you'd have to type reload(). Only typing reload will not call the command, and nothing will appear in your data pack.


Here is the command to give 64 diamonds to all players:
give('@a', 'minecraft:diamond', 64)
Here is the command to give Speed II to all players:
effect.give('@a', 'minecraft:speed', 1)
Here is the command to grant all advancements to all players:
Here is a command to replace all dirt blocks by sand inside an area:
fill('~ ~ ~', '~10 ~ ~10', 'minecraft:dirt').replace('minecraft:sand')


Use VSCode autocompletion to show you what arguments/property should be used on each command.
Sandstone includes the Wiki documentation on each command, and for each parameter: you can look it up to understand what a command or a parameter does.
This example shows that Sandstone hints you what arguments are needed, and tell you what they actually do:
notion image

Optional arguments

In Minecraft, some commands have optional arguments. Let's stay with the /effect give command. According to the Wiki, It has 2 to 5 arguments:
/effect give <targets> <effect> [<seconds>] [<amplifier>] [<hideParticles>]
As you can see, the targets and the effect arguments are mandatory. Minecraft doesn't know what to do if you do not provide them. However, the seconds, amplifier and hideParticles arguments are all optionals. If you do not specify them, Minecraft uses default values.
In this aspect, Sandstone is identical to Minecraft. When typing effect.give(), your IDE will show you the possible arguments:
notion image
The targets and the effect argument are not followed by a question mark ?. It means they are mandatory, just like in Minecraft. However, the seconds, amplifier and hideParticles arguments are followed by a question mark ?: you can omit them.
This feature is very useful: you don't have to remember the syntax of all commands, Sandstone does that for you. Also, Sandstone gives you precise documentation on the behaviour of each command: you don't have to check the Wiki anymore!


Single command

Sandstone has a special syntax for the /execute command. At its core, it looks just like Minecraft:'@a').at('@s')
Calling a single command is easy:
// Sets a block of dirt under all player's feet'@a').at('@s').run.setblock('~ ~-1 ~', 'minecraft:dirt')
This will result in execute as @a at @s run setblock ~ ~-1 ~ minecraft:dirt.

Multiple commands:

In Sandstone, run is used to execute single and multiple commands.
You can execute multiple commands with run using a callback:'@a').at('@s').run(() => {
  // All this commands are executed "as @a at @s".
  // Sets a block of dirt under all players, and air on their body & head.
  setblock('~ ~-1 ~', 'minecraft:dirt')
  setblock('~ ~ ~', 'minecraft:air')
  setblock('~ ~1 ~', 'minecraft:air')
Sandstone will automatically created a new MCFunction named main/execute_as. It contains all your nested commands, and is called by the execute .
You get the desired effect without managing several files youself.
Sandstone optimizes execute when needed. Using a callback with only 1 command will not create another file!


You can add comments to Minecraft using the comment function:
comment("This fills the floor under the player's feet with air")
fill('~-1 ~-1 ~-1', '~1 ~-1 ~1', 'air')
This will result in:
# This fills the floor under the player's feet with air
fill ~-1 ~-1 ~-1 ~1 ~-1 ~1 air

Custom Commands

The raw function will output its argument directly into the function. It is useful when:
  • Creating a custom command, for mods or plugins
  • Using the commands of an older Minecraft version
  • Trying a snapshot’s command
// Use the old version of execute
raw('execute @r ~ ~ ~ say Hi!')

// Create a new command
import { Coordinates } from 'sandstone'

function oldExecute(selector: Selector, coordinates: Coordinates, command: string) {
  raw('execute', selector, coordinates, command)

oldExecute('@s', '~ ~ ~', 'say Hi!')
Just like /say, raw will concatenate its arguments with a space.