
# tecs.debug


Debugger commands, and the tools they project to.

A command is declared once. Its argument schema types both a typed command line
and a JSON tool call, its action returns one structured result, and the debug
server advertises it with an input schema, an output schema and safety hints
that were all derived from that single declaration. Nothing about a command is
written twice, so the two surfaces cannot disagree.

## Getting the commands

`tecs.io.mcp` does not install them. An application with `mcpPort` set calls
`ensure` for its own world, so every session that has a debug server has the
whole command surface. A headless tool calls `ensure` itself.

## Adding one

```teal
local debugapi <const> = require("tecs.debug")

debugapi.ensure(world)
debugapi.register(
    world,
    {
        name = "wave",
        section = "Custom",
        shortHelp = "report the wave the game is on",
        agentHelp = "Reports the current wave number and how many enemies are left in it. "
            .. "Call it to check progress before spawning or despawning anything.",
        readOnly = true,
        outputSchema = {
            ["type"] = "object",
            properties = {
                wave = {["type"] = "integer"},
                remaining = {["type"] = "integer"},
            },
            required = {"wave", "remaining"},
        },
        run = function(_values: {string: any}): debugapi.Result
            return {
                message = "wave " .. tostring(state.wave),
                data = {
                    wave = state.wave, remaining = state.remaining
                },
            }
        end,
    }
)
```

That registers the tool `wave`. A command with `subcommands` registers one tool
per verb, named `<command>_<verb>`, and registers `<command>` as well when it
carries a `run` of its own.

## Results and failures

`Result.data` is the tool call's structured content, and `Result.message`
travels beside it under the key `message`. A result with `ok = false` raises its
`code` and `message` through the tool call, so an agent reads a failure the way
it reads any other tool error rather than by inspecting a field.

Declare `outputSchema` on anything a game ships. It is what lets an agent know
the shape of an answer before it makes the call, and it is what the reference
renders.

## Command names are a compatibility surface

A tool name is generated from a command name and a verb name, so renaming
either renames a tool that an agent already calls. Choose both once.

Requiring this module as `debug` shadows Lua's own `debug` library. A module
that needs both binds this one as `debugapi`.

## Module contents

### Types

