C++

ThicketScript

TypeScript-like syntax. C++ runtime.

ThicketScript compiles directly to bytecode for a C++ VM. No JavaScript, no V8, no transpilation. Write .tks files with full IDE support; the runtime handles the rest.

Coming Soon
First-class IDE support

ThicketScript is a scripting language with familiar TypeScript-style syntax and its own .tks file extension. It compiles directly to bytecode for a C++ VM, skipping JavaScript entirely. Dedicated language plugins for JetBrains and VS Code provide autocomplete, type checking, and go-to-definition.

The language is designed for game logic, UI scripting, editor tooling, modding, and server-side scripting. It has first-class structs, series and parallel for cleaner async code, workers for thread-level concurrency, built-in reactive state (Signal, Ref, computed), and 22 easing curves for animation.

ThicketScript integrates with the Dev Thicket ecosystem; Willow for 2D rendering, with shared Heartwood utilities built into the runtime. Willow is optional; the language works without it.

Quick Example

hello.tks

Features

Language

  • Strict typing; no implicit any, no loose equality, no prototype chain
  • Functions, closures, classes, interfaces, enums (numeric, string, bitflag), and generics
  • ES-style import/export with module caching and circular dependency handling
  • Destructuring, spread/rest, optional chaining, nullish coalescing, template literals
  • Range operator (0..10, 0..<10), inline try expressions, typed catch clauses
  • defer for scope-exit cleanup; runs on return, throw, break, or continue

Async & Concurrency

  • async/await with Promises
  • series and parallel work as function modifiers (series function) or scope blocks (series { })
  • series awaits every async call automatically; parallel runs everything at once
  • Workers (async worker function) run in a separate thread with full VM isolation
  • Mutex functions (async mutex function) serialize concurrent calls with per-key locking

Reactive State

  • Signal<T> for event broadcasting with on, once, off, emit, and close
  • Ref<T> for reactive values with automatic change detection and subscriptions
  • computed() for lazy derived state that re-evaluates when dependencies change
  • watch() to observe multiple Refs at once

Value Types

  • First-class struct keyword; structs live on the stack, not the heap with no garbage collection overhead
  • Numeric types: int, uint, float, boolean, and string; bigint for arbitrary-precision integers
  • Struct fields use sized numeric variants for explicit memory layout; a Color is 4 bytes, not 32
  • Operator overloading and struct spread for ergonomic value manipulation

Runtime

  • Bytecode VM written in C++
  • Values pack into 64-bit slots; numbers, booleans, integers, and small structs need zero allocation
  • Garbage collector with an API for the host to control when collection runs
  • Thread pool for workers; pool size configurable or auto-detected from hardware
  • Capability-based sandbox: scripts start with zero permissions; the embedder grants fs, net, database, crypto, shell, and more
  • Resource limits for call depth, memory, and instruction count prevent runaway scripts

Embedding

  • Links directly into your C++ app; no bridging layer, no serialization
  • Register your own functions, globals, and types with a simple C++ API
  • Run scripts in bounded steps; set limits on instructions, memory, and call depth
  • Hot reload support for live editing during development

Debugging & Tooling

  • Dual debug protocol: CDP (Chrome DevTools) and DAP (JetBrains/VS Code)
  • dump() prints any value with its variable name, captured at compile time
  • tks CLI: run, check, compile, fmt, and lsp from the command line
  • Compiled .tbc files can strip source maps and function names for production

Standard Library

  • Math with 22 easing curves (Math.tween), smoothstep, snap, wrap, moveTowards, fract
  • Collections with extras: unique, compact, sum, avg, first, last, sample; Set has union and intersection
  • Seedable xoshiro256** Random with pick, shuffle, weighted, and fork for parallel streams
  • DateTime, BigInt, Buffer, typed arrays, RegExp, JSON, and reactive primitives (Signal, Ref, computed)
  • System modules: fs, http, net, ws, crypto, compress, database, shell, env; no node_modules needed

