> For AI agents: the complete documentation index is available at https://docs.tessl.io/llms.txt, the full documentation bundle is available at https://docs.tessl.io/llms-full.txt.

# Import a Claude Code plugin

:::info

**Takeaway**
Run `tessl plugin import` in a Claude Code plugin folder. It writes `.tessl-plugin/plugin.json` from `.claude-plugin/plugin.json`, links the folder to a Tessl project, and prints the review, scenario, and eval commands to run next.

:::

You have a Claude Code plugin with several skills, and you want to review them, generate scenarios, and run an eval. Tessl reads only `.tessl-plugin/plugin.json`, so a Claude Code plugin needs a Tessl manifest and a linked project first. `tessl plugin import` does both in one step and leaves `.claude-plugin/` untouched, so the plugin keeps working in Claude Code.

## Import the plugin

From the plugin's root folder, the one that holds `.claude-plugin/`:

```bash
tessl plugin import . --workspace engteam
```

`engteam` is a stand-in workspace. Run `tessl workspace list` and use one of yours in its place.

The command:

1. Writes `.tessl-plugin/plugin.json` from the Claude manifest. The Claude name is flat, so the workspace becomes its prefix: `my-plugin` becomes `engteam/my-plugin`.
2. Checks the result with the same validator `tessl plugin lint` uses, and prints anything it finds.
3. Links the folder to a Tessl project. It reports a project that is already linked, links the project that matches the repository, or creates one. When no `tessl.json` encloses the folder, it creates one at the plugin root.
4. Prints the next commands with real paths: `tessl review run` for each skill, then `tessl scenario generate` and `tessl eval run` for the plugin.

Run it again and nothing changes; it reports that the plugin is already imported.

## What it imports

`plugin import` accepts four kinds of folder:

- **A Claude Code plugin**, with `.claude-plugin/plugin.json`. Its fields map to the Tessl manifest as described below.
- **A folder of skills with no manifest**, with `skills/<name>/SKILL.md`. The plugin is named after the folder. Pass `--description`, since there is no manifest to copy it from.
- **A single `SKILL.md`** at the folder root. This writes the same manifest as `tessl skill import`. You can pass the folder or the `SKILL.md` file itself.
- **A Claude Code marketplace**, with only `.claude-plugin/marketplace.json`. It writes nothing. For each plugin the marketplace keeps in a local folder, it lists the `tessl plugin import` command to run. A plugin whose source is a git repository or URL is listed by name only; clone it and import it from its own folder.

A folder that already has `.tessl-plugin/plugin.json` keeps it. The command goes straight to the project step. Pass `--force` to rebuild the manifest from `.claude-plugin/plugin.json`.

## How the Claude manifest maps

- **`name`** becomes `<workspace>/<name>`. Pass `--name` to change the name part. Plugin names use lowercase letters, numbers, dots, underscores, and hyphens, up to 90 characters. A Claude name outside that set is converted, with a warning: `My Plugin` becomes `my-plugin`. The same applies to a folder name or a `SKILL.md` name.
- **`version`** is copied, or set to `0.1.0`.
- **`description`** is copied. Tessl requires one, so without it pass `--description`, or answer the prompt in a terminal.
- **`author`** is copied. A string becomes `{ "name": "..." }`.
- **`homepage`** and **`license`** are copied.
- **`repository`** is kept when it is an http(s) URL. `git@github.com:owner/repo.git` becomes `https://github.com/owner/repo`. Anything else is dropped with a warning.
- **`skills`** and **`commands`** are left out when they point at the default `./skills` and `./commands` folders, which Tessl finds by convention. Other paths are written out as the list of skill folders and command files they reach, together with the ones in `./skills` and `./commands`, since Claude Code reads both and Tessl reads only the list.
- **`mcpServers`** pointing at `.mcp.json` is kept. An inline server map is written to `.mcp.json` when that file is absent. An existing `.mcp.json` with different content is kept, with a warning.
- **`agents`**, **`keywords`**, and **`hooks`** are not imported, and each one produces a warning that names what was dropped. Claude Code also loads `hooks/hooks.json` and `agents/` when `plugin.json` names neither, so those folders produce the same warning. Add hooks by hand under `hooks` or `nativeHooks`; see [Configuration files](https://docs.tessl.io/reference/configuration.md).

The plugin is private unless you pass `--public`.

## Choose the workspace and organization

The plugin name needs a workspace. It comes from the first of these that is set:

1. `--workspace`
2. The workspace of the project the folder is already linked to
3. `TESSL_WORKSPACE`
4. A prompt, in a terminal

In CI or a piped shell with none of these set, the command stops and names `--workspace`. A workspace name has 4 to 40 lowercase letters, numbers, and hyphens; any other value is refused before anything is written.

The project step uses the same organization rules as `tessl project create`: `--org`, then `TESSL_ORG`, then your only organization, then a prompt.

## Flags

| Flag            | Purpose                                                                                                                                                                                                                                                 |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workspace`   | Workspace for the plugin name, and for a project the command creates.                                                                                                                                                                                   |
| `--org`         | Organization for the project step.                                                                                                                                                                                                                      |
| `--name`        | Plugin name without the workspace.                                                                                                                                                                                                                      |
| `--description` | Description when the source has none.                                                                                                                                                                                                                   |
| `--public`      | Make the plugin public. Private by default.                                                                                                                                                                                                             |
| `--no-project`  | Write the manifest only. Skip linking or creating a project.                                                                                                                                                                                            |
| `--force`       | Rebuild an existing `.tessl-plugin/plugin.json` from `.claude-plugin/plugin.json`.                                                                                                                                                                      |
| `--dry-run`     | Print the manifest it would write, and write nothing.                                                                                                                                                                                                   |
| `--json`        | Print one JSON document: the source type, manifest path, manifest, warnings, project action (`existing`, `linked`, `created`, or `skipped`), and next commands. A failed import prints `{ "status": "error", "message": "..." }` and exits with code 1. |

Writing the manifest needs no login. Linking a project does: without one, the command writes the manifest, then stops and tells you to run `tessl login` and the import command to finish, with the same `--workspace`.

## Next

- [Prove a skill works using evaluation](https://docs.tessl.io/improving-your-skills/evaluate-skill-quality-using-scenarios.md): generate scenarios and run an eval on the imported plugin.
- [Create a plugin](https://docs.tessl.io/creating-skills-and-plugins/create-a-plugin.md): the plugin layout and the content types it can hold.
- [Publish and update](https://docs.tessl.io/creating-skills-and-plugins/publish-and-update.md): share the plugin with your team or publicly.