| Type | Kind | Description |
| --- | --- | --- |
| [`ArgSpec`](/modules/debug/#tecs.debug.ArgSpec) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Declares one argument. |
| [`Command`](/modules/debug/#tecs.debug.Command) | <span class="tealdoc-kind-badge tealdoc-kind-type">type</span> | Declares one command. |
| [`Registry`](/modules/debug/#tecs.debug.Registry) | <span class="tealdoc-kind-badge tealdoc-kind-type">type</span> | Holds the commands one world has declared. |
| [`Result`](/modules/debug/#tecs.debug.Result) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Reports what one command did. |
| [`Schema`](/modules/debug/#tecs.debug.Schema) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Declares a command's arguments. |
| [`Subcommand`](/modules/debug/#tecs.debug.Subcommand) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Declares one verb under a command. |

### Functions

| Function | Kind | Description |
| --- | --- | --- |
| [`bindRenderer`](/modules/debug/#tecs.debug.bindRenderer) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Tells the commands which renderer draws this world. |
| [`ensure`](/modules/debug/#tecs.debug.ensure) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Builds the world's command registry, or returns the one it already has. |
| [`of`](/modules/debug/#tecs.debug.of) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the registry installed in world. |
| [`register`](/modules/debug/#tecs.debug.register) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Registers a game's own command and projects it onto the debug server. |

### Values

| Value | Type | Description |
| --- | --- | --- |
| [`SECTIONS`](/modules/debug/#tecs.debug.SECTIONS) | `{string}` | Read-only. Groups commands in help and in the generated reference, in the order they are presented. |

## Types

<a id="tecs.debug.ArgSpec"></a>
### tecs.debug.ArgSpec <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Declares one argument.


```teal
record tecs.debug.ArgSpec
    required: boolean
    default: any
    help: string
    forward: string
    synthetic: {string}
    kind: string
    enum: {string}
    min: number
    max: number
    rest: boolean
end
```

<a id="tecs.debug.ArgSpec.required"></a>
#### tecs.debug.ArgSpec.required <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Requires the argument to hold a value once parsing finishes.


```teal
tecs.debug.ArgSpec.required: boolean
```

<a id="tecs.debug.ArgSpec.default"></a>
#### tecs.debug.ArgSpec.default <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Supplies the value used when the argument is absent, and infers the
value type when `kind` is omitted. A forwarding argument never receives its default,
which only types it.


```teal
tecs.debug.ArgSpec.default: any
```

<a id="tecs.debug.ArgSpec.help"></a>
#### tecs.debug.ArgSpec.help <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Describes the argument in generated help and in the MCP tool schema.


```teal
tecs.debug.ArgSpec.help: string
```

<a id="tecs.debug.ArgSpec.forward"></a>
#### tecs.debug.ArgSpec.forward <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Names the synthetic argument this argument feeds its value into.


```teal
tecs.debug.ArgSpec.forward: string
```

<a id="tecs.debug.ArgSpec.synthetic"></a>
#### tecs.debug.ArgSpec.synthetic <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Lists the source argument names this synthetic argument accepts, and
its presence marks the argument synthetic, so users neither name it nor see it.


```teal
tecs.debug.ArgSpec.synthetic: {string}
```

<a id="tecs.debug.ArgSpec.kind"></a>
#### tecs.debug.ArgSpec.kind <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. States the value type explicitly, as `"number"`, `"boolean"`,
`"string"`, `"list"`, `"table"` or `"rows"`. Omitting it infers the type from
`default`, so set it for an optional typed argument that has no default, such as a
number that leaves the current value unchanged when absent. A `"list"` is a
comma-separated string on the command line and a JSON string array over MCP. A
`"table"` is a brace-balanced Lua expression on the command line and a JSON object over
MCP. A `"rows"` argument is that same expression on the command line and a JSON array
of objects over MCP, so an action receives either a string or a table and handles both.


```teal
tecs.debug.ArgSpec.kind: string
```

<a id="tecs.debug.ArgSpec.enum"></a>
#### tecs.debug.ArgSpec.enum <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Restricts a string argument to these values, and projects to a JSON
Schema `enum`.


```teal
tecs.debug.ArgSpec.enum: {string}
```

<a id="tecs.debug.ArgSpec.min"></a>
#### tecs.debug.ArgSpec.min <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Bounds a number argument from below, inclusively.


```teal
tecs.debug.ArgSpec.min: number
```

<a id="tecs.debug.ArgSpec.max"></a>
#### tecs.debug.ArgSpec.max <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Bounds a number argument from above, inclusively.


```teal
tecs.debug.ArgSpec.max: number
```

<a id="tecs.debug.ArgSpec.rest"></a>
#### tecs.debug.ArgSpec.rest <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Makes the slot consume every remaining token as free text, joined with
single spaces, where a quoted span keeps its inner spacing. The argument must be the
last positional slot and must be string-, table- or rows-typed.


```teal
tecs.debug.ArgSpec.rest: boolean
```

<a id="tecs.debug.Command"></a>
### tecs.debug.Command <span class="tealdoc-kind-badge tealdoc-kind-type">type</span>

Declares one command.


```teal
type tecs.debug.Command = debugtypes.Command
```

<a id="tecs.debug.Registry"></a>
### tecs.debug.Registry <span class="tealdoc-kind-badge tealdoc-kind-type">type</span>

Holds the commands one world has declared.


```teal
type tecs.debug.Registry = registry.Registry
```

<a id="tecs.debug.Result"></a>
### tecs.debug.Result <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Reports what one command did.


```teal
record tecs.debug.Result
    ok: boolean
    code: string
    message: string
    data: {string: any}
end
```

<a id="tecs.debug.Result.ok"></a>
#### tecs.debug.Result.ok <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Reports whether the command did what it was asked.
Omitted counts as success. False raises the command's message
through the tool call rather than answering with it.


```teal
tecs.debug.Result.ok: boolean
```

<a id="tecs.debug.Result.code"></a>
#### tecs.debug.Result.code <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Names the failure in a word an agent can match on,
such as `no_match` or `invalid_ref`. Required when `ok` is false and
ignored otherwise.


```teal
tecs.debug.Result.code: string
```

<a id="tecs.debug.Result.message"></a>
#### tecs.debug.Result.message <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Summarizes the outcome for a person in one line.
A successful command carries it beside its data under the key
`message`.


```teal
tecs.debug.Result.message: string
```

<a id="tecs.debug.Result.data"></a>
#### tecs.debug.Result.data <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Carries the structured answer, which is what the
tool call returns and what `outputSchema` describes. Omitted answers
with the message alone.


```teal
tecs.debug.Result.data: {string: any}
```

<a id="tecs.debug.Schema"></a>
### tecs.debug.Schema <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Declares a command's arguments.


```teal
record tecs.debug.Schema
    args: {string: ArgSpec}
    positional: {string}
end
```

<a id="tecs.debug.Schema.args"></a>
#### tecs.debug.Schema.args <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Maps each argument name to the spec that types it.


```teal
tecs.debug.Schema.args: {string: ArgSpec}
```

<a id="tecs.debug.Schema.positional"></a>
#### tecs.debug.Schema.positional <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Lists the argument names bound by position, in order. A slot may name
a synthetic argument.


```teal
tecs.debug.Schema.positional: {string}
```

<a id="tecs.debug.Subcommand"></a>
### tecs.debug.Subcommand <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Declares one verb under a command.


```teal
record tecs.debug.Subcommand
    name: string
    aliases: {string}
    shortHelp: string
    agentHelp: string
    schema: cmdargs.Schema
    examples: {string}
    outputSchema: {string: any}
    readOnly: boolean
    destructive: boolean

    run: function({string: any}): Result
end
```

<a id="tecs.debug.Subcommand.name"></a>
#### tecs.debug.Subcommand.name <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Names the verb. The projected tool is
`<command>_<name>`, so this string is part of an externally typed
surface once it ships. Required.


```teal
tecs.debug.Subcommand.name: string
```

<a id="tecs.debug.Subcommand.aliases"></a>
#### tecs.debug.Subcommand.aliases <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Names other spellings that dispatch to this verb on
a typed command line. Aliases are never projected as tools.


```teal
tecs.debug.Subcommand.aliases: {string}
```

<a id="tecs.debug.Subcommand.shortHelp"></a>
#### tecs.debug.Subcommand.shortHelp <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Says what the verb does in one line, lowercase and
without a trailing period. Required.


```teal
tecs.debug.Subcommand.shortHelp: string
```

<a id="tecs.debug.Subcommand.agentHelp"></a>
#### tecs.debug.Subcommand.agentHelp <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Says what an agent needs: when to call this, what
it changes, what it answers with, and what to call next. The
projected tool description falls back to `shortHelp`, which is
written to fit one line rather than to brief an agent.


```teal
tecs.debug.Subcommand.agentHelp: string
```

<a id="tecs.debug.Subcommand.schema"></a>
#### tecs.debug.Subcommand.schema <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Declares the arguments. Omitted means the verb
takes none.


```teal
tecs.debug.Subcommand.schema: cmdargs.Schema
```

<a id="tecs.debug.Subcommand.examples"></a>
#### tecs.debug.Subcommand.examples <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Shows complete command lines that work, for the
generated reference and the usage output.


```teal
tecs.debug.Subcommand.examples: {string}
```

<a id="tecs.debug.Subcommand.outputSchema"></a>
#### tecs.debug.Subcommand.outputSchema <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Describes `Result.data` as a JSON Schema. The
projection advertises it as the tool's `outputSchema`, so an agent
knows the shape of the answer before making the call.


```teal
tecs.debug.Subcommand.outputSchema: {string: any}
```

<a id="tecs.debug.Subcommand.readOnly"></a>
#### tecs.debug.Subcommand.readOnly <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Declares that the verb only reads. Omitted derives
the answer from the verb: `list`, `info`, `status` and `get` read.


```teal
tecs.debug.Subcommand.readOnly: boolean
```

<a id="tecs.debug.Subcommand.destructive"></a>
#### tecs.debug.Subcommand.destructive <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Declares that the verb destroys something a caller
cannot get back. Omitted derives the answer from the verb.


```teal
tecs.debug.Subcommand.destructive: boolean
```

<a id="tecs.debug.Subcommand.run"></a>
#### tecs.debug.Subcommand.run <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Caller-writable. Runs the verb. Required.


```teal
function tecs.debug.Subcommand.run({string: any}): Result
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | `{string : any}` |  |

##### Returns

| Type | Description |
| --- | --- |
| `Result` |  |

## Functions

<a id="tecs.debug.bindRenderer"></a>
### tecs.debug.bindRenderer <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Tells the commands which renderer draws this world.

Commands that read or draw through the renderer answer with a failure until
something calls this, since a world alone does not name one.



```teal
function tecs.debug.bindRenderer(
    world: types.World, renderer: Renderer
)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`types.World`](/modules/ecs/#tecs.World) | The caller supplies the world the renderer draws. |
| `renderer` | [`Renderer`](/modules/gfx/#tecs.gfx.Renderer) | The caller supplies the renderer, or nil to unbind. |

#### Returns

None.

<a id="tecs.debug.ensure"></a>
### tecs.debug.ensure <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Builds the world's command registry, or returns the one it already has.

Registering the engine's own commands projects each of them onto the debug
server, so a session that calls this once has the whole surface. Calling it
again answers with the same registry and registers nothing further.



```teal
function tecs.debug.ensure(world: types.World): registry.Registry
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`types.World`](/modules/ecs/#tecs.World) | The caller supplies the world the commands read and write. |

#### Returns

| Type | Description |
| --- | --- |
| [`registry.Registry`](/modules/debug/#tecs.debug.Registry) | The world's registry. |

<a id="tecs.debug.of"></a>
### tecs.debug.of <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the registry installed in `world`.



```teal
function tecs.debug.of(world: types.World): registry.Registry
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`types.World`](/modules/ecs/#tecs.World) | The caller supplies a world with or without a registry. |

#### Returns

| Type | Description |
| --- | --- |
| [`registry.Registry`](/modules/debug/#tecs.debug.Registry) | The world's registry, or nil before `ensure` has run. |

<a id="tecs.debug.register"></a>
### tecs.debug.register <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Registers a game's own command and projects it onto the debug server.

Raises when the world has no registry, and raises on a malformed
declaration: a command is written once and called forever, so a mistake in
one belongs at the call that made it.



```teal
function tecs.debug.register(
    world: types.World, command: debugtypes.Command
)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`types.World`](/modules/ecs/#tecs.World) | The caller supplies a world `ensure` has already run on. |
| `command` | [`debugtypes.Command`](/modules/debug/#tecs.debug.Command) | The caller supplies a complete declaration. |

#### Returns

None.

## Values

<a id="tecs.debug.SECTIONS"></a>
### tecs.debug.SECTIONS <span class="tealdoc-kind-badge tealdoc-kind-variable">variable</span>

Read-only. Groups commands in help and in the generated reference, in
the order they are presented. A command that names no section groups as
`"Custom"`.


```teal
tecs.debug.SECTIONS: {string}
```