Skip to content

Manifest Specification

The xript manifest is the single source of truth for an application’s scripting API. It declares what functionality is exposed to scripts, how it is organized, what capabilities gate access, and what types are involved. From the manifest, everything else is derived: documentation, TypeScript definitions, validation, and interactive playgrounds.

A manifest is a JSON file conforming to the manifest JSON Schema. At minimum, a manifest declares a spec version and a name:

{
"xript": "0.1",
"name": "my-app"
}

From there, complexity is layered on only as needed. Every field beyond xript and name is optional, and each additional section enables more functionality.

The specification version this manifest conforms to. This is not the application’s version; it’s the version of the xript spec the manifest was written against.

Format: major.minor (e.g., "0.1").

A machine-readable identifier for the application. Used in generated package names, documentation URLs, and tooling output.

Constraints: lowercase letters, numbers, and hyphens. Must start with a letter. Maximum 64 characters.

The version of the application’s scripting API, following semver. Tracks how the exposed bindings evolve over time.

A human-readable display name. Used in documentation headers and UI.

A brief description aimed at extenders. Used in documentation landing pages and registry listings.

Bindings define the functions and namespaces that scripts can call.

A function binding declares a callable function:

{
"bindings": {
"getHealth": {
"description": "Returns the player's current health points.",
"returns": "number"
}
}
}

Every function binding requires a description. Optional fields include params, returns, async, capability, examples, and deprecated.

Namespaces group related functions using the members field:

{
"bindings": {
"player": {
"description": "Functions related to the player character.",
"members": {
"getHealth": {
"description": "Returns the player's current health points.",
"returns": "number"
},
"setHealth": {
"description": "Sets the player's health points.",
"params": [
{ "name": "value", "type": "number", "description": "The new health value." }
]
}
}
}
}
}

Namespaces can nest, but deep nesting is discouraged. Two levels is usually plenty.

Capabilities implement the default-deny security model. Every capability is a named permission that must be explicitly granted before scripts can use the functionality it protects.

{
"capabilities": {
"filesystem": {
"description": "Read and write files in the mod's data directory.",
"risk": "medium"
}
}
}

Functions reference capabilities via the capability field. Functions without a capability are always available.

The risk field (low, medium, high) is advisory and helps users make informed decisions about granting capabilities.

Custom types describe complex data structures used in bindings.

{
"types": {
"Position": {
"description": "A 2D position in world coordinates.",
"fields": {
"x": { "type": "number", "description": "Horizontal position." },
"y": { "type": "number", "description": "Vertical position." }
}
}
}
}
{
"types": {
"Direction": {
"description": "A cardinal direction.",
"values": ["north", "south", "east", "west"]
}
}
}

Anywhere a type is expected, you can use:

  • Primitives: "string", "number", "boolean", "void", "null"
  • Custom types: "Position", "Direction"
  • Array shorthand: "string[]", "Position[]"
  • Complex expressions: { "array": "Position" }, { "union": ["string", "number"] }, { "map": "number" }, { "optional": "string" }

Default bounds for script execution:

{
"limits": {
"timeout_ms": 5000,
"memory_mb": 64,
"max_stack_depth": 256
}
}

These are defaults that runtimes enforce unless the host application overrides them.

The manifest supports three adoption tiers through progressive complexity.

{
"xript": "0.1",
"name": "calculator"
}

Safe eval replacement. No bindings, no capabilities.

{
"xript": "0.1",
"name": "my-game",
"version": "1.0.0",
"bindings": {
"getPlayerName": {
"description": "Returns the current player's display name.",
"returns": "string"
},
"getHealth": {
"description": "Returns the player's current health (0-100).",
"returns": "number"
}
}
}

A few functions, no capabilities needed.

Namespaces, capabilities, custom types, examples, and execution limits. See the Game Mod System example walkthrough for a complete tier 3 manifest.

The full JSON Schema is available at spec/manifest.schema.json.