Pre-AlphaMetaScript is in early design phase. The compiler is not yet available.Join Discord for updates
MetaScript

Compile-Time Superpowers

MetaScript macros generate code at compile-time, not runtime. Zero overhead, full type safety, and you can inspect what they produce.

See What Macros Generate

Unlike runtime reflection, MetaScript macros run during compilation. The generated code is type-checked and optimized just like hand-written code.

You write:

@derive(Eq, Clone, Debug)
class Point {
  x: number
  y: number
}

Compiler generates:

class Point {
  x: number
  y: number

  equals(other: Point): boolean {
    return this.x === other.x
        && this.y === other.y
  }

  clone(): Point {
    return new Point(this.x, this.y)
  }

  toString(): string {
    return `Point { x: ${this.x}, y: ${this.y} }`
  }
}

Run msc expand src/file.ms anytime to see exactly what code macros generate. No magic, no hidden behavior.

Built-in Macros

@derive(...traits)

Auto-generate common methods based on class fields. The most-used macro.

Traits: Eq, Hash, Clone, Debug, Serialize, Default

@comptime { ... }

Execute code at compile-time. Results are embedded as constants in the output.

Capabilities: Arbitrary expressions, File reads, API calls

@serialize(options)

Customize serialization with field mapping, renaming, and format options.

Options: rename_all, skip_null, flatten

@test

Mark a function as a test case. Discovered and run by msc test.

Options: name, timeout, skip

@comptime: Compile-Time Execution

Execute arbitrary code during compilation. Read files, fetch configs, compute constants—all at build time, not runtime.

// This runs at compile-time:
@comptime {
  const config = JSON.parse(
    fs.readFileSync("./config.json")
  )
}

// 'config' is now a compile-time constant
// Embedded directly in the binary
console.log(config.apiUrl)  // No file read at runtime!

Writing Custom Macros

Macros are just MetaScript functions that transform AST nodes. They're defined in std/macros/ and you can write your own.

// Define a custom macro
@macro
function logger(target: ClassDecl): ClassDecl {
  // Add logging to every method
  for (const method of target.methods) {
    method.body = wrapWithLogging(method.body)
  }
  return target
}

// Use it
@logger
class UserService {
  async getUser(id: string) { ... }
}

Learn more about writing custom macros