CLI Tooling

  • system.terminal requires no permission; readLine, readPassword, and readKey with ctrl/alt/shift flags
  • Cursor control: moveTo, moveUp/Down/Left/Right, moveToColumn; clearLine, clearScreen, clearDown; rewriteLine for progress bars
  • ANSI text styling: bold, dim, italic, underline, strikethrough; full color set including 24-bit rgb(); raw mode for immediate keypresses
  • system.shell runs subprocesses; exec() returns stdout, stderr, exitCode, and ok; cwd and timeout options
  • spawn() for long-running processes with streaming stdout/stderr, exit event, and kill() with standard signals
  • No shell expansion: commands parsed directly to argv; no globbing, no variable substitution

Networking

  • HTTP client: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS; custom headers, body, timeout; response exposes status, ok, body, headers, and error
  • TCP client and server: event-driven sockets with onData, onClose, onError; listen() accepts connections with onConnection
  • WebSocket client and server: text and binary messages, graceful close with standard codes, onMessage, onBinary, onClose, onError
  • UDP: bind() for receive or create() for send-only; sendTo / recvFrom with configurable max bytes and timeout; sender address returned with each packet
  • All transports share a single net permission; granted per-script in thicket.json

Database

  • SQLite (built-in), MySQL, and Redis drivers; no external packages needed
  • Named connections registered once and retrieved anywhere in the script
  • SQL API: query, queryRow, queryScalar, execute with positional or named parameters
  • Transaction support: begin, commit, rollback
  • Streaming cursor for large MySQL result sets; fetch in configurable batches
  • Redis: strings, counters, lists, hashes, sets, TTL/expiry, pub/sub
  • Connection pooling for Redis; all operations are async/await

Bitmap Processing

  • CPU-side pixel buffer with RGBA8, RGB8, RGB16, and RGBA16 format support
  • Decode PNG, JPEG, WebP, BMP, TGA, GIF, PSD, PPM, ICO, and Aseprite; encode to PNG, JPEG, WebP, BMP, and TGA
  • Drawing primitives: fill, rect, line, circle; 12 blend-mode compositing; nearest, bilinear, and bicubic scaled draw
  • Filters: blur, gaussian blur, sharpen, grayscale, sepia, invert, brightness, contrast, hue, saturation, emboss, edge detect, and more
  • Transforms: crop, resize, rotate, flip, trim, and pad; all return new bitmaps
  • DrawContext canvas API: paths, bezier curves, gradients, clipping, flood fill, and text rendering with font loading

Why ThicketScript?

01

Full IDE Support

Dedicated language plugins for JetBrains and VS Code give you autocomplete, type checking, go-to-definition, and error highlighting. First-class tooling from day one.

02

Straight to Bytecode

No JavaScript anywhere in the pipeline. Source goes in, optimized bytecode comes out. Types are checked at compile time, not at runtime. The result is fast startup, low memory use, and smooth frame rates.

03

Built to Embed

ThicketScript is a library, not a platform. It does not own your main loop, manage windows, or assume it is the only thing running. Link it into your C++ app, register your own functions, and control execution step by step. The tks CLI is itself just a thin wrapper around the same runtime.

04

Secure and Crash-Proof

Scripts start with zero access. No filesystem, no network. You opt in to exactly what scripts can do. Stack overflows, infinite loops, and out-of-memory are caught and reported; the host app keeps running, even when scripts misbehave.

05

Batteries Included

The standard library covers Math, collections, reactive state, HTTP, TCP, WebSocket, UDP, database (SQLite, MySQL, Redis), filesystem, crypto, compression, shell, environment, terminal I/O, Bitmap, and DateTime. No package manager. No node_modules. Everything you need to build real tools is already there.

06

TypeScript Syntax, No JavaScript

If your team already knows TypeScript, ThicketScript has almost no learning curve. Same syntax, same patterns: classes, generics, destructuring, async/await, template literals. What you lose is the JavaScript ecosystem overhead. What you gain is a fast C++ VM, static dispatch, and a language designed for embedding rather than the browser.

Use Cases

