# Command Plugins

EDA tools generally extend their embedded Tcl shells with custom tool-specific commands.
`tclint` supports a command plugin system that allows it to check that scripts use these
commands correctly.

Currently, `tclint` includes one built-in plugin for the [OpenROAD][openroad]
place-and-route tool.

## Command Specs

Before you can use a plugin, you must first generate a "command spec". Command specs are
files that define what commands a tool supports. This concept removes the need for
plugins to hard-code these details. Instead, plugins generate command specs by running
the tool itself. Plugins can, for example, parse the tool's `help` output to determine
what arguments each command supports.

To facilitate this, the command spec must be generated on a machine that has the ability
to run the corresponding tool. However, the command spec itself can be shared and used
to check scripts on a different machine that does not have access to the tool.

> [!IMPORTANT]
> Tool APIs frequently change between versions. You should generate command specs using
the version of tool that your script targets.

Command specs are generated by the `tclint` plugin manager, `tclint-plugins` (this
command is installed alongside `tclint`). For example, the following command writes a
command spec for OpenROAD to `openroad.json`:

```shell
tclint-plugins make-spec openroad --output openroad.json
```

By default, the plugin expects you have the `openroad` binary on your path. You may
also specify an alternate mechanism for running the command via the `--exec` flag.
For example, if your OpenROAD installation lives in a Docker container, you may do
something like:

```shell
tclint-plugins make-spec openroad --output openroad.json \
    --exec 'docker run -i my_or_image openroad'
```

## Using Plugins

There are several ways to actually check a tool-specific script using a plugin. The
simplest is to pass the command spec to `tclint` via `--commands`:

```shell
tclint or_place.tcl --commands openroad.json
```

For codebases that contain scripts for multiple tools, it's best to use a configuration
file that defines multiple filesets. For example, for a codebase like:

```
├── openroad_scripts/
├── other_scripts/
└── tclint.toml
```

You might add the following section to `tclint.toml`:

```toml
[[fileset]]
paths = ["openroad_scripts/"]
commands = "~/.tclint/openroad.json"
```
[openroad]: https://github.com/The-OpenROAD-Project/OpenROAD
