ProtoHax UserScript
ProtoHax UserScript lets you write your own ProtoHax client modules in TypeScript. A userscript declares a module — its name and options — and wires up listeners against the live game session: game events, packets, the entity/world model, the local player, inventory, and the raw packet connection.
Modules you author this way appear in the client menu under the Script category, alongside the built-in ones. They can be toggled on and off, expose sliders and toggles and color pickers, and read or drive the game exactly like a first-party module.
The @protohax/userscript package
Everything is typed through a single package on npm:
The userscript API is at version 0.x: it is still taking shape, and breaking changes can land in any release until 1.x is reached. Expect to update your scripts between client versions, and pin the package version your script was built against.
This package is types-only. It ships a single index.d.ts and no runtime
code. That is deliberate:
- The types describe the authoring API and the host's own game model, so
your editor autocompletes
ctx.session.entityState.localPlayer.inventoryand type-checks every packet payload. - The values you import from it —
defineModule,moduleManager, the entity classes,AbstractBlockLocationTracker,nbt,utils— are resolved at runtime to the host's live singletons when your script is bundled into the client. Your script and the client share one instance of the game state, one module manager, and one (patched)prismarine-nbt.
In other words: you install the package for the types, and the ProtoHax client supplies the implementation when your script runs.
Install
Start from the template repository — it comes with the bundler, the deploy script, and a worked example module already wired up:
git clone https://github.com/hax0r31337/ProtoHax-UserScript-Template my-script
cd my-script
npm install
npm run build
Or add the package to an existing project:
npm install --save-dev @protohax/userscript
tsconfig.json
A minimal config that works with the published declarations:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true
}
}
Note —
skipLibCheckis required. The published.d.tsvendors the host's packet definitions verbatim, which contain a harmless duplicate declaration.skipLibCheck: truelets your project type-check cleanly while still fully checking your code against the API.
A script ships as a single ES module with @protohax/userscript left
external — that import is what binds your script to the host's live singletons.
Project Setup covers the bundler configuration and
where the built file goes.
A first module
import { defineModule } from "@protohax/userscript";
defineModule(
{ name: "AutoSprint" },
{
speed: { type: "number", def: 1, min: 0, max: 5, step: 0.1 },
},
(ctx) => {
// "movement_tick" is the game's own tick, fired from native before it
// moves — position and motion written on the state land in that tick.
ctx.on("movement_tick", (state) => {
state.strafe(ctx.options.speed.value, 1);
});
},
);
That is the whole shape of a module: a schema declaring the options once, and
a per-session setup function that reads them from ctx.options and
subscribes to events. The next pages walk through each layer.
Where to go next
- Project Setup — the template, bundling, and installing your script.
- Getting Started — the module lifecycle in detail.
- Modules — metadata, the Script category, and toggling.
- Options — sliders, toggles, enums, colors.
- Events & Packets — subscribing to the session.
- Movement —
movement_tick,MovementState, and sprint control. - API Reference — the session, entities, world, inventory, and packets.