01 ThicketScript Standalone

What you can do with tks and nothing else.

CLI Tools

Build scripts, file processing, code generation. tks run app.tks and you are done.

Servers

HTTP servers, API endpoints, background workers. Built-in system.http and system.net modules.

Automation

Task runners, data pipelines, deployment scripts. Same language whether you are scripting or building.

Image Processing

Resize, crop, filter, and composite images in script. Decode PNG, JPEG, WebP, Aseprite, and more; apply filters and transforms; encode to any supported format.

02 With the Dev Thicket Ecosystem

Add Willow or Willow UI.

2D Games

Build games with Willow's scene graph, sprites, cameras, and input handling.

Game UI

Menus, HUDs, inventory screens, dialog systems. Build with Willow UI's component library while the host renders at native speed.

Editor Tooling

Level editors, asset browsers, debug tools. Same language your game uses, so tools share types and code.

03 Embed in Your Own Engine

Link the runtime into any C++ application.

Game Scripting

Script gameplay, AI, and events in your own engine. The sandbox keeps scripts from breaking things.

Modding

Let players write mods in ThicketScript. Grant only the permissions you want; asset loading yes, filesystem no.

Server Logic

Event handlers, world rules, admin tools. Run game logic on the server with full access to the ThicketScript runtime.

Beyond TypeScript

Structs (Value Types)

Structs are first-class value types that live on the stack, not the heap. No garbage collection, no allocations. Fields use typed numerics like float32 and uint8 for compact memory. Define methods and operator overloads directly on the struct.

Structs (Value Types)

Numeric Precision Types

Primary types are int, uint, and float. Sized variants (int8, int16, int32, uint8, uint16, uint32, float32, float64) give explicit control in struct fields. A Color with four uint8 fields is 4 bytes, not 32.

Numeric Precision Types

Series and Parallel

Use series and parallel as function modifiers or scope blocks. series awaits every async call automatically. parallel runs everything at once and waits for the last one to finish. Nest scope blocks however you want.

Series and Parallel

Workers

Mark any function as async worker to run it in a separate thread with full VM isolation. Arguments and return values are deep-copied automatically. No shared state, no races, no locks.

Workers

Mutex Functions

Serialize concurrent calls to the same resource with async mutex. Use $ parameters as lock keys for fine-grained control; different keys run in parallel.

Mutex Functions

Math.tween and Game Math

Built-in tweening with 22 easing curves. Plus smoothstep, snap, wrap, moveTowards, and fract for frame-rate-independent game logic.

Math.tween and Game Math

Reactive State

Built-in Signal, Ref, and computed for reactive programming. Ref tracks value changes and notifies subscribers. computed derives state lazily. No external library needed.

Reactive State

defer

Run cleanup code when a scope exits, no matter how it exits. Works with return, throw, break, and continue. Multiple defers run in reverse order, like Go.

defer

dump() with Variable Name Capture

The dump() function accepts multiple arguments and prints each value alongside its variable name, captured at compile time. No string labels, no manual formatting.

dump() with Variable Name Capture

And so much more.

Roadmap

system.database: PostgreSQL and MongoDB drivers
system.audio: sound effects and music playback
Bytecode optimizer: constant folding, dead code removal, and strength reduction
Hot reload: edit .tks files and see changes without restarting the host
Incremental GC with budget-bounded stepping for predictable frame times
Advanced debugging: async stack traces, conditional breakpoints, watch expressions
Native plugin system for shared library extensions

How It Compares

ThicketScriptLuaV8 / NodeWren
Static Types Built-in× Third-party (Teal) TS layer×
IDE Plugins JetBrains, VS Code, Neovim Community Built-in×
Direct C++ Linking C API Complex C API
Value Types / Structs Stack-allocated×××
async/await + series/parallel Coroutines Fibers
Thread Workers async worker× Worker threads×
Reactive State Signal, Ref, computed× Third-party×
Built-in Tweening 22 easing curves×××
Embedder Sandbox Fine-grained capabilities× Manual only× Runtime isolates×
Host GC Control Collect on demand Incremental stepping×
Built-in DB Drivers MySQL, Redis, SQLite× Third-party×
Bitmap / Image API Built-in (CPU)× Third-party×

