Skip to content

About ThicketScript ​

ThicketScript is a new language, built from the ground up to make games. You write .tks scripts in a familiar, TypeScript-like syntax, and the ThicketScript runtime, thicket, runs, checks, debugs and builds them.

It is made by Phanxgames LLC. It is free to use, with no royalties and no revenue cap: see the license summary. The first public release is coming soon.

Why a new language for games ​

Most scripting languages were made for something else, and games borrow them. ThicketScript starts from games, and asks what a language looks like when play is the point.

  • It feels familiar. If you know TypeScript, you can read ThicketScript today.
  • It has its own type system. The type checker catches mistakes before your game runs, and sized numbers like int8 and float32 are real types, not hints.
  • It has its own VM and bytecode. Scripts compile to .tbc bytecode, and the same bytecode runs on every platform thicket builds for.
  • It is one runtime. Run, debug, check, format, the language server and the build all live in thicket, the ThicketScript runtime.
  • It comes with game modules. 2D is built in, and UI and game structure come as packages, all on one native platform layer.

Why ThicketScript ​

We love TypeScript. The syntax is clear, and the type system tells you what a value is without guessing. When we needed a language for game logic on top of a C++ engine, it was the only syntax we wanted to write in.

But TypeScript compiles to JavaScript, and JavaScript means a browser-style runtime that was never built to live inside a game. So we kept the syntax and built the rest: a compiler, a type checker and a VM made for play.

Why not Lua? ​

Lua is great: small, fast, proven in a lot of games. If it works for your project, use it. It didn't fit what we wanted:

  • Types are bolted on. Tools like Teal add annotations, but the language doesn't check them. With hundreds of scripts, catching a type mistake before the game runs saves real time.
  • Arrays start at 1. Every C++ developer who touches Lua writes an off-by-one in the first week.
  • Tables are everything. One structure that is an array, a dictionary and an object at once is elegant on paper and hard to reason about in a big codebase.
  • The syntax isn't home. That one is taste, and we own it. If we are going to write game logic for years, we want it to feel like TypeScript.

Why not actual TypeScript? ​

That was the first question we asked. Why not embed a JavaScript engine and be done?

  • Size. A full JavaScript engine adds tens of megabytes to a game you ship as a download.
  • Warm-up. Those engines get fast by compiling hot code as it runs. Game scripts that run for a few frames never get there.
  • Frame time. At 60 frames a second you have about 16 ms. A garbage collector tuned for throughput can spend that in one pause.
  • JavaScript underneath. Prototype chains, implicit coercion and this rebinding are still there at run time, whatever your type annotations say.

We also wanted things no JavaScript runtime can give: structs that are values, numbers smaller than 64 bits, real integers, and scripts that start with no access to the machine until the project grants it.

Why not write it all in C++? ​

If you write a whole game in one compiled language, that's a fine choice and plenty of great games ship that way. A scripting layer starts to pay off when:

  • You iterate on game logic all day. Recompiling C++ to tweak a dialogue line or an enemy's behavior is slow. thicket watch restarts your program every time you save.
  • You want scripts kept in a sandbox. ThicketScript starts with no file, network or shell access, and the project grants exactly what it needs. Every guarded call is checked when it runs.
  • Engine code and game code change at different speeds. The engine changes rarely and has to be rock solid. Game logic changes constantly. Different jobs, different tools.

What we built ​

ThicketScript takes the syntax we love and compiles it to bytecode for a purpose-built C++ VM, with its own .tks files and one runtime, thicket, for everything. Most TypeScript you write works as it is. Then come the things we always wished TypeScript had:

  • Structs. Value types with methods and operator overloads. A Vec2 is two numbers, not a heap object.
  • Packed numbers. int8, uint16, float32 and the rest, in struct fields. A color with four uint8 fields is four bytes.
  • series and parallel. Say how async work flows, and skip the Promise.all wrappers and an await on every line.
  • Threads with one keyword. An async worker function runs on its own thread in its own VM.
  • A sandbox by default. Scripts get file, network, crypto and other access only when the project grants it.

And the things we left out: conditional and mapped types are accepted and ignored, and eval, Proxy, Reflect, prototype chains, this rebinding and implicit coercion are gone. They serve framework authors doing type gymnastics. Game code doesn't need them, and leaving them out keeps the language simpler and faster. Coming from TypeScript has the details, and Features shows the additions running.

Tooling from day one ​

A language without good tooling is a language nobody wants to write. thicket lsp is a real language server, and the JetBrains plugin uses it for autocomplete, go-to-definition and errors as you type. thicket debug steps through your code in your IDE or in Chrome DevTools.

Who it's for ​

If you want TypeScript-style syntax, real types and real tooling for your game, ThicketScript is worth a look. If Lua works for you, keep using Lua. If you are happy in C++, stay there. We built ThicketScript because the options we had were all close, and none of them fit.

What you can build ​

With thicket alone ​

  • Command-line tools. Build scripts, file processing, code generation. thicket run tool.tks and you're done.
  • Servers. HTTP, TCP, WebSocket and UDP are built in.
  • Automation. Task runners, data pipelines and deployment scripts, in the same language as your game.
  • Image processing. Decode, resize, crop, filter and composite images, then encode them again.

With willow and willowui ​

  • 2D games. willow gives you a scene graph, sprites, cameras and input.
  • Game UI. willowui builds menus, HUDs, inventories and dialogue screens.
  • Editor tools. Level editors, asset browsers and debug panels, written in the language your game uses, so tools and game share types and code.

Questions? The FAQ has answers.

The architecture ​

ThicketScript is a stack of layers. Each layer only uses the ones below it.

ThicketScript architecture Four layers, top to bottom. Your game, written as .tks scripts. Then thicket, the ThicketScript runtime: compiler, type checker, VM, .tbc bytecode, language server and MCP server. Then the modules: willow for 2D, willowui for UI, and gamekit. At the bottom, heartwood, the native platform: windows, input, audio and rendering through bgfx and SDL3. Your game.tks scriptsthicketthe ThicketScript runtimecompilertype checkerVM.tbc bytecodelanguage serverMCP serverModuleswillow2DwillowuiUIgamekitgame structureheartwoodnative platformwindowsinputaudiorendering
Rendering goes through bgfx and SDL3.
  • Your game is your .tks scripts and assets, described by a thicket.json project file.
  • thicket is the ThicketScript runtime: the compiler, type checker and VM, the .tbc bytecode format, the language server your IDE talks to, and an MCP server for AI agents (thicket mcp).
  • Modules are the building blocks your game uses: willow for 2D, willowui for UI, and gamekit for game structure.
  • heartwood is the native platform underneath: windows, input, audio, and rendering through bgfx and SDL3.

How a build works ​

Your scripts compile to one bundle.tbc file, which ships beside the prebuilt ThicketScript runtime for each platform.