Common Questions

What is ThicketScript?

ThicketScript is a scripting language compiled to bytecode for a purpose-built C++ VM. You write .tks files with dedicated IDE support (JetBrains and VS Code). There is no JavaScript transpilation, no V8, and no intermediate language. The runtime is designed for embedding in C++ applications; games, editors, servers, tools.

Why did you make ThicketScript?

We wanted to live in TypeScript-like syntax for day-to-day game logic and app logic, without writing C++ for everything. C++ is great for the engine and libraries underneath, but scripting on top of that should feel lightweight and familiar. ThicketScript gives you that comfortable syntax while compiling to bytecode for a C++ VM, so you get the best of both worlds.

Is ThicketScript based on TypeScript?

No. ThicketScript is its own language with its own compiler, VM, and .tks file extension. It does not use the TypeScript compiler, libraries, or ecosystem in any way. That said, the syntax is heavily inspired by TypeScript; roughly 80% of TypeScript syntax works in ThicketScript as-is. It removes some TypeScript features and adds new ones: first-class structs with operator overloading, series and parallel as function modifiers and scope blocks for async control flow, compact numeric types (float32, uint8, int32), and dump() with compile-time variable name capture. Dedicated IDE plugins for JetBrains and VS Code provide full language support.

How does it compare to Lua?

Both are embeddable scripting languages with stack-based VMs and mark-and-sweep GC. ThicketScript has static type checking, async/await, classes, and dedicated IDE plugins for JetBrains and VS Code. Lua is smaller and more mature. ThicketScript has a richer type system, a stricter default posture, and a broader standard library.

See all questions →

Standard Library

Globalsprint, console, assert, dump, defer, type introspection, type conversion, timing
Mathtween (22 easing curves), clamp, lerp, inverseLerp, map, smoothstep, snap, wrap, moveTowards, fract
RandomSeedable xoshiro256** PRNG with next, nextInt, pick, shuffle, weighted, fork
ReactiveSignal<T>, Ref<T>, computed(), watch() for built-in reactive state management
Core TypesDateTime, JSON, Number, Object, String (with toBase64, toHex), Array, Map, Set, RegExp, Error, Promise, BigInt
CollectionsArray/Map/Set with unique, compact, sum, avg, first, last, sample; Set has union, intersection, difference
Binary DataBuffer and typed arrays (Uint8Array, Float32Array, etc.)
BitmapCPU-side pixel buffer; decode PNG, JPEG, WebP, BMP, TGA, GIF, PSD, Aseprite; pixel access, drawing primitives, 12 blend-mode compositing, filters (blur, sharpen, grayscale, sepia, hue, emboss, and more), transforms (crop, resize, rotate, flip, trim, pad), DrawContext canvas API (paths, gradients, clipping, flood fill, text), encode to PNG/JPEG/WebP/BMP/TGA
system.shellRun subprocesses; returns stdout, stderr, and exit code
system.envRead and write environment variables
system.fsreadText, writeText, readFile, writeFile, exists, size, readDir, mkdir, remove, rename, copy, stat, join, dirname, basename, extname, normalize, resolve, isAbsolute, relative, parsePath, formatPath
system.httpGET, POST, PUT, PATCH, DELETE, HEAD with headers, body, timeout
system.netTCP sockets with connect, listen, accept, send, recv
system.wsWebSocket client and server
system.cryptoHashing, HMAC, AES-256-CBC encrypt/decrypt
system.compressDeflate, inflate, gzip, gunzip
system.databaseMariaDB/MySQL, Redis, SQLite

Not Included (and why)

  • eval and Function() — no runtime code generation; security and performance
  • Proxy and Reflect — dynamic metaprogramming adds runtime cost with no compile-time benefit
  • Symbol — ThicketScript uses string keys; symbols add complexity without clear value for game scripting