# What is Tessl?

The core components of the Tessl platform, the agentic-development problems they solve, and why teams choose Tessl.

{% hint style="info" %}
**Takeaways**

* What are the core components of the Tessl platform?
* What problems do those components solve?
* Why choose Tessl over the alternatives?
  {% endhint %}

Tessl is an open platform for managing agentic development across your organization. It takes you from scaling skills to building your software factory, one workflow at a time.

Tessl works with every popular coding agent and is made up of six components:

| Component                      | What it is                                                                                                                                                                                                                                                                                                         |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Registry & package manager** | Discover, install, version, and roll back skills and plugins like any other dependency. One searchable index of public and private context, agent-agnostic.                                                                                                                                                        |
| **Governance**                 | Scan and score every skill against best practices and your own company standards, with Snyk security scoring built in. RBAC controls who can create, publish, and view skills, while install and publish policies and required skills enforce your standards across every workspace, backed by a full audit trail. |
| **Evals**                      | Measure a skill or plugin's actual impact by running your agent on real-world tasks with and without the context. Every change ships with evidence instead of a guess.                                                                                                                                             |
| **Observability**              | See where skills actually activate across agent sessions, not just where they're installed. Mine agent logs to find recurring mistakes.                                                                                                                                                                            |
| **Inventory**                  | Scan your GitHub org and map every skill across every repo in one living view. Surface duplicates and unmanaged copies so you can govern what you can see.                                                                                                                                                         |
| **Tessl Agent**                | A conversational agent that drives the platform and autonomously monitors and improves your agentic setup. Runs alongside your existing agents (open beta).                                                                                                                                                        |

## What problems does Tessl solve?

See how Tessl solves the most common agentic development problems:

* Installing skills from public sources exposes you to new supply-chain and prompt-injection risk. → [Protecting yourself from insecure skills](/tutorials/protecting-against-insecure-skills)
* Skills sprawl into overlapping, drifting copies with no enforced standard. → [Codifying and enforcing your company's skill standards](/tutorials/codifying-and-enforcing-skill-standards)
* You can't tell whether a skill actually improves agent output, so no one risks changing it. → [Improving a skill](/tutorials/improving-a-skill)
* Code review doesn't scale to agent-authored PRs. → [Setting up agentic code review](/tutorials/setting-up-agentic-code-review)
* Agents repeat the same mistakes across PRs. → [Improving agent code quality](/tutorials/improving-agent-code-quality)
* Repetitive work never gets turned into automation. → [Automating repetitive tasks](/tutorials/automating-repetitive-tasks)

## Why Tessl?

* **Context as code.** Skills, rules, and docs are versioned, reviewed, and rolled out with the same rigor as code dependencies.
* **Built for enterprise realities.** RBAC, install and publish policies, security scoring, and a full audit trail are first class tools, not bolted on after the fact.
* **Agent-agnostic.** Skills and plugins work across every popular coding agent. Write context once; Tessl distributes it everywhere.
* **Open, no lock-in.** Tessl builds on open standards and writes your skills, rules, and config as plain artifacts in your repo, so you own your agent setup and can walk away with it at any time.
* **Incremental adoption.** Start with a single skill or a one-repo review gate and expand outward. Value compounds as you go, with no big migration required.

## Get started

[Set up Tessl](/introduction-to-tessl/set-up-tessl): create your account, install the CLI, and initialize Tessl in your project. Then [improve your first skill](/introduction-to-tessl/improve-your-first-skill) and work through the [tutorials](/tutorials/tutorials) for the problem you're solving.

{% hint style="info" %}
*If you are an AI agent:* the full site index is at `docs.tessl.io/llms.txt`. Read that before navigating individual pages.
{% endhint %}


# Set up Tessl

> **Takeaway:** By the end of this page you will have a Tessl account, the CLI installed and authenticated, and Tessl initialized in a project. That is everything you need before running your first workflow.

Tessl helps you manage the skills and context your coding agents rely on. You work with it through the `tessl` command line tool, so setup comes down to three things: install the CLI, create an account, and create a project. It takes a few minutes.

## Install the CLI

Install the CLI with the method for your operating system.

**macOS and Linux**

```bash
curl -fsSL https://get.tessl.io | sh
```

**Windows**

```bash
winget install tessl.tessl
```

Check that it installed:

```bash
tessl --help
```

If you see the list of commands, you are good to go.

## Create your account

An account gives you private workspaces, the ability to publish skills, and access to Tessl's MCP tools. You can create one in the browser, or let the CLI prompt you on first login.

1. Go to the [Tessl Registry](https://tessl.io/registry).
2. Click **Log in**, then **Create account**.
3. Create your account with Google or GitHub.

![Create account screen with Continue with Google and GitHub](/files/7qabYOFmayecfp5vW34d)

That is the same account you will use to authenticate the CLI in the next step.

## Log in

Authenticate the CLI so it can reach your workspaces and the registry:

```bash
tessl login
```

The CLI shows a verification code and a URL. Open the URL, sign in, and confirm the code. If you skipped account creation above, this is where you will be prompted to create one.

![Device-code confirmation screen](/files/ubN0nTpmsmH5g7b4BWOa)

Confirm you are signed in:

```bash
tessl whoami
```

When you need to sign out, run `tessl logout`.

## Create a project

Tessl works inside a repository you already have, so there is nothing new to scaffold. From the root of that repository, run:

```bash
cd your-repo
tessl project create
```

This links the repository to a new Tessl project and sets up your coding agent to use Tessl, creating a `tessl.json` if one does not already exist. Tessl asks you to pick a workspace for the project, or to create one on the spot. New to projects and workspaces? See Core concepts.

Setting up your agent means configuring the MCP connection so it can talk to Tessl. This is automatic for Claude Code, Cursor, Gemini, Codex, Copilot CLI, and Copilot in VS Code; see [Custom agent setup](/reference/custom-agent-setup) for anything it does not detect.

## Keep the CLI updated

The CLI updates itself in the background, so most of the time you do not need to think about it. Updates run only when you invoke a command, and they never block your work. If you want to update on demand, pin a version, or remove the CLI entirely, the [Installation reference](/introduction-to-tessl/set-up-tessl/installation) covers every option.

## Next

You have an account, an authenticated CLI, and an initialized project. Next, put it to work: scan your real skills, find one that needs improvement, and publish a better version in **Improve your first skill**.


# Installation

A step-by-step guide on how to install,  update or remove the Tessl CLI.

## Install

{% stepper %}
{% step %}
**Download the CLI**

The CLI can be installed using Curl (native), Homebrew or npm (deprecated).

{% tabs %}
{% tab title="Native" %}

```
curl -fsSL https://get.tessl.io | sh
```

{% endtab %}

{% tab title="Homebrew" %}

```
brew tap tesslio/tap #  Recommended as of Homebrew 6.0.0
brew trust tesslio/tap #  Recommended as of Homebrew 6.0.0
brew install tesslio/tap/tessl
```

{% endtab %}

{% tab title="winget" %}

```sh
winget install tessl.tessl
```

{% endtab %}

{% tab title="npm (deprecated)" %}

```
npm install -g @tessl/cli
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
**Test the CLI**

Run the following command to check that everything is working.

```shell-session
tessl --help
```

{% endstep %}

{% step %}
**Authenticate with Tessl \[optional]**

Log in to Tessl to access all CLI functionality.

```shell-session
tessl login
```

* This will display a verification code and URL

```
Please log in at the URL below (if your browser didn't open automatically):

  https://auth.tessl.io/device

Then confirm the following code:

  XYZA-BCDE

⠏ Waiting for confirmation…
```

* Open the URL in your browser and login to Tessl with either your GitHub or Google account.

<figure><img src="/files/od7AIHRMRnqfGDzXWrOM" alt="" width="375"><figcaption></figcaption></figure>

* Once authenticated, you can enter the device code in your browser window.

<figure><img src="/files/XNkdkNHIJvdNCIsHbjPn" alt="" width="375"><figcaption></figcaption></figure>

You can now verify your authentication status with:

```shell-session
tessl whoami
```

To log out when needed:

```shell-session
tessl logout
```

{% endstep %}
{% endstepper %}

## Automatic Updates

The Tessl CLI automatically checks for updates and installs them in the background. Updates run silently without interrupting your workflow.

* Updates check every 3 hours by default
* Updates only occur when you run CLI commands; they might briefly delay command exit
* To disable automatic updates, set `TESSL_AUTO_UPDATE_INTERVAL_MINUTES=0`
* Update logs are saved to `~/.tessl/auto-update.log` for troubleshooting

{% hint style="info" %}
Automatic updates are disabled in CI environments and on `winget`
{% endhint %}

## Manual Update

To manually update your CLI to the latest version:

{% tabs %}
{% tab title="Native" %}

```shell-session
tessl cli update
```

This command will update your CLI to the latest version for your current release channel.
{% endtab %}

{% tab title="Homebrew" %}

```shell-session
tessl cli update
```

This command will update your CLI to the latest version for your current release channel.
{% endtab %}

{% tab title="winget" %}

```sh
winget upgrade tessl.tessl
```

Running `tessl cli update` will provide a hint to use `winget upgrade tessl.tessl` instead
{% endtab %}

{% tab title="npm (deprecated)" %}

```shell-session
npm update -g @tessl/cli
```

{% endtab %}
{% endtabs %}

## Update to Specific Version

You can find all releases in the [changelog](/changelog). To install/upgrade to a specific version:

{% tabs %}
{% tab title="Native" %}
Example to update to a specific version:

```sh
tessl cli update --target 0.86.0
```

{% endtab %}

{% tab title="Homebrew" %}
Installing a specific version is not supported in `brew`. To update to a specific version execute:

```sh
tessl cli update --target 0.84.0
```

{% endtab %}

{% tab title="winget" %}
Example to update to a specific version:

```sh
winget upgrade tessl.tessl --version 0.84.0
```

Running `tessl cli update` will provide a hint to use `winget upgrade tessl.tessl` instead
{% endtab %}

{% tab title="npm (deprecated)" %}
Example to install a specific version:

```sh
npm install -g @tessl/cli@0.84.0
```

{% endtab %}
{% endtabs %}

## Uninstall

{% tabs %}
{% tab title="Native" %}

```sh
rm -rf ~/.local/bin/tessl ~/.local/share/tessl
```

To remove Tessl config files, delete the `~/.tessl` directory
{% endtab %}

{% tab title="Homebrew" %}

```sh
brew uninstall tessl
rm -rf ~/.local/bin/tessl ~/.local/share/tessl
```

To remove Tessl config files, delete the `~/.tessl` directory
{% endtab %}

{% tab title="winget" %}

```sh
winget uninstall tessl.tessl
```

{% endtab %}

{% tab title="npm (deprecated)" %}
Determine which `npm` Tessl package you have:

```sh
npm ls -g | grep tessl
```

To uninstall `@tessl/cli`

```sh
npm uninstall -g @tessl/cli
```

To uninstall `tessl`

```sh
npm uninstall -g tessl
```

Remove the native binaries:

```sh
rm -rf ~/.local/bin/tessl ~/.local/share/tessl
```

To remove Tessl config files, delete the `~/.tessl` directory
{% endtab %}
{% endtabs %}


# Improve your first skill

> **Takeaway:** You will scan your real skills with Skill Inventory, bring them into a workspace, find a skill that needs work, improve it, and publish a new version your team can install.

This is the end-to-end loop you will repeat with Tessl: see what context you have, find what is weak, make it better, and ship it. A few terms show up along the way, namely skills, plugins, workspaces, reviews, and evals. You can follow every step without reading ahead; each term links to a fuller explanation in Core concepts if you want the detail. As a quick orientation: a plugin is the content you package, a workspace is the team space that owns it, and a project ties Tessl to a single repository.

Before you start, make sure you have completed **Set up Tessl**: an account, the CLI installed and authenticated, and a project initialized. You will also need the [GitHub CLI](https://cli.github.com/) authenticated, since the inventory step reads your repositories through your existing GitHub access.

## Step 1: Scan your skills

Most teams have no clear picture of how many skills they have, who owns them, or how many are near-duplicates. Skill Inventory gives you that map. Run:

```bash
tessl inventory import
```

Tessl asks which GitHub org to scan and which workspace to store the results in, then collects every `skill.md` and manifest file across that org's repositories and uploads a snapshot. If you do not have a workspace yet, you can create one right from this prompt. It reads context files only, never your source code, and it never clones a repo. Each run is diffed against the last, so you build a living view of what is new, unchanged, and removed over time.

![Choosing a GitHub org and workspace during tessl inventory import](/files/7ZBzl9Qc4bkSHBuqkKpq)

To scan only specific repositories, scope the run:

```bash
tessl inventory import --repo repo-a --repo repo-b
```

## Step 2: Review your inventory

Open the workspace you chose to read the results: how many skills you have, where they live, who last touched them, and how they score for quality. A workspace is the shared home for your team's private context and these inventory results. This is where the next step starts, because the scores tell you which skills are worth your attention.

![Workspace inventory view with skill scores](/files/PUdU6AvPH5GSOK83fH72)

## Step 3: Find a skill that needs work

A skill can be flagged for two different reasons, and a single skill can hit both at once. They are worth telling apart, because each has its own fix.

The first is a **low review score**. A review measures the quality of the skill itself: how clear and actionable its instructions are, and how well its description tells an agent when to use it. This is the kind of problem you fix by improving the skill.

The second is a **security finding**. Tessl scans skills and plugins for risky or malicious patterns in their content and behavior, such as prompt injection hidden in the instructions, hardcoded secrets, suspicious download URLs, or obfuscated text, and warns you about anything critical or high severity. This is about safety rather than quality, so it is separate from the review score.

For this walkthrough, pick a skill with a low review score from your inventory.

## Step 4: Improve it

Run a review to see the detailed breakdown:

```bash
tessl review run ./<skill> --workspace engteam
```

The review runs server-side against your workspace and returns three scores: validation (structure and formatting), implementation (the quality of the instructions), and activation (how well the description triggers the skill at the right time). Each comes with specific suggestions.

To apply those suggestions automatically, run a fix:

```bash
tessl review fix ./<skill> --workspace engteam
```

`tessl review fix` runs an improve-and-review loop, applying changes and re-reviewing until the score is high enough or it reaches its iteration limit, improving the skill in place. Run a review once more to confirm the score went up. Aim for 70% or higher before you publish.

A security finding is handled differently, because it is about safety, not quality. Tessl never blocks you; it warns you before installing a skill or plugin with critical or high severity findings so you can decide whether to proceed. If it is your own skill, fix the flagged content, for example by removing a hardcoded secret or a suspicious URL. If it is someone else's, treat a serious finding as a reason not to install, since it can signal a compromised skill. You can read more in Core concepts.

## Step 5: Publish a new version

Once the skill passes review, publish it to your workspace and bump the version in one step:

```bash
tessl skill publish ./<skill> --workspace engteam --bump patch
```

Use `patch`, `minor`, or `major` depending on the size of the change. Skills publish as **private** by default, so only members of your workspace can install them, and a review runs automatically on publish. Teammates pick up your new version by installing it:

```bash
tessl install engteam/<skill>
```

That is the full loop. You scanned your estate, found a weak skill, improved it against best practices, and shipped a better version to your team.

## Where to go next

* Improve skills in more depth, including evaluating them against real tasks, in the Tutorials section.
* Roll context out across your repositories automatically with the [repository integration](/distribute/rollout-to-your-repositories).
* Understand the building blocks you just used in Core concepts.


# Core concepts

> **Takeaway:** Understand the building blocks of Tessl, namely the kinds of context, how they are packaged, where they live, and how Tessl measures quality, so the rest of the docs make sense.

If you have worked through the getting started flow, you have already used most of these ideas. This page names them and explains how they fit together.

## Context as software

Giving an agent good context is useful, but on its own it does not last. Libraries change, APIs evolve, and conventions drift, and static instructions quietly go stale. Tessl treats agent context the way you treat code: something you build, evaluate, distribute, and keep up to date. That single idea, context managed with a real lifecycle, is what everything below supports.

## The two kinds of context

Tessl works with two types of context, each suited to a different job.

| Type   | When it is used | Purpose                                            |
| ------ | --------------- | -------------------------------------------------- |
| Rules  | Always          | Your team's standards, applied to every task       |
| Skills | When relevant   | Procedural workflows, loaded when the task matches |

Rules and skills are where Tessl starts, not where it stops. Plugins can also carry other agent capabilities alongside context; see the [Plugins](#plugins) section below.

## Skills

A skill is a folder of instructions, and sometimes scripts, that teaches an agent how to do something: a specific workflow, a procedure, or a way of using a tool correctly. An agent loads a skill when its description matches the task at hand. Skills are the primary unit of context in Tessl, and they are agent-agnostic, so the same skill works across Claude Code, Cursor, Gemini, Codex, and others.

## Plugins

A plugin is a versioned bundle. It packages skills and rules, and can also carry MCP servers, which connect agents to external tools and services, and hooks, which run deterministic commands in response to specific agent events: `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `SessionStart`, and `Stop`. Everything in a plugin is installed, versioned, and updated as one unit, much like a package in npm or pip. When you want to share a coherent set of context and capabilities rather than a single skill, you publish a plugin.

## The Registry

The [Tessl Registry](https://tessl.io/registry) is where context is discovered and distributed. Your team's private context lives in your workspace; the public registry, with thousands of evaluated skills and plugins you can browse and install, is there when you want to reach beyond it. It is also where your published quality scores appear, so others can judge whether a skill is worth installing.

## Workspaces

A workspace is the shared, private home for your team's context. It holds the skills and plugins you publish privately, controls who can access them, and is where your Skill Inventory results and the private index Tessl generates from them live. Workspace context stays with your team unless you choose to share it.

## Projects

A project is the stable anchor for Tessl inside a repository. It identifies the repository and gives Tessl a fixed place to attach repository-connected data, such as evaluation runs, so your results stay tied to the right codebase over time even as branches and checkouts come and go.

## How projects, workspaces, and plugins fit together

These three are easy to mix up, because each one groups things, but they work on different axes. A plugin is content and capability: the skills, rules, MCP servers, and hooks you package up. A workspace is ownership: the team boundary that decides who can see and publish private plugins, and where your inventory lives. A project is location: the tie between Tessl and one repository, so your results stay attached to the right codebase.

In practice, your team shares a workspace and publishes plugins to it, and in each repository where you want Tessl to track work, you create a project. A workspace can hold many plugins and back many projects, while each project belongs to one workspace and maps to a single repository.

## Reviews and evals

Tessl offers two ways to judge context quality, and they answer different questions. It is worth being clear on the distinction, because the names sound similar.

A **review** checks a single skill against best practices. It is fast and cheap, it runs automatically when you publish, and it produces a score across three areas: validation (structure and format), implementation (the quality of the instructions), and activation (how well the description triggers the skill). It is also where a team enforces its own skill-authoring standards, much like static analysis for code. Use a review for quick, structural feedback on the skill itself.

A **scenario eval** measures impact rather than structure. It runs an agent on real tasks, once with your context and once without, and compares the results, so you can see how much the context actually improves performance. Each scenario pairs a task with a rubric of weighted criteria used to grade the result. Evals are slower and more involved, and they attach to a project. Use an eval when you want evidence that context helps, not just that it is well formed.

In short: a review tells you whether a skill is well written; an eval tells you whether it works.

## Security checks

Alongside quality, Tessl checks the safety of skills and plugins. A security scan looks for risky or malicious patterns in a component's content and behavior, such as prompt injection buried in instructions, hardcoded secrets, suspicious download URLs, unverifiable external dependencies, or hidden and obfuscated text. Findings are graded by severity. Tessl surfaces critical and high severity findings when you install, warning rather than blocking and leaving the decision to you. A serious finding on a third-party skill can signal a supply-chain attack, so treat it with care.

## Next

With the vocabulary in place, the Tutorials section goes deeper on creating, improving, and distributing context.


# Overview

End-to-end walkthroughs for the most common agentic-development workflows on Tessl.

{% hint style="info" %}
**Takeaways**

* Which workflow solves the problem you're facing?
* Which Tessl components and commands each workflow uses.
  {% endhint %}

Each tutorial walks through one common agentic-development workflow from start to finish. Start with the one that matches the problem you're solving.

| Tutorial                                                                                                     | Use it when                                                                                  |
| ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| [Using Tessl as a package manager](/tutorials/using-tessl-as-a-package-manager)                              | You want to install, version, and publish skills like code dependencies.                     |
| [Protecting yourself from insecure skills](/tutorials/protecting-against-insecure-skills)                    | Installing skills from public sources exposes you to supply-chain and prompt-injection risk. |
| [Codifying and enforcing your company's skill standards](/tutorials/codifying-and-enforcing-skill-standards) | Skills sprawl into overlapping, drifting copies with no enforced standard.                   |
| [Improving a skill](/tutorials/improving-a-skill)                                                            | You can't tell whether a skill actually improves agent output, so no one risks changing it.  |
| [Setting up agentic code review](/tutorials/setting-up-agentic-code-review)                                  | Code review doesn't scale to agent-authored PRs.                                             |
| [Improving agent code quality](/tutorials/improving-agent-code-quality)                                      | Agents repeat the same mistakes across PRs.                                                  |
| [Automating repetitive tasks](/tutorials/automating-repetitive-tasks)                                        | Repetitive work never gets turned into automation.                                           |


# Using Tessl as a package manager

Use Tessl as a package manager for agent context: find and install skills, keep them up to date, and publish your own to a workspace.

{% hint style="info" %}
**Takeaways**

* How to find, install, and update skills from the registry or a git repo.
* How to publish your own skill to a workspace, public or private.
* How to develop a plugin locally and reinstall it on every change.
  {% endhint %}

Tessl manages agent context the way npm or pip manages code dependencies. Skills, rules, and docs are versioned packages you install into a project, update when new versions ship, and publish for others to consume. This tutorial covers the basics of using Tessl: the day-to-day package-manager flows you reach for most.

## Find and install a skill

Search the registry by keyword:

```bash
tessl search "react testing"
```

You can also browse the registry UI, open a skill, and copy its install command straight from the page.

Install a skill or plugin by its registry name, a GitHub repo, or a local path:

```bash
tessl install engteam/react-testing      # from the registry
tessl install github:acme/skills          # from a GitHub repo
tessl install file:./local-plugin         # from a local directory
```

By default Tessl installs into the current project and records the dependency in your `tessl.json` manifest. Pass `--global` to install into `~/.tessl` for every project, and `--skill` to pick specific skills from a multi-skill source. Without `--agent`, Tessl installs for every coding agent it detects in the project; pass `--agent` to target a specific one instead.

## Keep installed skills up to date

See which installed dependencies have newer versions:

```bash
tessl outdated
```

This lists each dependency with its current, compatible-update, and latest version. Apply the updates:

```bash
tessl update
```

`tessl update` selects the compatible updates and lets you choose which to apply. A new major version that could break compatibility is held back until you pass `--force`. Pass `--yes` to apply all compatible updates without prompting. Remove a dependency you no longer want with `tessl uninstall engteam/react-testing`.

## Publish your own skill

If you have a `SKILL.md` that is not yet a package, turn it into one:

```bash
tessl skill import ./path-to-skill
```

This writes a manifest next to the skill. Publish it to a workspace:

```bash
tessl skill publish ./path-to-skill --workspace engteam
```

The first publish starts at version `0.1.0`. On later publishes, pass `--bump patch`, `--bump minor`, or `--bump major` to increment the version. Use `--dry-run` to validate what would be published without publishing.

## Choose public or private

A skill is published privately by default: it goes to its workspace, where only members can find and install it. If you expect to see it in the public registry and do not, this is usually why. Add `--public` to publish it for anyone to install:

```bash
tessl skill publish ./path-to-skill --workspace engteam --public
```

Workspaces are how Tessl scopes who can see and install a package. List the workspaces you belong to with `tessl workspace list`. A skill's full name includes its workspace, for example `engteam/react-testing`, so workspace names are visible to anyone who can see the package.

## Develop a plugin locally

A plugin is a bundle of skills, rules, commands, and hooks described by a `.tessl-plugin/plugin.json` manifest. You can install one straight from a local directory and iterate on it before publishing.

First add the local plugin to your project:

```bash
tessl install file:./my-plugin
```

Then run install in watch mode, which re-syncs every local source in your manifest whenever its files change:

```bash
tessl install --watch-local
```

Leave it running while you edit `./my-plugin`. Each save reinstalls the updated plugin into your project, so you can test changes against a real codebase before you publish. When it is ready, publish the whole bundle with `tessl plugin publish`:

```bash
tessl plugin publish ./my-plugin --workspace engteam
```

Like `tessl skill publish`, it accepts `--bump patch|minor|major` to increment the version and `--dry-run` to validate without publishing.

## Where to go next

* [Creating skills](/create/creating-skills) and [Creating plugins](/create/creating-plugins) to go deeper on authoring.
* [Distributing via registry](/distribute/distributing-via-registry) to share with your team or publicly.
* [Protecting yourself from insecure skills](/tutorials/protecting-against-insecure-skills) to review what you install for security.


# Protecting yourself from insecure skills

Inventory the skills running across your org, read their Snyk-powered security scores, and use install policies to block risky skills before they reach a developer.

{% hint style="info" %}
**Takeaways**

* How to inventory the skills across your org and tell first-party skills from matched third-party ones.
* How Snyk-powered security scores surface on import, and how to review any skill on demand.
* How an admin sets org, workspace, or project install policies to block risky skills.
  {% endhint %}

Skills run inside your agent with access to your code, your shell, and your secrets. A skill pulled from a public source can carry a prompt-injection payload or instructions that exfiltrate data, and the risk compounds once a skill spreads across repos. The danger is not only external: a first-party skill can leak credentials through an honest mistake by the developer who wrote it, or carry a deliberate payload from an insider. This tutorial maps what is already installed, reads each skill's security score, and gates future installs against a policy.

## Inventory the skills across your org

Start from what is already running. `tessl inventory import` scans the repositories in a GitHub org through your local `gh` CLI and uploads the result to a workspace:

```bash
tessl inventory import --org your-org --workspace engteam
```

This relies on the [GitHub CLI](https://cli.github.com/) being installed and authenticated locally, and on being logged in to Tessl for the upload, so run `gh auth login` and `tessl login` before you import. For more on inventory, see [Understand your skill estate](/use/understand-your-skill-estate).

The scan collects every `SKILL.md` and sorts what it finds. Skills that match a published registry skill are flagged as third-party; skills unique to your repos are your first-party skills, marked publishable, untracked, or unmanaged. It also surfaces overlap and drift between near-duplicate copies. Browse the result in the app at `Workspaces → your workspace → Inventories`. Use `--repo` to scope the scan, or `--dry-run ./inventory.json` to write it to disk without uploading.

## Read the security scores

Security scores are powered by Snyk. Each score is a severity: `LOW`, `MEDIUM`, `HIGH`, or `CRITICAL`.

Third-party skills that match a published registry skill show their score in the inventory automatically. For your first-party skills, connect the Tessl GitHub App and import them; the import security-scans each one and brings its score into the inventory. Between the two, your whole skill estate ends up scored in one place. Sort the inventory by security score to find the skills that need attention first.

## Review a single skill on demand

You do not need a full inventory to check one skill. Review any skill directly from its directory:

```bash
tessl review run security ./path-to-skill --workspace engteam
```

This is the quickest way to vet a skill before you install it, or to gate a skill in CI. The review is powered by Snyk and returns the same severities. Add `--json` for machine-readable output, or `--fail-on high` to make the command exit non-zero when a finding meets or exceeds a severity. The `--fail-on` values are lowercase: `low`, `medium`, `high`, `critical`.

## Gate risky installs with a policy

An inventory and a score tell you what is risky. An install policy stops a risky skill from being installed at all. As a security admin, this is your main lever.

Policies can be set at three levels, and the tightest one wins:

* Org level: the broadest reach and your most impactful control as a security admin. It applies to every workspace and project in the org.
* Workspace level: tightens the org policy for a single workspace.
* Project level: tightens it further for a single project.

Set policy in the app under `Settings → Policy`. Setting org-level policy is an organization admin action, so if you do not see it, ask your admin. A policy combines three kinds of rule:

* Security threshold: choose the severity at which an install is warned and the severity at which it is blocked, for example warn at `MEDIUM` and block at `HIGH`.
* Source restriction: limit the registry to your own org, or to Tessl plus your org, and choose whether installs from git sources are allowed at all. When git sources are allowed, add a git source allowlist to permit only specific hosts and orgs, for example `github.com/your-org`, so developers can still install public skills from your trusted vendors while everything else is blocked.
* Minimum release age: for git sources, require a release to be a minimum number of days old before it can be installed.

Once a policy is in place, `tessl install` evaluates every source against it:

* A source under the warn threshold installs without interruption.
* A source that hits the warn threshold prompts for confirmation. A developer can proceed, or pass `--accept-warnings` to skip the prompt in automation.
* A source that hits the block threshold cannot be installed. There is no override.

```bash
tessl install your-org/some-skill
```

When the skill's score meets the block threshold, the install is refused and the offending finding is shown. The headline uses a severity label: `Passed` for `LOW`, `Advisory` for `MEDIUM`, `Risky` for `HIGH`, and `Critical` for `CRITICAL`. A `Risky` headline below therefore means a `HIGH` score that met the block threshold:

```
Blocked by install policy (not added to tessl.json):
  ✖ Security  Risky · Do not use without reviewing
    your-org/some-skill
    W011 Third-party content exposure detected.
    View full report: https://app.tessl.io/...
```

{% hint style="info" %}
You can also set a publish policy that blocks publishing a skill whose security score is under a threshold, so risky skills never enter your registry in the first place. See [Codifying and enforcing your company's skill standards](/tutorials/codifying-and-enforcing-skill-standards).
{% endhint %}

## Where to go next

* [Understand your skill estate](/use/understand-your-skill-estate) for more on inventory.
* [Administrating organizations, workspaces, and roles](/administrators/administrating-organizations-workspaces-and-roles) to control who can install and publish.
* [Codifying and enforcing your company's skill standards](/tutorials/codifying-and-enforcing-skill-standards) to extend governance from security to quality.


# Codifying and enforcing your company's skill standards

Capture your team's quality bar as a custom review rubric and enforce it on every skill in CI.

{% hint style="info" %}
**Takeaways**

* How to gate pull requests on a review score using `--threshold`.
* How to authenticate CI with an API key so reviews run without manual login.
* How to fork the default rubric to encode your organisation's own quality bar.
* How to apply a custom reviewer consistently across local reviews and CI.
  {% endhint %}

When a team shares skills, quality stops being a personal matter. A weak skill that one person tolerates becomes everyone's problem once it is in the shared repository, shaping how every agent on the team behaves. This tutorial shows you how to hold a quality line automatically, first by setting a score threshold that blocks substandard skills from merging, and then by forking the default rubric to encode what your organisation actually cares about.

## The core workflow

1. Run `tessl review run --threshold` locally to confirm the score gate works
2. Create an API key and add it as a CI secret so reviews can run non-interactively
3. Add a review step to your pull request workflow
4. Install `tessl/review-plugin-creator` and build a custom reviewer plugin
5. Apply the custom reviewer via `--review-plugin` in local reviews and CI

## Prerequisites

* Tessl installed and initialised (`tessl init`)
* Authenticated (`tessl login`)
* A workspace to attribute reviews to
* A GitHub repository with Actions enabled (for the CI steps)

## Step 1: Test the threshold locally

Before wiring anything into CI, confirm the score gate behaves as expected:

```bash
tessl review run ./my-skill --workspace <workspace> --threshold 80
```

`--threshold` takes a 0-100 integer. The command exits non-zero when the score falls below it, which is what fails a CI step. The default is 0, which never fails. Any value above 0 enforces the gate.

Add `--json` when you need machine-readable output in a script that parses the result:

```bash
tessl review run ./my-skill --workspace <workspace> --json --threshold 80
```

`--workspace` is required when `--json` is set, because a non-interactive run cannot prompt for one.

## Step 2: Authenticate CI

A review runs against your workspace, so CI needs to authenticate without an interactive login. Create an API key for the workspace:

```bash
tessl api-key create --workspace <workspace>
```

Copy the key and add it as a repository secret named `TESSL_TOKEN` in your GitHub repository settings (**Settings → Secrets and variables → Actions → New repository secret**).

## Step 3: Add the review step to CI

Tessl publishes a GitHub Action that installs the CLI. Add a job to your pull request workflow:

```yaml
name: Skill review

on:
  pull_request:

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: tesslio/setup-tessl@v2
        with:
          token: ${{ secrets.TESSL_TOKEN }}
      - name: Review skill
        run: tessl review run ./my-skill --workspace <workspace> --json --threshold 80
```

The step fails when the score falls below 80. Adjust the path, workspace, and threshold to match your repository. For a full reference of flags and options, see [Review, lint & publish with GitHub Actions](/distribute/review-and-publish-with-github-actions).

## Step 4: Build a custom reviewer

The default rubric scores against general best practices. To score against your organisation's own standards, build a custom reviewer plugin with the `create-review-plugin` skill:

```bash
tessl install tessl/review-plugin-creator
```

Ask your agent to create a reviewer. It scaffolds the plugin structure, helps you define judges and their weights, writes the rubric files, and validates the finished plugin by running a test review.

A reviewer plugin is a standard Tessl plugin. Its key components are a `config.json` that sets the weight each judge contributes to the score, and one rubric file per judge that defines the scoring dimensions. The weights across validation and all judges must sum to 1.0.

The default rubric is worth forking rather than building from scratch. It scores a skill's description on specificity, completeness, trigger term quality, and distinctiveness, and the content on conciseness, actionability, workflow clarity, and progressive disclosure. Forking lets you adjust those weights or add judges for concerns specific to your team.

## Step 5: Apply the custom reviewer

Point any review at your reviewer with `--review-plugin`, passing a local path or a `workspace/plugin` registry reference:

```bash
tessl review run ./my-skill --workspace <workspace> --review-plugin <reviewer-plugin>
```

The same flag works in `tessl review fix` and in your CI gate, so the standard you define in the rubric is the standard you enforce everywhere:

```bash
tessl review run ./my-skill --workspace <workspace> --review-plugin <reviewer-plugin> --json --threshold 80
```

Pass `--review-plugin` explicitly on each run. There is no workspace-level default; passing the flag consistently is how you apply your standard.

## Next steps

* [Gate skill quality in CI](https://github.com/tesslio/monorepo/blob/main/apps/docs/codifying-and-enforcing/gate-skill-quality-in-ci.md) - full reference for `--threshold`, `--json`, and `tessl api-key create`.
* [Define your own quality standards](https://github.com/tesslio/monorepo/blob/main/apps/docs/codifying-and-enforcing/define-your-own-quality-standards.md) - deeper coverage of reviewer plugin structure and the weight invariant.
* [Review, lint & publish with GitHub Actions](/distribute/review-and-publish-with-github-actions) - complete GitHub Actions workflow for skill CI.


# Improving a skill

Use reviews and evals to measure a skill's impact, find what's holding it back, and ship an improvement with evidence.

{% hint style="info" %}
**Takeaways**

* How to run a review to get a quality score and identify what to fix.
* How to apply automated improvements with `tessl review fix`.
* How to generate evaluation scenarios and measure whether a change actually helps.
* How to use Skill Optimizer to run the full cycle automatically.
  {% endhint %}

A skill can look well-written and still fail to improve what an agent does. This tutorial walks through both checks: a review, which tells you whether the skill is well-formed; and an evaluation, which tells you whether it actually changes agent behaviour. Together they give you the evidence to ship a skill with confidence.

## The core workflow

1. Run a review to get a quality score and see what to fix
2. Apply automated fixes and re-run until the score is in good shape
3. Generate evaluation scenarios from the skill
4. Run an evaluation to measure the before/after delta
5. Edit, re-run, and confirm the improvement holds

## Prerequisites

* Tessl installed and initialised (`tessl init`)
* Authenticated (`tessl login`)
* A workspace to run reviews against
* A plugin containing the skill you want to improve (see [Creating plugins](/create/creating-plugins) if you have a standalone `SKILL.md`)

## Step 1: Run a review

A review scores the skill on how well it is written: whether the description is specific enough for an agent to load it at the right moment, and whether the content is concise, actionable, and complete.

```bash
tessl review run ./my-skill --workspace <workspace>
```

The output shows a score out of 100 broken down by dimension:

```
Judge Evaluation
  Description: 72%
    specificity: 2/3 - names the domain but lists variations of one action
    completeness: 2/3 - trigger present but capability understated
    ...
  Content: 85%
    conciseness: 3/3
    actionability: 2/3 - steps present but no worked example
    ...
Review Score: 79%
```

A score above 90 means the skill conforms well to best practices. 70-89 is good. Below 70 needs work. The dimension breakdown tells you where to focus: a low description score usually means the skill is not activating reliably; a low content score usually means the instructions are not specific enough for the agent to act on.

## Step 2: Apply fixes

`tessl review fix` runs an automated improve-and-review loop. It applies edits, re-runs the review, and iterates until the score stops improving:

```bash
tessl review fix ./my-skill --workspace <workspace>
```

Pass `--threshold 85` to keep going until it hits that score, `--max-iterations 5` to allow more rounds, or `--yes` to apply changes without prompting. Re-run `tessl review run` afterwards to confirm the final score.

## Step 3: Generate evaluation scenarios

A review measures whether the skill reads well. An evaluation measures whether it actually changes what an agent does. Generate scenarios from the skill:

```bash
tessl scenario generate ./my-skill
```

Generation runs server-side. Check progress with `tessl scenario list --mine`, then download once it completes:

```bash
tessl scenario download --last
```

By default the generator targets three scenarios. Pass `--count 5` for broader coverage. Only scenarios that pass a feasibility check are saved, so you may get fewer than you ask for on a narrowly scoped skill.

## Step 4: Run an evaluation

```bash
tessl eval run ./my-skill
```

The agent solves each scenario twice, once without the skill and once with it, and a judge scores both. The summary shows the baseline average, the with-skill average, and the difference:

```
Summary
  Scenarios:         3 completed
  Baseline avg:      71%
  With context avg:  92%
```

A large positive difference means the skill reliably moves the agent toward the right behaviour. Little or no difference usually means the skill is not activating, or the instructions are not specific enough to change what the agent does. Run with `--runs 3` to average out model variance before drawing conclusions.

## Step 5: Edit and confirm

If the evaluation shows little impact, the most common causes are a description that is too vague to trigger the skill reliably, content that tells the agent what to do without showing how, or instructions that are ambiguous enough for the agent to ignore. Make your edits, re-run the review to confirm the score held, then re-run the evaluation:

```bash
tessl review run ./my-skill --workspace <workspace>
tessl eval run ./my-skill --label "after-edits"
```

Compare the two runs with `tessl eval list --mine`. The scenarios from the first run are saved in the plugin's `evals/` directory and become a regression test you can re-run after every future change.

## Shortcut: Skill Optimizer

If you want the full cycle handled automatically, install Skill Optimizer and ask your agent to improve a skill:

```bash
tessl install tessl/skill-optimizer
```

Skill Optimizer runs review, applies fixes, escalates to scenario generation and evaluation, diagnoses failures, and re-runs until scores improve. Use it when you want results fast; use the manual commands when you want to understand what is happening or debug a specific dimension.

## Next steps

* [Check a skill's quality using review](/improving-your-skills/reviewing-skills) - full reference for `tessl review run`, all flags, and score interpretation.
* [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios) - deeper coverage of scenario generation, agent selection, and reading eval output.
* [Codifying and enforcing your company's skill standards](/tutorials/codifying-and-enforcing-skill-standards) - gate future changes in CI so the bar you set here holds for everyone.


# Setting up agentic code review

Set up the Tessl Agent to review pull requests against your team's skills, locally and in CI.

{% hint style="info" %}
**Takeaways:** After reading this page you will understand how the `tessl change` command group works, how to use the `tessl agent` to create a code review skill for your repository, how to set up a policy-based risk gate that decides when PRs need a human reviewer, and how to wire verifiers as CI checks that enforce code invariants.
{% endhint %}

Agents write code faster than human reviewers can keep up with. The tools described here handle three distinct problems: catching obvious issues before human reviewers see them, deciding which PRs actually need human review, and enforcing structural invariants automatically.

Throughout this tutorial the `tessl agent` does the heavy lifting. It ships with the `tessl/harness-engineering` plugin pre-bundled, so the skills that drive code-review setup — `change-review`, `change-risk`, `change-verify`, and `plugin-creator` — are available without installing anything. You describe what you want; the agent runs the underlying `tessl change` commands and shows you what it ran.

{% hint style="info" %}
Prefer your own coding agent? Install the plugin into it with `tessl install tessl/harness-engineering` and the same skills become available there. The rest of this tutorial assumes the `tessl agent` as the base case.
{% endhint %}

## How the tessl change command group works

`tessl change` groups three commands, each covering a separate concern:

* `tessl change review` — runs a readonly agent against the current diff using the skills you specify, and emits a structured review (summary and inline comments keyed to GitHub hunk positions). The command never posts to GitHub; a separate publisher step does that.
* `tessl change risk` — scores the current diff against a checked-in policy and outputs a gate decision: does this PR require human review? The agent's risk judgment is advisory; the policy decides whether the PR is clearly low-risk enough to skip review, and requires a human whenever it is uncertain.
* `tessl change verify` — runs verifiers against changed files. Verifiers are LLM-as-judge checks for targeted, observable invariants — things a linter cannot express but a reviewer can score by reading the file. They run like linting checks in CI, and you can generate them from skills already in your repo (see [Step 5](#step-5-author-and-deploy-verifiers)).

Each command can be tried locally before you automate anything.

## Concepts

**Skills** are the unit of code review knowledge. A skill contains instructions that guide the agent's analysis of a diff. Any skill in your repo can act as a review lens — not only ones explicitly built for review — and one call to `tessl change review` can run several skills in parallel and interlace their findings into one review.

**Risk policy** is a set of checked-in files under `.github/pr-review-gate/` that define what makes a PR low-risk enough to skip human review. The agent's risk judgment is advisory; the policy decides the gate, and when in doubt it requires a human reviewer.

**Verifiers** are checks that describe binary, observable invariants about committed files — things like "API response handlers must use typed helpers" — that are hard to express as a lint rule but judgeable from the file. A verifier targets a glob of files, so new files added later are covered too. They are the right tool when a reviewer keeps flagging the same structural pattern and no deterministic check can own it.

## Prerequisites

* Tessl installed and initialized (`tessl init`)
* Authenticated (`tessl login`)
* Access to a workspace

## Step 1: Try a code review locally

Before setting up automation, run a review on the current diff to see what output looks like.

The `tessl agent` already bundles the `tessl/code-review` skills, which provide several focused review lenses. Ask the agent to run a review:

> Run a code review on my current diff using the code-legibility lens.

Under the hood the agent runs:

```sh
tessl change review --skill tessl/code-review#review-code-legibility
```

The `--skill` flag accepts three formats:

* Registry ref: `workspace/plugin[@version]#skill-name` — the `#skill-name` selector is optional when the plugin has exactly one skill
* Local path: a path to a `SKILL.md` file or skill directory in this repo
* Installed skill name: a bare name resolved against installed skills

To run multiple lenses in one call, repeat `--skill`. The CLI executes them in parallel and interlaces their findings into one structured output:

```sh
tessl change review \
  --skill tessl/code-review#review-code-legibility \
  --skill tessl/code-review#review-test-risk
```

Available skills in `tessl/code-review`:

| Skill                        | Use when the most important signal is                                                  |
| ---------------------------- | -------------------------------------------------------------------------------------- |
| `review-code-legibility`     | Whether names, types, return shapes, and abstractions are clear from the code alone    |
| `review-test-risk`           | Changed behaviour without meaningful tests, or brittle/uncovered async and error paths |
| `review-contract-boundaries` | API schemas, generated clients, CLI flags, event payloads, database migrations         |
| `review-security-risks`      | Auth, untrusted input, injection, secrets, crypto, sensitive logging                   |
| `review-local-precedent`     | Whether new code should have reused an existing helper, component, or convention       |

To compare against a specific base commit, pass `--base origin/main`. To capture the structured data, add `--json --output review.json`.

## Step 2: Create your own code review skill

The published skills are a starting point. Once you know what signals matter for your codebase, create a focused skill that captures project-specific patterns.

Ask the `tessl agent` to build it. The agent uses its `plugin-creator` skill to scaffold the plugin, interview you about scope, and validate the result:

> Create a code review skill for this repo that flags breaking changes to our API schemas, generated clients, and route contracts. Put it in a plugin under the engteam workspace.

As it works, the agent runs the underlying CLI commands and reports them back. The ones you will see most often:

* `tessl plugin new` — scaffolds the plugin and skill directory ([reference](/reference/cli-commands#tessl-plugin-new))
* `tessl plugin lint` — checks packaging and schema ([reference](/reference/cli-commands#tessl-plugin-lint))
* `tessl review` — reviews the SKILL.md quality and can gate CI ([reference](/reference/cli-commands#tessl-review))
* `tessl plugin publish` — publishes to the registry when the skill is stable ([reference](/reference/cli-commands#tessl-plugin-publish))

To iterate, ask the agent to run the skill against the current diff and tune the `SKILL.md` based on what the review misses or gets wrong:

> Run my new review skill on the current diff, then sharpen the instructions for anything it flagged incorrectly.

Old PRs make good test cases. The `tessl agent` can check out or reconstruct a past PR's diff, run the skill against it, and compare the findings to what reviewers actually cared about — repeating until the skill is stable:

> Backtest this review skill against PRs #1189 and #1201 and tell me where its findings differ from the human review comments.

## Step 3: Wire the review into every PR

The `tessl change review` command emits structured review data only — it never posts to GitHub. To run it on every PR you need a GitHub Actions workflow that runs the command plus a publisher step that posts the single review with inline comments.

Rather than copy a fixed workflow file, ask the `tessl agent` to set it up. It reads how your repo is configured and calibrates the workflow accordingly:

> Set up a code review for every new PR.

The agent (via its `change-review` skill) chooses sensible defaults. The ones worth knowing — and how you might change them:

* **One reviewer lens to start** — it wires a single `--skill`, because trust builds faster with one focused lens. Add more `--skill` values to the same run once you trust the output.
* **An explicit base ref** — a detached PR checkout often has no `origin/main` tracking ref, so the workflow fetches it and passes `--base`. Without this the default base is unresolvable and the run fails.
* **A gated manual re-run trigger** — an `@tessl-change-review` PR comment, restricted to repository insiders (owner, member, collaborator, admin) so external contributors cannot start a secret-backed run. Drop it if you only want automatic runs.
* **One automatic review per PR** — a starting cadence, not a rule. Move to every-push only when the added cost and noise are worth it.

Set `TESSL_TOKEN` (and `ANTHROPIC_API_KEY`) as repository secrets; `GITHUB_TOKEN` is provided automatically.

## Step 4: Set up the risk gate

The risk gate decides whether a PR requires human review based on a checked-in policy, combining git measurements with an advisory agent judgment.

Ask the `tessl agent` to set it up — it uses its `change-risk` skill to initialize the policy, design it with you, and trial it before you rely on it:

> Set up a PR risk gate for this repo.

The agent runs `tessl change risk init`, which writes starter files under `.github/pr-review-gate/`. Two starters are available:

* `conservative-starter` (default) — requires human review for most changes; gradually relax as you verify the gate behavior
* `official-review-policy-parity` — matches your existing branch protection rules more closely

Read and edit the policy files before relying on the gate. To score the current diff against the policy, the agent runs `tessl change risk` (add `--base origin/main` to compare against a base, `--json` for CI-friendly output). In CI, `--fail-if-review-required` exits non-zero when the gate decides a human reviewer is needed:

```sh
tessl change risk --base origin/main --fail-if-review-required --json
```

Add this to GitHub Actions as an advisory status check first. Watch it on real PRs for a few weeks before making it required. When the signal is trusted, enable it as a required status check in branch protection settings.

## Step 5: Author and deploy verifiers

Verifiers check binary, observable invariants about committed files. Use them when a reviewer keeps flagging the same structural pattern and no linter can own it. Drive the whole flow through the `tessl agent`, which uses its `change-verify` skill.

**Create a first verifier.** Ask the agent for one targeted check:

> Create a verifier that checks every Fastify route file returns via our typed response helpers.

The agent authors the verifier JSON and wires it into the `verify` block in `tessl.json` (see the [`verify` block reference](/reference/configuration#verify-block) for the full schema). Before any broad judge run it previews the scope — `tessl change verify lint <file>` to check the structure, then `tessl change verify --dry-run --all --show-files` to confirm which files match.

**Run that first verifier.** Have the agent run just the new check on changed files and sample a few outputs so you can confirm the failures are real violations:

```sh
tessl change verify --sample 5
```

**Generate more, then run them all.** Once the first verifier earns trust, ask the agent to propose additional ones — often mined from your reviewer skills or recurring review feedback — and run the full set:

> Suggest a few more verifiers from the patterns my reviewers keep flagging, then run them all on the current diff.

**Put them into PR review.** Finally, ask the agent to add verification as a CI gate:

> Run verifiers on every PR.

The agent fetches the base ref and runs `tessl change verify --base origin/main --github`. The `--github` flag emits GitHub Actions annotations for warn-level findings so they appear in the PR UI even when the run exits 0. Start with verifiers set to `warn` severity in `tessl.json` while calibrating; promote to `error` (which makes the check blocking) only after you have confirmed the verifier avoids false positives on real PRs.

## Next steps

* Mine your PR review history for recurring patterns and turn them into new verifier rules or reviewer skill improvements with the [Improving agent code quality](/tutorials/improving-agent-code-quality) tutorial.
* Improve the quality of your reviewer skills with the `tessl/skill-optimizer` plugin (pre-bundled with the `tessl agent`): ask the agent to review a SKILL.md, generate eval scenarios, run evals, and re-run until scores improve. See [Improving your skills](/improving-your-skills/overview-improving-skills-and-plugins) for the underlying review and eval capabilities.
* Once a verifier is validated, publish it alongside your reviewer skills as a single plugin so the whole review setup can be distributed across repositories.


# Improving agent code quality

Turn recurring agent mistakes into fixes. Mine PRs and session logs with the Tessl Agent, then prove the fix with evals.

{% hint style="info" %}
**Takeaways:** After reading this page you will know how to identify concrete quality problems in agent-written code using the `find-optimizations` skill, how to turn those findings into actionable tickets, how to fix the issues, and how to set up a weekly automated scan so the process runs continuously — all driven through the `tessl agent`.
{% endhint %}

This tutorial starts from a concrete symptom: agents are getting something wrong repeatedly. It covers finding what the pattern is, filing tickets, fixing the root cause, and automating the scan so it runs on its own.

## The core workflow

1. Identify the problem area (e.g. "agents are getting the frontend layout wrong")
2. Run `find-optimizations` to extract patterns from PR review history
3. File tickets for the findings
4. Fix the issues by improving skills, rules, or verifiers
5. Set up a scheduled scan to catch new patterns before they accumulate

## Prerequisites

* Tessl installed and initialized (`tessl init`)
* Authenticated (`tessl login`)
* Access to a workspace with at least one repository connected

## Step 1: Find optimization opportunities

The `find-optimizations` skill reads PR review history and CI run results to extract patterns where agents needed corrections, then proposes improvements that would prevent those corrections in the future.

The `tessl agent` ships with the `tessl/harness-engineering` plugin pre-bundled, so `find-optimizations` is available without installing anything.

{% hint style="info" %}
Prefer your own coding agent? Install the plugin with `tessl install tessl/harness-engineering` and the skill becomes available there too. The rest of this tutorial assumes the `tessl agent`.
{% endhint %}

Give the agent a description of the mistake you are seeing plus a specific PR or time range to look at:

> Agents keep breaking our frontend layout. Look over PRs from the last 2 weeks and tell me the pattern.

The skill collects PR review comments, review summaries, CI run results, and the diffs of commits that addressed them. It categorizes each piece of feedback into an improvement type and proposes a concrete next step.

A typical output looks like this:

```
1. Type: rule
   Summary: Agents are not checking for null session before accessing user properties
   Evidence: PRs #1189, #1201, #1218 — reviewer corrected undefined access three times
   Suggested approach: Add a rule in plugins/frontend/rules/ that instructs agents to
   always check session?.user before accessing nested properties

...
```

The skill does not make any changes. It only produces output for you to review.

## Step 2: File tickets for the findings

Once you have the numbered list of findings, create tickets for the ones worth fixing. The `tessl agent` can create them directly. Refer back to the findings by number:

> Create a ticket from item 2.

For each ticket, the agent includes the evidence (PR numbers), the proposed improvement type, and the suggested approach. This gives whoever implements the fix enough context to act without re-running the analysis.

The `tessl agent` builds up memory about how you like to create and assign tickets — which issue tracker you use, how you format titles, who things get assigned to. It records this under `.tessl/memory/preferences/` (run `/setup-memory` if it has not been initialized yet), so after the first ticket you rarely have to repeat yourself. The next time you say "file a ticket from item 1," it already knows where it goes.

## Step 3: Fix the issues

Each ticket identifies the improvement type. Ask the `tessl agent` to implement the fix — it uses its `plugin-creator` skill to decide where the change belongs and to scaffold and validate it:

> Implement the fix from item 1 — a rule that makes agents check `session?.user` before accessing nested properties.

The approach the agent takes depends on the type:

**Rule** — an always-on instruction that every agent reads on every task. Rules are the right tool for conventions and constraints that apply without exception.

**Skill** — a procedural workflow the agent activates for specific tasks. Skills are the right tool when the fix involves a multi-step process (e.g. "when creating a route, first check the registry, then create the route, then register it").

**Verifier** — an LLM-as-judge check on committed files. Verifiers are the right tool when the fix is a binary, observable invariant about file structure (e.g. "component files must export at least one element with data-testid").

**Refactor** — structural code changes that make the right pattern easier to follow, paired with a rule or verifier to enforce the resulting convention going forward.

## Step 4: Verify the improvement

After implementing a fix, confirm it helps. Use evals to measure the impact of your context changes on agent task completion. Ask the `tessl agent` to set this up — it generates scenarios from commits in the problem area and runs the eval with and without the new context:

> Generate eval scenarios from PRs #1189, #1201, and #1218, then run the eval with and without my new frontend-skills plugin and compare the scores.

Under the hood the agent runs `tessl scenario generate` to build scenarios from those commits, then `tessl eval run` twice — once as a baseline and once with `--context` pointed at the new plugin. If the with-context variant scores higher on the criteria that correspond to the problem area, the fix is working.

To gate skill quality in CI so regressions are caught automatically, ask the agent to wire `tessl review run --json --threshold 80` into a check — it exits non-zero if the skill quality score drops below 80%.

## Step 5: Automate the weekly scan

Once the manual process is familiar, automate it so the scan runs without prompting. Ask the `tessl agent` to set up the schedule — it uses its `workflow-automator` skill to build the CI workflow and pick sensible defaults:

> Set up a weekly job to find future optimizations.

The agent runs `find-optimizations` headlessly with `tessl launch skill find-optimizations --agent tessl-agent`, passing a short static `--instructions` string (any dynamic content like date ranges is handled by the agent reading repository files). The defaults it chooses, and how you might change them:

* **A weekly schedule plus manual dispatch** — a Monday-morning cron with a `workflow_dispatch` trigger so you can also run it on demand. Adjust the cadence to match how fast your PR volume grows.
* **Findings written to an artifact** — the scan output is uploaded so the team can review it without re-running the analysis. Point it at a file, an issue, or a Slack message depending on where your team looks.
* **`TESSL_TOKEN` and `ANTHROPIC_API_KEY` from repository secrets** — the agent confirms these exist and walks you through creating any that are missing.

Review the weekly output. When findings recur across multiple weeks, escalate them to tickets and implementation work. This creates a continuous feedback loop: agents write code, the scan surfaces patterns, you improve the skills and rules, agents get better.

## Next steps

* Catch issues at PR time before they accumulate into patterns by [Setting up agentic code review](/tutorials/setting-up-agentic-code-review) with `tessl change review` and `tessl change verify`.
* Discover other manual workflows in your repository that can be automated with the [Automating repetitive tasks](/tutorials/automating-repetitive-tasks) tutorial and the `find-automations` skill.


# Automating repetitive tasks

Identify repetitive work in your development loop and turn it into repeatable, automated workflows with the Tessl Agent.

{% hint style="info" %}
**Takeaways:** After reading this page you will know how to use the `find-automations` skill to identify manual workflows in your repository that should be automated, how to turn findings into implementation tickets, and how to have the `tessl agent` build a CI workflow that runs an agent on a schedule to handle recurring work.
{% endhint %}

Every repository accumulates manual chores: the same kind of dependency update PR every week, a maintainer who manually applies the same changelog format to every release, a reviewer who leaves the same comment about a missing label. These are automation candidates. The `find-automations` skill reads your PR history to surface them.

## The core workflow

1. Run `find-automations` to identify manual workflows in your repository
2. Review the numbered list of automation candidates
3. File tickets for the ones worth building
4. Have the `tessl agent` build the automation as a CI workflow
5. Run `find-automations` on a schedule to catch new candidates as they emerge

## Prerequisites

* Tessl installed and initialized (`tessl init`)
* Authenticated (`tessl login`)
* `gh` CLI installed and authenticated (for reading PR data)
* Access to a workspace

## Step 1: Find automation opportunities

The `find-automations` skill reads recent PR history to identify manual workflows, recurring chores, and coordination patterns that could be automated.

The `tessl agent` ships with the `tessl/harness-engineering` plugin pre-bundled, so `find-automations` is available without installing anything.

{% hint style="info" %}
Prefer your own coding agent? Install the plugin with `tessl install tessl/harness-engineering` and the skill becomes available there too. The rest of this tutorial assumes the `tessl agent`.
{% endhint %}

Ask the agent to run it:

> Run find-automations on this repo and show me the candidates.

The skill inspects the last 90 days of PR history. For each candidate it finds, it produces a structured output entry. A typical output looks like this:

```
Summary: Found 4 clear automation candidates across 3 months of PR history.

1. Title: Automate weekly dependency updates
   Summary: The same contributor opens a dependency update PR every Monday morning.
   Pattern Type: established
   Why Automate: Predictable, low-judgment, repeating chore.
   Evidence: PRs #1180, #1190, #1202, #1215, #1223 — all titled "chore: update deps",
             all opened by @alice between 9am and 10am UTC on Mondays.
   Suggested Execution Mode: scheduled
   Suggested Trigger: Weekly on Monday morning
   Manual Trigger: none
   Implementation Direction: Run npm outdated, apply compatible updates, run tests,
                             open a PR if anything changed. Skip major bumps.

...
```

The skill is read-only. It does not modify any files, create commits, or open issues.

## Step 2: File tickets for the candidates

Review the numbered list and pick the candidates worth building. The `tessl agent` can create the tickets directly — refer to findings by number:

> Create a ticket from item 1.

For each ticket, the agent includes the evidence, the suggested execution mode, and the implementation direction from the finding. This gives the implementer enough context to act without re-running the analysis.

The `tessl agent` builds up memory about how you like to create and assign tickets — which issue tracker you use, how you format titles, who things get assigned to. It records this under `.tessl/memory/preferences/` (run `/setup-memory` if it has not been initialized yet), so after the first ticket you rarely have to repeat yourself.

## Step 3: Build the automation

Each finding includes an implementation direction. Ask the `tessl agent` to build it — it uses its `workflow-automator` skill to classify the task, create any plugin it needs, set up CI secrets, and write the workflow. It runs the underlying commands and reports them back; you stay in control of the design decisions.

### Recurring chores

For purely mechanical tasks — applying a label, posting a comment, running a script — no agent is needed at runtime. Ask the `tessl agent` to set up a standard GitHub Actions workflow:

> Build the stale-PR automation from item 3 as a scheduled GitHub Actions workflow.

The agent wires a plain Action (for example, `actions/stale`) on a daily schedule. The settings it chooses — the stale label, the inactivity window, the message — come straight from the finding's implementation direction, and you can adjust any of them.

### Agent-driven tasks

For tasks that require judgment — writing changelog entries, reviewing code, updating documentation — the automation runs an agent headlessly with `tessl launch skill`.

`tessl launch skill <skill> --agent <agent>` is the entrypoint for agent workflows: it runs an installed plugin skill through an agent in a CI environment, with per-run inputs passed via a short `--instructions` string. The `--agent` flag selects the backend.

The pattern is:

1. Create a plugin that encodes what the agent should do
2. Run the plugin with `tessl launch skill` in a CI workflow

Ask the `tessl agent` to do both:

> Build the release-notes automation from item 2: create a plugin that generates a formatted changelog block, then run it from a GitHub Actions workflow on release-branch pushes.

As it works, the agent runs the relevant CLI commands and names what it creates:

* `tessl plugin new` — scaffolds the plugin and skill ([reference](/reference/cli-commands#tessl-plugin-new))
* `tessl plugin lint` and `tessl review` — validate the plugin and skill ([reference](/reference/cli-commands#tessl-plugin-lint))
* `tessl plugin publish` — publishes it so CI can install it ([reference](/reference/cli-commands#tessl-plugin-publish))
* `tessl install` — installs the plugin in the workflow ([reference](/reference/cli-commands#tessl-install))
* `tessl launch skill <skill> --agent tessl-agent --yolo` — runs the skill headlessly in CI

The defaults the agent chooses for the workflow, and how you might change them:

* **`--agent tessl-agent`** — the workflow runs the Tessl built-in agent. The `tessl agent` is particularly good at harness and repo-maintenance tasks like these. For automations that build product features, you may prefer a coding agent backend (`claude-code`, `codex`, `cursor`); pass it to `--agent` instead.
* **`--yolo`** — lets the agent apply edits without prompting, which a headless CI run requires.

## Step 4: Run find-automations on a schedule

As your repository grows, new patterns emerge. Set up a weekly scan so new automation candidates surface before they become entrenched manual chores. Ask the `tessl agent` to schedule it:

> Set up a weekly GitHub Actions job that runs find-automations over the last 7 days and saves the candidate list where the team can review it.

The agent runs `find-automations` headlessly with `tessl launch skill find-automations --agent tessl-agent` on a weekly cron plus `workflow_dispatch`, and uploads the findings as an artifact for the team to review. Adjust the cadence and the output destination to fit your team.

Review the weekly artifact. When candidates appear across multiple weeks, escalate them to tickets. This prevents the backlog of manual chores from growing quietly.

## Next steps

* Use [Improving agent code quality](/tutorials/improving-agent-code-quality) and the `find-optimizations` skill to find recurring patterns in PR review feedback that suggest improvements to skills and rules, not just workflows.
* Use [Setting up agentic code review](/tutorials/setting-up-agentic-code-review) and `tessl change verify` to enforce structural invariants automatically so reviewers don't have to leave the same comment repeatedly.
* Combine both scans into a single scheduled workflow that runs both skills and aggregates their findings.


# Administrating Organizations, Workspaces, and Roles

{% hint style="info" %}
**Takeaways**

* How organizations, workspaces, and roles fit together in Tessl.
* How to set up your organization, create workspaces, and invite users with and without SSO.
* Which role to give a user, with worked examples for common team setups.
  {% endhint %}

## How organizations, workspaces, and roles fit together

An **organization** is the top-level entity, usually your billing or corporate entity. Inside it, **workspaces** group skills and give role-based access to the people who work on them. A user is granted a **role** per workspace, and that role decides what they can do there: install, publish, run evals, manage members, or administer the workspace. Skills are published as plugins, so the [role](/administrators/roles) permission tables describe these same actions in terms of plugins.

* **Organization: Acme**
  * **Org admin: Samira** manages all workspaces and users.
  * **Workspace: engteam**
    * **Manager: Jennifer** invites members and publishes.
    * **Publisher: Eddie** publishes skills for the team.
    * **Member: Joe** installs skills and runs reviews.
  * **Workspace: dsteam**

Actions such as running evaluations and publishing happen from the CLI against the Tessl platform, and what a user can do depends on their role and the workspace selected for the task. Access to skills and features in the web app follows the same rule.

## Set up your organization

An organization is created automatically for you when you sign up, and it is sometimes created during the presales phase. If someone has already invited you to an organization, you are added to that organization instead when you accept the invite, so you do not need to create one.

Create your first workspace from the workspace dropdown.

{% hint style="info" %}
When prompted, click **Create workspace** and name it after your team, for example *engteam*. Workspace names must be unique, and they appear in the names of any plugins published from them, which is most visible for publicly published plugins.
{% endhint %}

{% hint style="info" %}
If you are in an organization with teammates but have no workspaces, you were likely invited to the organization but not to a workspace. Contact one of your organization admins, who you can see on the organization **Members** screen.
{% endhint %}

<figure><img src="/files/empo5mDwkJLsDwn4eItJ" alt="" width="155"><figcaption></figcaption></figure>

Open **Settings** for your organization from the account menu at the bottom left. Rename the organization to your company name, and enable public sharing if you want users to be able to share skills publicly.

<figure><img src="/files/ZdqSh35ewnMSsaltTm1L" alt="" width="375"><figcaption></figcaption></figure>

## Invite users

### Without SSO

Only organization admins can invite users to the organization. Invite users from the organization's **Members** menu, assigning the workspaces each user should access along with the workspace role they get there. Invited users join the organization as members, and you can promote them to organization admin later, as below. You can also change their workspace roles from the workspace **Members** menu. A user must accept their invite before you can edit them further.

<figure><img src="/files/Q3CFpyLQtkQLrag52J8m" alt="" width="563"><figcaption></figcaption></figure>

### With SAML SSO

Users are provisioned on their first login and start with the organization **member** role and no workspace access. An administrator then adds each user to workspaces with the right roles from the workspace **Members** menu. See [SSO](/administrators/sso) for setup.

## Promote a user to organization admin

Once a user exists, you can elevate them to organization admin to let them create workspaces and manage users. On the organization **Members** screen, open the **Actions** menu for the user and assign the admin role.

<figure><img src="/files/VlliY17eRE7Zr0gmA87c" alt="" width="218"><figcaption></figcaption></figure>

## Admin keys

Admin keys give programmatic access across workspaces, for integrations and automation. Set an expiry of up to one year.

<figure><img src="/files/TGbO0WochNRDbkuwHDvU" alt=""><figcaption></figcaption></figure>

## Manage workspace membership

Switch to a workspace from the workspace dropdown, then open **Members** to set [roles](/administrators/roles) for users who need more than the default access, such as running evals, publishing, or managing members. Search for a user, select a [role](/administrators/roles), and click **Add**.

<figure><img src="/files/PlVyRj1YG14zeZElSKSr" alt=""><figcaption></figcaption></figure>

## Example role setups

These examples show common [role](/administrators/roles) assignments when rolling Tessl out.

### Samira, organization admin

Samira administers Tessl and champions skills. She needs to manage every workspace, assign users, and create new workspaces. Make her an organization admin.

### Jennifer, team manager

Jennifer runs a workspace. She needs to add members, publish, and remove other managers. Give her the **manager** or **owner** role on her workspace, depending on whether she needs to remove other owners or delete the workspace.

### Eddie, lead engineer

Eddie installs published skills and publishes skills for his team in the engteam workspace. Give him the **publisher** role there. He can be a **member** of other workspaces where he only needs to search and install.

### Joe, new-hire engineer

Joe searches and installs skills from the engteam workspace and runs reviews, but does not yet publish. Make him a **member** of the engteam workspace. The **consumer** role is for pure consumption only: a consumer can install skills but cannot run reviews or see who else is in the workspace.


# Roles

Roles for workspaces and orgs and permissions per role

{% hint style="info" %}
**Takeaways**

* A role controls what a user can do: install, publish, run evals, manage members, or administer a workspace.
* Roles are assigned per workspace, so a user can hold different roles in different workspaces.
* Separate organization-level roles, member and admin, govern org-wide actions such as creating workspaces.
  {% endhint %}

## Workspace Roles

Roles are assigned per workspace. To learn more about creating a workspace, see [Workspace management](/reference/cli-commands#workspace-management).

<table><thead><tr><th width="269.550537109375">Permission</th><th width="115.26123046875">consumer</th><th width="104.5859375">member</th><th width="119.615234375">publisher</th><th width="109.95703125">manager</th><th>owner</th></tr></thead><tbody><tr><td>Can view and install private plugins in the workspace</td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Can see other users in the workspace and their permissions</td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Generate workspace scoped API keys</td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Review, security-scan, and fix agent skills from the CLI (<code>tessl review run</code>, <code>tessl review run security</code>, <code>tessl review fix</code>)</td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Generate eval scenarios</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Run evals</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Manage eval visibility</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Create and publish plugins</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Unpublish plugin (within 2 days of publishing)</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Rolling out plugins (to repositories)</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Setup and manage integrations</td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Invite users and change user permissions</td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Can remove other managers</td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Archive plugins</td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Edit / delete workspace scoped API keys</td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Add/remove other owners from workspaces</td><td></td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Delete the workspace</td><td></td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>View skill inventory, scans, findings, committers, and breakdowns</td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Run a skill inventory import, trigger a rescan, and ignore or unignore repositories</td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr><tr><td>Create or delete a skill inventory, enable automatic scanning, and manage private indexing</td><td></td><td></td><td></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td></tr></tbody></table>

## Org Roles

| Permission                                  | member               | admin                |
| ------------------------------------------- | -------------------- | -------------------- |
| View org                                    | :white\_check\_mark: | :white\_check\_mark: |
| Manage org scoped API keys                  |                      | :white\_check\_mark: |
| Create workspaces                           |                      | :white\_check\_mark: |
| Inherit owner on every workspace in the org |                      | :white\_check\_mark: |


# SSO

{% hint style="info" %}
**Takeaways**

* SAML SSO is a paid feature available on the Business and Enterprise tiers.
* Users are provisioned on first login as organization members with no workspace access.
* An administrator then grants each user workspace roles.
  {% endhint %}

## Enabling SAML based SSO

To enable SAML based Single Sign On (SSO), your Tessl account manager or technical contact will provide a link for your SSO system to connect and configure Tessl.

## Configuring Users

{% hint style="info" %}
Users are provisioned on first login
{% endhint %}

By setting up the integration, a user will authenticate via your SSO and be assigned the “member” role of the Organization when they visit Tessl. Your Tessl Org or Tessl Workspace administrators can add the user to workspaces with the desired roles by navigating to ***Workspace→Members.***

For information on setting roles and managing users, see:

* [Organizations, Workspaces, and Roles](/administrators/administrating-organizations-workspaces-and-roles)
* [Roles](/administrators/roles)


# Enhance your workflow with skills

Learn how to discover and install skills that enhance your agent's capabilities with procedural workflows

Skills provide step-by-step workflows that help your agent perform specific tasks correctly. This guide shows you how to find, install, and use skills to improve your development workflow.

## What are skills?

Skills are procedural guides that teach agents how to perform specific workflows. Unlike documentation (which explains what something is), skills explain how to do something step-by-step.

**Example skills:**

* Debug API endpoints systematically
* Review code for security issues
* Write comprehensive test suites
* Generate API documentation

When you work on tasks, your agent automatically loads relevant skills to follow best practices and team procedures.

## Prerequisites

Before installing skills, make sure you've initialized Tessl in your project:

```bash
# Initialize Tessl (auto-detects and configures your agent)
tessl init
```

See [Improve your first skill](/introduction-to-tessl/improve-your-first-skill) and [Custom agent setup](/reference/custom-agent-setup) for details.

## Discovering skills

### Browse the registry

Visit the [Tessl Registry](https://tessl.io/registry) to browse available skills. You can further filter the results by:

* plugin
* Skill

### Search from CLI

Search for skills directly from your terminal:

```bash
# Search for testing skills & plugins
tessl search testing

# Search for code review skills & plugins
tessl search "code review"

# Interactive search
tessl search
```

### Ask your agent

You can also ask your agent to find and install skills:

```
Find me a skill for debugging API endpoints
```

## Installing skills

{% hint style="info" %}
Note, if you're installing skills to your OpenClaw agent, you must install skills from your agent's workspace. Check out [OpenClaw](/reference/custom-agent-setup/openclaw) for more information.
{% endhint %}

By default, skills are installed into your current project (`.tessl/plugins/`) and tracked in `tessl.json`. Use `--global` to install a skill to `~/.tessl/` instead, making it available across all your projects without needing to reinstall it per project.

```bash
# Install into the current project (default)
tessl install tessl-labs/debug-api-endpoints

# Install globally, available in all projects
tessl install --global tessl-labs/debug-api-endpoints
```

### From the registry

Install skills by name from the Tessl registry:

```bash
# Install a specific skill
tessl install tessl-labs/debug-api-endpoints

# Install multiple skills
tessl install tessl-labs/code-review tessl-labs/testing-workflow
```

### From GitHub repositories

Many open source projects publish skills on GitHub:

```bash
# Install from GitHub with interactive skill selection
tessl install https://github.com/anthropics/skills

# Install specific skills by name
tessl install https://github.com/anthropics/skills --skill pdf --skill pptx

# Install from a specific branch or path
tessl install https://github.com/owner/repo/tree/main/skills/my-skill

```

The registry shows a commit-specific install command when security results are available for that version — use it to install the exact version that was scanned. See [Security scores](#security-scores) for details.

## Using installed skills

Once installed, skills work automatically. Your agent loads relevant skills based on:

* Your task description
* The files you're working with
* The context of your conversation

### How skills activate

Skills use "lazy push" - they're automatically loaded when relevant:

**Example: Debugging workflow**

1. You say: "Debug the failing API endpoint"
2. Agent recognizes this matches the debug-api-endpoints skill
3. Skill is loaded with its step-by-step workflow
4. Agent follows the procedure: check infrastructure → verify auth → validate I/O → test functionality

You don't need to explicitly invoke skills - they activate automatically when needed.

## Managing installed skills

### List installed skills

View all skills in your project:

```bash
tessl list
```

This shows all installed plugins, including those containing skills.

### Update skills

Check for newer versions and reinstall to update:

```bash
# Check which installed plugins have updates available
tessl outdated

# Reinstall to get latest version
tessl install tessl-labs/debug-api-endpoints
```

### Remove skills

Uninstall skills you no longer need:

```bash
# Remove from the current project
tessl uninstall tessl-labs/debug-api-endpoints

# Remove a globally installed skill
tessl uninstall --global tessl-labs/debug-api-endpoints
```

## Reviewing skill quality

Before installing skills, check their review scores and evaluations in the registry to understand their quality and effectiveness.

### Understanding review scores

Skills in the registry show multiple quality indicators:

**Review Score** (0-100%): Overall quality assessment

* 90%+: High-quality, production-ready
* 70-89%: Good quality, may have minor improvements needed
* Below 70%: Needs work before deployment

**Validation Score**: Checks for required fields, trigger hints, workflow structure, and metadata completeness

**Implementation Score**: Code quality in examples, security practices, error handling

**Activation Score**: How well agents discover and load the skill when relevant

### Viewing evaluations

Click on any skill in the registry to see:

* Detailed validation results (what passed/failed)
* Specific recommendations for improvement
* Example usage and trigger conditions
* Community feedback and ratings

Use these scores to choose skills that meet your quality standards before installing.

For more details on how skills are scored, see [Check a skill's quality using review](/improving-your-skills/reviewing-skills).

## Security scores

Skills installed from the Tessl Registry are scanned for security vulnerabilities using Snyk. Security scores are shown in the registry UI alongside quality scores so you can assess risk before installing.

Security scanning can produce false positives, and Tessl is designed to give you flexibility in how much weight you give the findings rather than blocking you outright.

### Security gating

When you run `tessl install` or `tessl update`, if a skill has critical or high security findings, the CLI will ask for your permission before continuing. You can always choose to proceed — installation is never blocked.

To skip the prompt automatically (for example in CI or automated workflows):

```bash
tessl install engteam/my-skill --accept-warnings
```

### Installing a pinned version

The registry shows a commit-specific install command alongside security results, so you can install the exact version that was scanned:

```bash
tessl install engteam/my-skill@abc1234
```

You can also install the latest version at any time by omitting the version, or run `tessl update` on an already-installed skill.

### Reporting false positives

Each security finding in the registry includes a **Report Incorrect Findings** link. Use it to flag suspected false positives — the Tessl team will investigate and feed confirmed corrections back to Snyk to improve the scanner.

## Best practices

**Start with popular skills**: Browse featured skills in the registry to find well-reviewed, widely-used workflows.

**Install skills for your tech stack**: Look for skills specific to your frameworks and tools (React, FastAPI, Docker, etc.).

**Create team skills**: Build custom skills for your team's specific workflows and procedures. See [Creating skills](/create/creating-skills).

**Review before installing**: Check skill review scores in the registry to understand quality and completeness.

**Keep skills updated**: Reinstall periodically to get improvements and bug fixes.

## Troubleshooting

**Skill not activating?**

* Make sure the skill is installed: `tessl list`
* Try being more specific in your request to match skill triggers
* Check that your agent has MCP configured: `tessl init --agent <name>`

**Multiple skills conflicting?**

* Skills are designed to work together, but if you notice issues, uninstall less relevant ones
* More specific skills usually take precedence over general ones

**Need a skill that doesn't exist?**

* Create your own: [Creating skills](/create/creating-skills)
* Request it in the Tessl community
* Check GitHub for open source skills in your domain

## Next steps

* [Creating skills](/create/creating-skills) - Build custom workflows for your team
* [Check a skill's quality using review](/improving-your-skills/reviewing-skills) - Understand skill quality scores


# Spec-Driven Development with Tessl

Spec-driven development is a workflow where your AI coding [agent](/reference/custom-agent-setup) gathers requirements and writes specifications *before* writing any code. You review and approve the specs, then the agent implements them.

## The Problem with Vibecoding

When you prompt an agent without structure, you get vibecoded output:

* The agent assumes what you want instead of asking
* It hallucinates APIs from stale training data
* There's no way to verify the result matches your intent
* When you restart the session, the agent has no easy way to regain context

This creates an **intent-to-code chasm** — a gap between what you meant and what you got. The agent produced *something*, but you have no systematic way to check if it's the right thing.

{% hint style="info" %}
Vibecoding is fine for throwaway prototypes. For anything you actually care about, you need a process that bridges that gap.
{% endhint %}

## Quick Start

Assuming Tessl is already [set up and ready to go in your terminal](broken://pages/nGU0rz0uGSZv5cYBrzwd), install the spec-driven development plugin:

```bash
tessl init
tessl install tessl-labs/spec-driven-development
```

Then include "use spec-driven development" in your prompt:

```
Build a REST API for managing team projects. Use spec-driven development.
```

That's it. The agent now follows a structured workflow instead of diving straight into code.

## What Happens Next

{% stepper %}
{% step %}
**The agent asks questions first**

Instead of making assumptions, the agent interviews you:

* What endpoints do you need?
* How should authentication work?
* What happens when a resource isn't found?
* Should deleted items be soft-deleted or permanently removed?

One question at a time, until requirements are clear.
{% endstep %}

{% step %}
**The agent writes specs before code**

The agent creates specification documents in a `specs/` folder. These are markdown files that capture:

* Functional requirements
* API contracts
* Edge cases and error handling
* Links to tests that verify each requirement
  {% endstep %}

{% step %}
**You approve before implementation begins**

The agent pauses while you (and all the stakeholders) review the specs. This is your checkpoint — if something's wrong or missing, you catch it *before* any code is written.
{% endstep %}

{% step %}
**Implementation follows the specs**

Once you approve, the agent builds against the documented requirements. When it's done, it verifies that all requirements are satisfied and updates specs with anything discovered during development.
{% endstep %}
{% endstepper %}

## Combining with Documentation plugins

The spec-driven development plugin teaches your agent *how to work*. plugins with documentation from the [Tessl Registry](https://tessl.io/registry) teach it *what tools to use correctly*.

Together, they're powerful:

```bash
tessl install tessl-labs/spec-driven-development
tessl install tessl/npm-express
tessl install tessl/npm-langchain
```

Now your agent:

* Follows a structured workflow (spec-driven plugin)
* Uses Express APIs correctly without hallucinating (Express plugin)
* Implements LangChain patterns properly (LangChain plugin)

Process without library context gives you well-organized hallucinations. Documentation and code samples without process yield correctly spelled chaos. You need both.

## Learn More

For details on the spec format, the `[@test]` linking syntax, and what's inside the plugin: see the [plugin documentation on GitHub](https://github.com/tesslio/spec-driven-development-tile).


# Migrating from tiles to plugins

Guide for migrating from the legacy tile.json format to the new plugin format

Tessl is transitioning from **tiles** to **plugins** as the packaging format for shareable agent rules and skills. This document explains why, what changed, and how to migrate your existing tile packages.

## Why the change?

Tessl started with tiles: prepackaged bundles of context for agents. Since then, the wider agent ecosystem is settling on plugins as the standard format for the same idea, so we're moving Tessl onto plugins.

For you, this means what you build in Tessl travels naturally to different coding agents, and the terminology lines up with what your teams are already seeing. For us, it's a stronger foundation to build on. As agents start handling richer kinds of context, plugins give us the base to layer versioning, distribution, evaluation, and security on top of these new context types.

***

## What changed

### Manifest location and filename

| Format | File          | Location                    |
| ------ | ------------- | --------------------------- |
| Tile   | `tile.json`   | Package root                |
| Plugin | `plugin.json` | `.tessl-plugin/plugin.json` |

The manifest moves into a dedicated `.tessl-plugin/` directory. This keeps the root clean and makes space for sibling agent manifests (`.claude-plugin/`, `.cursor-plugin/`) without naming collisions, if and when they are added.

### Field-by-field comparison

| Concept           | tile.json                                 | plugin.json               | Notes                                          |
| ----------------- | ----------------------------------------- | ------------------------- | ---------------------------------------------- |
| Package name      | `name`                                    | `name`                    | Same format: `workspace/package`               |
| Version           | `version`                                 | `version`                 | Required at publish in both                    |
| Short description | `summary`                                 | `description`             | Field renamed; trimmed and required at publish |
| Private flag      | `private`                                 | `private`                 | Identical                                      |
| Repository URL    | `repository`                              | `repository`              | Both accept `https://` URLs                    |
| Package author    | —                                         | `author`                  | New: `{ name, email, url }` object             |
| Homepage          | —                                         | `homepage`                | New: URL string                                |
| License           | —                                         | `license`                 | New: SPDX identifier, e.g. `"MIT"`             |
| Skills            | `skills: { "name": { path: "..." } }`     | `skills: "./skills/"`     | Changed from keyed object to path(s)           |
| Rules / Steering  | `rules: { "name": { rules: "..." } }`     | `rules: "./rules/"`       | Changed from keyed object to path(s)           |
| Commands          | `commands: { "name": { script: "..." } }` | `commands: "./commands/"` | Changed from keyed object to path(s)           |
| Docs file         | `docs: "./README.md"`                     | —                         | Removed; move content into skills or rules     |
| Describes (PURL)  | `describes: "pkg:..."`                    | —                         | Removed; not carried forward                   |

### Skills: from keyed registry to directory discovery

In `tile.json`, each skill had an explicit key and path:

```json
{
  "skills": {
    "my-skill": { "path": "./skills/my-skill/SKILL.md" },
    "other-skill": { "path": "./skills/other-skill/SKILL.md" }
  }
}
```

In `plugin.json`, you point at a directory and Tessl discovers skills automatically. A skill's identity comes from the `name:` field in its `SKILL.md` frontmatter (falling back to the directory basename if no frontmatter is present):

```json
{
  "skills": "./skills/"
}
```

You can also pass an explicit array of paths when you want precise control:

```json
{
  "skills": ["./skills/my-skill/SKILL.md", "./skills/other-skill/SKILL.md"]
}
```

### Rules: from nested objects to directory paths

In `tile.json`:

```json
{
  "rules": {
    "style-guide": { "rules": "./rules/style-guide.md" }
  }
}
```

Note: `steering` was accepted as an alias for `rules` in `tile.json` and normalised automatically. Both wrote to the same field internally.

In `plugin.json`:

```json
{
  "rules": "./rules/"
}
```

All `.md` files found in the declared directory are included as rules. There are no longer named keys; the rule name is derived from the filename.

### Docs and Describes: removed

The `docs` field (a standalone markdown file) and `describes` field (a PURL for a versioned dependency) have no equivalent in `plugin.json`.

* **`docs`**: Fold the content into a rule or skill. If the doc was user-facing guidance about a tool or library, it belongs as a skill.
* **`describes`**: This field declared that a tile described a specific versioned package (e.g. a Go library). It was used as part of Docs, as Docs have not been carried forward, neither has Describes.

If you publish with `TESSL_PLUGIN=1` and your `tile.json` still has `docs` or `describes` set, the CLI will warn you at pack time that these fields will not be included.

For converting docs to skills, there is a [skill available in the Tessl Registry](https://tessl.io/registry/tessleng/doc-skill-creator).

***

## Compatibility during the transition

Tiles and plugins coexist. The CLI continues to read and publish `tile.json` packages without any changes required. No existing tile breaks.

When both a `tile.json` and a `.tessl-plugin/plugin.json` are present in the same package `.tessl-plugin/plugin.json` takes precedence for metadata (name, version, description).

{% hint style="info" %}
For new work, use plugins: `.tessl-plugin/plugin.json` and `tessl plugin ...`. Use tiles only for legacy compatibility or migration. Publish legacy `tile.json` packages with `tessl tile ...`. Publish new plugin packages with `tessl plugin ...`.
{% endhint %}

***

## How to migrate

Using the migrate command

The CLI can generate `.tessl-plugin/plugin.json` from your existing tile.json automatically:

```
tessl tile migrate
```

Run this from your package root (the directory containing tile.json). The command:

* Creates `.tessl-plugin/` if it doesn't exist
* Translates all supported fields (name, version, summary → description, repository, private, skills, commands, rules)
* Warns if your tile.json contains docs or describes — these have no plugin equivalent and will not appear in the output

If you want to migrate a package that isn't in the current directory, pass the path:

```
tessl tile migrate ./path/to/my-package
```

What the command does not do

The migrate command handles the mechanical translation. A few steps still require your attention:

* docs and describes: If your tile.json uses these fields, the command will warn you and omit them. See Docs and Describes: removed for how to fold that content into skills or rules.
* SKILL.md frontmatter: The command copies your skill paths as-is. If your SKILL.md files are missing a name: field, Tessl will fall back to the directory basename — but adding frontmatter is recommended. See Step 4: Add SKILL.md frontmatter.
* tile.json is kept: The command does not delete your existing tile.json. Once you've verified the new manifest with `tessl plugin lint` and `tessl plugin publish --dry-run`, you can remove it manually.

***

### Alternatively:

### Step 1: Create `.tessl-plugin/plugin.json`

Create the directory and manifest:

```
mkdir .tessl-plugin
touch .tessl-plugin/plugin.json
```

Translate your `tile.json` fields:

**tile.json (before):**

```json
{
  "name": "myorg/my-package",
  "version": "1.2.0",
  "summary": "Linting rules for our TypeScript monorepo",
  "repository": "https://github.com/myorg/my-package",
  "skills": {
    "lint-fix": { "path": "./skills/lint-fix/SKILL.md" }
  },
  "rules": {
    "ts-style": { "rules": "./rules/ts-style.md" },
    "imports": { "rules": "./rules/imports.md" }
  }
}
```

**.tessl-plugin/plugin.json (after):**

```json
{
  "name": "myorg/my-package",
  "version": "1.2.0",
  "description": "Linting rules for our TypeScript monorepo",
  "repository": "https://github.com/myorg/my-package",
  "skills": "./skills/",
  "rules": "./rules/"
}
```

### Step 2: Check your directory layout

The path values in `plugin.json` are relative to the **package root** (i.e. the directory containing `.tessl-plugin/`). Verify that the paths you declared actually exist:

```
my-package/
├── .tessl-plugin/
│   └── plugin.json          ← manifest
├── skills/
│   └── lint-fix/
│       └── SKILL.md         ← discovered automatically
└── rules/
    ├── ts-style.md           ← discovered automatically
    └── imports.md            ← discovered automatically
```

### Step 3: Handle docs and describes

If your `tile.json` has a `docs` field:

1. Open the file it points to.
2. If the content is a step-by-step procedure for the agent to follow, convert it to a skill: create a `SKILL.md` in your skills directory with the content.
3. If the content is constraints or style guidance, move it into your rules directory as a `.md` file.
4. Remove `docs` from `tile.json` (or skip it entirely if you're dropping `tile.json`).

### Step 4: Add SKILL.md frontmatter (recommended)

With `tile.json`, skill identity was the key in the `skills` object. With `plugin.json`, identity comes from the `name:` field in `SKILL.md` frontmatter. Add frontmatter if it's missing:

```markdown
---
name: lint-fix
description: Fix lint errors in TypeScript files using the project's oxlint config
---

# Lint Fix

...
```

If there's no frontmatter, Tessl uses the directory basename as the skill name — so existing skills continue to work without changes.

### Step 5: Verify with the CLI

Run the linter to catch any issues:

```
tessl plugin lint
```

In plugin mode (`TESSL_PLUGIN=1`), the CLI will:

* Warn if `tile.json` is still present with `docs` or `describes` fields that have no plugin equivalent.
* Validate that every path declared in `plugin.json` resolves and contains recognisable content.

Do a dry-run pack to confirm what will be included in the tarball:

```
tessl plugin publish --dry-run
```

### Step 6: Publish

```
tessl plugin publish
```

Once you're confident in the new format, you can delete `tile.json` from your repository to remove the duplication.

***

## Running evaluations after migration

`tessl eval run` works the same way it did for tiles: point it at the package root. The only change is where that root is.

Before migration, you pointed at the tile directory (where `tile.json` lives):

```
tessl eval run <path-to-tile>
```

After migration, point at the plugin directory (where `.tessl-plugin/plugin.json` lives):

```
tessl eval run <path-to-plugin>
```

The plugin directory is the *parent* of `.tessl-plugin/`, not `.tessl-plugin/` itself. From a plugin root, this is usually just `.`:

```
tessl eval run .
```

***

## Quick reference

### tile.json → plugin.json field mapping

| tile.json                                  | plugin.json                                |
| ------------------------------------------ | ------------------------------------------ |
| `summary`                                  | `description`                              |
| `skills.X.path`                            | `skills` (directory or array)              |
| `rules.X.rules`                            | `rules` (directory or array)               |
| `steering.X.rules`                         | `rules` (directory or array)               |
| `commands.X.script`                        | `commands` (directory or array)            |
| `docs`                                     | No equivalent — move to skills or rules    |
| `describes`                                | No equivalent — contact us                 |
| `name`, `version`, `private`, `repository` | Identical                                  |
| —                                          | `description` (required at publish)        |
| —                                          | `author`, `homepage`, `license` (optional) |

### Minimum valid plugin.json

```json
{
  "name": "workspace/package-name",
  "version": "1.0.0",
  "description": "One sentence describing what this plugin does"
}
```

By convention, skills will be pulled from the `./skills` directory and rules from `./rules`. If they are not set, these conventions will be used.


# Understand your skill estate

How to use Tessl Skill Inventory to understand the skills you have across your org and the extent of your skill sprawl.

Skills are multiplying across your repos. Most teams have no idea how many they have, who owns them, or how many are near-duplicates of each other.

Tessl Skill Inventory gives you a living map of every skill in your org - what exists, where it's used, and where you're duplicating effort.

It's free, and you can run it today.

***

The CLI import in the Quickstart below needs at least the **publisher** role. Creating an inventory from the web, enabling automatic scanning, and private indexing are manager-only. See [Roles](/administrators/roles) for the full permission breakdown.

### Quickstart

**1.** [**Download Tessl**](/introduction-to-tessl/set-up-tessl/installation)

**2.** [**Download the Github CLI**](https://cli.github.com/) (we access your code through your Github auth via the CLI)

**3. Authenticate**

```
tessl login
```

**4. Run the import**

```
tessl inventory import
```

Tessl scans your repos, collects your skills and manifests, and gives you a snapshot of your whole inventory. Run it again any time - each scan is diffed, so you get a living view of what's new, unchanged, and removed over time.

> Want to test on a subset first? `tessl inventory import --repo repo-a --repo repo-b`

***

### Detailed Guide

#### How It Works

The tessl CLI scans your repository, collects your skills and manifest files, and uploads them to Tessl. Each upload is a snapshot — Tessl tracks what's new, what's unchanged, and what's been removed across successive uploads so you get a living view of your skill inventory over time.

***

#### The Tessl CLI

The scan runs entirely from your local machine using the `tessl` CLI. Before running it, you need two things:

* **GitHub CLI (`gh`) authenticated** - the CLI uses your GitHub credentials to read repos and files. Access is scoped to whatever your GitHub account can see.
* **Logged in to Tessl** - run `tessl login` to authenticate before scanning.

**Running the scan**

By default, `tessl` scans your last 100 most recently active repositories. For large organisations this is a good starting point, but you can be more selective using `--repo`:

`tessl inventory import --repo repo-a --repo repo-b`

You can pass `--repo` as many times as you like. This is useful for testing the import on a small subset before running it across your whole organisation.

**What we don't collect**

* **No code** - only `skill.md` files and manifest files are read. Source code files are never accessed.
* **No names or email addresses** - only GitHub usernames are collected, never real names or email addresses.
* **No repo clones** - repos are never checked out. Individual files are fetched directly via the GitHub API.

**GitHub API rate limits**

The CLI uses the GitHub API under the hood, which has a limit of 5,000 requests per hour. If you have a large number of repos or skills, you may hit this limit mid-scan. In that case, wait for the limit to reset and re-run - successive scans are diffed, so you won't lose previously collected data.

***

#### What Gets Collected

**Skills (`skill.md` files)**

Every `skill.md` file found anywhere in your repository is collected, including:

* The full markdown body
* Any YAML frontmatter (name, description, etc)
* The file path within the repo
* Git metadata: created/updated dates, last touched by username.

Skills inside test fixture directories are included but tagged separately so they don't pollute your inventory metrics.

**Manifest files**

The following manifest files are collected if present:

| File                              | What it represents                                                              |
| --------------------------------- | ------------------------------------------------------------------------------- |
| `skills-lock.json`                | Skills installed via `npx skills` with pinned versions and content hashes       |
| `tessl.json`                      | Tessl's installed skill manifest                                                |
| `tile.json`                       | Legacy tessl plugin definition with skill declarations                          |
| `.tessl-plugin/plugin.json`       | Tessl plugin definition                                                         |
| `.claude-plugin/plugin.json`      | Claude plugin definition                                                        |
| `.claude-plugin/marketplace.json` | Marketplace plugin listing                                                      |
| `.claude/settings.json`           | Claude Code agent settings. Used to determine which marketplaces are being used |

***

#### Limitations

* **Linked files are not uploaded.** If your `skill.md` references other markdown files (e.g. via `@rules.md` or a markdown link), those files are not followed or stored — only the `skill.md` itself is captured.
* **Scripts are not uploaded.** Any executable files (`.sh`, `.py`, etc.) associated with a skill are not collected.
* **Manifest references are not resolved.** The manifest files themselves are stored, but any file paths referenced *inside* them are not read or uploaded.
* **Default scan is capped at 100 repos.** Only the 100 most recently active repositories are scanned by default. Use `--repo` to target specific repos if needed.


# Creating skills

Learn how to create and manage skills using Tessl.

Skills are reusable capabilities that extend AI coding agents with specialized knowledge, workflows, or tool integrations. Tessl makes it easy to create, publish, and share skills with your team or the broader community through the Tessl Registry.

This guide walks you through creating a skill, publishing it, and installing it so your agent can use it.

## Prerequisites

Before you begin, make sure you have:

* Tessl CLI installed (see [Installation](/introduction-to-tessl/set-up-tessl/installation))
* Authenticated with Tessl (`tessl login`)
* A workspace created (see [Workspace management](/reference/cli-commands#workspace-management))

## Creating a skill

### Step 1: Create a new skill

Use the `tessl skill new` command to create a new skill. You can run it interactively or with flags:

**Option 1: Interactive wizard (recommended for first-time users)**

```sh
tessl skill new
```

This launches an interactive wizard that guides you through creating the skill.

**Option 2: Create with flags**

You can create a skill with all parameters specified:

```sh
# Create a new skill
tessl skill new --name "database-migration-helper" --description "When you need to create and manage database migrations" --workspace myworkspace --path ./my-skill
```

The command creates a new directory with a `SKILL.md` file following the Agent Skills specification. See the [CLI commands reference](/reference/cli-commands#tessl-skill-new) for all available options.

**Option 3: Import an existing skill**

If you already have a skill (e.g., from a local directory), you can import it:

```sh
# Import from a local directory
tessl skill import ./path/to/my-skill --workspace myworkspace

# Import and make it public
tessl skill import ./my-skill --workspace myworkspace --public
```

This validates and imports the skill into your workspace. See the [CLI commands reference](/reference/cli-commands#tessl-skill-import) for all import options.

### Step 2: Write your skill

Your skill file must be named `SKILL.md` and should contain the skill definition following the Agent Skills format. For the complete specification, see:

* [Agent Skills Specification](https://agentskills.io/specification) - The official Agent Skills format specification
* [Anthropic Agent Skills Documentation](https://docs.anthropic.com/en/docs/agents-and-tools/agent-skills/overview) - Anthropic's official documentation for Agent Skills

#### Example SKILL.md

Here's what a well-documented `SKILL.md` file looks like:

```markdown
---
name: database-migration-helper
description: When you need to create and manage database migrations.
---

# Database Migration Helper

## Creating a Migration

When creating a new migration:

1. Always include both `up` and `down` migrations
2. Use transactions when possible
3. Test migrations on a copy of production data first

### Example: Adding a Column

    -- Up migration
    ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT FALSE;

    -- Down migration
    ALTER TABLE users DROP COLUMN email_verified;


## Best Practices

* Never modify existing migrations that have been applied to production
* Always test rollbacks
* Keep migrations small and focused
```

**Key components:**

* **YAML frontmatter** (required):
  * `name`: The skill identifier (lowercase, hyphens only)
  * `description`: Clear description of the trigger when skill should activate - this is critical for skill discovery by agents
* **Markdown body**: Concise instructions, examples, and guidance

**Important:** Keep the documentation simple and focused. The frontmatter `description` helps agents discover your skill, while the body provides clear, actionable guidance.

#### Understanding the Tessl package structure

When you create a skill with `tessl skill new`, it creates a Tessl package structure with a `.tessl-plugin/plugin.json` manifest file. This file contains metadata about your skill:

```
my-skill/
├── .tessl-plugin/plugin.json    # Package manifest
└── skills/my-skill/SKILL.md     # Your skill file
```

The `.tessl-plugin/plugin.json` file looks like this:

```json
{
  "name": "myworkspace/database-migration-helper",
  "version": "1.0.0",
  "description": "Helper for creating and managing database migrations",
  "private": true,
  "skills": "skills/database-migration-helper"
}
```

**Key fields:**

* **name**: Package name in `workspace/skill-name` format
* **version**: Semantic version ([semver](https://semver.org/))
* **skills**: An array of directories containing `SKILL.md` files.
  * If this is omitted, then `./skills` is used as the directory to look for skills in, by convention.

You typically don't need to manually edit `.tessl-plugin/plugin.json` unless you're updating the version for a new release. For more details on the plugin structure and configuration options, see [Configuration files](/reference/configuration).

### Step 3: Validate your skill against best practices

Before publishing, validate your skill structure and contents:

```sh
tessl skill lint ./my-skill
```

This command checks:

* `SKILL.md` format and structure
* Required frontmatter fields (name, description)
* Conformance to the Agent Skills specification
* Markdown validity

For a more comprehensive review with detailed recommendations:

```sh
tessl skill review ./my-skill
```

Fix any errors before proceeding.

### Step 4: Evaluate quality using scenarios

Once you've built your skill the final step before publishing is to create scenarios your skill can be evaluated against. The following document illustrates how you would accomplish this:

* [Evaluate skill quality using scenarios](/improving-your-skills/evaluate-skill-quality-using-scenarios)

### Step 5: Publish your skill

Publish your skill to the Tessl Registry:

```sh
tessl skill publish ./my-skill --workspace myworkspace
```

By default, skills are published as private. This means only members of your workspace can install them.

If you're in the skill directory, you can omit the path:

```sh
cd my-skill
tessl skill publish --workspace myworkspace
```

To make a skill public (after approval):

```sh
tessl skill publish --workspace myworkspace --public
```

After publishing, your skill will be available in the Tessl Registry and can be installed by members of your workspace.

**Giving others access to your private skill:**

To allow team members to install your private skill, add them to your workspace using `tessl workspace add-member`. See [Workspaces](/reference/workspaces) for details on managing workspace members and [Workspace management](/reference/cli-commands#workspace-management) for the complete command reference.

## Installing a skill

Once published (as private or public), you or your team members can install the skill in any project:

```sh
tessl install myworkspace/my-skill
```

Or install a specific version:

```sh
tessl install myworkspace/my-skill@1.0.0
```

Skills are installed as part of Tessl packages and automatically made available to your configured agent.

{% hint style="info" %}
If you have an issue with installing a skill from GitHub, you can enable verbose mode using -v
{% endhint %}

## How skills are made available to your agent

When you install a skill (via `tessl install`), Tessl automatically makes it available to your configured agent:

1. **Package installation**: The skill is downloaded as part of a Tessl package to `.tessl/plugins/<workspace>/<package-name>/` in your project
2. **Skill extraction**: Skills are extracted and made available to the agent
3. **Agent integration**: Skills are made available to your agent depending on your agent platform.

## Updating a skill

To update a published skill:

1. Make your changes to the `SKILL.md` file
2. Update the version number in `.tessl-plugin/plugin.json` (following [semantic versioning](https://semver.org/))
3. Validate with `tessl skill lint` or `tessl skill review`
4. Publish the new version with `tessl skill publish`

```sh
# Update your SKILL.md file
vim my-skill/SKILL.md

# Update version in .tessl-plugin/plugin.json (e.g., from "1.0.0" to "1.1.0")
vim .tessl-plugin/plugin.json

# Validate the changes
tessl skill lint ./my-skill

# Publish the updated version
tessl skill publish ./my-skill --workspace myworkspace
```

**Important:** Always increment the version in `.tessl-plugin/plugin.json` when publishing updates. Use semantic versioning:

* **Patch** (1.0.0 → 1.0.1): Bug fixes, minor improvements
* **Minor** (1.0.0 → 1.1.0): New features, backward-compatible changes
* **Major** (1.0.0 → 2.0.0): Breaking changes

Users who have installed your skill can update to the new version by running:

```sh
tessl install myworkspace/my-skill
```

This will automatically fetch the latest version of your skill.

## Making your skill public (optional)

If you want to share your skill publicly so anyone can install it, you need to request to make it public:

1. Navigate to the [Tessl Registry](https://tessl.io/registry) in your browser
2. Log in if you're not already authenticated
3. Navigate to your workspace and find your skill
4. Click on the skill to view its details
5. Select **Actions** → **Make Public**
6. Click **Request to Make Public**

Tessl will review your request and contact you about the status. Once approved, you can publish with the `--public` flag:

```sh
tessl skill publish --workspace myworkspace --public
```

For more details, see [Sharing plugins publicly](/distribute/sharing-plugins-publicly).

## Best practices

* **Use SKILL.md format**: Skills must be named `SKILL.md` and follow the Agent Skills specification
* **Write clear descriptions**: The `description` in your frontmatter is critical for skill discovery - make it specific about when the skill should be used
* **Keep skills focused**: Each skill should have a single, clear purpose
* **Test before publishing**: Use `tessl skill lint` and `tessl skill review` to validate your skill against best practices and then [Evaluate skill quality using scenarios](/improving-your-skills/evaluate-skill-quality-using-scenarios) to ensure effectiveness.
* **Document clearly**: Include concise instructions and examples in your `SKILL.md` body
* **Use the `--install` flag**: When creating a new skill, use `--install` to test it locally immediately
* **Version carefully**: Always update the version in `.tessl-plugin/plugin.json` before publishing updates (following semantic versioning)

## Alternative: Creating a plugin for your skill

The workflow above uses `tessl skill` commands for a skill-first approach. If you need more flexibility (such as combining docs, rules, and skills in one package), you can use the plugin-first workflow:

1. Use `tessl plugin new` to create a plugin structure with `.tessl-plugin/plugin.json`
2. Add your `SKILL.md` file to the plugin's `skills/my-skill` directory
3. Reference the skill in `.tessl-plugin/plugin.json`:

   ```json
   {
     "name": "myworkspace/my-skill",
     "version": "1.0.0",
     "skills": "skills" // this can be omitted, "skills" is used by convention
   }
   ```
4. Use `tessl plugin lint` and `tessl plugin publish` to validate and publish

## Related documentation

* [Agent Skills Specification](https://agentskills.io/specification) - The official Agent Skills format specification
* [Anthropic Agent Skills Documentation](https://docs.anthropic.com/en/docs/agents-and-tools/agent-skills/overview) - Anthropic's official documentation for Agent Skills
* [Distributing via registry](/distribute/distributing-via-registry) - Share and maintain plugins via the registry
* [Configuration files](/reference/configuration) - Complete reference for `.tessl-plugin/plugin.json` structure
* [CLI commands](/reference/cli-commands) - Full command reference
* [Custom agent setup](/reference/custom-agent-setup) - How agents access plugins and skills


# Creating plugins

Learn how to create your own skills, rules, MCP servers, and hooks to share with your team

This section covers how to create custom Tessl packages (plugins) containing skills, rules, MCP servers, and hooks tailored to your team's specific needs.

## When to create plugins

Create custom plugins when you want to:

* **Codify team standards** - Capture your coding conventions, best practices, and style guidelines as rules
* **Share procedural knowledge** - Document workflows and processes as skills that team members can follow
* **Ensure consistency** - Make sure everyone on your team follows the same practices automatically

## What can you create?

### Skills

Procedural workflows that guide agents through complex tasks step-by-step.

**Example use cases:**

* API testing workflows
* Database migration procedures
* Deployment checklists
* Code review processes

**Learn more:** [Creating skills](/create/creating-skills)

### Rules

Mandatory coding standards and conventions that agents always follow.

**Example use cases:**

* Error handling patterns
* Validation requirements
* Response format conventions
* Security best practices
* Naming conventions

**Learn more:** Rules are included in plugins - see [Developing plugins locally](/create/developing-plugins-locally)

### MCP

MCP (Model Context Protocol) tools let your plugin expose custom tools that agents can call during a session — connecting them to internal APIs, databases, or services that wouldn't otherwise be accessible.

**Example use cases:**

* Query an internal feature flag service so the agent knows which flags are active
* Look up your internal component library to suggest the right component for a given UI pattern
* Fetch live API schema from a staging environment to keep the agent's understanding current

A plugin declares MCP servers by adding a `.mcp.json` file at the plugin root.

**Learn more:** [Configuration files](/reference/configuration)

### Hooks

Hooks are deterministic commands that run automatically in response to events within an agent harness. For example, running a linter after the agent edits a file, or validating input when the user submits a prompt.

**Example use cases:**

* Run `npm run lint` automatically after the agent edits a TypeScript file
* Validate an OpenAPI spec whenever a route handler changes
* Post a notification when a session ends

A plugin declares hooks by adding a `hooks` (cross-agent) and/or `nativeHooks` (per-agent) field to `.tessl-plugin/plugin.json`.

**Learn more:** [Configuration files](/reference/configuration)

## Development workflow

1. **Develop locally** - Create and test your plugin in your project
   * See [Developing plugins locally](/create/developing-plugins-locally)
2. **Package as a plugin** - Structure your skills, rules, MCP servers, and hooks into a plugin format
   * Skills: [Creating skills](/create/creating-skills)
3. **Distribute** - Share your plugin with your team or the community
   * See [Distributing via registry](/distribute/distributing-via-registry)

## Quick links

<table data-view="cards"><thead><tr><th data-type="content-ref"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td><a href="/pages/4d1qxFXPDzWDnh0yqk7O">/pages/4d1qxFXPDzWDnh0yqk7O</a></td><td></td><td><a href="/files/LvjP0ckl5Rp0XSl5eDAh">/files/LvjP0ckl5Rp0XSl5eDAh</a></td></tr><tr><td><a href="/pages/H3TBZZO6LEPzRCvYou4X">/pages/H3TBZZO6LEPzRCvYou4X</a></td><td></td><td><a href="/files/LvjP0ckl5Rp0XSl5eDAh">/files/LvjP0ckl5Rp0XSl5eDAh</a></td></tr></tbody></table>

## Related documentation

* [Glossary](/reference/glossary) - Understanding plugins, skills, docs, and rules
* [Distributing via registry](/distribute/distributing-via-registry) - Publishing your plugins
* [Configuration files](/reference/configuration) - plugin configuration reference


# Developing plugins locally

Develop and test plugins locally

When creating plugins, you'll often want to test them locally before publishing to the Tessl Registry. Tessl lets you install plugins directly from your filesystem, making it easy to iterate on your plugin content and validate it works correctly with your agent.

## Why develop locally

* **Test before publishing** - Validate your plugin works correctly before sharing it
* **Iterate quickly** - Make changes and test them immediately without publishing
* **Create repository-specific plugins** - Build context that's specific to one codebase
* **Work with monorepos** - Create plugins for different parts of your monorepo that stay with the code

## Development workflow

### 1. Create your plugin

Create a new plugin with a skill

```bash
tessl skill new --name my-skill --path ./my-plugin/skills/my-skill
```

or a generic plugin structure:

```bash
tessl plugin new --name myworkspace/my-plugin --path ./my-plugin
```

### 2. Install locally

Install your plugin from the filesystem:

```bash
tessl install file:./my-plugin
```

The plugin is now available to your agent.

### 3. Test and validate

Test with your agent:

* **Skills**: Invoke the skill - confirm it executes correctly and produces expected results
* **Rules**: Ask agent to generate code - check it follows your guidance

Then validate the plugin structure:

```bash
tessl plugin lint ./my-plugin
tessl plugin pack --output ./dist ./my-plugin
```

### 4. Iterate

Edit content → reinstall → test → repeat.

## Plugin structure

Plugins can contain two types of content:

<pre><code><strong>&#x3C;your-plugin-name>/
</strong><strong>├── .tessl-plugin/
</strong>│     └── plugin.json
└── skills/&#x3C;your-skill-name>/SKILL.md
├── rules/             # Mandatory guidance - always loaded
│   └── standards.md
├── evals/
│     └── scenario-1/
│          ├── task.md
│          ├── criteria.json
│          └── scenario.json        # optional: fixtures, includes, setup scripts
│     └── scenario-2/
</code></pre>

* `.tessl-plugin/plugin.json` will have a reference to where your SKILL.md is located in relation to the .tessl-plugin root. For example, if the skill is in the root of the plugin folder, use `"skills" : [.]` or if it resides like above use: `"skills" : [./skills/<your-skill-name>]` where the actual name of the directory is specified.
* evals/ is only present if [scenarios](/improving-your-skills/overview-improving-skills-and-plugins) were generated
* `skills/<your-skill-name>/SKILL.md` is suggested structure, otherwise plugin.json will need a specific pointer

See [Configuration files](/reference/configuration#plugin-configuration) for complete `.tessl-plugin/plugin.json` reference.


# Overview

{% hint style="info" %}
**Takeaway** Know whether a skill is any good, and make it better. Use a review for fast feedback on the skill itself. Run an evaluation when you need proof it changes how an agent behaves, for example before you share it with your team.
{% endhint %}

This page is the place to start if you want to improve a skill. It walks through the two ways Tessl assesses skill quality, review and evaluation, and how you use each to make a skill better.

A review and an evaluation answer different questions.

|                |                                                                                                                                                                                                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Review**     | Reads the skill itself and scores how well it is written: whether the description is clear enough for an agent to load it at the right time, and whether the content is specific, actionable, and complete. Runs in under a minute and needs nothing but the skill. |
| **Evaluation** | Runs an agent on real tasks with and without the skill, then scores the difference. Tells you whether the skill actually changes what the agent does, not just whether it reads well. Takes longer and runs against a set of scenarios.                             |

## Building trust in a skill

Both reviews and evaluations help you assess different aspects of skill quality and guide improvement. In practice it helps to treat them as different levels of rigour, applied according to how much trust you need to build in the skill.

For example, if you are building a skill for yourself to use day to day, and you make quick ad hoc improvements as you go, a review may be enough. You will notice when a skill misfires and fix it, using review to guide your improvements.

If you are putting the skill into a shared repository to shape how other people's agents behave, you may decide this needs an extra level of rigour. An evaluation gets ahead of that: it proves the skill does what it claims, and the scenarios you generate are saved with the skill, so anyone who edits it later can re-run them and confirm it still works. They become a regression test for the skill.

Over the following pages we walk through both review and evaluation in depth.

## Quick start: Skill Optimizer

Alternatively, Tessl's [Skill Optimizer plugin](https://tessl.io/registry/tessl/skill-optimizer) runs this whole progression for you. It includes both review and evaluation and applies them as needed. Install it, point your agent at a skill, and it reviews the skill, applies quick win improvements, and escalates into evaluation when the skill is worth testing harder, generating evaluation scenarios, diagnosing failures, and re-running until the scores improve.

```bash
tessl install tessl/skill-optimizer
```

Then ask your agent to optimise the skill. Use Skill Optimizer when you want the full cycle handled for you. Use the commands directly, covered in the next pages, when you want control over each step.

## Next

* [Check a skill's quality using review](/improving-your-skills/reviewing-skills) - run a review, read the score, and apply fixes with `tessl review`.
* [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios) - generate scenarios and measure a skill's impact with `tessl eval`.
* To enforce a quality bar across your organisation, for example gating pull requests on a review score or scoring against your own standards, see [Codifying and enforcing your skill standards](/codifying-and-enforcing-your-skill-standards/overview).


# Check a skill's quality using review

Run a review to score how well a skill is written, read the result, and apply fixes.

{% hint style="info" %}
**Takeaway** Run a review to score how well a skill is written, read the result, and apply fixes. A review checks the skill itself in under a minute. It does not run the skill against any task.
{% endhint %}

`tessl review` reads a skill and scores it against Tessl's standard rubric. Use it for fast feedback while you are writing a skill, or to check one before you rely on it. At a high level it tells you whether the skill is well structured and formatted, and whether its description and content are clear. It does not tell you whether the skill improves what the agent produces; for that, see [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios).

A review runs through an agent that reads your whole skill bundle, not just `SKILL.md`. References, scripts, and assets are all in scope. It runs server-side: `tessl review run` polls until it finishes and prints the score, so a single command feels synchronous.

{% hint style="info" %}
All the steps on this page are also available through your agent. Install Tessl's Skill Optimizer to run reviews, apply fixes, and check scores without leaving your editor: `tessl install tessl/skill-optimizer`
{% endhint %}

{% hint style="info" %}
Still using `tessl skill review`? `tessl review` replaces it. See [Migrate from skill review](/improving-your-skills/migrate-from-skill-review).
{% endhint %}

## Run a review

```bash
tessl review run ./my-skill --workspace engteam
```

The command packs the skill, uploads it, runs the review pipeline, and prints the score when it finishes. Pressing Ctrl+C detaches from the run; the review continues server-side and you can check on it later.

`tessl review run` scores quality. To scan a skill for security issues instead, run `tessl review run security ./my-skill --workspace engteam` — see [Protect against insecure skills](/tutorials/protecting-against-insecure-skills).

```bash
# View the most recent run
tessl review view --last

# View a specific run by ID
tessl review view <run-id>

# List recent runs
tessl review list

# Re-run a failed review
tessl review retry --last
```

## Read the score

A review produces an overall score from 0 to 100, a weighted average of three components:

|                 |                                                                                                                                                                                                                 |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Validation**  | Deterministic checks that the skill follows the [Agent Skills specification](https://agentskills.io/specification): line count, frontmatter, schema, licence, and metadata. Each check passes, warns, or fails. |
| **Description** | An LLM judge on the description, scoring how likely an agent is to load the skill at the right time. Graded on specificity, completeness, trigger term quality, and distinctiveness.                            |
| **Content**     | An LLM judge on the `SKILL.md` body, scoring how well it guides the agent once loaded. Graded on conciseness, actionability, workflow clarity, and progressive disclosure.                                      |

Each component comes with specific recommendations, for example tightening a vague description or adding trigger terms a user would naturally say. As a rough guide:

* **90% and above**: the skill conforms well to best practices.
* **70% to 89%**: a good skill, with minor improvements available.
* **Below 70%**: likely needs work before you rely on it or share it.

Example output:

```
Validation Checks

  ✔ skill_md_line_count - SKILL.md line count is 9 (<= 500)
  ✔ frontmatter_valid - YAML frontmatter is valid
  ✔ name_field - 'name' field is valid: 'format-commit-messages'
  ✔ description_field - 'description' field is valid (70 chars)
  ✔ body_present - SKILL.md body is present

Overall: PASSED (0 errors, 0 warnings)

Judge Evaluation

  Content: 85%
    A tightly written, token-efficient body that gives clear and unambiguous
    guidance for a simple task. Adding one complete worked commit-message
    example would lift actionability from good to fully concrete.

    Suggestions:
      - Add a short worked example showing a complete commit message to
        make the guidance copy-paste concrete.

  Description: 90%
    A concise, well-triggered description that clearly states both capability
    and usage conditions with natural user-facing language.

Review Score: 90%
```

## Apply fixes

`tessl review fix` runs an improve-and-review loop: it reviews the skill, applies improvements, and re-reviews, up to `--max-iterations` times (default 3, maximum 10) or until the score reaches a target you set with `--threshold`.

```bash
tessl review fix ./my-skill --workspace engteam
```

It prompts before applying changes, since the loop edits the skill content directly. Pass `--yes` (or `-y`) to apply without a prompt, which is useful in CI or batch workflows. Review the changes before you publish.

## Score against your own standards

By default a review scores against Tessl's standard rubric, based on Anthropic's best practices. To score against your organisation's own bar instead, with your own judges and weights, run the review against a custom reviewer plugin. Pass a local directory or a `workspace/plugin` registry reference with `--review-plugin`:

```bash
tessl review run ./my-skill --workspace engteam --review-plugin <reviewer-plugin>
```

The same `--review-plugin` flag works with `tessl review fix`. To build a reviewer, see [Define your own quality standards](/codifying-and-enforcing-your-skill-standards/define-your-own-quality-standards).

## Gate a pull request on a review score

You can run the same review in CI and fail the build when the score is too low. Combine `--json` with `--threshold`:

```bash
tessl review run ./my-skill --workspace engteam --json --threshold 80
```

The command exits non-zero when the score is below the threshold, so the CI step fails. For a complete GitHub Actions workflow, see [Gate skill quality in CI](/codifying-and-enforcing-your-skill-standards/gate-skill-quality-in-ci).

## Reviews when you publish

You do not have to run a review by hand. When you publish a plugin to the registry, Tessl lints and reviews it automatically, and the score appears on the registry. See [Distributing via registry](/distribute/distributing-via-registry).

## Prerequisites

`tessl review run` and `tessl review fix` need authentication and a workspace. The companion commands `view`, `list`, and `retry` need authentication only.

* Authentication, either a logged-in session, confirmed with `tessl whoami` and started with `tessl login`, or a `TESSL_TOKEN` API key in the environment. Any workspace member can run a review.
* A workspace to attribute the run to, passed with `--workspace`. It is required when `--json` is set, because a non-interactive run cannot prompt for one.

## Next

* [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios) - measure whether a skill changes an agent's output, not just how it reads.
* [Codifying and enforcing your skill standards](/codifying-and-enforcing-your-skill-standards/overview) - build a custom rubric, set an organisation-wide quality bar, and gate pull requests on it.


# Migrate from skill review to Tessl Review

How to switch from tessl skill review to Tessl Review, and what to expect

Tessl Skill Review lets you quickly evaluate the quality of a skill against best practices, providing scores on validation, content and description quality. It is being superseded by Tessl Review.

This page explains what is changing, the impact on how skill quality is scored, and how to switch.

{% hint style="warning" %}
**Tessl Skill Review is deprecated.** It still works and remains available through July 2026, after which it will be removed. Switch to Tessl Review before then.
{% endhint %}

## What's changed, and why

Tessl Review brings skill review into Tessl's wider agentic evaluation architecture.

Tessl Skill Review evaluated individual `SKILL.md` files in a single pass against a fixed rubric. With Tessl Review, the review runs through an agent that works across the whole skill and its connected files, and reasons over multiple steps to reach its result.

This allows us to introduce several improvements:

* **Full-bundle review.** The review reads your entire skill, not just `SKILL.md`. References, scripts, and assets are all in scope, so nothing in your skill is missed.
* **Customisable rubric.** Fork the default quality scoring rubric and define what "good" means for your organisation. Set it as your workspace default and every review uses your standard.
* **Review history.** Reviews are stored and queryable with `tessl review list` and `tessl review view`, so you have a persistent record of quality over time.
* **Built for CI.** `--json` and `--threshold` gate pull requests on a review score, exactly as before.

{% hint style="info" %}
**Scores returned by Tessl Review may differ slightly from skill review.** Because the review now runs as an agent over your full skill bundle rather than a single pass, Tessl Review scores are more accurate and more reflective of real skill quality. And because the agent reasons over multiple steps, it can reach a clearer, better-founded conclusion than skill review's single pass.
{% endhint %}

The shift to Tessl Review also makes it easier for us to expand what reviews can do. You can now run a security scan directly from the CLI with `tessl review run security` — see [Protect against insecure skills](/tutorials/protecting-against-insecure-skills). Coming soon:

* Choose the model a review runs on.

## What changes on the CLI

{% hint style="info" %}
**Both tools now require authentication.** To bring skill review in line with Tessl Review, running a review with either `tessl skill review` or `tessl review run` now requires you to be signed in. Sign in with `tessl login`, or set a `TESSL_TOKEN` API key in CI.
{% endhint %}

Most workflows map across directly:

| Workflow                           | Deprecated (`tessl skill review`)          | New (Tessl Review)                                |
| ---------------------------------- | ------------------------------------------ | ------------------------------------------------- |
| Run a review                       | `tessl skill review <path>`                | `tessl review run <path>`                         |
| Review one skill from a plugin     | `tessl skill review --skill <name> <path>` | Point `tessl review run` at the skill's directory |
| Improve a skill automatically      | `tessl skill review --optimize`            | `tessl review fix`                                |
| Gate CI on a score                 | `--threshold <score>`                      | `--threshold <score>` (unchanged)                 |
| Output machine-readable results    | `--json`                                   | `--json` (unchanged)                              |
| Limit improvement iterations       | `--max-iterations` (with `--optimize`)     | `--max-iterations` (on `tessl review fix`)        |
| Auto-apply fixes without prompting | `--yes` (with `--optimize`)                | `--yes` (on `tessl review fix`)                   |
| Attribute a run to a workspace     | -                                          | `--workspace` (new)                               |
| Score against a custom rubric      | -                                          | `--review-plugin` (new)                           |
| Label a run for history            | -                                          | `--label` (new)                                   |
| Force a fresh run                  | -                                          | `--force` (new)                                   |

What stays the same:

* The default rubric (Anthropic best practices) is unchanged. Reviews still score the same three components out of the box: validation, description, and content.
* Reviews still produce a 0-100 score.
* `--json` with `--threshold` still gates CI through the exit code.
* The GitHub Action still drives reviews in CI.

What's new to know:

* **Authentication.** `tessl review run` and `tessl review fix` run against your workspace, so you need to be signed in (`tessl login`, or a `TESSL_TOKEN` API key in CI) and run against a workspace (pass `--workspace`, or pick one when prompted). Any workspace member can run reviews.
* **Asynchronous by default.** A review runs server-side. `tessl review run` polls until it finishes and then prints the score, so a single command still feels the same. Press Ctrl+C to detach and pick the run back up later with `tessl review view --last`.

## Migrating your CI

Replace the `tessl skill review` step with `tessl review run`, add a workspace, and keep your threshold:

```sh
tessl review run ./my-skill --workspace <workspace> --json --threshold 80
```

`--workspace` is required when `--json` is set, because a non-interactive run cannot prompt for one. In CI, authenticate with a `TESSL_TOKEN` repository secret. For a complete GitHub Actions workflow, see [Review, lint & publish with GitHub Actions](/distribute/review-and-publish-with-github-actions).

## Next steps

* [Check a skill's quality using review](/improving-your-skills/reviewing-skills) - the full guide to running reviews, customising the rubric, and gating CI
* [`tessl review run` reference](/reference/cli-commands#tessl-review-run) - all flags
* [Review, lint & publish with GitHub Actions](/distribute/review-and-publish-with-github-actions) - run reviews on pull requests


# Prove a skill works using evaluation

Generate scenarios, run an evaluation, and read the score difference to see whether a skill actually changes what an agent produces.

{% hint style="info" %}
**Takeaway** Generate scenarios from a skill, run an evaluation, and read the score difference to see whether the skill actually changes what an agent produces. Scenarios are saved with the skill, so they become a regression test you re-run after every change.
{% endhint %}

An evaluation runs an agent on real tasks twice, once without the skill and once with it, then scores the difference. That difference is the skill's value: proof it changes what the agent does, not just that it reads well. Where a review checks the skill itself, an evaluation measures its effect.

Evaluation is more rigorous than review and takes longer to set up and run. Reach for it when you need confidence a skill works, for example before you publish it or share it into a repository where you will not see how others' agents use it.

You can evaluate a single skill against generated scenarios, or evaluate context files against real tasks taken from your codebase's commit history. Both run through the same `tessl eval` commands.

{% hint style="info" %}
All the steps on this page are also available through your agent. Install Tessl's Skill Optimizer to generate scenarios, run evaluations, and improve skills without leaving your editor: `tessl install tessl/skill-optimizer`
{% endhint %}

## Skills are evaluated inside Tessl plugins

A Tessl plugin is a structure that bundles the skills, rules, and documentation an agent needs for an area of context, packaged so it can be versioned and shared. An evaluation generates scenarios and produces results, and a plugin is the natural place to keep them with the skill they belong to.

For this reason `tessl eval run` expects the generated scenarios to live inside the plugin, and the shorthand `tessl eval run ./my-skill` expects a directory containing a `.tessl-plugin/plugin.json`. If you have a standalone skill, import it into a plugin first:

```bash
tessl skill import ./my-skill
```

## Generate scenarios

Scenarios are the tasks an agent is assessed against. Generate them from the plugin:

```bash
tessl scenario generate ./my-skill
```

Each generated scenario is put through a feasibility check on the server. Only scenarios that pass are saved, so the generator gives you tests that actually exercise the skill rather than filler.

`--count` sets how many scenarios to target, and defaults to 3. Pass a higher number to cover more of what the skill claims to do. For a narrowly scoped skill the generator may return fewer than requested, because it will not save scenarios that fail the feasibility check.

```bash
tessl scenario generate ./my-skill --count 5
```

Generation runs server-side. Check progress with `tessl scenario list --mine`, then download the scenarios once it completes:

```bash
tessl scenario download --last
```

`tessl scenario download` writes scenarios into an `evals/` directory relative to your current directory. Override the location with `--output`, and choose whether new scenarios merge with or replace existing ones with `--strategy merge` (the default) or `--strategy replace`. Because `tessl eval run ./my-skill` looks for `evals/` inside the plugin directory, run the download from the plugin root, or move the folder there afterwards.

The scenarios are saved with the skill, so anyone who changes it later can re-run the same scenarios and confirm it still behaves as expected.

You do not have to generate scenarios. You or your agent can write them by hand instead, as long as they sit in the plugin's `evals/` directory, one scenario per subdirectory. See [File formats](#file-formats) for the structure.

### Generate scenarios from your codebase

Instead of generating scenarios from a skill, you can build them from real changes in your repository, so the tasks reflect work your team actually does. Point `tessl scenario generate` at a repository with commit hashes or PR numbers:

```bash
# From commits
tessl scenario generate org/repo --commits abc123,def456 --workspace engteam

# From pull requests
tessl scenario generate org/repo --prs 42,107 --workspace engteam
```

Tessl analyses each diff and reconstructs the intent of the change as a task brief and a scoring rubric. The starting state has your context files stripped out, so the agent solves the task without them.

`--context` tells Tessl which files are context files. The patterns are saved in each scenario as the codebase fixture's exclude list. When omitted, Tessl excludes `*.mdc`, `*.md`, `tile.json`, `.tessl-plugin/plugin.json`, `tessl.json`, and `.tessl/` by default.

To browse recent commits and choose which to turn into scenarios, use `tessl repo select-commits org/repo`. It accepts `--keyword`, `--author`, `--since` / `--until`, and `--count`, and prints a table of commit hashes to pass to `generate`.&#x20;

{% hint style="info" %}
Your GitHub or GitLab account must be connected in workspace settings.
{% endhint %}

Because these scenarios start from a state with your context files stripped out, pass `--context` again at run time with a glob matching those files. This adds a with-context variant on top of the baseline so you can measure the delta:

```bash
tessl eval run ./my-skill/evals/ --context 'src/**/*.knowledge.md'
```

Match the `--context` glob to the files each scenario excludes. With no `--context`, only the baseline runs.

## Run an evaluation

```bash
tessl eval run ./my-skill
```

The agent solves each scenario twice, without the skill and with it, and a judge scores both against a per-scenario rubric. The run reports the baseline score, the with-skill score, and the difference between them. Runs can take a while; pressing Ctrl+C detaches and the run continues server-side.

Label a run to find it again later:

```bash
tessl eval run ./my-skill --label "baseline"
```

```bash
# List your recent runs
tessl eval list --mine

# View a run, including the per-scenario breakdown
tessl eval view --last
tessl eval view abc123

# Retry a failed run
tessl eval retry abc123
```

## Read the result

A run produces output like this:

```
Eval Results: baseline

Agent:     claude:deepseek-v4-flash
Variants:  baseline, with context
Status:    Completed

Scenario: Commit message formatting for complex refactor

  Baseline
  Check                         Score
  ------------------------------------------
  Conventional Commits format   30/30  (100%)
  Valid type                    0/20   (0%)
  Subject line <= 72 chars      0/30   (0%)
  Blank line separator          20/20  (100%)
  Total                         50/100  (50%)

  With context
  Check                         Score
  ------------------------------------------
  Conventional Commits format   30/30  (100%)
  Valid type                    20/20  (100%)
  Subject line <= 72 chars      30/30  (100%)
  Blank line separator          20/20  (100%)
  Total                         100/100  (100%)

Scenario: Type selection for a small fix

  Baseline
  Total                         90/100  (90%)

  With context
  Total                         95/100  (95%)

Summary
  Scenarios: 3 completed
  Baseline avg:      71%
  With context avg:  92%
```

The score difference tells you what the skill is worth:

* **A large positive difference** means the skill reliably moves the agent toward the right behaviour.
* **Little or no difference** means the agent already did the task well without the skill, or the skill is not landing.
* **A small negative difference** is usually normal model variance, not evidence the skill is harmful.
* **A large or consistent negative difference** is a real sign the skill is confusing the agent or pushing it toward unhelpful behaviour, and the content needs work.

Read the per-scenario breakdown rather than just the headline average, since a strong result on one scenario can hide a weak one on another.

### Outcome and activation

A standard evaluation measures **outcome**: with the context forced on, does the agent produce better work against the rubric. It does not test whether the agent would have loaded the skill on its own.

To measure **activation**, whether the agent picks up the skill itself without being told to, add `--skip-forced-context-activation`. A skill can score well on outcome but fail to activate, which means it would not help in practice because the agent never reaches for it.

```bash
# Measure activation only: don't force the context, and skip outcome scoring
tessl eval run ./my-skill --skip-forced-context-activation --skip-scoring
```

The two flags are independent: `--skip-forced-context-activation` stops forcing the context so activation can be observed, and `--skip-scoring` skips rubric scoring. Used together they give a pure activation check.

Example activation output:

```
Activation Results

Agent:     claude:deepseek-v4-flash
Variants:  baseline, with context
Status:    Completed

Injected context
Plugin: format-commit-messages@0.1.0

Scenario                                            Activated skills
--------------------------------------------------------------------
1. Conventional Commits format and type selection   format-commit-messages
2. Commit message formatting for complex refactor   format-commit-messages
3. Conventional Commits with multi-line message     —
```

`—` in the Activated skills column means the skill was not selected by the agent on its own. A skill that does not activate is a description problem, best fixed with a [review](/improving-your-skills/reviewing-skills). A skill that activates but does not improve the outcome is a content problem to fix in the skill body.

## Choose how rigorous to be

Evaluation is a toolkit, not a single fixed test. Scale the rigour to how much confidence you need.

* **More scenarios.** Generate a higher `--count` to cover more of what the skill claims to do.
* **Repeated runs.** An evaluation runs a real agent, and agents are non-deterministic, so a single run can mislead. Pass `--runs` (or `-n`) to run each scenario several times and average out the variance. Worth doing before you publish.
* **Different agents.** Run the evaluation against more than one agent with `--agent` to check the skill holds up across the models your team uses.
* **Quality filter.** Pass `--quality-check` to exclude scenarios the platform judges low-feasibility, rubric-leaking, or low-signal at run time, a stricter filter than the one applied at generation.
* **Skip the baseline.** Pass `--skip-baseline` to run only the with-context variant when you do not need the comparison.
* **Override the scorer.** Pass `--scorer-agent` to score with a different agent from the one solving the tasks.

## Passing secrets to an evaluation

Some scenarios need external credentials, for example an API key or a database URL. The `--env-file` flag encrypts a local `.env` file client-side and injects the variables into the eval sandbox, where setup scripts and the agent inherit them:

```bash
tessl eval run ./my-skill --env-file ./secrets.env
```

The file uses standard `KEY=VALUE` lines; blank lines and `#` comments are ignored. The CLI rejects reserved keys at submit time, including `LITELLM_ADMIN_KEY`, `LITELLM_MASTER_KEY`, `UPLOAD_WORKSPACE`, `DOWNLOAD_WORKSPACE`, and any key prefixed `AWS_`, `S3_`, `DAYTONA_`, or `RECIPE_RUN_`. Rename conflicting keys before running.

## Choosing an agent

By default an evaluation runs against `claude:deepseek-v4-flash`. Choose a different agent with `--agent`, and run `tessl eval run --list-agents` to print the current list. An evaluation takes a single `--agent`; to compare models, run it once per model.

```bash
tessl eval run ./my-skill --agent claude:claude-opus-4-8
```

{% tabs %}
{% tab title="Claude" %}

| Model             | `--agent` value            |
| ----------------- | -------------------------- |
| Claude Fable 5    | `claude:claude-fable-5`    |
| Claude Opus 4.8   | `claude:claude-opus-4-8`   |
| Claude Opus 4.7   | `claude:claude-opus-4-7`   |
| Claude Opus 4.6   | `claude:claude-opus-4-6`   |
| Claude Sonnet 4.6 | `claude:claude-sonnet-4-6` |
| Claude Opus 4.5   | `claude:claude-opus-4-5`   |
| Claude Sonnet 4.5 | `claude:claude-sonnet-4-5` |
| Claude Haiku 4.5  | `claude:claude-haiku-4-5`  |
| {% endtab %}      |                            |

{% tab title="Other hosted models" %}

| Model                       | `--agent` value                 |
| --------------------------- | ------------------------------- |
| Deepseek V4 Flash (default) | `claude:deepseek-v4-flash`      |
| Deepseek V4 Pro             | `claude:deepseek-v4-pro`        |
| Kimi K2.6                   | `claude:kimi-k2.6`              |
| Kimi K2.7 Code              | `claude:kimi-k2.7-code`         |
| GLM 5.2                     | `claude:glm-5.2`                |
| Qwen3.7 Plus                | `claude:qwen3.7-plus`           |
| MiniMax M3                  | `claude:minimax-m3`             |
| MiniMax M2.7                | `claude:minimax-m2.7`           |
| GPT OSS 20B                 | `claude:gpt-oss-20b`            |
| GPT OSS 120B                | `claude:gpt-oss-120b`           |
| Nemotron 3 Ultra            | `claude:nemotron-3-ultra-nvfp4` |
| {% endtab %}                |                                 |

{% tab title="Codex" %}

| Model         | `--agent` value       |
| ------------- | --------------------- |
| GPT 5.5       | `codex:gpt-5.5`       |
| GPT 5.4       | `codex:gpt-5.4`       |
| GPT 5.4 Mini  | `codex:gpt-5.4-mini`  |
| GPT 5.4 Nano  | `codex:gpt-5.4-nano`  |
| GPT 5 Codex   | `codex:gpt-5-codex`   |
| GPT 5.3 Codex | `codex:gpt-5.3-codex` |
| GPT 5.2 Codex | `codex:gpt-5.2-codex` |
| {% endtab %}  |                       |

{% tab title="Tessl" %}

| Model             | `--agent` value                |
| ----------------- | ------------------------------ |
| Claude Fable 5    | `tessl:claude-fable-5`         |
| Claude Opus 4.8   | `tessl:claude-opus-4-8`        |
| Claude Opus 4.7   | `tessl:claude-opus-4-7`        |
| Claude Opus 4.6   | `tessl:claude-opus-4-6`        |
| Claude Sonnet 4.6 | `tessl:claude-sonnet-4-6`      |
| Claude Opus 4.5   | `tessl:claude-opus-4-5`        |
| Claude Sonnet 4.5 | `tessl:claude-sonnet-4-5`      |
| Claude Haiku 4.5  | `tessl:claude-haiku-4-5`       |
| Kimi K2.6         | `tessl:kimi-k2.6`              |
| Deepseek V4 Flash | `tessl:deepseek-v4-flash`      |
| GLM 5.2           | `tessl:glm-5.2`                |
| Kimi K2.7 Code    | `tessl:kimi-k2.7-code`         |
| Qwen3.7 Plus      | `tessl:qwen3.7-plus`           |
| MiniMax M3        | `tessl:minimax-m3`             |
| Deepseek V4 Pro   | `tessl:deepseek-v4-pro`        |
| MiniMax M2.7      | `tessl:minimax-m2.7`           |
| GPT OSS 20B       | `tessl:gpt-oss-20b`            |
| GPT OSS 120B      | `tessl:gpt-oss-120b`           |
| Nemotron 3 Ultra  | `tessl:nemotron-3-ultra-nvfp4` |
| {% endtab %}      |                                |
| {% endtabs %}     |                                |

## Evaluations when you publish

Publishing a plugin to the registry runs an evaluation as part of publishing, and the results appear on the registry. The evaluation is optional: pass `--skip-evals` to publish without it, or `--with-scenario-quality-check` to apply the quality filter to the publish-time run. See [Distributing via registry](/distribute/distributing-via-registry).

## Prerequisites

* Authentication, either a logged-in session, confirmed with `tessl whoami` and started with `tessl login`, or a `TESSL_TOKEN` API key in the environment.
* Workspace access at Publisher level or above.
* A Tessl project, so Tessl knows which repository an evaluation belongs to and your results stay tied to your codebase over time. Create one with `tessl project create <name> --workspace engteam`, link an existing one with `tessl project link`, and repair a broken link with `tessl project repair`. See [Projects overview](/projects/overview).

A plugin that holds evaluations looks like this on disk:

```
my-plugin/
├── .tessl-plugin/
│   └── plugin.json      workspace, name, version
├── skills/<name>/SKILL.md
├── tessl.json           links the directory to a Tessl project
└── evals/
    └── scenario-name/
        ├── task.md          the task brief the agent sees
        ├── criteria.json    the scoring rubric
        └── scenario.json    fixture and include declarations
```

## File formats

### task.md

Free-form markdown, and the only file the agent sees. Typically structured with problem, expected behaviour, and acceptance criteria sections. Edit it freely before running.

### criteria.json

Defines how a solution is scored, as a weighted checklist:

```json
{
  "context": "Brief description of what is being evaluated.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "fixes_syntax_error",
      "description": "The solution adds the missing closing parenthesis.",
      "max_score": 1,
      "category": "INTENT"
    }
  ]
}
```

Each checklist item carries a `category`: `INTENT`, `DESIGN`, `MUST_NOT`, `MINIMALITY`, `REUSE`, `INTEGRATION`, or `EDGE_CASE`. The score is the sum of awarded scores over the sum of maximum scores, as a percentage, and the grader can award partial credit.

### scenario.json

Optional. Declares fixtures, included files, and setup scripts. A skill scenario can simply list `include` paths to copy into the working directory. A codebase scenario carries a commit fixture with the repository URL, the starting commit, and the context exclude patterns. See the [configuration reference](/reference/configuration) for the full schema.

## Next

* [Codifying and enforcing your skill standards](/codifying-and-enforcing-your-skill-standards/overview) - set an organisation-wide quality bar and enforce it.
* [Troubleshooting reviews and evaluations](/improving-your-skills/troubleshooting-reviews-and-evals) - what to do when a run fails or scores look wrong.


# Troubleshooting reviews and evaluations

Most problems with reviews and evaluations come down to a few causes. Work through these when something does not behave as expected.

{% hint style="info" %}
**Takeaway** Most problems with reviews and evaluations come down to a few causes: scenarios in the wrong place, missing permissions, a skill that never activated, or normal model variance read as a real result. Work through the questions below when something does not behave as expected.
{% endhint %}

## Why does my evaluation say "no scenarios found"?

`tessl scenario download` writes scenarios into an `evals/` directory relative to your current directory, but `tessl eval run <path>` looks for `evals/` inside the plugin directory you point it at. If you downloaded scenarios somewhere else, they are not where the run expects them.

Run `tessl scenario download` from inside the plugin root, the directory containing `.tessl-plugin/`, or pass the location explicitly:

```bash
tessl scenario download --output <plugin-root>/evals
```

## Why do I only see baseline results, with no "with context" column?

The evaluation completed, but every scenario shows a baseline score and nothing for the skill. This means the run could not find the skill to inject, usually because the plugin layout is wrong.

Check that `evals/`, `.tessl-plugin/`, and the skill directory all sit under the same plugin root, and that `skills[]` in `plugin.json` points at the skill directory correctly, relative to the plugin root.

## Why does my run fail on permissions?

Evaluations require at least **publisher** access to the workspace. Member access is not enough to run `tessl eval run` or `tessl scenario generate`. A review needs only member access, so a skill you can review may still fail to evaluate.

Confirm who you are logged in as with `tessl whoami`, and check your access to the workspace the plugin is attributed to in `.tessl-plugin/plugin.json`.

## Why do scores look worse with the skill than without?

A small negative difference is usually normal model variance, not evidence the skill is harmful. An evaluation runs a real agent, so results vary from run to run. Run each scenario several times with `--runs` and read the overall pattern rather than a single result. A large or consistent negative difference is a real signal that the skill is confusing the agent, and the content needs work.

## Why does the skill make no difference at all?

If the "with context" score sits at zero improvement across repeated runs, the skill most likely never activated, so the agent never used it. That is a different problem from variance. Check activation: run `tessl review run` and look at the description score, and make sure the skill's `description` states clear trigger conditions for when it should be used. See [Check a skill's quality using review](/improving-your-skills/reviewing-skills).

## A scenario keeps failing to complete

It is normal for an agent not to solve every scenario on every attempt. Retry the run, or adjust the scenario if it is consistently failing for the wrong reason.

```bash
tessl eval retry abc123
tessl eval retry --last
```

## Still using `tessl skill review`?

`tessl skill review` is the local, unauthenticated review that ran before `tessl review`. It has been replaced. If you are still on it, see [Migrate from skill review](/improving-your-skills/migrate-from-skill-review) for what changed and how to move across.

## Getting help

If none of the above surfaces the cause, share the output of `tessl doctor --json` when you reach out, since it reports your authentication status. See [Giving feedback](/support/giving-feedback).


# Overview

Gate skill quality automatically and define your organisation's standard for what a good skill looks like.

{% hint style="info" %}
**Takeaway** Keep poor-quality skills out of your repository. Set the bar for what "good" means, then gate it in CI so skills that fall short do not get merged.
{% endhint %}

When a team shares skills, quality stops being a personal matter. A weak skill that one person tolerates becomes everyone's problem once it is in the shared repository, shaping how every agent on the team behaves. This section is about holding a quality line automatically, so you do not depend on everyone remembering to check.

There are two parts to it:

* **Gate on a review score.** Run a review in CI and fail the build when a skill scores below your bar, so substandard skills never merge. See [Gate skill quality in CI](/codifying-and-enforcing-your-skill-standards/gate-skill-quality-in-ci).
* **Define your own bar.** The default rubric scores against general best practices. Fork it to encode what your organisation cares about, and apply it to every review. See [Define your own quality standards](/codifying-and-enforcing-your-skill-standards/define-your-own-quality-standards).

This section covers protecting a repository from low-quality skills. It does not cover managing your wider skill estate, surveying what is installed across your organisation, or org-level policy; those are separate capabilities.

## Next

* [Gate skill quality in CI](/codifying-and-enforcing-your-skill-standards/gate-skill-quality-in-ci) - run reviews on pull requests and block merges below your threshold.
* [Define your own quality standards](/codifying-and-enforcing-your-skill-standards/define-your-own-quality-standards) - build a custom rubric and apply it to every review.


# Gate skill quality in CI

Run a review on every pull request and fail the build when a skill scores below your threshold.

{% hint style="info" %}
**Takeaway** Run a review on every pull request and fail the build when a skill scores below your threshold. Skills that fall short of the bar never merge.
{% endhint %}

A review tells one person whether a skill is good. Gating in CI applies that check to everyone, automatically, so a substandard skill cannot reach your shared repository in the first place.

## Fail a build below a threshold

Pass `--threshold` to exit non-zero when a review score falls below your bar:

```bash
tessl review run ./my-skill --workspace engteam --threshold 80
```

`--threshold` takes a 0-100 integer. The default is 0, which never fails. Any value above 0 causes the command to exit non-zero - and fail the CI step - when the score falls below it.

Add `--json` when you need machine-readable output, for example in a script that reads the score programmatically:

```bash
tessl review run ./my-skill --workspace engteam --json --threshold 80
```

`--workspace` is required when `--json` is set, because a non-interactive run cannot prompt for one. In practice, always pass `--workspace` in CI regardless.

You can also re-check an existing run against a threshold without starting a new review:

```bash
tessl review view <run-id> --json --threshold 80
```

## Authenticating in CI

A review runs against your workspace, so CI needs to authenticate without an interactive login. Create an API key for your workspace:

```bash
tessl api-key create --workspace engteam
```

Set the key as a repository secret named `TESSL_TOKEN`. The CLI and the Tessl GitHub Action both read it from that variable.

## Run it on pull requests

Tessl publishes a GitHub Action that installs the CLI and runs this gate on pull requests, so you do not have to wire up the CLI by hand. For the complete workflow, see [Review, lint & publish with GitHub Actions](/distribute/review-and-publish-with-github-actions).

## Next

* [Define your own quality standards](/codifying-and-enforcing-your-skill-standards/define-your-own-quality-standards) - gate against your organisation's own rubric, not just the default.
* [Check a skill's quality using review](/improving-your-skills/reviewing-skills) - full reference for `tessl review run`, score interpretation, and applying fixes.


# Define your own quality standards

Fork the default review rubric to encode your organisation's quality bar, then apply it to every review.

{% hint style="info" %}
**Takeaway** The default review rubric scores against general best practices. Fork it to encode what your organisation cares about, then apply it everywhere: local reviews, automated fixes, and your CI gate.
{% endhint %}

The default rubric is a good baseline, but it does not know your conventions. If your team has its own bar for what a skill must do, a custom reviewer plugin lets you define it once and apply it consistently.

## Build a reviewer

The `create-review-plugin` skill from [`tessl/review-plugin-creator`](https://tessl.io/registry/tessl/review-plugin-creator) scaffolds a reviewer plugin for you. Install it, then ask your agent to create a reviewer:

```bash
tessl install tessl/review-plugin-creator
```

A reviewer plugin is a standard Tessl plugin with this layout:

```
<plugin-name>/
├── .tessl-plugin/
│   └── plugin.json
└── skills/skill-reviewer/
    ├── SKILL.md
    ├── references/
    │   ├── config.json
    │   └── rubrics/
    │       └── <judge-name>.json   (one per judge)
```

`config.json` sets the weight each judge contributes to the final score, plus a `validation_weight` for the deterministic validation pass. All weights must sum to 1.0:

```
validation_weight + sum of judge weights = 1.0
```

Set `validation_weight` to `0.0` to exclude validation from scoring. Validation still runs as a gate but does not affect the numeric score.

Each rubric file defines one judge: what it evaluates (`evaluation_target`), a scoring scale, and a set of dimensions. Dimension weights within a single rubric also sum to 1.0. The `create-review-plugin` skill validates the finished plugin by running `tessl review run` against a test skill, so you catch misconfigured weights before you use it.

The [default rubric](https://github.com/tesslio/product-plugins/tree/main/default-skill-review) is worth forking rather than building from scratch. It scores a skill's description on specificity, completeness, trigger term quality, and distinctiveness, and the content on conciseness, actionability, workflow clarity, and progressive disclosure. Forking keeps those dimensions and lets you adjust weights, remove ones that do not apply, or add judges of your own.

## Use a reviewer

Point a review at your reviewer with `--review-plugin`, passing either a local directory or a `workspace/plugin` registry reference:

```bash
tessl review run ./my-skill --workspace engteam --review-plugin <reviewer-plugin>
```

The same flag works with `tessl review fix` and in your CI gate:

```bash
tessl review run ./my-skill --workspace engteam --review-plugin <reviewer-plugin> --threshold 80
```

Pass `--review-plugin` explicitly on each run, or set your reviewer as the workspace default in workspace settings so every review in that workspace uses your standard automatically.

## Next

* [Gate skill quality in CI](/codifying-and-enforcing-your-skill-standards/gate-skill-quality-in-ci) - enforce your rubric automatically on pull requests.


# Distributing via registry

Distribute, share, and maintain plugins through the Tessl Registry

Once you've created and published a plugin, you'll need to share it with your team, keep it updated, and manage its lifecycle. This guide covers the common tasks for managing published plugins.

## Sharing with your team

Add members to your workspace so they can access your private plugins:

```bash
tessl workspace add-member --username <tessl-username> --role member --workspace myworkspace
```

The `member` role gives read-only access to plugins. See [Roles](/administrators/roles) for more information about workspace roles and permissions.

To verify members have been added:

```bash
tessl workspace list-members myworkspace
```

## Installing plugins in projects

Team members can install your plugin in their projects:

```bash
tessl install myworkspace/your-plugin
```

Or search for it:

```bash
tessl search your-plugin
```

Private plugins appear in search results for workspace members just like public plugins.

To install a specific version:

```bash
tessl install myworkspace/your-plugin@1.0.0
```

## Updating documentation

When your library or service changes, update the plugin to keep documentation current.

### For automated plugins

If you used automated generation from a repository:

1. Merge code changes to your repository
2. Navigate to the Tessl interface and regenerate the plugin
3. Review new evaluation results
4. Publish the updated version

See [Autogenerating documentation](broken://pages/igFZovBVTWCexNCUgNsz) for details on the automated workflow.

### For manual plugins

If you created the plugin manually:

1. Edit your documentation files
2. Increment the version in `.tessl-plugin/plugin.json` (following [semantic versioning](https://semver.org/))
3. Validate with `tessl plugin lint`
4. Publish with `tessl plugin publish`

**Version guidelines:**

* **Patch** (1.0.0 → 1.0.1): Bug fixes, typo corrections
* **Minor** (1.0.0 → 1.1.0): New content, backward-compatible changes
* **Major** (1.0.0 → 2.0.0): Restructuring, breaking changes

Users can update to the latest version:

```bash
tessl install myworkspace/your-plugin
```

## Archiving plugins

To remove a plugin from search results without deleting it:

```bash
tessl plugin archive --plugin myworkspace/your-plugin@1.0.0 --reason "replaced by new library"
```

Archived plugins:

* No longer appear in search results
* Cannot be installed by new users
* Remain accessible to projects that already have them installed
* Can be restored by contacting support

Use archiving when:

* A library is deprecated but still used by some projects
* You're migrating to a new plugin and want to phase out the old one
* The plugin is outdated but may still be needed for reference

## Unpublishing plugins

To completely remove a plugin within ***2 days*** of upload:

```bash
tessl plugin unpublish --plugin myworkspace/your-plugin@1.0.0
```

**Important:** Unpublishing is only available within 2 days of the original publish. After that, use archiving instead.

Unpublished plugins are completely removed and cannot be recovered.

## Monitoring plugin usage

Track how your plugins are being used:

1. Navigate to the [Tessl Registry](https://tessl.io/registry)
2. Log in and select your workspace
3. View your plugins to see usage statistics and install counts

This helps you understand which plugins are most valuable to your team.

## Best practices

* **Update regularly** - Keep documentation in sync with code changes
* **Use semantic versioning** - Help users understand the impact of updates
* **Archive deprecated plugins** - Guide users to replacement plugins
* **Monitor usage** - Focus maintenance effort on widely-used plugins
* **Document breaking changes** - Communicate major version updates to your team

## Related

* [Autogenerating documentation](broken://pages/igFZovBVTWCexNCUgNsz) - Automated plugin creation
* [Workspaces](/reference/workspaces) - Understanding workspaces and permissions
* [Configuration files](/reference/configuration) - Complete `.tessl-plugin/plugin.json` reference


# Sharing with your team and publicly

Making your plugins publicly discoverable in the Tessl Registry

Plugins can be shared with your team or with the entire internet. This is controlled by the `private` field in your plugin's [`.tessl-plugin/plugin.json`](https://docs.tessl.io/distribute/pages/wpdogFLQtCeEnXfbelvK#plugin.json) file.

## Understanding public vs private plugins

### Private plugins (`"private": true`) - Default

**Shared only with your team:**

* Only accessible to workspace members
* Not discoverable in public searches
* Useful for proprietary code, internal standards, company-specific content
* **Team sharing:** [Add members to your workspace](/reference/workspaces#add-member) to give them access

If you don't specify the `private` field in your `.tessl-plugin/plugin.json`, it defaults to `true` (private).

### Public plugins (`"private": false`)

**Shared with the entire internet:**

* Anyone can discover and install them via the Tessl Registry
* Appear in search results and on your workspace's public profile
* Useful for open source libraries, shared standards, community resources
* **Cannot be made private again once published**

## Making a plugin public

**Warning:** Once you make a plugin public, you cannot make it private again. Use this with caution.

To make a plugin publicly discoverable, set `"private": false` in your [`.tessl-plugin/plugin.json`](https://docs.tessl.io/distribute/pages/wpdogFLQtCeEnXfbelvK#plugin.json):

```json
{
  "name": "myworkspace/my-plugin",
  "version": "1.0.0",
  "description": "My public plugin",
  "private": false,
  "skills": "skills"
}
```

Then publish (or republish) your plugin:

```sh
tessl plugin publish
```

Your plugin is now publicly discoverable in the [Tessl Registry](https://tessl.io/registry) and accessible to anyone on the internet.

## Best practices

* **Start private** - Develop and test plugins privately before making them public
* **Use semantic versioning** - Especially important for public plugins that others depend on
* **Document thoroughly** - Include clear README files and usage examples
* **Validate before publishing** - Run `tessl plugin lint` to check for issues

## Related documentation

* [Distributing via registry](/distribute/distributing-via-registry) - How to publish plugins
* [Configuration files](/reference/configuration) - plugin.json field reference
* [Creating plugins](/create/creating-plugins) - How to create your own plugins


# Rollout to your repositories

Connect Tessl to your codebase to automatically generate, evaluate, and optimize context!

## Apply coding standards for agents across all your repos

**Configure and update multiple codebases automatically with pull requests**

Tessl connects directly to GitHub and GitLab so you can initialize repositories and rollout shared guidance (coding standards, conventions, and agent instructions) across your codebase, automatically through pull requests (PRs).

Without this integration, teams rely on manual edits, onboarding docs, or one-off repo configuration. With the Tessl integrated, Tessl can use branches and PRs to:

* add the [configuration files](/reference/configuration) needed to use Tessl (`tessl.json`, `.mcp.json`)
* update those files as your guidance evolves
* apply the same guidance to multiple repositories in a single action
* keep every change visible, reviewable, and merge-controlled

Nothing is applied directly to your codebases, *every update ships as a PR you review and merge like any other change.*

***

## What you can do with Repository Integration

Once GitHub or GitLab access is enabled, you can perform three core actions:

### 1. Initialize a repository for Tessl

Tessl generates a PR that may include:

* a new or updated `tessl.json`
* a `.mcp.json` file enabling Tessl as an MCP server

You merge whenever you're ready.

### 2. Distribute shared guidance across repositories

From the Tessl interface, you can select a guidance resource and generate pull requests across multiple repositories at once. This capability is helpful for rolling out:

* coding conventions
* architectural patterns
* internal standards
* agent instructions

### 3. Remove the integration at any time

Uninstall the integration and remove the connection from Tessl.

***

## What this guide covers

This documentation walks through five workflows:

1. [**Permissions**](/distribute/rollout-to-your-repositories/permissions)\
   Required permissions in Tessl and integration
2. [**Connect Tessl to GitHub**](/distribute/rollout-to-your-repositories/connect-tessl-to-github)

   Enable the GitHub App so Tessl can create pull requests.
3. [**Connect Tessl to GitLab**](/distribute/rollout-to-your-repositories/connect-tessl-to-gitlab)\
   Configure GitLab so Tessl can create pull requests.
4. [**Initialize a repository**](/distribute/rollout-to-your-repositories/initialize-a-repository)<sup>**\***</sup>

   Use the Setup action to generate configuration inside a repository.
5. [**Distribute plugins across multiple repositories**](/distribute/rollout-to-your-repositories/distribute-plugins-across-multiple-repositories)<sup>**\***</sup>

   Select a resource and generate PRs across the repositories you choose.
6. [**Remove the integration**](/distribute/rollout-to-your-repositories/removing-the-integration)

   Uninstall the integration and remove the connection from Tessl.

<sup>\*</sup>Each workflow ends with a pull request, reviewed and merged through your normal development process.


# Permissions

The following permissions are required to configure and use Tessl with your repositories.

## **GitHub permissions**

You must have **`write` access**, so Tessl can create branches and open PRs.

## GitLab permissions

* A token with the scope of **`api`** is required.\* Project or Group tokens is required, webhooks will be set.
  * For Group tokens, the **`Owner`** permission is required.
  * Project tokens require **`Maintainer`** or above.

## **Tessl permissions**

* To enable GitHub or GitLab integration: **`Manager` or `Owner`.**
* To generate a plugin: **`Member`**.
* To distribute guidance across repositories: **`Publisher` or above** for the workspace.

If these permissions are missing, specific actions won’t appear in the interface.


# Connect Tessl to GitHub

To enable Tessl on your repositories, you will first navigate to the [Tessl Registry](https://tessl.io/registry) and login, if required.

## Enabling the Integration

* Select your workspace from the selector on the left side menu.\
  ![](/files/V9nMMDmUKpXSLQJrnvrE)
* Click on Integrations from the menu\
  ![](/files/pkYZPOonwKVCpyyOrzeC)

  .
* Select *Enable Integration*.<br>

  <div align="left"><figure><img src="/files/nBLnGrcqANHSAXoyXDOw" alt="" width="375"><figcaption></figcaption></figure></div>
* Select *Configure* next to the Organization to add the Tessl App to. Accounts that already have Tessl will not have the option.

  <div align="left"><figure><img src="/files/892jONSNB5kRh0MzTxrW" alt="" width="563"><figcaption></figcaption></figure></div>
* Decide if you want to authorize Tessl on specific repositories or provide access to everything. Once selected, click *Install & Authorize*

  <div align="left"><figure><img src="/files/rIPje4QWB2aIpGT5fgYW" alt="" width="375"><figcaption></figcaption></figure></div>
* If the required permissions are available the Tessl integrations screen will show Connected.

  <div align="left"><figure><img src="/files/5K8xV5vxOmjXeeeujUSp" alt="" width="375"><figcaption></figcaption></figure></div>

## Add or remove Repositories when *Only Select Repositories* are in use.

If you wish to later add repositories, you will navigate to the Tessl app in GitHub:

* Click *Configure* next to the Tessl App.

  <div align="left"><figure><img src="/files/mdW1HF0JOo1PhAiXwW1R" alt=""><figcaption></figcaption></figure></div>
* Select or remove repositories as needed.

  <div align="left"><figure><img src="/files/SXglBk4RJOUV1plC21I9" alt="" width="375"><figcaption></figcaption></figure></div>
* Click *Save*.<br>

  <div align="left"><figure><img src="/files/fneaTQ8PR6xtyM6Qb0oq" alt="" width="81"><figcaption></figcaption></figure></div>

## Troubleshooting

What if the option to *Enable Integration* isn't available? In the following example Tessl is not enabled and the user does not have the correct [Role](/administrators/roles) within Tessl (manager or owner) so the interface does not provide the option to integrate GitHub. To address this, ensure you have the correct [Role](/administrators/roles) within Tessl or request a user with these permissions to setup the integration.

<div align="left"><figure><img src="/files/c0ybEshXUBijPM753ds1" alt="" width="375"><figcaption></figcaption></figure></div>


# Connect Tessl to GitLab

To enable Tessl on your repositories, you will first navigate to the [Tessl Registry](https://tessl.io/registry) and login, if required.

## Enabling the Integration

* Select your workspace from the selector on the left side menu.\
  ![](/files/pdUHkPUeGfPyqqndKPad)
* Click on Integrations from the menu\
  ![](/files/pkYZPOonwKVCpyyOrzeC)

  .
* Select *Enable Integration*.

<figure><img src="/files/bV9MvYdMQYnmNUw6KXMn" alt=""><figcaption></figcaption></figure>

* Provide an access token with the correct [permissions](/distribute/rollout-to-your-repositories/permissions#gitlab-permissions) for a gitlab.com instance. \* If you are using a self hosted or customer-url for your instance, check the Use a custom instance URL box, and provide the necessary URL.<br>

  ```
  <div align="left"><figure><img src="../../../.gitbook/assets/image (2).png" alt="" width="375"><figcaption></figcaption></figure></div>
  ```

## Troubleshooting

What if the option to *Add Integration* isn't available? In the following example Tessl is not enabled and the user does not have the correct [Role](/administrators/roles) within Tessl (manager or owner) so the interface does not provide the option to integrate GitLab. To address this, ensure you have the correct [Role](/administrators/roles) within Tessl or request a user with these permissions to setup the integration.

<figure><img src="/files/JmYsVKt2i8YnzZJSs54w" alt=""><figcaption></figcaption></figure>


# Initialize a repository

Using *Setup* on the Repositories view in [Tessl Registry](https://tessl.io/registry) creates a `tessl.json` file and adds any plugins Tessl has for the dependencies your repository uses. It also creates a `.mcp.json` file so people working in the repository can use Tessl as an MCP server for their coding agent.

## Setup Tessl

* Select your workspace from the selector, with your name, on the top right of your screen.\
  ![](/files/pdUHkPUeGfPyqqndKPad)
* Click on Repositories from the menu.\
  ![](/files/UwqI1lAw9fwaUE3nkgJ1)
* Select *Setup Tessl*.

  <figure><img src="/files/gW749qWtBTDuYWw176FO" alt=""><figcaption></figcaption></figure>
* Select the agents you wish to use and click *Setup*.

  <div align="left"><figure><img src="/files/XmuAOM81dydHdfEHaHvp" alt="" width="375"><figcaption></figcaption></figure></div>
* Once clicked, a pull request will be created and a popup will be displayed to bring you to the pull request.

  <div align="left"><figure><img src="/files/Cart4Em1COnmhYZ5Vd1b" alt="" width="357"><figcaption></figcaption></figure></div>

### The Pull request created

Pull requests may contain updates to `tessl.json` and `.mcp.json` based on your selections and the dependencies the repository contains.

* You or your pipeline automation would merge the request(s).\
  ![](/files/Bh5am8LMhqKKDpMyNij4)

## Troubleshooting

If you do not see your repositories listed, see [Connect Tessl to GitHub](/distribute/rollout-to-your-repositories/connect-tessl-to-github) or [Connect Tessl to GitLab](/distribute/rollout-to-your-repositories/connect-tessl-to-gitlab).

* It's possible you are only allowing specific repositories, in which case you may need to select the additional repositories you wish to display in the GitHub settings or provide a group token with access in GitLab.


# Distribute plugins across multiple repositories

The Tessl web interface allows users, with the correct permissions, to create pull requests adding plugins to selected repositories. The following workflow demonstrates distributing a plugin that has guidelines that must be followed by the agents that company is using. This could include style guides, architecture and other guidelines that you now want to push across your organization. To do so, follow these steps:

* Navigate to the workspace your plugin resides in.
* Click *Rollout* next to the plugin you wish to push.<br>

  <figure><img src="/files/uH9scZSgJhiMMXeAGJMm" alt=""><figcaption></figcaption></figure>
* Indicate the Tessl workspace to roll the plugin out to.\ <img src="/files/rYhioUR1SCVLACiqM1Cg" alt="" data-size="original">
* Select which repositories the pull request will be created in.

  <div align="left"><figure><img src="/files/8ZCJsSnr0uQ8w4uceHu3" alt="" width="375"><figcaption></figcaption></figure></div>
* To complete the action, click *Create a rollout PR*.\
  ![](/files/IETE1xc6UbAXT8EpTvZj)
* By doing this it will create a pull request adding the plugin to the tessl.json. A `.tessl-plugin/plugin.json` will be created if Tessl has not been initialized for that repository. An option to view the PR will be displayed:

  <div align="left"><figure><img src="/files/Cart4Em1COnmhYZ5Vd1b" alt="" width="357"><figcaption></figcaption></figure></div>
* The PR will then be merged by you or your pipeline automations.


# Removing the integration

## GitHub Integration

To remove the GitHub integration, two steps are required:

\
1\) GitHub: Remove the Tessl App from within your GitHub Organization settings.

2\) Tessl: Click the Remove button on the popup to remove the integration.

### GitHub removal

* Navigate to *Applications* and click on *Configure*<br>

  <figure><img src="/files/6OML2dHpkL3Ry1SoChkD" alt=""><figcaption></figcaption></figure>
* Scroll and click the option to Uninstall, completing the steps to Uninstall when requested.<br>

  <figure><img src="/files/9KAXMTBargSnXgyhEpy3" alt=""><figcaption></figcaption></figure>

### Tessl Removal

* Select your workspace from the selector on the left side menu.\
  ![](/files/lUcdjjExYgxdX7JQabsK)
* Click on Integrations from the menu.

  .\
  ![](/files/7R8miEBPUtZaFNNPBWw8)
* Select *How to remove integration.*<br>

  <div align="left"><figure><img src="/files/NlMsKqtEJs40tg5PeEVF" alt="" width="375"><figcaption></figcaption></figure></div>
* When prompted, click the red *Remove* button on the lower portion of the popup.

  <div align="left"><figure><img src="/files/HDOAckz1kdqEOtk4M2nc" alt="" width="375"><figcaption></figcaption></figure></div>

***

## Gitlab integration

To remove the GitLab integration, two steps are required:

1\) Tessl: Click the Remove button on the popup to remove the integration.

2\) GitLab, delete the integration token if it is no longer in use.

### Tessl & GitLab removal

* Select your workspace from the selector on the left side menu.\
  ![](/files/FCk1s1bBdUPpY3xddKEI)
* Click on Integrations from the menu.\
  ![](/files/kARLCZUSRs6GyefF7x6M)

  .
* Select *How to remove integration.*\ <img src="/files/D81WH0P4L5LTrGHfb6GH" alt="" data-size="original">
* Enter in the requested value\
  ![](/files/qTFgkgHL3asJdzWL7Ntr)

### Gitlab removal

For security purposes, it is generally good practice to delete old tokens that are no longer used. Navigate to the correct token area in Gitlab and delete the token used for the integration

<div align="left"><figure><img src="/files/iJWpENmPLO8Ix2pcIpKB" alt="" width="98"><figcaption></figcaption></figure></div>


# Using plugins directly from your repo

Use plugins directly from your repository for codebase-specific context

Instead of publishing plugins to the Tessl Registry, you can also check them directly into your repository. This is a simpler way to distribute plugins together with your code.

## When to check plugins into your repo vs using the registry

**Check plugins into your repo when:**

* You want a simple distribution method - plugins travel automatically with your code
* Context is tightly coupled to this specific codebase
* You don't need version management across multiple projects

**Use the Tessl Registry when:**

* You need centralized management and updates
* You want evaluation and review workflows
* You need automated distribution across multiple repositories
* You want to keep plugins up to date independently from code changes

## How it works

Repository-specific plugins are committed to your codebase and referenced in `tessl.json` with a `file:` source. Team members automatically get the plugin when they clone the repo and run `tessl install`.

## Setup

### 1. Create the plugin in your repository

<pre class="language-bash"><code class="lang-bash">cd my-repo
<strong>tessl plugin new --name myworkspace/my-plugin --path ./plugins/my-plugin
</strong></code></pre>

This creates the plugin structure for skills or rules:

```
my-repo/
├── plugins/my-plugin/
│   ├── .tessl-plugin/plugin.json
│   └── skills
│       └── my-plugin/
│          └── SKILL.md
│   └── rules/                 # This repo's conventions
│       └── standards.md
└── tessl.json
```

### 2. Install it locally

Add the plugin to your project by referencing it in `tessl.json` with a `file:` source:

```bash
tessl install file:./plugins/my-plugin
```

This updates your `tessl.json`:

```json
{
  "name": "my-project",
  "dependencies": {
    "myworkspace/my-plugin": {
      "version": "1.0.0",
      "source": "file:./plugins/my-plugin"
    }
  }
}
```

### 3. Commit both to version control

```bash
git add plugins/my-plugin/ tessl.json
git commit -m "Add repository-specific context plugin"
```

## Team workflow

When team members clone the repository:

```bash
git clone <repo>
cd <repo>
tessl install
```

The plugin installs automatically from the `file:` source in `tessl.json`. Everyone gets the same codebase-specific context.

## Updating the plugin

Changes to the plugin go through your normal code review process:

1. Edit plugin content (rules, skills)
2. Commit changes: `git commit -m "Update architecture docs"`
3. Create pull request
4. Team reviews context changes like code changes
5. Merge to main

Team members get updates when they pull and run `tessl install`.

## Benefits

* **Versioned with code** - plugin evolves alongside the codebase
* **Automatic distribution** - Team gets context when they clone
* **Code review** - Changes to patterns/architecture reviewed via PR
* **Private** - Context stays internal, no publishing needed
* **Self-documenting** - Codebase carries its own context

## Example: Monorepo workspaces

In monorepos, create workspace-specific plugins:

```
my-monorepo/
├── frontend/
│   ├── plugins/my-plugin/           # Frontend patterns
│   │   ├── .tessl-plugin/plugin.json
│   │   ├── skills/            # Frontend Testing methodology
│   │   └── rules/             # UI standards
│   └── tessl.json             # References frontend plugin
├── backend/
│   ├── plugins/my-plugin/           # Backend patterns
│   │   ├── .tessl-plugin/plugin.json
│   │   ├── skills/            # Database migration process
│   │   └── rules/             # Backend standards
│   └── tessl.json             # References backend plugin
└── shared/
    └── plugins/my-plugin/           # Cross-cutting concerns
        └── skills/            # Unified Code Review
```

Each workspace's `tessl.json` references its local plugin and any shared plugins:

```json
{
  "dependencies": {
    "myworkspace/frontend-context": {
      "source": "file:./plugins/my-plugin"
    },
    "myworkspace/shared-context": {
      "source": "file:../shared/plugins/my-plugin"
    }
  }
}
```

## Related

* [Developing plugins locally](/create/developing-plugins-locally) - Create and test plugins with local development workflow before checking them into your repo
* [Configuration files](/reference/configuration#plugin-configuration) - Complete plugin.json reference


# Promote or claim a skill you have created

Have you authored a skill in GitHub and want to promote it using Tessl? Tessl allows you to take a skill from a local repository or GitHub repository, and generate the plugin.json, which is essential for Tessl plugins and Skills. Once imported, you will publish the plugin to make it available, publicly or privately, to your teams. The following section discusses organization of your skills and how to publish them. Additionally if you have authored a plugin on GitHub that appears in Tessl, there is a section on [claiming that skill in Tessl](#claim-a-tessl-skill).

## Prerequisites

* Tessl [installed](/introduction-to-tessl/set-up-tessl/installation)
* Tessl logged in
* Skill code available locally
* Access to a [workspace](/reference/workspaces)

## Mapping and importing your skills into Tessl plugins

If you've authored a number of skills and documents to help your agents, you can logically group the related files together and create individual skill plugins in Tessl. For example:

* If you're developing a "data migration" skill, place all the files related to that skill and documentation in a single folder or repository. This would be a single plugin.

<figure><img src="/files/UJb8ncBGSktk40nC9pRY" alt="" width="375"><figcaption></figcaption></figure>

* Similarly if you've built a skill for "building a front end", that might contain best practices and design skills you would group them together into its own plugin, create the plugin.json, by running the import command, then lint, review, eval and publish the skill to your workplace.

<div align="center"><img src="/files/cZSwQuHu4IMb9FTPJNsc" alt=""></div>

### Anti-patterns

To avoid performance issues and confusion of your agents, avoid throwing in the kitchen sink! Make your skill purpose built, providing the information for specific tasks.<br>

<figure><img src="/files/8WJH5Znn06WGMdQnCghv" alt="" width="375"><figcaption></figcaption></figure>

## Clone the Repository

Clone your repository locally.

## Create a .tessl-plugin/plugin.json

* Create a [.tessl-plugin/plugin.json](/reference/configuration#plugin-configuration) (metadata describing it) by running the following command, with your workspace and folder location values:<br>

  ```
  tessl skill import ./<directory with SKILL.md> --workspace <myworkspace>
  ```
* You can create an eval file in `/eval` or request one through the web interface. More on this coming soon!

## Improve your skill with Lint, Review, and Evaluate your Skill

### Review your Skill against best practices

Before publishing, validate your skill structure and contents:

```sh
tessl skill lint ./my-skill
```

This command checks:

* `SKILL.md` format and structure
* Required frontmatter fields (name, description)
* Conformance to the Agent Skills specification
* Markdown validity

To optimize your skill, run the following:

```sh
tessl skill review --optimize ./my-skill
```

Fix any errors before proceeding.

### Evaluate quality using Scenarios

Once you've built your skill the final step before publishing is to create scenarios your skill can be evaluated against. The following document illustrates how you would accomplish this:

* [Evaluate skill quality using scenarios](/improving-your-skills/evaluate-skill-quality-using-scenarios)

## Set up GitHub Action to publish to Tessl's Registry

The following steps introduce the [GitHub action](https://github.com/tesslio/setup-tessl) to your repository to publish your plugin automatically.

Using the GitHub action will automatically link your plugin to the repository, and all skills we previously indexed in the repository will be hidden and redirected to the plugins.\
\
See Tessl's [setup-tessl GitHub action](https://github.com/tesslio/setup-tessl) for additional options and information.

{% stepper %}
{% step %}
**Create your workflow**

Create your workflow file `.github/workflows/tessl-publish.yml`. [Here's an example action for auto-publishing](https://github.com/tesslio/setup-tessl?tab=readme-ov-file#publish-a-plugin-on-push).
{% endstep %}

{% step %}
**Create an API Key**

Log into [Tessl](https://tessl.io/registry) on web UI, then navigate to [API keys](https://tessl.io/account/api-keys). Create a new API key. Copy the value as it will only be shown once.

![](/files/v4AWhByPOpN0RqduSHd2)
{% endstep %}

{% step %}
**Add your API Key as a Repository Secret**

In GitHub, navigate to your repo **Settings**, select **Secrets and variables**, under actions find **New Repository Secret**. Provide the name: `TESSL_TOKEN` and the value is the Tessl API key you procured in the earlier step.
{% endstep %}

{% step %}
**Run your workflow**

Kick off your workflow by running the relevant trigger, or manually triggering from the UI if you enabled that in your workflow definition.
{% endstep %}
{% endstepper %}

## Claim a Tessl Skill

Found a skill in Tessl that is created/indexed from your Skill/GitHub repository of skills? You'll want to claim ownership and disable indexing by Tessl. To do this, you will:

* Recreate the skill in your workspace by importing it locally, update the workspace in `.tessl-plugin/plugin.json`.
* Use the [GitHub action to publish](https://github.com/tesslio/setup-tessl?tab=readme-ov-file#publish-a-plugin-on-push) , which will manage the Skill and ensure changes to the repo are reflected in your Tessl workspace and not reindexed by Tessl.

{% hint style="info" %}
If you accidentally use the CLI to publish a skill to your workspace, and the skill was already indexed by Tessl in the Tessl workspace, you would find two versions, in two different workspaces, when searching for that skill. You can [contact Tessl support](/support/giving-feedback) to claim your plugin and address the duplicate. Be sure to set up the GitHub action as part of this.
{% endhint %}


# Review, lint & publish with GitHub Actions

The following steps introduce the [GitHub action](https://github.com/tesslio/setup-tessl) to your repository. This action sets up `tessl` so it can be used for any CI/CD use case, such as auto-publishing plugins, linting or running skill reviews on PRs, etc.

If you're migrating your skill into Tessl's registry, using the GitHub action will automatically link your plugin to the repository, and all skills we previously indexed in the repository will be hidden and redirected to the plugins.\
\
See Tessl's [setup-tessl GitHub action](https://github.com/tesslio/setup-tessl) for additional options and information.

{% stepper %}
{% step %}
**Create your workflow**

Create your workflow file in `.github/workflows` for your desired action. For example, [here's how you'd set up an auto-publish action](https://github.com/tesslio/setup-tessl?tab=readme-ov-file#publish-a-plugin-on-push).
{% endstep %}

{% step %}
**Create an API Key**

Log into [Tessl](https://tessl.io/registry) on web UI, then navigate to [API keys](https://tessl.io/account/api-keys). Create a new API key. Copy the value as it will only be shown once.

![](/files/v4AWhByPOpN0RqduSHd2)
{% endstep %}

{% step %}
**Add your API Key as a Repository Secret**

In GitHub, navigate to your repo **Settings**, select **Secrets and variables**, under actions find **New Repository Secret**. Provide the name: `TESSL_TOKEN` and the value is the Tessl API key you procured in the earlier step.
{% endstep %}

{% step %}
**Run your workflow**

Kick off your workflow by running the relevant trigger, or manually triggering from the UI if you enabled that in your workflow definition.
{% endstep %}
{% endstepper %}

## Gating pull requests with Tessl Review

Once `TESSL_TOKEN` is set as a repository secret, you can gate a pull request on a skill's review score using `tessl review run`. This is the authenticated, asynchronous review path: it requires auth and a workspace, kicks off a review pipeline server-side, and polls until the review completes. With `--json --threshold`, the command exits non-zero when the score falls below the threshold, failing the check.

The job below reviews a skill and fails if its score is under 80%:

```yaml
name: Skill review

on:
  pull_request:

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: tesslio/setup-tessl@v2
        with:
          token: ${{ secrets.TESSL_TOKEN }}
      - name: Review skill
        run: tessl review run ./my-skill --workspace engteam --json --threshold 80
```

`--workspace` is required whenever `--json` is set, since CI runs non-interactively and cannot prompt for a workspace. Point the path at the skill file or skill directory you want to review.

For the full flag reference, see [`tessl review run`](/reference/cli-commands#tessl-review-run). For more on running reviews and the companion commands, see [Check a skill's quality using review](/improving-your-skills/reviewing-skills).


# Overview

Understand what Tessl projects are and why we need them.

A Tessl project gives Tessl a stable place to attach eval runs and other repository-connected data, so your results stay tied to your codebase over time.

### Why projects exist

Tessl needs a project so it knows where an eval belongs. That way your results aren’t just a one-off run — they stay linked to the repository, so you can find them later, compare runs, and keep improving the same codebase.

### Common workflows

#### Create a new project

Use `tessl project create` when this repository is not linked yet and you want to create a new Tessl project. The command creates the project, then records the project link in `tessl.json` — creating the file if it does not exist yet. You do not need to run `tessl init` before using this command.

#### Link to an existing project

Use `tessl project link` when the Tessl project already exists for that repository.

#### Repair a project link

Use `tessl project repair` when the project link is missing, broken, outdated, or linked to the wrong project.

### Current limitations

Projects currently have limited fallback when a directory is not a Git repository.

### See also

* [Manage projects from the CLI](/projects/manage-projects-from-the-cli)
* [Evals](/projects/evals)
* [Projects in the app](/projects/projects-in-the-app)


# Manage projects from the CLI

Create, link, and repair project links from the Tessl CLI.

Use the `tessl project` commands to create, link, or repair the Tessl project for a repository.

If you're blocked when starting an eval, this is usually the page you need.

Creating a Tessl project does not create a new Git repository. It creates the Tessl project for the repository you are already working in.

### When you are asked to create a project

Tessl asks for a project when it needs to identify the repository behind the current directory.

This happens most often when you run an eval from a repository that is not linked yet.

### Which command should I use?

| Command                | Use it when                        | What it does                                                                        |
| ---------------------- | ---------------------------------- | ----------------------------------------------------------------------------------- |
| `tessl project create` | This directory is not linked yet   | Creates a new project and records the link in `tessl.json` (creating it if missing) |
| `tessl project link`   | The project already exists         | Links this directory to that existing project                                       |
| `tessl project repair` | The local link is missing or wrong | Inspects and fixes the link                                                         |

### `tessl project create`

Creates a new Tessl project for the current repository checkout and records the project link in `tessl.json`.

Use this when the current repository is not linked yet and you want to create a new project in Tessl.

If no `tessl.json` is found in this directory or any parent directory, the command creates one before proceeding. Once the project is created, the manifest is updated to link this repository to the new project. You do not need to run `tessl init` first.

If a `tessl.json` already exists in a parent directory (but not in the current directory), the command stops and asks you to pass `--nested`. Run it again with `--nested` to create a new `tessl.json` in the current directory and a separate project for it, rather than reusing the parent project.

This command always creates a new project. It does not link to an existing one.

If the repository should use a project that already exists, use `tessl project link` instead.

### `tessl project link`

Links the current repository to an existing Tessl project.

Use this when the project already exists in Tessl and you want the repository to use it.

This command only links to an existing project. It does not create a new one.

If you want to create a brand new project for this repository, use `tessl project create` instead.

### `tessl project repair`

Inspects or repairs the Tessl project link for the current repository.

Use this when the repository should already be linked to a project, but the link is missing, broken, outdated, or no longer matches the expected repository.

Use `--relink` to connect the repository to a different existing project, `--update-source` to keep the linked project but approve this repository as its source, and `--update-name` to rename the linked project to match `tessl.json`.

### What happens after linking

Once a repository is linked:

* Evals attach to that Tessl project
* The CLI and app can show one shared evaluation history


# Repairing projects

Understand how to diagnose and fix issues with projects.

Use `tessl project repair` when Tessl detects that the project identity for your current repository no longer matches the project it is linked to.

A Tessl project has two parts of identity:

* its **locator** — the project name in `tessl.json`
* its **source** — the repository Tessl sees for the current directory

If those drift apart, Tessl can stop evals from running until you repair the association.

### What `tessl project repair` does

`tessl project repair` helps you diagnose and fix **project identity drift** for the current repository.

Depending on the problem, you can use it to:

* inspect the current mismatch
* **relink** this repository to a different existing Tessl project
* **update the source** recorded for the currently matched Tessl project
* **update the project name** to match a local rename

### Start by diagnosing

Run this first:

```bash
tessl project repair
```

This checks the current repository and shows whether the problem is:

* a **locator drift**
* a **source drift**
* a **rename drift**
* a more complete mismatch that needs relinking or project creation

If you just want machine-readable output, use:

```bash
tessl project repair --json
```

### When to use each repair action

### Relink to a different project

Use this when your current repository is linked to the **wrong Tessl project**.

```bash
tessl project repair --relink --workspace <workspace> --project <project> --yes
```

Use `--relink` when:

* Tessl matched the wrong project
* your repository should belong to a different existing project
* you are in a monorepo and the current package or subpath was associated with the wrong project
* the locator in `tessl.json` is missing, stale, or points at the wrong project

#### Example: locator drift

Your current repository source matches an existing Tessl project, but the project named in `tessl.json` does not.

For example:

* local `tessl.json` does **not** point to the right project
* Tessl can see that the current repo actually matches `team-two/real-project`

In that case, relink the current repository to the correct project:

```bash
tessl project repair --relink --workspace team-two --project real-project --yes
```

### Update the source for the current project

Use this when the **project is correct**, but Tessl has the wrong **repository source** recorded for it.

```bash
tessl project repair --update-source --yes
```

Use `--update-source` when:

* the repo remote changed
* the repo was renamed or transferred
* the repo subpath changed in a way Tessl should now treat as the project’s canonical source
* Tessl found the right project by name, but the current repository source no longer matches the stored source

#### Example: repoistory name change

Your `tessl.json` still points to the correct project, but the underlying repository source has changed.

For example:

* locator: `team-one/old-name`
* recorded source: `https://github.com/acme/old-name`
* current local source: `https://github.com/acme/new-name`

In that case, keep the same project and update its recorded source:

```bash
tessl project repair --update-source --yes
```

Use this when the project identity is still right and only the source has drifted.

### Update the project name

Use this when the **repository is still linked correctly**, but the **project name has changed** locally.

```bash
tessl project repair --update-name --yes
```

Use `--update-name` when:

* you renamed the project in `tessl.json`
* the repo still matches the existing project source
* you want the Tessl project name to match the new local name

#### Example: rename drift

Your repository still matches the same project source, but the name in `tessl.json` changed.

For example:

* old name: `team-one/old-project`
* new local name: `team-one/renamed-project`

In that case, repair the name without relinking or recreating the project:

```bash
tessl project repair --update-name --yes
```

### How to decide which one to use

Use:

* `--relink` when the repository should point to a **different existing project**
* `--update-source` when the **project is right** but its **recorded source is outdated**
* `--update-name` when the **project is right** but its **name changed**

A simple rule:

* wrong project → **relink**
* wrong repo source → **update source**
* wrong project name → **update name**

### When repair is not the right command

You usually do **not** need repair when:

* you are creating a Tessl project for the first time
* there is no existing project association yet
* Tessl is asking you to create a project before your first eval

In those cases, use the normal create or link flow instead.


# Evals

Understand how eval runs connect to a Tessl project.

Evals attach to a Tessl project.

A project context exists when the current directory, or a parent directory, is linked to a Tessl project.

This lets Tessl recognise the same repository across repeated runs.

### Why this matters

Without a Tessl project, an eval run is just a one-off local run.

With a Tessl project, Tessl has a stable identity for that repository, so source context and evaluation history stay connected.

This makes it easier to:

* Find old runs
* Compare runs over time
* Keep results attached to the right codebase

### What `tessl eval run` does

`tessl eval run` still runs from your local source.

When you run it in a directory, or subdirectory, where a project exists, the run is attached to that project so Tessl can keep its evaluation history together over time.

If the current repository is not linked yet, Tessl may ask you to create or link a project first.

### When continuity breaks

Continuity may be interrupted if the project link in `tessl.json` is missing, broken, or no longer correct.

When that happens:

* Inspect the link
* Repair it if needed
* Rerun once the directory is linked to the expected project

### See also

* [Overview](/projects/overview)
* [Manage projects from the CLI](/projects/manage-projects-from-the-cli)
* [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios)


# Projects in the app

Browse projects and review project-level evaluations in the Tessl app.

Projects are visible in the workspace Projects list and in project-specific views.

Each Tessl project represents a repository, so the app can show repository-level eval history in one place.

### Workspace Projects list

Use the Projects list to:

* Browse known projects in the workspace
* Locate a project before linking a local checkout
* Open a project's detail view

<figure><img src="/files/rNBFL6XrvfjRlcN1Flp9" alt=""><figcaption></figcaption></figure>

### Project eval views

Each project has app views that show project-level evaluation history.

Use these views to:

* Inspect evaluation history over time
* Review results connected to the same repository
* Understand the state of evaluations for a codebase

<figure><img src="/files/G1x1Q8eL9O1kDl9LCLLc" alt=""><figcaption></figcaption></figure>


# CLI commands

The Tessl CLI provides commands for managing plugins, workspaces, authentication, repository configuration, and Tessl projects. This page provides a comprehensive reference for all available commands.

{% hint style="info" %}
On this page, **repository** means your Git repository. **Tessl project** means the stable home for Tessl in that repository.
{% endhint %}

## Getting started

### tessl help command

To see all available commands, run:

```sh
tessl --help
```

To get detailed information about a specific command or command group, use the `--help` flag:

```sh
tessl <command> --help
tessl <command-group> <subcommand> --help
```

***

## Authentication

### tessl login

Authenticate with Tessl.

**Usage**

```sh
tessl login
```

**Alternative**

```sh
tessl auth login
```

### tessl logout

Sign out and clear credentials.

**Usage**

```sh
tessl logout
```

**Alternative**

```sh
tessl auth logout
```

### tessl whoami

Show current authenticated user.

**Usage**

```sh
tessl whoami
```

**Alternative**

```sh
tessl auth whoami
```

***

## Setup and initialization

### tessl init

Set up your repository and configure your coding agent.

**Usage**

```sh
tessl init [--agent <name>]... [--name <name>]
```

**Flags**

* `--agent` (string, optional, repeatable): Configure MCP for coding agent. Supported values: `claude-code`, `cursor`, `gemini`, `codex`, `openhands`, `openclaw`, `copilot`, `copilot-vscode`, `agents`, `tessl-agent`. Can specify multiple agents. See [Custom Agents](/reference/custom-agent-setup) for information on configuring additional agents.
* `--name` (string, optional): Project name for new `tessl.json` (default: current directory name)

**Notes**

* Configures MCP server settings for AI coding agents
* Creates a `tessl.json` manifest at the repository root

**Examples**

```sh
# Basic initialization with default settings
tessl init

# Initialize and configure Cursor integration
tessl init --agent cursor

# Initialize with multiple agents
tessl init --agent cursor --agent claude-code
```

### tessl project

Create, link, or repair the Tessl project for this repository.

A Tessl project gives Tessl a stable place to attach eval runs and other repository-connected data, so your results stay tied to your codebase over time.

Use these commands to create a new project, link this checkout to an existing project, or repair a missing or broken reference in `tessl.json`. For a workflow guide, see [Manage projects from the CLI](/projects/manage-projects-from-the-cli).

**Usage**

```sh
tessl project <create|link|repair>
```

### tessl project create

Create a new Tessl project for the current repository.

**Usage**

```sh
tessl project create [--new] [--workspace <name-or-id>] [<project-name>]
```

**Flags**

* `--new` (boolean, optional): Create a new project for a different workspace. Use with `--workspace` and provide a project name when you intentionally want a separate new project for the same repository.
* `--workspace` (string, optional): Name or ID of workspace

**Arguments**

* `project-name` (string, optional): Name for the new project. If omitted, you'll be prompted.

**Notes**

* Use this when this repository is not linked to a project yet and you want to create one in Tessl
* This command always creates a new project
* If this repository should use a project that already exists, use `tessl project link` instead

### tessl project link

Link the current repository to an existing Tessl project.

**Usage**

```sh
tessl project link [--workspace <name-or-id>]
```

**Flags**

* `--workspace` (string, optional): Name or ID of workspace to search

**Notes**

* Use this when the project already exists in Tessl and you want this repository to use it
* This command only links to an existing project
* If you want to create a brand new project for this repository, use `tessl project create` instead

### tessl project repair

Inspect or repair the Tessl project link for the current repository.

**Usage**

```sh
tessl project repair [--json] [--relink] [--workspace <name-or-id>] [--project <name>] [--update-source] [--update-name] [--yes]
```

**Flags**

* `--json` (boolean, optional): Output as JSON, for automation or agent workflows
* `--relink` (boolean, optional): Relink this repository to a different existing project
* `--workspace` (string, optional): Workspace name or ID for `--relink`
* `--project` (string, optional): Project name for `--relink` target
* `--update-source` (boolean, optional): Approve this repository as the linked project source
* `--update-name` (boolean, optional): Rename the linked project to match `tessl.json`
* `--yes` / `-y` (boolean, optional): Confirm and apply requested repair

**Notes**

* Use this when this repository should already be linked to a project, but the link is missing, broken, outdated, or no longer matches the expected repository or project details

***

## Project dependencies

### tessl install

Install plugins into your repository. plugins are versioned bundles of reusable, agent-agnostic context that make coding agents more effective. They can contain skills, documentation, and rules.

**Alias**: `tessl i`

**Usage**

```sh
tessl install [--global] [--skill <value>]... [--yes] [--verbose] [--watch-local] [--accept-warnings] [--strict] [--agent <name>]... <source>...
```

**Arguments**

* `source` (string, required): plugin or GitHub URL to install. Can be:
  * Registry plugin: `workspace/plugin[@version]` (version optional, defaults to latest)
  * GitHub repository:
    * Full URL: `https://github.com/owner/repo`
    * Shorthand: `github:owner/repo` (e.g., `github:softaworks/agent-toolkit`)
  * File path: `file:<path>` to install from local directory

**Flags**

* `--global` / `-g` (boolean, optional): Install plugins globally to `~/.tessl/` instead of the current repository. Global plugins are available across all your repositories.
* `--skill` (string, repeatable, optional): Select specific skills to install from GitHub repositories. Used when a repository contains multiple skills. If omitted, you'll be prompted interactively to select from available skills. Can be specified multiple times to install multiple skills from the same repository.
* `--yes` (boolean, optional): Skip confirmation prompts and auto-select all skills
* `--verbose` / `-v` (boolean, optional): Show detailed warning messages during installation
* `--watch-local` (boolean, optional): Watch local file-source plugins and reinstall on changes
* `--accept-warnings` (boolean, optional): Pre-accept install policy warnings (no interactive prompt)
* `--strict` (boolean, optional): Fail if a version is too new rather than installing an older fallback
* `--agent` (string, optional, repeatable): Override agents to install for. Supported values: `claude-code`, `cursor`, `gemini`, `codex`, `openhands`, `openclaw`, `copilot`, `copilot-vscode`, `agents`, `tessl-agent`.

**Notes**

* Plugins are installed to `.tessl/plugins/<plugin-name>/` in your repository (or `~/.tessl/plugins/` when using `--global`)
* Your repository's `tessl.json` is automatically updated with the plugin reference
* If a plugin is already installed and up-to-date, it will be skipped
* **GitHub URL formats**: `https://github.com/owner/repo`, `github:owner/repo`, or with branch/path: `https://github.com/owner/repo/tree/main/skills/pdf`
* **File system installation**: Use `file:<path>` to install from a local directory (`.tessl-plugin/plugin.json` expected in the path)
* **Install policy warnings**: If a plugin triggers install policy warnings (such as critical or high Snyk security findings), you will be asked for permission before installation continues. You can always choose to proceed — installation is never blocked. Use `--accept-warnings` to pre-accept these warnings and skip the prompt.

**Examples**

```sh
# Install a specific plugin from registry
tessl install tessl/svelte@5.38.0

# Install multiple plugins from registry
tessl install tessl/svelte tessl/react

# Install from file system (.tessl-plugin/plugin.json is expected in the specified path)
tessl install file:<path to plugin>

# Install from GitHub repository with interactive skill selection
tessl install https://github.com/anthropics/skills

# Install using GitHub shorthand syntax
tessl install github:softaworks/agent-toolkit

# Install specific skill by name from GitHub repository (when repo has multiple skills)
tessl install https://github.com/anthropics/skills --skill pdf

# Install multiple skills by name from GitHub repository using shorthand
tessl install github:anthropics/skills --skill pdf --skill pptx

# Install from specific branch and path in GitHub repository
tessl install https://github.com/anthropics/skills/tree/main/skills/pdf

# Install from a specific commit (useful when the registry shows security results for that commit)
tessl install engteam/my-skill@abc1234

# Install a plugin globally (available across all repositories)
tessl install --global tessl/svelte
```

### tessl search

Search for plugins and skills in the Tessl registry by name, PURL, or HTTP URL.

**Usage**

```sh
tessl search [--global] [--type skills|docs|rules] [--json] [<query>]
```

**Flags**

* `--global` / `-g` (boolean, optional): Install selected plugins and skills globally to `~/.tessl/` instead of the current project
* `--type` (string, optional): Filter by content type. Supported values: `skills`, `docs`, `rules`
* `--json` (boolean, optional): Output search results as JSON

**Arguments**

* `query` (string, optional): Search query (name, PURL, or HTTP URL). If omitted, you'll be prompted interactively.

**Examples**

```sh
# Search for plugins matching "svelte"
tessl search svelte
# Search and install selected results globally
tessl search --global svelte

# Interactive search
tessl search
```

### tessl uninstall

Uninstall plugins from your repository.

**Usage**

```sh
tessl uninstall [--global] [--skill <value>]... <workspace/plugin>
```

**Arguments**

* `workspace/plugin` (string, required): Full plugin name in the format `workspace/plugin`

**Flags**

* `--global` / `-g` (boolean, optional): Uninstall plugins from the global `~/.tessl/` directory instead of the current repository
* `--skill` (string, repeatable, optional): Remove specific skills instead of the entire plugin (repeatable)

**Notes**

* Removes the plugin from `tessl.json` and deletes files from `.tessl/plugins/`
* Does not require authentication (local operation only)

**Examples**

```sh
# Uninstall a plugin from the current repository
tessl uninstall tessl/svelte

# Uninstall a globally installed plugin
tessl uninstall --global tessl/svelte
```

### tessl list

List all installed plugins in your repository.

**Usage**

```sh
tessl list [--global] [--json]
```

**Flags**

* `--global` / `-g` (boolean, optional): List plugins installed in global `~/.tessl/` instead of the current repository
* `--json` (boolean, optional): Output plugins as JSON instead of human-readable format

**Notes**

* Lists all plugins installed in your repository based on `tessl.json`
* Shows plugin names in the format `workspace/plugin` with their versions
* Does not require authentication (local operation only)

**Examples**

```sh
# List all installed plugins
tessl list

# List plugins in JSON format
tessl list --json
```

### tessl outdated

Check for available plugin updates.

**Usage**

```sh
tessl outdated [--json]
```

**Flags**

* `--json` (boolean, optional): Output as JSON

**Examples**

```sh
# Check for outdated plugins
tessl outdated

# Output as JSON
tessl outdated --json
```

### tessl update

Update plugins to newer versions.

**Usage**

```sh
tessl update [--yes] [--force] [--global] [--accept-warnings] [--agent <name>]... [<plugin>]
```

**Flags**

* `--yes` / `-y` (boolean, optional): Skip prompts and update all compatible plugins
* `--force` / `-f` (boolean, optional): Include breaking updates
* `--global` / `-g` (boolean, optional): Update plugins installed globally in `~/.tessl/` instead of the current repository
* `--accept-warnings` (boolean, optional): Pre-accept install policy warnings (no interactive prompt)
* `--agent` (string, optional, repeatable): Override agents to sync for. Supported values: `claude-code`, `cursor`, `gemini`, `codex`, `openhands`, `openclaw`, `copilot`, `copilot-vscode`, `agents`, `tessl-agent`.

**Arguments**

* `plugin` (string, optional): plugin to update in the format `workspace/plugin`. If omitted, updates all plugins.

**Notes**

* If a plugin triggers install policy warnings in the new version (such as critical or high Snyk security findings), you will be asked for permission before the update is applied. Use `--accept-warnings` to pre-accept these warnings and skip the prompt.

**Examples**

```sh
# Update all plugins interactively
tessl update

# Update all plugins without prompts
tessl update --yes

# Update a specific plugin
tessl update engteam/my-plugin

# Include breaking updates
tessl update --force
```

***

## Skill management

### tessl skill new

Create a new skill with an interactive wizard or using flags.

**Usage**

```sh
tessl skill new [--name NAME] [--description DESCRIPTION] [--workspace WORKSPACE] [--path PATH] [--install] [--public]
```

**Flags**

* `--name` (string, optional): Skill name
* `--description` (string, optional): When the skill should be triggered
* `--workspace` (string, optional): Workspace for the skill (default: local)
* `--path` (string, optional): Directory path where the skill will be created
* `--install` (boolean, optional): Automatically install in the current repository after creation
* `--public` (boolean, optional): Make the skill public (default: private)

**Notes**

* If flags are omitted, an interactive wizard will guide you through skill creation
* The skill will be created as a directory with the proper Agent Skills specification structure
* Use `--install` to immediately add the skill to your local agent configuration

**Examples**

```sh
# Create a skill interactively
tessl skill new

# Create a skill with all details specified
tessl skill new --name "commit-conventions" --description "Enforce commit message standards" --workspace myteam --install
```

### tessl skill import

Create `.tessl-plugin/plugin.json` from a local `SKILL.md` file.

**Usage**

```sh
tessl skill import [--workspace WORKSPACE] [--public] [--force] [<path>]
```

**Flags**

* `--workspace` (string, optional): Workspace for the skill (default: local)
* `--public` (boolean, optional): Make skill public (default: private)
* `--force` (boolean, optional): Overwrite existing `.tessl-plugin/plugin.json` without prompting

**Arguments**

* `path` (string, optional): Local path to directory containing SKILL.md or to SKILL.md file. Defaults to current directory if omitted.

**Examples**

```sh
# Import from current directory
tessl skill import

# Import from a specific path
tessl skill import ./my-skill

# Import and make public
tessl skill import --public --workspace myteam ./my-skill
```

### tessl skill lint

Validate skill structure and contents.

**Usage**

```sh
tessl skill lint [<source>]
```

**Arguments**

* `source` (string, optional): Path to skill folder or plugin.json. Defaults to current directory if omitted.

**Notes**

* Checks for required files and proper structure
* Validates frontmatter fields (name, description, etc.)
* Verifies conformance to the Agent Skills specification at [agentskills.io/specification](https://agentskills.io/specification)
* Returns validation errors and warnings

**Examples**

```sh
# Lint skill in current directory
tessl skill lint

# Lint skill at specific directory path
tessl skill lint ./my-skill

```

### tessl skill publish

Import (if needed) and publish skill to the registry. This command bundles skills, rules, documentation into a plugin.

**Usage**

```sh
tessl skill publish [--workspace WORKSPACE] [--public] [--force] [--bump patch|minor|major] [--dry-run] [--skip-evals] [--with-scenario-quality-check] [--eval-scenarios <path>] [--resolve-symlinks] [<path>]
```

**Flags**

* `--workspace` (string, optional): Workspace for the skill (used if importing)
* `--public` (boolean, optional): Make skill public (used if importing)
* `--force` (boolean, optional): Overwrite existing `.tessl-plugin/plugin.json` without prompting
* `--bump` (string, optional): Auto-bump version if it already exists in the registry. Supported values: `patch`, `minor`, `major`
* `--dry-run` (boolean, optional): Run all pre-publish checks without publishing
* `--skip-evals` (boolean, optional): Skip publishing eval scenarios from evals/ directory
* `--with-scenario-quality-check` (boolean, optional): Exclude misleading scenarios from the publish-time eval run
* `--eval-scenarios` (string, optional): Path to eval scenarios directory (default: `<path>/evals`)
* `--resolve-symlinks` (boolean, optional): Resolve symlinked files to their target contents when packing

**Arguments**

* `path` (string, optional): Path to the skill directory to publish. Defaults to current directory if omitted.

**Notes**

* Skills are automatically linted before publishing
* Published skills are versioned based on the version in the skill manifest
* Eval scenarios from the `evals/` directory are published by default; use `--skip-evals` to exclude them
* **Automatic evaluation**: When published, skills are automatically evaluated and review scores are calculated (see [Check a skill's quality using review](/improving-your-skills/reviewing-skills))

**Examples**

```sh
# Publish skill from current directory
tessl skill publish

# Publish to a specific workspace
tessl skill publish --workspace myteam ./my-skill

# Publish publicly
tessl skill publish --public
```

### tessl skill review

Review a skill file for quality and compliance.

**Usage**

```sh
tessl skill review [--json] [--optimize] [--max-iterations <count>] [--skill <name>] [--yes] [--threshold <score>] [<path-or-url>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--optimize` (boolean, optional): Automatically improve the skill file and apply changes
* `--max-iterations` (number, optional): Maximum number of improvement iterations (1-10, default: 3)
* `--skill` (string, optional): Select specific skill to review from a remote repository
* `--yes` / `-y` (boolean, optional): Skip confirmation prompt and auto-apply improvements
* `--threshold` (number, optional): Minimum score percentage to pass (0-100, fails if below). `0` never fails (skips validation and score gating). Cannot be used with `--optimize`.

**Arguments**

* `path-or-url` (string, optional): Path to SKILL.md, skill directory, or GitHub URL. Defaults to current directory if omitted.

**Notes**

* Performs a comprehensive conformance review against the Agent Skills specification
* Validates skill structure, formatting, and best practices
* Provides detailed feedback on how to improve the skill
* `--optimize` runs up to 3 improvement iterations by default, stopping early only if the skill reaches 100%
* `--threshold` is for review-only mode (without `--optimize`) and causes the command to exit with a non-zero status if the score falls below the specified value
* This command runs synchronously and requires you to be logged in (`tessl login`). For asynchronous, server-side reviews, including CI gating, custom rubrics, and the improve-and-review loop, use [Tessl Review](#tessl-review) (`tessl review run` and `tessl review fix`)

**Examples**

Reviewing a skill

```sh
# Review skill in current directory
tessl skill review

# Review skill at specific path
tessl skill review ./my-skill

# Review specific skill by name from a plugin with multiple skills
tessl skill review --skill pdf ./my-plugin
```

Optimizing a skill

```bash
# Optimize skill in current directory
tessl skill review --optimize

# Optimize skill at specific path with 10 rounds of iteration
tessl skill review --optimize --max-iterations 10 ./my-skill

# Optimize skill by name from a plugin with multiple skills
tessl skill review --optimize --skill pdf ./my-plugin

# Optimize and auto-apply changes without confirmation prompt
tessl skill review --optimize --yes ./my-skill
```

***

## Tessl Review

The `tessl review` family runs an asynchronous review pipeline server-side. These commands require authentication; `run` and `fix` also require a workspace. The pipeline is bundle-aware, and `tessl review run` polls until it completes. This is the primary path for authenticated users and CI gating.

### tessl review run

Run an asynchronous **quality** review of a skill — it scores the skill against a reviewer rubric. `tessl review run` is shorthand for `tessl review run quality`; to run a security scan instead, use `tessl review run security` (documented below). Requires authentication and a workspace.

**Usage**

```sh
tessl review run [--json] [--workspace WORKSPACE] [--threshold <percent>] [--label <text>] [--force] [--review-plugin <ref>] [<path>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--workspace` / `-w` (string, optional): Workspace name or ID. Required when `--json` is set
* `--threshold` (number, optional): Exit non-zero if the review score is below this percentage. `0` never fails (skips validation and score gating)
* `--label` / `-l` (string, optional): Label to describe this review run
* `--force` / `-f` (boolean, optional): Run a fresh review even when cached results exist
* `--review-plugin` (string, optional): Reviewer plugin — a path to a local plugin directory, or a registry ref `workspace/plugin[@version]`. Requires a paid plan; on a Free organisation, passing this flag returns an upgrade error

**Arguments**

* `path` (string, optional): Path to a skill file or skill directory. Defaults to current directory if omitted.

**Notes**

* Requires authentication; sign in with `tessl login` or set the `TESSL_TOKEN` API key in the environment
* `--workspace` is required when `--json` is set, since non-interactive runs cannot prompt for a workspace
* The command polls until the review completes, then prints the results
* `--threshold` causes a non-zero exit when the score falls below the percentage, making it a CI gate
* Press Ctrl+C to detach — the review continues server-side and can be viewed later with `tessl review view`
* `run` has two subcommands: `quality` (the default, documented here) and `security` (below). `tessl review run quality` is the explicit form of the default

**Examples**

```sh
# Review the skill in the current directory
tessl review run --workspace engteam

# Review a skill at a specific path
tessl review run ./my-skill --workspace engteam

# CI gate: fail if the score is below 80%
tessl review run ./my-skill --workspace engteam --json --threshold 80

# Review with a specific reviewer plugin
tessl review run ./my-skill --workspace engteam --review-plugin engteam/my-reviewer
```

### tessl review run security

Run an asynchronous security scan of a skill, powered by Snyk. Reports findings and the highest severity. Requires authentication and a workspace.

**Usage**

```sh
tessl review run security [--json] [--workspace WORKSPACE] [--label <text>] [--force] [--fail-on <severity>] [<path>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--workspace` / `-w` (string, optional): Workspace name or ID. Required when `--json` is set
* `--label` / `-l` (string, optional): Label to describe this security review run
* `--force` / `-f` (boolean, optional): Run a fresh scan even when cached results exist
* `--fail-on` (string, optional): Exit non-zero if the highest severity is at or above this level: `low`, `medium`, `high`, `critical`

**Arguments**

* `path` (string, optional): Path to a skill file or skill directory. Defaults to current directory if omitted.

**Notes**

* Requires authentication; sign in with `tessl login` or set the `TESSL_TOKEN` API key in the environment
* The scan runs server-side; the command polls until it completes, then prints the findings and the highest severity
* `--fail-on` gates the exit code on severity, making it a CI gate — the security equivalent of `--threshold` on a quality review

**Examples**

```sh
# Security-scan the skill in the current directory
tessl review run security --workspace engteam

# Scan a skill at a specific path
tessl review run security ./my-skill --workspace engteam

# CI gate: fail if any finding is high or critical
tessl review run security ./my-skill --workspace engteam --json --fail-on high
```

### tessl review view

View results for a review run of either kind. The run ID resolves whether it is a quality or a security review, and the results are rendered accordingly.

**Usage**

```sh
tessl review view [--json] [--last] [--threshold <percent>] [--fail-on <severity>] [--workspace <name>] [<id>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON, in the same shape as `tessl review run --json`
* `--last` (boolean, optional): View results for the most recent review run
* `--threshold` (number, optional): Quality reviews only. Exit non-zero if the review score is below this percentage (0-100)
* `--fail-on` (string, optional): Security reviews only. Exit non-zero if the highest severity is at or above this level: `low`, `medium`, `high`, `critical`
* `--workspace` / `-w` (string, optional): Workspace name or ID. Only applies with `--last`; an explicit review run ID already identifies its workspace.

**Arguments**

* `id` (string, optional): Review run ID. Provide an ID or use `--last`.

**Notes**

* Provide a review run ID or use `--last`; one is required
* The gate flag follows the run's kind: `--threshold` gates a quality run, `--fail-on` gates a security run. Passing the flag for the other kind is a usage error
* `--workspace` is only accepted with `--last`; passing it alongside an explicit review run ID fails with a validation error

**Examples**

```sh
# View a specific review run
tessl review view abc123

# View the most recent review run
tessl review view --last

# Re-check a stored run against a threshold
tessl review view abc123 --json --threshold 80
```

### tessl review list

List recent review runs.

**Usage**

```sh
tessl review list [--json] [--limit <count>] [--workspace WORKSPACE]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--limit` (number, optional): Maximum number of review runs to display (default: 20)
* `--workspace` / `-w` (string, optional): Workspace name or ID

**Examples**

```sh
# List recent review runs
tessl review list

# List the 50 most recent runs
tessl review list --limit 50

# List runs for a specific workspace
tessl review list --workspace engteam
```

### tessl review retry

Re-run a failed review run.

**Usage**

```sh
tessl review retry [--json] [--workspace <name>] [--last] [<id>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--workspace` / `-w` (string, optional): Workspace name or ID. Only applies with `--last`; an explicit review run ID already identifies its workspace.
* `--last` (boolean, optional): Retry the most recent review run

**Arguments**

* `id` (string, optional): Review run ID to retry. Provide an ID or use `--last`.

**Notes**

* `--workspace` is only accepted with `--last`; passing it alongside an explicit review run ID fails with a validation error

**Examples**

```sh
# Retry a specific review run
tessl review retry abc123

# Retry the most recent review run
tessl review retry --last

# Retry the most recent review run in a specific workspace
tessl review retry --last --workspace engteam
```

### tessl review fix

Improve a skill by running an automated review-and-fix loop server-side. Requires authentication and a workspace.

**Usage**

```sh
tessl review fix [--json] [--workspace WORKSPACE] [--threshold <percent>] [--max-iterations <count>] [--yes] [--review-plugin <ref>] [<path>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--workspace` / `-w` (string, optional): Workspace name or ID
* `--threshold` (number, optional): Stop once a review scores at or above this percentage (0-100)
* `--max-iterations` (number, optional): Maximum improve→review iterations to attempt (1-10)
* `--yes` / `-y` (boolean, optional): Apply the improved skill without confirmation
* `--review-plugin` (string, optional): Reviewer plugin — a path to a local plugin directory, or a registry ref `workspace/plugin[@version]`. Requires a paid plan; on a Free organisation, passing this flag returns an upgrade error

**Arguments**

* `path` (string, optional): Path to a local skill file or skill directory. Defaults to current directory if omitted.

**Notes**

* Requires authentication; sign in with `tessl login` or set the `TESSL_TOKEN` API key in the environment
* `--workspace` is required when `--json` is set, since non-interactive runs cannot prompt for a workspace
* Runs an asynchronous improve→review loop, stopping early once `--threshold` is met

**Examples**

```sh
# Improve the skill in the current directory
tessl review fix --workspace engteam

# Improve until the score reaches 90%, up to 5 iterations
tessl review fix ./my-skill --workspace engteam --threshold 90 --max-iterations 5

# Apply improvements without a confirmation prompt
tessl review fix ./my-skill --workspace engteam --yes
```

***

## Plugin management

### tessl plugin new

Create a new plugin with an interactive wizard.

**Usage**

```sh
tessl plugin new [--name <workspace/plugin-name>] [--summary <description>] [--path <path>] [--rules <rule-name>] [--rule-description <description>] [--workspace <workspace>] [--skill] [--skill-name <name>] [--skill-description <description>] [--install] [--public]
```

**Flags**

* `--name` (string, optional): plugin name in format `workspace/plugin-name`
* `--summary` (string, optional): Brief description of the plugin
* `--path` (string, optional): Directory path where plugin will be created
* `--rules` (string, optional): Include rule by name
* `--rule-description` (string, optional): Initial rule instructions to include in generated rule file
* `--workspace` (string, optional): Workspace for the plugin
* `--skill` (boolean, optional): Include a skill in the plugin
* `--skill-name` (string, optional): Skill name (implies `--skill`)
* `--skill-description` (string, optional): Skill description (required with `--skill` or `--skill-name`)
* `--install` (boolean, optional): Automatically install in the current repository
* `--public` (boolean, optional): Make plugin public (default: private)

**Notes**

* Creates a new plugin directory with a basic `.tessl-plugin/plugin.json` template
* If run without flags, launches an interactive wizard to guide you through plugin creation
* For non-interactive use, include at least one component with `--skill`, `--skill-name`, or `--rules`
* Use `--skill` or `--skill-name` to create a plugin with a skill component

**Examples**

```sh
# Interactive wizard mode
tessl plugin new

# Create a plugin with specific options
tessl plugin new --name myworkspace/my-skill --summary "My skill description" --path ./my-skill-plugin

# Create a plugin with a skill
tessl plugin new --name myworkspace/my-skill --skill --skill-name "my-skill" --skill-description "Description of my skill"

# Create and automatically install
tessl plugin new --name myworkspace/my-skill --install
```

### tessl plugin lint

Validate plugin structure and contents

**Usage**

```sh
tessl plugin lint [<source>]
```

**Arguments**

* `source` (string, optional): Path to the plugin directory to lint. Defaults to current directory if omitted.

### tessl plugin migrate

Migrate `tile.json` to `.tessl-plugin/plugin.json`.

**Usage**

```sh
tessl plugin migrate [--force] [<path>]
```

**Flags**

* `--force` (boolean, optional): Overwrite existing `.tessl-plugin/plugin.json`

**Arguments**

* `path` (string, optional): Path to plugin directory. Defaults to current directory if omitted.

### tessl plugin pack

Package a plugin into a .tgz file.

**Usage**

```sh
tessl plugin pack [--output path] [<source>]
```

**Flags**

* `--output` (string, optional): Output path for .tgz file. If omitted, uses the plugin name and version to create a file in your current directory.

**Arguments**

* `source` (string, optional): Path to plugin folder. Defaults to current directory if omitted.

### tessl plugin info

Show plugin details from the registry.

**Usage**

```sh
tessl plugin info [<name-or-path>]
```

**Arguments**

* `name-or-path` (string, optional): plugin name (`workspace/plugin[@version]`) or path to plugin directory. Defaults to current directory if omitted.

**Examples**

```sh
# Show info for plugin in current directory
tessl plugin info

# Show info for a specific plugin
tessl plugin info engteam/my-plugin

# Show info for a specific version
tessl plugin info engteam/my-plugin@1.0.0
```

### tessl plugin publish

Publish plugins to the Tessl registry. This command bundles skills, rules, documentation into a plugin.

**Usage**

```sh
tessl plugin publish [--dry-run] [--bump patch|minor|major] [--skip-evals] [--with-scenario-quality-check] [--workspace <workspace>] [--version <version>] [--verbose] [<path>]
```

**Flags**

* `--dry-run` (boolean, optional): Run all pre-publish checks without publishing
* `--bump` (string, optional): Auto-bump version if it already exists in the registry. Supported values: `patch`, `minor`, `major`
* `--skip-evals` (boolean, optional): Skip publishing eval scenarios from evals/ directory
* `--with-scenario-quality-check` (boolean, optional): Have the backend's LLM judge filter out misleading scenarios (low feasibility, rubric leakage, low value) from the publish-time eval run. Equivalent to `tessl eval run --quality-check` for the eval that runs as part of publishing.
* `--workspace` (string, optional): Workspace to publish under when the plugin manifest name is flat (no `workspace/` prefix)
* `--version` (string, optional): Version to publish when the plugin manifest omits one
* `--verbose` / `-v` (boolean, optional): Print every archived file with the reason it was included

**Arguments**

* `path` (string, optional): Path to the plugin directory to publish. Defaults to current directory if omitted.

**Examples**

```sh
# Publish a plugin from current directory
tessl plugin publish

# Publish a plugin from a specific directory
tessl plugin publish path/to/my/plugin
```

{% hint style="info" %}
Not sure what your published plugin's URL will look like? See [Workspaces](/reference/workspaces#how-workspaces-appear-in-the-registry) to learn how workspace and plugin names map to Registry URLs.
{% endhint %}

### tessl plugin unpublish

Unpublish plugins from the registry (within 2 days of publishing).

**Usage**

```sh
tessl plugin unpublish [--plugin <workspace/plugin@version>]
```

**Flags**

* `--plugin` (string, optional): plugin to unpublish in the format `workspace/plugin@version`. If omitted, you'll be prompted.

**Notes**

* Only available within 2 days of publishing

**Examples**

```sh
# Unpublish a specific plugin version
tessl plugin unpublish --plugin myworkspace/myplugin@1.0.0

# Interactive mode
tessl plugin unpublish
```

### tessl plugin archive

Archive plugins in the registry.

**Usage**

```sh
tessl plugin archive [--plugin <workspace/plugin[@version]>] --reason <reason>
```

**Flags**

* `--plugin` (string, optional): plugin to archive in the format `workspace/plugin` (archives all versions) or `workspace/plugin@version` (archives a single version)
* `--reason` (string, required): Reason for archiving the plugin

**Notes**

* Prevents new installations while preserving existing installations

**Examples**

```sh
# Archive a specific plugin version
tessl plugin archive --plugin engteam/myplugin@1.0.0 --reason "Deprecated in favor of v2"

# Archive all versions of a plugin
tessl plugin archive --plugin engteam/myplugin --reason "No longer maintained"
```

***

## Organization management

### tessl org list

List all organizations that you are a member of.

**Usage**

```sh
tessl org list
```

***

## Workspace management

Workspaces enable you to create private collections of plugins that are restricted to yourself or your organization. You can control member access and permissions. To learn more, see [Distributing via registry](/distribute/distributing-via-registry).

### tessl workspace create

Create a new workspace.

**Usage**

```sh
tessl workspace create [--org-id <uuid>] [<name>]
```

**Flags**

* `--org-id` (string, optional): ID of organization to create the workspace in

**Arguments**

* `name` (string, optional): Name for the workspace. The name must be lowercase. If omitted, you'll be prompted.

**Examples**

```sh
# Create a workspace
tessl workspace create myworkspace

# Interactive creation
tessl workspace create

# Create a workspace in a specific organization
tessl workspace create --org-id 01935e2c-1234-5678-abcd-ef0123456789 engteam
```

### tessl workspace list

List all workspaces that you are a member of.

**Usage**

```sh
tessl workspace list
```

### tessl workspace delete

Delete an existing workspace.

**Usage**

```sh
tessl workspace delete [<name>]
```

**Arguments**

* `name` (string, optional): The name or ID of the workspace. If omitted, you'll be prompted.

**Examples**

```sh
# Delete a workspace
tessl workspace delete myworkspace

# Interactive deletion
tessl workspace delete
```

### tessl workspace add-member

Add a user to a workspace with specified permissions.

**Usage**

```sh
tessl workspace add-member [--workspace <name>] [--username <username>] [--role <role>]
```

**Flags**

* `--workspace` (string, optional): Name or ID of workspace
* `--username` (string, optional): Username or ID of user to add
* `--role` (string, optional): Role to assign. Supported values: `member`, `publisher`, `manager`, `owner`

See [Roles](/administrators/roles) for more information

**Examples**

```sh
# Add a user to the workspace with a member role
tessl workspace add-member --workspace myworkspace --username johnsmith --role member

# Add a user to the workspace with an owner role
tessl workspace add-member --workspace myworkspace --username janesmith --role owner

# Interactive mode (prompts for all fields)
tessl workspace add-member
```

### tessl workspace remove-member

Remove a user from a workspace.

**Usage**

```sh
tessl workspace remove-member [--workspace <name>] [--username <username>]
```

**Flags**

* `--workspace` (string, optional): Name or ID of workspace
* `--username` (string, optional): Username or ID of user to remove

**Examples**

```sh
# Remove a member
tessl workspace remove-member --workspace myworkspace --username johnsmith

# Interactive mode
tessl workspace remove-member
```

### tessl workspace list-members

List all members of a workspace.

**Usage**

```sh
tessl workspace list-members [<name>]
```

**Arguments**

* `name` (string, optional): The name or ID of the workspace. If omitted, you'll be prompted.

**Examples**

```sh
# List members of a workspace
tessl workspace list-members myworkspace

# Interactive mode
tessl workspace list-members
```

### tessl workspace archive

Archive a workspace. An archived workspace won't be available to publish to or read from, but can be unarchived later.

**Usage**

```sh
tessl workspace archive --reason <text> [<name>]
```

**Flags**

* `--reason` (string, required): Reason for archiving the workspace

**Arguments**

* `name` (string, optional): The name or ID of the workspace. If omitted, you'll be prompted.

**Notes**

* Archiving is a safer alternative to deleting, as archived workspaces can be restored
* Use `tessl workspace unarchive` to restore an archived workspace

**Examples**

```sh
# Archive a workspace with a reason
tessl workspace archive --reason "deprecated" myworkspace

# Interactive mode
tessl workspace archive --reason "no longer in use"
```

### tessl workspace unarchive

Unarchive an archived workspace, making it active again.

**Usage**

```sh
tessl workspace unarchive <name>
```

**Arguments**

* `name` (string, required): The name or ID of the workspace.

**Examples**

```sh
# Unarchive a workspace
tessl workspace unarchive myworkspace
```

***

## Configuration management

### tessl config get

Get a configuration value or show all configuration.

**Usage**

```sh
tessl config get [<key>]
```

**Arguments**

* `key` (string, optional): Configuration key to get. If omitted, shows all configuration.

**Examples**

```sh
# Show all configuration
tessl config get

# Get a specific configuration value
tessl config get shareUsageData
```

### tessl config set

Set a configuration value.

**Usage**

```sh
tessl config set <key> <value>
```

**Arguments**

* `key` (string, required): Configuration key to set. Supported values: `shareUsageData`, `termsAcceptedAt`, `evalDefaultModelNoticeShownAt`, `evalDefaultModelNoticeModel`, `agents`
* `value` (string, required): Configuration value to set

**Examples**

```sh
# Set a configuration value
tessl config set shareUsageData false
```

### tessl config list

List all configuration values.

**Usage**

```sh
tessl config list [<key>]
```

**Arguments**

* `key` (string, optional): Configuration key to list. If omitted, lists all configuration.

**Notes**

* Similar to `tessl config get` but specifically for listing configuration values

**Examples**

```sh
# List all configuration
tessl config list

# List a specific configuration key
tessl config list shareUsageData
```

### tessl config add

Add one or more values to a configuration array.

**Usage**

```sh
tessl config add <key> <value>...
```

**Arguments**

* `key` (string, required): Configuration key for the array
* `value` (string, required, repeatable): One or more values to add to the array

**Notes**

* Use this command to add values to array-type configuration settings
* Can specify multiple values in a single command

**Examples**

```sh
# Add a single value to an array configuration
tessl config add agents cursor

# Add multiple values to an array configuration
tessl config add agents cursor claude-code
```

### tessl config remove

Remove a value from a configuration array.

**Usage**

```sh
tessl config remove <key> <value>
```

**Arguments**

* `key` (string, required): Configuration key for the array
* `value` (string, required): Value to remove from the array

**Notes**

* Use this command to remove values from array-type configuration settings
* Only removes the specified value, not the entire configuration key

**Examples**

```sh
# Remove a value from an array configuration
tessl config remove agents cursor
```

***

## Diagnostics and utilities

### tessl doctor

Run authentication and manifest diagnostics to troubleshoot issues.

**Usage**

```sh
tessl doctor [--json]
```

**Flags**

* `--json` (boolean, optional): Output diagnostics as JSON for programmatic processing

**Examples**

```sh
# Run diagnostics with human-readable output
tessl doctor

# Output diagnostics as JSON
tessl doctor --json
```

### tessl feedback

Send feedback to the Tessl team.

**Usage**

```sh
tessl feedback [<message>]
```

**Arguments**

* `message` (string, optional): Feedback message to send. If omitted, you'll be prompted interactively.

**Examples**

```sh
# Send feedback directly
tessl feedback "Great tool! Would love to see Python support."

# Interactive feedback
tessl feedback
```

***

## CLI self-management

### tessl cli update

Update the CLI to the latest or specified version.

**Usage**

```sh
tessl cli update [--target <version>] [--channel <name>] [--dry-run]
```

**Flags**

* `--target` / `-t` (string, optional): Target version to update to (example: v1.0.0)
* `--channel` / `-c` (string, optional): Release channel to switch to. Supported values: `latest`, `beta`
* `--dry-run` (boolean, optional): Show what would be run without executing the update

**Examples**

```sh
# Update to the latest version
tessl cli update

# Update to a specific version
tessl cli update --target v1.0.0

# Switch to the beta release channel
tessl cli update --channel beta

# Preview update without executing
tessl cli update --dry-run
```

***

## API key management

### tessl api-key create

Create an API key for a workspace.

**Usage**

```sh
tessl api-key create [--workspace <name>] [--name <name>] [--role <role>] [--expiry-date <date>]
```

**Flags**

* `--workspace` (string, optional): Name or ID of workspace
* `--name` (string, optional): Name for the API key
* `--role` (string, optional): Role to assign. Supported values: `member`, `publisher`, `manager`, `owner`
* `--expiry-date` (string, optional): Expiry date in ISO 8601 format (example: 2027-12-31T00:00:00Z)

**Examples**

```sh
# Create an API key interactively
tessl api-key create

# Create an API key with all details specified
tessl api-key create --workspace engteam --name "ci-key" --role publisher --expiry-date 2027-12-31T00:00:00Z
```

### tessl api-key list

List API keys for a workspace.

**Usage**

```sh
tessl api-key list [--workspace <name>]
```

**Flags**

* `--workspace` (string, optional): Name or ID of workspace

**Examples**

```sh
# List API keys interactively
tessl api-key list

# List API keys for a specific workspace
tessl api-key list --workspace engteam
```

### tessl api-key delete

Delete an API key from a workspace.

**Usage**

```sh
tessl api-key delete [--workspace <name>] [<api-key-id>]
```

**Flags**

* `--workspace` (string, optional): Name or ID of workspace

**Arguments**

* `api-key-id` (string, optional): ID of the API key to delete. If omitted, you'll be prompted.

**Examples**

```sh
# Delete an API key interactively
tessl api-key delete

# Delete a specific API key
tessl api-key delete --workspace engteam <api-key-id>
```

***

## Model Context Protocol (MCP)

### tessl mcp start

Start the Tessl MCP (Model Context Protocol) server for integration with AI coding agents.

**Usage**

```sh
tessl mcp start
```

### tessl mcp proxy

Bridge a coding agent to a workspace MCP server through the Tessl MCP gateway. Starts a stdio MCP proxy that forwards JSON-RPC messages to a workspace-registered upstream MCP server, authenticating to the gateway with your Tessl credentials (`tessl login`) or `TESSL_TOKEN`. See [MCP gateway](/reference/mcp-gateway) for how to register the upstream server and wire the proxy into an agent or plugin `.mcp.json`.

**Usage**

```sh
tessl mcp proxy <workspace>/<mcp>
```

**Arguments**

* `workspace/mcp` (string, required): Slug of the workspace and the MCP server registered in that workspace's gateway (for example `engteam/linear`).

**Authentication**

* **Interactive use** — sign in once with `tessl login`; the proxy reuses the same credentials.
* **CI or other non-interactive contexts** — set `TESSL_TOKEN` to a Tessl API key for the workspace. See [`tessl api-key create`](#tessl-api-key-create).

**Examples**

```sh
# Proxy to an MCP server named `linear` in the `engteam` workspace
tessl mcp proxy engteam/linear
```

***

## Repository

### tessl repo select-commits

Browse recent commits in a repository and select which ones to evaluate. Used as the first step in [generating codebase scenarios](/improving-your-skills/evaluate-skill-quality-using-scenarios#generate-scenarios-from-your-codebase).

{% hint style="info" %}
This command is not listed in `tessl --help` but works when invoked directly.
{% endhint %}

**Usage**

```sh
tessl repo select-commits <org/repo> [flags]
```

**Arguments**

* `org/repo` (string, required): Repository in `org/repo` format

**Flags**

* `--keyword` (string, optional): Filter by commit message keyword
* `--author` (string, optional): Filter by author name
* `--since` / `--until` (string, optional): Date range in YYYY-MM-DD format
* `--count` / `-n` (number, optional): Number of commits to show (1–100)
* `--workspace` / `-w` (string, optional): Required outside interactive mode
* `--json` (boolean, optional): Output as JSON

**Prerequisite:** your GitHub or GitLab account must be connected in workspace settings. If it isn't, the error message includes a direct link to the settings page.

**Examples**

```sh
# Browse recent commits
$ tessl repo select-commits org/repo

# Filter by keyword and date range
$ tessl repo select-commits org/repo --keyword=feat --since=2026-01-01

# Show last 50 commits by a specific author
$ tessl repo select-commits org/repo --author="Alice" --count=50
```

***

## Inventory

### tessl inventory import

Scan a GitHub account or org for installed skills and upload an inventory. Forked repos are skipped.

**Usage**

```sh
tessl inventory import [--org <account>] [--workspace <name>] [--repo <repo>]... [--ignore-repo <repo>]... [--dry-run <path>]
```

**Flags**

* `--org` (string, optional): GitHub account or org to scan. Prompted if omitted.
* `--workspace` (string, optional): Name or ID of workspace to upload to. Prompted if omitted.
* `--repo` (string, repeatable, optional): Limit scan to this repo (repeatable)
* `--ignore-repo` (string, repeatable, optional): Exclude this repo from the scan (repeatable)
* `--dry-run` (string, optional): Write inventory JSON to the given path instead of uploading

**Notes**

* `--org` and `--workspace` are prompted when omitted in interactive sessions, but required as flags in non-interactive environments (including with `--dry-run`)

**Examples**

```sh
# Scan an org and upload to a workspace
tessl inventory import --org my-github-org --workspace engteam

# Limit the scan to specific repositories
tessl inventory import --org my-github-org --workspace engteam --repo repo-a --repo repo-b

# Preview the inventory without uploading
tessl inventory import --org my-github-org --workspace engteam --dry-run ./inventory.json
```

***

## Scenario management

{% hint style="warning" %}
Scenario management and evals are in public beta. Workflows and output formats may change in upcoming releases.
{% endhint %}

Scenario commands generate and manage eval scenarios from real repository commits. For a full walkthrough, see [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios).

### tessl scenario generate

Generate eval scenarios from a plugin or repository commits. Runs server-side — the CLI polls until complete. Ctrl-C detaches without cancelling; check progress with `tessl scenario list`.

**Alias:** `tessl scenarios generate`

**Usage**

```sh
tessl scenario generate [--commits <hash1,hash2>] [--prs <id1,id2>] [--count <n>] [--workspace <name>] [--context <globs>] [--json] <source>
```

**Arguments**

* `source` (string, required): plugin path or `org/repo` to generate scenarios from

**Flags**

* `--commits` (string, optional): Comma-separated commit hashes to generate scenarios from (repo only)
* `--prs` (string, optional): Comma-separated PR numbers to resolve as commit ranges (repo only)
* `--count` / `-n` (number, optional): Number of new scenarios to add (plugin only)
* `--context` (string, optional): Glob patterns for context files to exclude from baseline, comma-separated (repo only). These patterns are stored in each generated `scenario.json` as `fixture.exclude` — they are stripped for the baseline eval variant and injected back for the with-context variant. Defaults to `*.mdc`, `*.md`, `tile.json`, `.tessl-plugin/plugin.json`, `tessl.json`, `.tessl/` when omitted.
* `--workspace` / `-w` (string, optional): Workspace name or ID (repo only). Required outside interactive mode.
* `--json` (boolean, optional): Output as JSON

**Examples**

```sh
# Generate scenarios for two commits
$ tessl scenario generate org/repo --commits=abc123,def456

# Generate scenarios from PRs
$ tessl scenario generate org/repo --prs=42,43

# Generate scenarios from a plugin
$ tessl scenario generate ./my-plugin --count=5

# Specify context file patterns
$ tessl scenario generate org/repo --commits=abc123 --context="*.mdc,*.md"

# Non-interactive with workspace
$ tessl scenario generate org/repo --commits=abc123 --workspace=engteam
```

### tessl scenario list

List recent scenario generation runs in reverse chronological order.

**Alias:** `tessl scenarios list`

**Usage**

```sh
tessl scenario list [--mine] [--workspace <name>] [--limit <count>] [--status <status>] [--json]
```

**Flags**

* `--mine` (boolean, optional): Only show generation runs created by you
* `--workspace` / `-w` (string, optional): Filter by workspace name
* `--limit` (number, optional): Maximum number of runs to display (default: 20)
* `--status` (string, optional): Filter by status. Supported values: `pending`, `in_progress`, `completed`, `failed`
* `--json` (boolean, optional): Output as JSON

### tessl scenario view

Inspect a scenario generation run. Shows run metadata and a table of generated scenarios with titles and checklist item counts.

**Alias:** `tessl scenarios view`

**Usage**

```sh
tessl scenario view [--last] [--json] [<id>]
```

**Flags**

* `--last` (boolean, optional): View the most recent generation run
* `--json` (boolean, optional): Output as JSON

**Arguments**

* `id` (string, optional): Generation run ID. Either `id` or `--last` is required.

**Examples**

```sh
# View the most recent generation run
$ tessl scenario view --last

# View a specific run
$ tessl scenario view 019c4791-9eec-7458-b28a-6c94405a3d38
```

### tessl scenario download

Download generated scenarios to your local `evals/` folder.

**Alias:** `tessl scenarios download`

**Usage**

```sh
tessl scenario download [--output <dir>] [--strategy <strategy>] [--json] [--last] <id>...
```

**Flags**

* `--output` / `-o` (string, optional): Output directory (default: `evals`)
* `--strategy` / `-s` (string, optional): Write strategy: `merge` (default) adds new scenarios alongside existing ones; `replace` clears the directory first
* `--json` (boolean, optional): Output as JSON
* `--last` (boolean, optional): Download from the most recent generation run

**Arguments**

* `id` (string, required, repeatable): Generation IDs to download. Can specify multiple IDs. Either `id` or `--last` is required.

If the generation run is still in progress or pending, the command reports the status and exits.

**Downloaded structure:**

```
evals/
  <7-char-hash>-<slug>/
    task.md          ← task brief shown to the agent
    criteria.json    ← weighted checklist rubric
    scenario.json    ← fixture with repo URL, commit ref, and context exclude patterns
```

**Examples**

```sh
# Download from the most recent generation run
$ tessl scenario download --last

# Download to a custom directory, replacing existing scenarios
$ tessl scenario download --last --output=my-evals --strategy=replace

# Download a specific run
$ tessl scenario download 019c4791-9eec-7458-b28a-6c94405a3d38
```

***

## Evaluations

For more information on workflows and usage, see [Prove a skill works using evaluation](/improving-your-skills/evaluate-skill-quality-using-scenarios).

### tessl eval run

Run evals from a scenarios directory. The context under test, if any, comes from `--context`; with no context, the run is the baseline variant alone (see Notes).

* **Codebase eval** — source directory contains `scenario.json` fixtures → runs with smart defaults (agent `claude:deepseek-v4-flash`, context pattern from `fixture.exclude`, context ref `infer`)
* **Plugin eval** — source contains `.tessl-plugin/plugin.json` → runs the plugin's own evals. Pass the plugin root directory (the directory that contains `.tessl-plugin/`, not `.tessl-plugin/` itself).

Pointing at a plugin directory is shorthand: `tessl eval run ./my-plugin` expands to `tessl eval run ./my-plugin/evals --context ./my-plugin` — the plugin's `evals/` as the scenarios, the plugin itself as the context. An explicit `--context` opts out of the shorthand.

**Usage**

```sh
tessl eval run [--agent <agent:model>] [--scorer-agent <agent:model>] [--context <source>] [--context-commit <ref>] [--skill <name>]... [--skip-baseline] [--runs <count>] [--label <text>] [--env-file <path>] [--skip-forced-context-activation] [--skip-scoring] [--force] [--quality-check] [--list-agents] [--yes] [--json] [<source>]
```

**Flags**

* `--agent` (string, optional): Agent and model as `agent:model` (e.g. `claude:claude-sonnet-4-6`). Run `tessl eval run --list-agents` to see supported values. Default: `claude:deepseek-v4-flash`
* `--scorer-agent` (string, optional): Override the agent and model used for the scoring step (`agent:model`); the solver agent is unchanged.
* `--context` (string, optional): Context to test — a local path (a plugin directory, or a file/glob), or a published `workspace/plugin@version`. Adds the with-context variant alongside the baseline. See the examples below.
* `--context-commit` (string, optional): Commit, branch, or tag to source a local `--context` from instead of the working tree. Requires `--context`.
* `--skill` (string, optional, repeatable): Narrow a local plugin `--context` to specific skills. Local plugin contexts only — not valid with a published context.
* `--skip-baseline` (boolean, optional): Skip the always-on baseline variant, running only the with-context variant.
* `--runs` / `-n` (number, optional): Number of times to repeat each agent configuration.
* `--label` / `-l` (string, optional): A short description to attach to this eval run. Visible in `tessl eval list` and the Tessl web UI.
* `--env-file` (string, optional): Path to a `.env` file whose variables are encrypted client-side and made available to the run's sandbox environment.
* `--skip-forced-context-activation` (boolean, optional): Omit the prompt line that tells the agent to use the injected context, so the run measures whether the agent activates the context on its own. Default off (the agent is told to use the context).
* `--skip-scoring` (boolean, optional): Skip the rubric scoring step. Default off (runs are scored).
* `--force` / `-f` (boolean, optional): Re-run all evals, including previously solved cases.
* `--quality-check` (boolean, optional): Exclude misleading scenarios (low feasibility, rubric leakage, low value) from the run. Excluded scenarios appear in `tessl eval view` under a `✗ Excluded by quality check` line.
* `--list-agents` (boolean, optional): Print the supported `agent:model` values, then exit without running an eval. Combine with `--json` for a machine-readable shape.
* `--yes` / `-y` (boolean, optional): Skip the confirmation prompt for large-scale eval runs.
* `--json` (boolean, optional): Output eval run IDs as JSON immediately without polling.

**Arguments**

* `source` (string, optional): Path to a plugin folder or scenarios directory. Defaults to the current directory if omitted.

**Notes**

* A run has up to two variants. The **baseline** solves each scenario as authored; the **with-context** variant solves it with the injected context added on top. Baseline is not an empty run — each scenario keeps any fixtures it defines; no context is injected on top. The with-context variant runs when context is specified. Baseline runs by default; use `--skip-baseline` to run only the with-context variant.
* Eval runs require this directory to be linked to a Tessl project first, and always run under that project's workspace. See [Projects overview](/projects/overview).
* To measure whether the agent activates the injected context on its own, with no rubric scoring, combine both flags: `--skip-forced-context-activation --skip-scoring`.
* Ctrl-C detaches without cancelling — runs continue server-side. The CLI prints each run ID.

**Agent format:** `<agent>:<model>` — run `tessl eval run --list-agents` for the supported list.

**Examples**

```sh
# Run a plugin's evals (shorthand for ./my-plugin/evals --context ./my-plugin)
$ tessl eval run .

# ...or point at the plugin by path
$ tessl eval run ./my-plugin

# Run a scenarios directory directly — baseline only, no context
$ tessl eval run ./evals/

# Force re-run all evals
$ tessl eval run --force ./my-plugin

# Run with a specific agent
$ tessl eval run ./evals/ --agent claude:claude-sonnet-4-6

# List the supported agent:model values
$ tessl eval run --list-agents

# Skip scenarios the LLM judge flags as misleading
$ tessl eval run ./my-plugin --quality-check

# Measure context activation only: don't force the agent to use the context, and skip scoring
$ tessl eval run ./my-plugin --skip-forced-context-activation --skip-scoring

# Test a published context against a scenarios directory
$ tessl eval run ./evals/ --context engteam/my-plugin@1.0.0

# Test a local plugin directory as the context
$ tessl eval run ./evals/ --context ./my-plugin

# Test a glob of local files as the context
$ tessl eval run ./evals/ --context 'src/**/*.knowledge.md'

# Test a local context as it was at a specific commit
$ tessl eval run ./evals/ --context ./my-skill --context-commit HEAD

# Run only the with-context variant (skip the baseline)
$ tessl eval run ./my-plugin --skip-baseline

# Label a run for easier identification later
$ tessl eval run ./my-plugin --label "testing claude-opus-4-6"

# Pass secrets into the sandbox via an env file
$ tessl eval run ./my-plugin --env-file ./secrets.env
```

### tessl eval list

List recent eval runs in reverse chronological order.

**Usage**

```sh
tessl eval list [--json] [--limit <count>] [--mine] [--workspace <name>] [--plugin <name>] [--status <status>] [--context-type <type>]
```

**Flags**

* `--json` (boolean, optional): Output results as JSON
* `--limit` (number, optional): Maximum number of eval runs to display (default: 20)
* `--mine` (boolean, optional): Only show eval runs created by you
* `--workspace` / `-w` (string, optional): Filter by workspace name
* `--plugin` (string, optional): Filter by plugin name
* `--status` (string, optional): Filter by run status. Supported values: `pending`, `completed`, `failed`
* `--context-type` (string, optional): Filter by eval type. Supported values: `plugin`, `plugin-directory`, `files`, `commit`, `no-context`

**Notes**

* The output table includes ID, Type, Subject, Status, Created By, and Created columns
* The Type column reflects the context fixture used by the run:
  * `plugin` → `Plugin`
  * `plugin-directory` → `Plugin directory`
  * `files` (alias for the `directory` fixture) → `Selected files` when globs filter it to a subset, otherwise `Directory`
  * `commit` → `Commit`
* The Subject column formats entries by fixture: `plugin` runs as `workspace/plugin@version` (or just `workspace/plugin` when no version is set); `plugin-directory` and `files` as the source path; `commit` as `org/repo@ref`
* `--context-type no-context` filters to baseline runs that did not inject any context fixture
* `files` is the documented spelling of the canonical `directory` fixture — both names accepted

**Examples**

```sh
# List all recent eval runs
tessl eval list

# List only completed runs
tessl eval list --status completed

# List your runs in a specific workspace
tessl eval list --mine --workspace myteam

# Output as JSON
tessl eval list --json
```

### tessl eval view

View results for a specific eval run.

**Usage**

```sh
tessl eval view [--json] [--last] [<id>]
```

**Flags**

* `--json` (boolean, optional): Output results as JSON
* `--last` (boolean, optional): View results for the most recent eval run

**Arguments**

* `id` (string, optional): Eval run ID

**Examples**

```sh
# View a specific eval run
tessl eval view 019c4791-9eec-7458-b28a-6c94405a3d38

# View the most recent eval run
tessl eval view --last

# View results as JSON
tessl eval view --json 019c4791-9eec-7458-b28a-6c94405a3d38
```

### tessl eval retry

Re-run a failed eval run.

**Usage**

```sh
tessl eval retry [--json] [--last] [<id>]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--last` (boolean, optional): Retry the most recent eval run

**Arguments**

* `id` (string, optional): Eval run ID to retry. Either `id` or `--last` is required.

**Examples**

```sh
# Retry a specific eval run
tessl eval retry 019c4791-9eec-7458-b28a-6c94405a3d38

# Retry the most recent eval run
tessl eval retry --last
```

***

## Agent

The `tessl agent` command runs the Tessl agent directly from the CLI. The `tessl agent mcp` subcommands manage MCP server entries used by the Tessl agent.

### tessl agent

Run the Tessl agent in an interactive or non-interactive session.

**Usage**

```sh
tessl agent [flags] [prompt]
```

**Arguments**

* `prompt` (string, optional): Prompt to send to the agent.

**Flags**

* `--permission-mode` (string, optional): Permission mode for this run (supported values: `ask`, `accept-edits`, `auto`, `yolo`) (default: `auto`)
* `--yolo` (boolean, optional): Auto-approve every permission check (alias for `--permission-mode yolo`)
* `--print` / `-p` (boolean, optional): Run non-interactively, print the response, and exit
* `--output` (string, optional): Output format when `--print` is set (supported values: `text`, `json`) (default: `text`)
* `--message` (string, optional): Initial user message to send to the agent
* `--model` (string, optional): Model ID to use (example: `anthropic/claude-opus-4-6`)
* `--thinking` (string, optional): Thinking level (supported values: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`)
* `--continue` / `-c` (boolean, optional): Resume the most recent session for this directory
* `--resume` / `-r` (string, optional): Resume a specific session by ID (uuid or unambiguous prefix)
* `--no-session` (boolean, optional): Disable agent session persistence
* `--session-dir` (string, optional): Agent session storage directory
* `--ephemeral` (boolean, optional): Use in-memory agent settings for this run only
* `--tools` (string, optional): Comma-separated tool allowlist (example: `read,grep,find,ls`)
* `--no-builtin-tools` (boolean, optional): Disable built-in tools but keep extension tools enabled
* `--no-tools` (boolean, optional): Disable all tools
* `--extension` (string, repeatable, optional): Extension source to load (example: `./my-extension.ts` or `npm:my-ext`)
* `--no-extensions` (boolean, optional): Disable extension discovery while keeping explicit `--extension`
* `--skill` (string, repeatable, optional): Skill path to load
* `--no-skills` (boolean, optional): Disable skill discovery while keeping explicit `--skill`
* `--prompt-template` (string, repeatable, optional): Prompt template path to load
* `--no-prompt-templates` (boolean, optional): Disable prompt template discovery while keeping explicit `--prompt-template`
* `--theme` (string, repeatable, optional): Theme path to load
* `--no-themes` (boolean, optional): Disable theme discovery while keeping explicit `--theme`
* `--no-context-files` (boolean, optional): Disable AGENTS.md and CLAUDE.md discovery
* `--no-memory` (boolean, optional): Disable `.tessl/memory` injection and updates

**Notes**

* Uses Tessl-managed model settings and shared Tessl authentication. `tessl login` and `/login` inside the agent are equivalent.
* Use `--print` / `-p` for non-interactive use (combine with `--output json` for structured output).
* Use `--continue` / `-c` to resume the most recent session for the current directory, or `--resume` / `-r <id>` to reopen a specific session.

**Examples**

```sh
# Start an interactive agent session
tessl agent

# Send a one-shot prompt and print the response
tessl agent --print "Summarize the recent changes"

# Run non-interactively with JSON output
tessl agent --print --output json "List the files changed in the last commit"

# Resume the most recent session
tessl agent --continue

# Use a specific model
tessl agent --model anthropic/claude-opus-4-6

# Run in yolo mode (auto-approve all permissions)
tessl agent --yolo
```

### tessl agent mcp add

Add or update an MCP server entry in the agent's MCP configuration.

**Usage**

```sh
tessl agent mcp add [--scope <project|global>] [--url <url>] [--env KEY=VALUE]... [--header Header: value]... <name> [-- <command> [args...]]
```

**Arguments**

* `name` (string, required): MCP server name.

**Flags**

* `--scope` (string, optional): Config scope (supported values: `project`, `global`) (default: `project`). `project` writes to `.mcp.json` in the current directory; `global` writes to `~/.tessl/`.
* `--url` (string, optional): HTTP MCP server URL. Omit for stdio servers.
* `--env` / `-e` (string, repeatable, optional): Environment variable for stdio servers in `KEY=VALUE` format.
* `--header` (string, repeatable, optional): HTTP header for HTTP servers in `Header: value` format.

**Notes**

* For stdio servers: omit `--url` and pass the server command after `--` (e.g., `-- npx my-server`).
* For HTTP servers: pass `--url`. Use `--header` for authentication headers.
* If the server name already exists, it is overwritten.

**Examples**

```sh
# Add a stdio MCP server
tessl agent mcp add my-server -- npx my-mcp-server

# Add a stdio server with environment variables
tessl agent mcp add my-server --env API_KEY=abc123 -- npx my-mcp-server

# Add an HTTP MCP server
tessl agent mcp add my-server --url https://mcp.example.com

# Add an HTTP server with an authentication header
tessl agent mcp add my-server --url https://mcp.example.com --header "Authorization: Bearer token"

# Add to global scope (available across all projects)
tessl agent mcp add my-server --scope global -- npx my-mcp-server
```

### tessl agent mcp get

Show a configured MCP server entry.

**Usage**

```sh
tessl agent mcp get [--json] <name>
```

**Arguments**

* `name` (string, required): MCP server name.

**Flags**

* `--json` (boolean, optional): Emit the resolved server entry as JSON.

### tessl agent mcp list

List all configured MCP servers.

**Usage**

```sh
tessl agent mcp list [--scope <project|global>] [--json]
```

**Flags**

* `--scope` (string, optional): Config scope to list (supported values: `project`, `global`). When omitted, servers from all scopes are listed.
* `--json` (boolean, optional): Output as JSON.

### tessl agent mcp remove

Remove an MCP server entry from the agent's MCP configuration.

**Usage**

```sh
tessl agent mcp remove [--scope <project|global>] <name>
```

**Arguments**

* `name` (string, required): MCP server name.

**Flags**

* `--scope` (string, optional): Config scope to remove from (supported values: `project`, `global`) (default: `project`)

***

## Change

The `tessl change` family assesses, reviews, and verifies the current diff against your team's policies. Commands require a checked-in configuration and produce structured output suitable for CI use.

### tessl change review

Review the current PR/diff with explicit reviewer skills and emit structured review data.

**Usage**

```sh
tessl change review [--skill <skill-ref>]... [--base <ref>] [--output <path>] [--model <provider/model>] [--json]
```

**Flags**

* `--skill` (string, repeatable, optional): Reviewer skill — a local path (SKILL.md or skill directory), an installed skill name, or a registry ref `workspace/plugin[@version]#skill-name`. At least one `--skill` is required; skills are not auto-discovered.
* `--base` (string, optional): Diff base ref (default: `origin/main`)
* `--output` (string, optional): Write results to a file
* `--model` (string, optional): Model ID for the review agent (default: `claude-opus-4-8`)
* `--json` (boolean, optional): Output as JSON

**Notes**

* Each `--skill` runs its own readonly-loop review in parallel; results are interlaced into a single output.
* The summary carries one subheading per skill; inline comments from every skill are interleaved (same-line findings are merged into one comment).
* Comments that fall outside a changed hunk are demoted to the summary as unplaced findings.
* This command only outputs review data — it never posts to GitHub.

**Examples**

```sh
# Review with a skill from the registry
tessl change review --skill tessl/code-review#review-code-legibility

# Review with multiple skills
tessl change review --skill tessl/code-review#review-code-legibility --skill ./local-skill

# Review against a specific base ref and write results to a file
tessl change review --skill tessl/code-review#review-code-legibility --base origin/develop --output review.json --json
```

### tessl change risk

Assess the risk of the current PR/diff against the team's checked-in risk policy and decide whether it requires human review.

**Usage**

```sh
tessl change risk [--base <ref>] [--output <path>] [--fail-if-review-required] [--json]
```

**Flags**

* `--base` (string, optional): Diff base ref (default: the `baseRef` in the risk config, or `origin/main`)
* `--output` (string, optional): Write results to a file
* `--fail-if-review-required` (boolean, optional): Exit non-zero when scoring succeeds but human review is required
* `--json` (boolean, optional): Output as JSON

**Notes**

* Requires a risk policy under `.github/pr-review-gate`. Run `tessl change risk init` first if it is missing.
* Scoring is split into deterministic git measurements, an advisory agent risk judgment, strict validation, and a deterministic gate decision.
* Tooling failures (missing config, failed agent call, malformed output) are reported as distinct errors rather than a "human review required" result.

**Examples**

```sh
# Assess risk for the current diff
tessl change risk

# Assess risk and exit non-zero if human review is required (for CI use)
tessl change risk --fail-if-review-required

# Write results to a file as JSON
tessl change risk --output risk.json --json
```

### tessl change risk init

Write PR review-gate starter files under `.github/pr-review-gate`.

**Usage**

```sh
tessl change risk init [--policy <starter>] [--force] [--json]
```

**Flags**

* `--policy` (string, optional): Starter policy to write. Supported values:
  * `conservative-starter`: strict — clears only clearly surface-level changes; requires review for real behavior changes, sensitive paths, migrations, auth, architecture, and policy/config changes.
  * `official-review-policy-parity`: permissive — requires human review only when the official written review policy requires it.
  * If omitted, prompts interactively.
* `--force` (boolean, optional): Overwrite existing files.
* `--json` (boolean, optional): Output as JSON.

**Notes**

* Writes `config.json`, `policy.md`, and `prompt.md` under `.github/pr-review-gate`.
* Existing files are left untouched unless `--force` is passed.
* Read and edit the generated policy and config before relying on the gate.
* This command does not change branch protection rules or create any GitHub workflow.

**Examples**

```sh
# Write starter files interactively
tessl change risk init

# Write the conservative starter without prompting
tessl change risk init --policy conservative-starter

# Overwrite existing files
tessl change risk init --policy conservative-starter --force
```

### tessl change verify

Verify changed files against configured verifiers.

**Usage**

```sh
tessl change verify [--json] [--all] [--recursive] [--base <ref>] [--changed-files-mode introduced-only|whole-file] [--group <name>] [--verifier <id>]... [--include <glob>]... [--exclude <glob>]... [--max-concurrency <n>] [--max-calls <n>] [--sample <n>] [--batch-timeout <s>] [--dry-run] [--show-files] [--include-disabled] [--output <path>] [--no-cache] [--refresh-cache] [--verbose] [--strict-coverage] [--fail-on-warn] [--github] [<path>...]
```

**Arguments**

* `path` (string, repeatable, optional): Optional path scope (file or directory) to verify

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--all` (boolean, optional): Verify every matching file, not just the diff
* `--recursive` (boolean, optional): Verify each configured root from this project plus its child manifests
* `--base` (string, optional): Diff base ref (default: `main`)
* `--changed-files-mode` (string, optional): How to judge changed files. Supported values: `introduced-only` (gates on diff-attributable violations), `whole-file` (judges each changed file in full) (default: `introduced-only`)
* `--group` (string, optional): Run only this verifier group from the manifest
* `--verifier` (string, repeatable, optional): Run only this verifier id (repeatable)
* `--include` (string, repeatable, optional): Override include glob (repeatable)
* `--exclude` (string, repeatable, optional): Override exclude glob (repeatable)
* `--max-concurrency` (number, optional): Cap parallel judge calls (default: 48)
* `--max-calls` (number, optional): Refuse broad runs above this many judge calls (default: 300)
* `--sample` (number, optional): Run a deterministic sample of verifier targets
* `--batch-timeout` (number, optional): Abort the judge batch if it runs longer than this many seconds
* `--dry-run` (boolean, optional): Show what a verify run would do without spending judge calls
* `--show-files` (boolean, optional): Print the matched file list for each verifier (use with `--dry-run`)
* `--include-disabled` (boolean, optional): Also run groups marked `enabled=false`
* `--output` (string, optional): Write the report to a file instead of stdout
* `--no-cache` (boolean, optional): Skip the local result cache entirely (no reads, no writes)
* `--refresh-cache` (boolean, optional): Skip cache reads but save new results
* `--verbose` (boolean, optional): Show every considered file/verifier target
* `--strict-coverage` (boolean, optional): Stale `covered_by` links cause non-zero exit even when judges pass
* `--fail-on-warn` (boolean, optional): Treat warning verdicts as non-zero exit
* `--github` (boolean, optional): Emit GitHub Actions warning/error annotations for findings

**Examples**

```sh
# Verify the current diff against configured verifiers
tessl change verify

# Preview what a run would do without spending judge calls
tessl change verify --dry-run --show-files

# Verify only a specific group and emit GitHub annotations (for CI use)
tessl change verify --group my-group --github
```

### tessl change verify suggest-scopes

Suggest repo-specific verifier scopes for a group.

**Usage**

```sh
tessl change verify suggest-scopes [--json] [--group <name>] [--heuristic] [--no-llm] [--apply] [--force]
```

**Flags**

* `--json` (boolean, optional): Output as JSON
* `--group` (string, optional): Suggest scopes only for this verifier group
* `--heuristic` (boolean, optional): Use the offline heuristic instead of the default LLM suggestion
* `--no-llm` (boolean, optional): Alias for `--heuristic`
* `--apply` (boolean, optional): Write suggestions into `tessl.json`
* `--force` (boolean, optional): Replace existing verifier-level overrides

### tessl change verify lint

Validate a verifier JSON file against the schema.

**Usage**

```sh
tessl change verify lint <verifier.json>
```

**Arguments**

* `verifier.json` (string, required): Path to the verifier JSON file to validate

***

## Launch

The `tessl launch` family runs agent workflows. Use `tessl launch skill` to run a specific skill with a chosen agent, or `tessl launch <agent>` to open an interactive agent session. The `list`, `view`, and `logs` subcommands inspect past cloud launch runs.

### tessl launch \<agent>

Launch a coding agent in an interactive session.

**Usage**

```sh
tessl launch <agent>
```

**Arguments**

* `agent` (string, required): Coding agent to launch. Supported values: `claude-code`, `codex`, `gemini`, `cursor`, `copilot`, `openhands`, `tessl-agent`.

**Examples**

```sh
# Launch Claude Code
tessl launch claude-code

# Launch Cursor
tessl launch cursor
```

### tessl launch skill

Run a skill using an agent.

**Usage**

```sh
tessl launch skill <skill> [--agent <agent>] [--interactive] [--yolo] [--instructions <text>]
tessl launch skill <skill> --cloud --repo <owner/name> [--agent <agent>] [cloud flags]
```

**Arguments**

* `skill` (string, required): Skill name (`workspace/skill[@version]`) or local path (`file:path/to/skill`).

**Flags**

* `--agent` (string, optional): Agent to run the skill with. Supported values: `claude-code`, `codex`, `gemini`, `cursor`, `copilot`, `openhands`, `tessl-agent`. Required for local (non-cloud) runs; with `--cloud` it selects the cloud strategy (supported: `claude-code`, `cursor`, `codex`, `tessl-agent`).
* `--interactive` / `-i` (boolean, optional): Run the agent in the foreground instead of streaming output.
* `--yolo` (boolean, optional): Skip agent permission prompts and approval checks.
* `--instructions` (string, optional): Instructions to append to the skill prompt.

**Cloud flags**

Run the skill against a repository in the cloud rather than locally.

* `--cloud` (boolean, optional): Run the skill against a repo in the cloud.
* `--repo` (string, optional): Target repository as `owner/name` or URL (required with `--cloud`).
* `--base-branch` (string, optional): Branch to clone and target the PR against (default: `main`).
* `--snapshot` (string, optional): Recipe-runner snapshot to run the cloud launch on.
* `--env-file` (string, optional): Path to a `.env` file whose variables are encrypted and made available to the cloud launch.
* `--workspace` (string, optional): Name of workspace to launch in (default: linked project workspace).
* `--wait` / `--no-wait` (boolean, optional): Wait for the cloud launch to finish before returning (default: wait; use `--no-wait` to return immediately).
* `--label` (string, optional): Label to describe this launch run.
* `--model` (string, optional): Model to use for the cloud launch run.
* `--cwd` (string, optional): Subdirectory to run the skill in, relative to the current directory (default: repo root).

**Examples**

```sh
# Run a skill with the Tessl agent
tessl launch skill engteam/my-skill --agent tessl-agent

# Run a skill interactively with Claude Code
tessl launch skill engteam/my-skill --agent claude-code --interactive

# Run a skill and skip permission prompts
tessl launch skill engteam/my-skill --agent tessl-agent --yolo

# Run a skill with additional instructions
tessl launch skill engteam/my-skill --agent tessl-agent --instructions "Focus on the auth module only"

# Run a local skill by path
tessl launch skill file:./my-skill --agent claude-code

# Run a skill against a repo in the cloud and wait for the result
tessl launch skill engteam/my-skill --cloud --repo tesslio/monorepo --agent tessl-agent

# Trigger a cloud launch without waiting for completion
tessl launch skill engteam/my-skill --cloud --repo tesslio/monorepo --no-wait
```

### tessl launch list

List recent launch runs in reverse chronological order.

**Usage**

```sh
tessl launch list [--workspace <name>] [--limit <count>] [--json]
```

**Flags**

* `--workspace` / `-w` (string, optional): Filter by workspace name.
* `--limit` (number, optional): Maximum number of launch runs to display (default: 20).
* `--json` (boolean, optional): Output as JSON.

**Examples**

```sh
# List recent launch runs
tessl launch list

# List runs for a specific workspace
tessl launch list --workspace engteam

# List as JSON
tessl launch list --json
```

### tessl launch view

View status and details for a launch run.

**Usage**

```sh
tessl launch view [--json] <id>
```

**Arguments**

* `id` (string, required): Launch run ID.

**Flags**

* `--json` (boolean, optional): Output as JSON.

**Examples**

```sh
# View a specific launch run
tessl launch view 019c4791-9eec-7458-b28a-6c94405a3d38
```

### tessl launch logs

Print agent logs for a launch run.

**Usage**

```sh
tessl launch logs <launchRunId>
```

**Arguments**

* `launchRunId` (string, required): Launch run ID.

**Examples**

```sh
# Print logs for a launch run
tessl launch logs 019c4791-9eec-7458-b28a-6c94405a3d38
```


# Configuration files

## Plugin configuration

### plugin.json

The `.tessl-plugin/plugin.json` file is the configuration file for a plugin. It includes important metadata that helps Tessl identify, version and describe plugins.

Plugins can contain four types of content:

* **rules**: Rule files (markdown) that provide subjective guidance and instructions to agents, such as coding standards, best practices, and organizational policies.
* **skills**: Skill files (SKILL.md format) that extend AI coding agents with specialized knowledge, workflows, or tool integrations. Skills follow the [Agent Skills Specification](https://agentskills.io/specification).
* **MCP servers**: [Model Context Protocol](https://modelcontextprotocol.io) servers, declared in a bundled `.mcp.json` file, that connect agents to external tools and services during a session.
* **hooks**: Deterministic commands that run automatically in response to agent events (for example, running a linter after an edit), declared with the `hooks` and `nativeHooks` fields.

A plugin can contain one or more of these content types. For example, a plugin might have only rules, only skills, only MCP servers, or any combination of the four.

Here's an example `.tessl-plugin/plugin.json`:

```json
{
  "name": "tessl/skill-optimizer",
  "version": "0.8.1",
  "description": "Optimize your skills and plugins: review SKILL.md quality, generate eval scenarios, run evals, compare across models, diagnose gaps, and re-run until scores improve.",
  "private": false
}
```

The following sections show examples of plugins with different content types. Remember that plugins can contain **rules**, **skills**, **MCP servers**, or **hooks**.

For example, here's what the `./tessl-plugin/plugin.json` for a private, rules-only plugin might look like:

```json
{
  "name": "myorg/code-style",
  "version": "0.0.1",
  "description": "TypeScript code style guidelines for MyOrg",
  "private": true,
  "rules": "rules" // not needed, when rules is omitted, "rules" is used as the path by convention
}
```

Plugins can also contain skills, which are reusable capabilities that extend AI coding agents. Here's an example of a plugin with skills:

```json
  {
  "name": "myworkspace/my-skill",
  "version": "1.0.0",
  "description": "A skill that provides specialized functionality for my agent",
  "private": true,
  "skills": "skills" // not needed, when skills is omitted, "skills" is used as the path by convention
}
```

And here's a plugin that combines rules, and skills:

```json
{
  "name": "myorg/comprehensive-plugin",
  "version": "2.0.0",
  "description": "Complete plugin with rules, and skills",
  "rules": "rules",      // can be omitted, set to "rules" when missing
  "skills": "skills",    // can be omitted, set to "skills" when missing
}
```

`.tessl-plugin/plugin.json` supports the following fields:

`name (string, required)`: Name for the plugin in workspace/plugin-name format

`version (string, required)`: Semantic version of the plugin

`description (string, required)`: Brief description of the plugin

`private (boolean, optional)`: Controls plugin visibility in the registry. Set to false to make the plugin publicly discoverable by all users, or true to restrict access to your workspace only. Defaults to true if not specified. Note: Authentication with tessl login is required to publish plugins regardless of this setting.

`rules (string or string[], optional)`: Path to a directory of rule files, or an array of specific .md file paths. Rules are always-loaded guidance for agents — the plugin.json equivalent of steering. Omit to use convention discovery, which scans ./rules/ for .md files automatically.

`skills (string or string[], optional)`: Path to a directory containing skill subdirectories, or an array of specific skill directory paths. Each skill directory must contain a SKILL.md file. Skills are reusable capabilities that extend AI coding agents with specialized knowledge, workflows, or tool integrations. Omit to use convention discovery, which scans ./skills/ for subdirectories containing SKILL.md automatically.

`mcpServers (string, optional)`: Pointer to the plugin's bundled `.mcp.json` file at the plugin root. The value is fixed — either `".mcp.json"` or `"./.mcp.json"`. Declaring it is optional and non-gating: the `.mcp.json` file is discovered by convention at the plugin root whether or not the manifest mentions it, so the field only lets authors be explicit. Note that this string field is a *pointer* to the file — not to be confused with the `mcpServers` map *inside* the `.mcp.json` file itself (see below), which lists the actual servers. See [Bundled `.mcp.json`](#bundled-mcp-json) for the file's shape.

`hooks (object, optional)`: Cross-agent (generic) hooks, deterministic commands that run in response to agent events. A map of event name to hook groups, authored once and dispatched to every supported agent. See [Hooks](#hooks) for the shape.

`nativeHooks (object, optional)`: Per-agent (native) hooks, hook entries written in an individual agent's own hook format, keyed by agent id. Use this when a hook needs an agent-specific event or field the generic `hooks` field can't express. See [Hooks](#hooks).

A note on plugin.json validation:

1. `rules`, `skills`, `mcpServers`, `hooks`, and `nativeHooks` are all optional. A plugin with none of these relies entirely on convention discovery. There is no requirement that at least one content type be explicitly declared.

### Bundled `.mcp.json`

A plugin declares MCP (Model Context Protocol) servers by adding a `.mcp.json` file at the plugin root — the same format Claude Code already reads in a repository. This is the file the `mcpServers` pointer field above points at; it is discovered by convention even when the field is omitted. (The pointer field shares the `mcpServers` name with the map *inside* this file, described below, but the two are distinct: the field names the file, the map lists the servers.)

> **Note:** This is a *different* file from the `.mcp.json` Tessl writes into a consuming project (see [MCP configuration files](#mcp-configuration-files) below). The plugin-bundled `.mcp.json` is authored and shipped *inside* the plugin package to declare the servers it provides. The project `.mcp.json` is generated by Tessl in the consuming repository to wire the agent up to Tessl's own `tessl mcp` server. They share a name and format but serve different purposes.

The file has a top-level `mcpServers` map of server name to server config. Each config is one of two transport types, selected by its `type` field:

**stdio** — a server the agent launches as a local subprocess:

* `type` (string, required): `"stdio"`.
* `command` (string, required): The executable to run.
* `args` (string\[], optional): Arguments passed to the command.
* `env` (object, optional): Environment variables (string values) set for the process.

**http** — a server reachable over HTTP:

* `type` (string, required): `"http"`.
* `url` (string, required): The server endpoint. Must be an `http` or `https` URL.
* `headers` (object, optional): HTTP headers (string values) sent with each request.

```json
{
  "mcpServers": {
    "feature-flags": {
      "type": "stdio",
      "command": "node",
      "args": ["./scripts/flags-mcp.js"],
      "env": {
        "FLAGS_ENV": "staging"
      }
    },
    "component-library": {
      "type": "http",
      "url": "https://components.internal.example.com/mcp",
      "headers": {
        "X-Workspace": "myorg"
      }
    }
  }
}
```

#### How bundled servers are installed

When a plugin is installed, Tessl materialises its bundled servers into each supported agent's own native MCP configuration — the file that agent already reads, in the format and location it expects. By default servers are written into the project; installing with `--global` writes them into each agent's user-scope configuration instead.

Tessl reconciles these servers on every install and prunes them when the plugin is uninstalled. Your own hand-added MCP servers are always left untouched. If you hand-edit a server Tessl wrote, it stops recognising the entry as its own and leaves it in place with a warning rather than overwriting it.

### Hooks

Hooks are deterministic commands that run automatically in response to events within an agent harness: running a linter after an edit, validating a spec when a route handler changes, or posting a summary when a session ends. A plugin declares hooks in `.tessl-plugin/plugin.json` using one of **two tiers**, expressed as two separate top-level fields:

* **`hooks`**: the **cross-agent (generic)** tier. You author **one** command against Tessl's generic event schema, and Tessl dispatches it to each agent that supports the event. This is the paved road: use it whenever the hook's logic is agent-independent (a linter, a validator, a notifier) so it works across agents without per-agent authoring. Not every agent implements every event; an event an agent doesn't support is skipped for that agent (see the note below).
* **`nativeHooks`**: the **per-agent (native)** tier. You write hook entries in an individual agent's own hook format, keyed by agent id. This is the escape hatch: use it when a hook needs an agent-specific event or field that the generic schema can't express. Tessl carries these entries through near-verbatim. It does not own the shape, so each agent validates its own entries.

A plugin can use either tier or both.

#### Cross-agent hooks (`hooks`)

The `hooks` field is a map of **event name** to an array of **hook groups**. The supported event names are:

* `PreToolUse`: before the agent runs a tool.
* `PostToolUse`: after a tool call completes.
* `UserPromptSubmit`: when the user submits a prompt.
* `SessionStart`: when a session begins.
* `Stop`: when the agent finishes responding.

> **Note:** Agents vary in which of these events they implement. Gemini, for example, supports only `PreToolUse`, `PostToolUse`, and `SessionStart`. When an agent does not implement a declared event, that event is skipped for that agent (the rest still install), so prefer events supported by the agents you target.

Each hook group has an optional `matcher` and one or more command hooks:

* `matcher` (string, optional): A tool-name filter: a single tool name (`Bash`), a pipe-separated list (`Edit|Write`), or a regex. Omit it to fire the group for every tool call. It only narrows tool-call events (`PreToolUse`, `PostToolUse`); on `UserPromptSubmit`, `SessionStart`, and `Stop` there is no tool name to match, so omit it.
* `hooks` (array, required): One or more command hooks (see below).

A **command hook** has a `type` of `"command"` and takes one of two forms, selected by whether `args` is present:

* **Exec form** (`args` present): `command` is the program to spawn (`argv[0]`, e.g. `bash` or `node`) and `args` are its arguments. The program is spawned directly, with **no shell**, so pipes, globs, and `&&` are *not* interpreted.
* **Shell form** (`args` absent): `command` is a full command string run via `sh -c`, so shell features like pipes, globs, and `&&` work.

Command hook fields:

* `type` (string, required): Always `"command"`.
* `command` (string, required): The program (exec form) or the shell command string (shell form).
* `args` (string\[], optional): The program's arguments. Its presence selects exec form; its absence selects shell form. `[]` is a valid exec form (a program with no arguments).
* `env` (object, optional): Environment variables for the hook. A value can be a static string, or `{ "fromEnv": "VAR" }` to forward the named variable from the agent's shell environment at hook-fire time.

To reference a file bundled inside your plugin, use the `${TESSL_PLUGIN_DIR}` token: it is substituted across `command` and `args` with the plugin's installed location. A **bare relative path is not anchored to the plugin**; it resolves against the event's working directory (the project root) at spawn time, like any argument. In shell form, quote the token (`"${TESSL_PLUGIN_DIR}/lint.sh"`) so paths with spaces survive.

> **Note:** Shell form runs under POSIX `sh -c` (on Windows this relies on git-bash). PowerShell and `cmd.exe` are not used.

```json
{
  "name": "engteam/lint-on-edit",
  "version": "1.0.0",
  "description": "Run the workspace linter after the agent edits a file",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash",
            "args": ["${TESSL_PLUGIN_DIR}/scripts/lint.sh"]
          }
        ]
      }
    ]
  }
}
```

#### Per-agent hooks (`nativeHooks`)

The `nativeHooks` field is a map keyed by **agent id** (for example `claude-code`). Each agent's value is that agent's own native hook config, keyed by the agent's own event names, which Tessl passes through near-verbatim. Because Tessl does not own this shape, refer to the target agent's own hook documentation for the events and fields it accepts.

`${TESSL_PLUGIN_DIR}` works here too, but is resolved at **install time** (not hook-fire time) into a path the agent will find when the hook fires: anchored to the agent's project-directory variable or a repo-relative path in project scope, and an absolute path in global scope. Resolved paths that would escape the plugin directory are rejected.

```json
{
  "name": "engteam/native-hook-example",
  "version": "1.0.0",
  "description": "A hook using an agent-specific event",
  "nativeHooks": {
    "claude-code": {
      "PreToolUse": [
        {
          "matcher": "Bash",
          "hooks": [
            {
              "type": "command",
              "command": "${TESSL_PLUGIN_DIR}/scripts/guard.sh"
            }
          ]
        }
      ]
    }
  }
}
```

#### How hooks are installed

When a plugin is installed, Tessl materialises its hooks into each supported agent's own native hook configuration: the file that agent already reads.

* **Cross-agent hooks** are installed as a `tessl hook run` dispatch entry: the agent invokes Tessl when the event fires, and Tessl runs your declared command, translating the agent's native event payload to and from the generic schema.
* **Per-agent hooks** are written into the agent's config as your own entries (after `${TESSL_PLUGIN_DIR}` is resolved).

By default hooks are written into the project; installing with `--global` writes them into each agent's user-scope configuration instead. Agents without a user-scope hook location are the exception: OpenHands, for instance, has no global hook config, so `--global` skips it with a warning rather than writing an unread file. Tessl tracks the entries it writes and prunes them when the plugin is uninstalled, leaving your hand-added hooks untouched.

## Project configuration

### tessl.json

The `tessl.json` file is the manifest for your repository's plugin dependencies. It specifies which plugins are installed and their versions:

```json
{
  "name": "my-project",
  "dependencies": {
    "workspace/plugin-name": {
      "version": "1.0.0"
    }
  }
}
```

This file is created automatically when you run `tessl init`, `tessl install`, or `tessl project create`. Tessl manages the dependencies in this file as you install or uninstall plugins.

### Verify block

The optional `verify` block in `tessl.json` configures `tessl change verify`. It groups the standalone verifier JSON files in your repository, points each group at the files it should check, and sets the severity of its findings. The block is the runtime source of truth for verification — `tessl change verify` reads it plus the verifier files its groups reference.

```json
{
  "name": "my-project",
  "dependencies": {
    "workspace/plugin-name": {
      "version": "1.0.0"
    }
  },
  "verify": {
    "groups": {
      "core": {
        "path": "verifiers/*.json",
        "level": "error",
        "include": ["src/**/*.ts"],
        "exclude": ["**/*.test.ts"]
      }
    }
  }
}
```

#### `verify`

* `groups` (object, optional): Named groups of verifiers. Keys are arbitrary group names; values are group entries (see below).

#### Group entry

Each entry under `verify.groups` accepts:

* `path` (string or string\[], required): Path or glob (or list of them) to the verifier JSON files this group runs.
* `level` (string, required): Severity for the group's findings — one of `info`, `warn`, or `error`. `error` makes a failing check blocking in CI; `warn` and `info` are advisory.
* `include` (string\[], optional): Globs of files this group targets. Files added later that match are covered automatically.
* `exclude` (string\[], optional): Globs of files to drop from the group's targets.
* `content` (object, optional): Content-based file filtering (see [Content predicate](#content-predicate)).
* `enabled` (boolean, optional): Set to `false` to skip the whole group.
* `verifiers` (object, optional): Per-verifier overrides, keyed by verifier file name. Each override accepts `include`, `exclude`, `content`, `enabled`, and `level` — letting the same verifier be advisory (`warn`) in one project and blocking (`error`) in another without editing the verifier JSON.

#### Content predicate

The `content` field (on a group or a per-verifier override) keeps or drops files by what they contain, before the judge runs:

* `containsAny` (string\[]): Keep files containing at least one of these literal strings.
* `containsAll` (string\[]): Keep files containing every one of these literal strings.
* `regexAny` (string\[]): Keep files matching at least one JavaScript regular-expression pattern.
* `regexAll` (string\[]): Keep files matching every JavaScript regular-expression pattern.
* `notContainsAny` (string\[]): Drop files containing any of these literal strings.
* `notRegexAny` (string\[]): Drop files matching any of these JavaScript regular-expression patterns.

#### Verifier JSON files

The files referenced by a group's `path` describe the invariant to check. A verifier file accepts:

* `name` (string, required): Short human label for CLI output. The filename remains the stable identifier.
* `instruction` (string, required): What the judge should check for.
* `relevant_when` (string, required): When the verifier applies.
* `context` (string, required): Background the judge needs to score the file.
* `scope` (string, required): The unit the judge evaluates — `file`, `paths`, or `diff`.
* `scope_reason` (string, required): Why that scope is the right target shape.
* `checklist` (array, required): One or more check items, each with a `name`, a `rule`, and an optional `relevant_when`.
* `references` (array, optional): Informational provenance for where the rule came from.
* `project_when` (object, optional): A precondition evaluated once per run (no LLM call); when it is false the verifier is skipped entirely. Supports `package_json_has_dep`, `file_exists`, `glob_matches`, and the combinators `any_of`, `all_of`, and `not`.
* `covered_by` (array, optional): Links to existing lint rules or tests that already enforce the rule. When every link is fresh the judge is skipped and the verifier reports as `covered`; when any link is stale the judge runs anyway and the staleness is surfaced.

```json
{
  "name": "User-facing errors include a next step",
  "instruction": "When code returns a user-facing error, it should tell the user what to do next.",
  "relevant_when": "TypeScript code that constructs a UserFacingError or prints an error for a CLI command.",
  "context": "CLI errors should be actionable for users running commands in a terminal.",
  "scope": "file",
  "scope_reason": "Each command file can be checked independently for its own error handling.",
  "checklist": [
    {
      "name": "actionable-error",
      "rule": "Each user-facing error includes either the command to run next, the flag to change, or the file to inspect."
    }
  ]
}
```

Validate a verifier file with `tessl change verify lint <file>`, and preview which files a group matches with `tessl change verify --dry-run --all --show-files` before running judge calls. See [Setting up agentic code review](/tutorials/setting-up-agentic-code-review) for the end-to-end workflow.

### Tessl project link

`tessl.json` stores the Tessl configuration for this repository, including its project link.

A Tessl project gives Tessl a stable place to attach eval runs and other repository-connected data, so your results stay tied to your codebase over time.

For example:

```diff
{
-   "name": "my-project",
+   "name": "my-workspace/my-project",
    "dependencies": {
      "workspace/plugin-name": {
        "version": "1.0.0"
    }
  }
}
```

If the local project link is missing or no longer correct, use `tessl project link` or `tessl project repair`. See [Manage projects from the CLI](/projects/manage-projects-from-the-cli).

### Project Mode (Managed vs Vendored)

The `mode` field in `tessl.json` controls how plugin content is managed in your repository. You can choose between two modes depending on your workflow and requirements:

#### Managed mode

**Default for existing repositories** - plugin contents are gitignored like `node_modules`

```json
{
  "name": "my-project",
  "mode": "managed",
  "dependencies": {
    "workspace/plugin-name": {
      "version": "1.0.0"
    }
  }
}
```

**Behavior:**

* plugin contents in `.tessl/plugins/` are automatically added to `.gitignore`
* plugins are reinstalled from the registry based on `tessl.json`
* Works like package managers (npm, pip) - dependencies not committed
* Keeps repository clean and small
* Team members run `tessl install` after cloning the repository

**Best for:**

* Repositories with frequent plugin updates
* Teams who prefer lighter repositories
* Standard development workflows with internet access

#### Vendored mode

**Default for new repositories** - plugin contents are committed to your repository

```json
{
  "name": "my-project",
  "mode": "vendored",
  "dependencies": {
    "workspace/plugin-name": {
      "version": "1.0.0"
    }
  }
}
```

**Behavior:**

* Plugin contents in `.tessl/plugins/` are committed to version control
* Exact plugin versions are checked into the repository
* Works offline without registry access
* Team members get plugins automatically when cloning
* Ensures reproducible builds in all environments

**Best for:**

* Air-gapped or restricted network environments
* Repositories requiring complete offline capability
* Ensuring exact reproducibility without external dependencies
* Compliance requirements for vendoring all dependencies

#### Switching modes

You can change modes at any time by updating the `mode` field in `tessl.json`:

```json
{
  "name": "my-project",
  "mode": "vendored",  // Change to "managed" or "vendored"
  "dependencies": {
    "workspace/plugin-name": {
      "version": "1.0.0"
    }
  }
}
```

After changing the mode:

* Tessl will automatically update `.gitignore` accordingly
* In **managed mode**, `.tessl/plugins/` will be added to `.gitignore`
* In **vendored mode**, `.tessl/plugins/` will be removed from `.gitignore`
* Commit the changes to apply the new mode for your team

#### Default behavior

* **New projects** (running `tessl init` in a fresh project): Defaults to **vendored mode**
* **Existing projects** (running `tessl init` in a project with existing plugins): Defaults to **managed mode**
* You can explicitly set the mode in `tessl.json` to override the default

### .tessl directory

The `.tessl` directory contains Tessl's configuration and cached data:

```
.tessl/
|-- .gitignore                  # Ignores plugins/ and RULES.md (in managed mode)
|-- plugins/                      # Downloaded plugins
|   `-- workspace/
|       `-- plugin-name/
|           |-- .tessl-plugin/plugin.json
|           |-- evals
|           |-- rules/           # Rule files
|           `-- skills/          # Skill files
|               `-- skill-name/
|                   `-- SKILL.md
`-- RULES.md                    # Generated rules for agents (not committed to git)
```

The `.tessl/.gitignore` file is automatically managed based on your project mode:

* **Managed mode**: The `plugins/` directory and `RULES.md` are added to `.gitignore` (not committed to version control)
* **Vendored mode**: The `plugins/` directory is removed from `.gitignore` (committed to version control), but `RULES.md` remains ignored as it's generated from plugin content

### Plugin directory structure

Below we see a plugin structure as it's being authored:

<pre><code><strong>&#x3C;your-plugin/skill-name>/
</strong><strong>├── .tessl-plugin/
</strong>│     └── plugin.json
└── skills/&#x3C;your-skill-name>/SKILL.md
├── evals/
│     └── scenario-1/
│          ├── task.md
│          ├── criteria.json
│          └── scenario.json        # optional: fixtures, includes, setup scripts
│     └── scenario-2/
</code></pre>

* evals/ is only present if [scenarios](/improving-your-skills/overview-improving-skills-and-plugins) were generated
* skills/\<your-skill-name>/SKILL.md is suggested structure, otherwise plugin.json will need a specific pointer

### Agent rule files

Tessl creates and updates rule files for AI coding agents to help them understand your repository context and installed plugins. The location and format of these files varies by agent:

* **Cursor**:
  * `.cursor/rules/tessl__*.mdc` - plugin-specific rules (auto-generated, not committed to git)
  * `.cursor/rules/tessl_context.mdc` - Instructions for gathering context from Tessl MCP
* **Claude Code**:
  * `CLAUDE.md` - Context file with instructions for gathering context from Tessl MCP
  * `.tessl/RULES.md` - Consolidated rules from all installed plugins
  * `AGENTS.md` - If this file exists, Tessl adds a reference to `.tessl/RULES.md`

These files are created when you run `tessl init --agent <agent-name>` or when Tessl auto-detects an agent in your repository.

### MCP configuration files

When configuring AI agents, Tessl adds MCP (Model Context Protocol) server configuration to connect the agent to Tessl's MCP server. The location varies by agent:

* **Cursor**: `.cursor/mcp.json`
* **Claude Code**: `.mcp.json` in the repository root

These files configure the agent to run `tessl mcp start` as an MCP server, enabling the agent to access Tessl's tools and context.

This is the agent host configuration Tessl writes into a consuming project. It is distinct from the [bundled `.mcp.json`](#bundled-mcp-json) a plugin author ships inside their package to declare the servers the plugin provides.

### AGENTS.md

The `AGENTS.md` file provides repository context to AI coding agents. This file is similar to `CLAUDE.md` and other agent context files used by various AI coding assistants.

**Note**: Tessl does not create or manage `AGENTS.md` directly. However, if `AGENTS.md` exists in your repository, Tessl will automatically add a reference to `.tessl/RULES.md` when you configure an agent with `tessl init`. This allows your agent to access plugin-specific guidance and context.

If you're using `AGENTS.md` in your repository:

* Add your own repository context, coding conventions, and patterns
* Tessl will append a section linking to `.tessl/RULES.md` (marked with `<!-- tessl-managed -->`)
* The content is used by AI agents during code generation

### .tesslignore

Exclude files from plugin validation and packing.

**Purpose**

The `.tesslignore` file allows you to exclude files from orphaned file warnings and prevent them from being included in published plugin packages.

**Location**

Place a `.tesslignore` file in the root of your plugin directory (same level as `.tessl-plugin/plugin.json`).

**Syntax**

Uses gitignore-style patterns:

```gitignore
# Comments start with #

# Exact file names
notes.md

# Glob patterns
*.draft.md

# Directory patterns (trailing slash)
drafts/

# Recursive patterns
**/internal/**

# Path-specific patterns
docs/internal.md

# Negation patterns (exclude from ignore)
!important.md
```

**Default ignored files**

These files are always ignored, even without a `.tesslignore` file:

* `AGENTS.md`
* `CLAUDE.md`
* `GEMINI.md`

**Important rules**

* **Links to ignored files cause errors**: If your docs link to a file that's in `.tesslignore`, validation will fail. This prevents broken links in published plugins.
* **Manifest files can't be ignored**: You cannot put `docs`, `rules`, or `skills` entrypoints in `.tesslignore`.

**Example `.tesslignore`**

```gitignore
# Development notes
notes.md
TODO.md

# Draft files
*.draft.md

# Local testing
test-data/

# Keep this one even though it matches *.draft.md
!important.draft.md
```

## Eval scenario configuration

### scenario.json

`scenario.json` lives next to `task.md` and `criteria.json` in a scenario directory. It declares what the platform sets up in the working directory before an agent solves the task — fixtures to install, local files to copy in, and setup scripts to run.

`scenario.json` is **optional**. With nothing but `task.md` and `criteria.json`, conventional defaults take over (see [Conventional defaults](#conventional-defaults)).

```json
{
  "description": "Add a CSV import endpoint",
  "fixtures": {
    "codebase": {
      "type": "commit",
      "repoUrl": "https://github.com/org/repo.git",
      "ref": "abc1234",
      "exclude": ["*.mdc", "*.md", ".tessl/"]
    }
  },
  "include": ["./resources"],
  "setup": ["./seed-db.sh"]
}
```

#### Fields

* `description` (string, optional): Human-readable summary of the scenario.
* `fixtures` (object, optional): Named external content the platform installs into the working directory. Keys are arbitrary names; values are fixture objects (see [Fixture types](#fixture-types)). Order-independent.
* `include` (string\[], optional): Paths inside the scenario directory copied into the working directory at the **same relative path**. Each entry must be a directory.
* `setup` (string\[], optional): Paths to scripts inside the scenario directory, run **in order** after fixtures and includes are installed.

#### Fixture types

Two fixture types are supported in `scenario.json`:

`commit` — snapshot of a git repo at a specific ref.

```json
{
  "type": "commit",
  "repoUrl": "https://github.com/org/repo.git",
  "ref": "abc1234",
  "installPath": ".",
  "exclude": ["*.mdc"]
}
```

* `repoUrl` (string, required): HTTPS clone URL.
* `ref` (string, required): Commit SHA or any ref resolvable in the remote.
* `installPath` (string, optional, default `.`): Write destination, confined to the working directory.
* `exclude` (string\[], optional): Glob patterns of paths to exclude from the snapshot.

`directory` — content from a local path relative to the scenario.

```json
{
  "type": "directory",
  "path": "./fixtures/seed-data",
  "installPath": "data",
  "include": ["src/**/*.ts"],
  "exclude": ["**/*.test.ts"]
}
```

* `path` (string, required): Read source, resolved relative to the scenario directory but not confined to it; it may resolve to a location outside the scenario directory, including parent traversal.
* `installPath` (string, required): Write destination, confined to the working directory.
* `include` (string\[], optional): Glob patterns of files to keep from the directory. When omitted, the whole directory is installed; when present, only matching files are kept. Applied before `exclude`.
* `exclude` (string\[], optional): Glob patterns of files to remove from the directory. Applied after `include`.

#### Conventional defaults

Without explicit configuration, two on-disk conventions take effect:

* If a `resources/` directory sits alongside `task.md`, it's automatically copied into the working directory at `resources/`. Equivalent to `"include": ["./resources"]`.
* If a `setup.sh` file sits alongside `task.md`, it's automatically run after fixtures and includes install. Equivalent to `"setup": ["./setup.sh"]`.

A scenario directory containing only `task.md`, `criteria.json`, `resources/`, and `setup.sh` therefore needs no `scenario.json` at all.

#### Working directory assembly order

1. Install fixtures (all entries, order-independent).
2. Copy includes (paths preserved).
3. Run setup scripts in `setup` order, with auto-detected `setup.sh` last.

#### Legacy format

A singular `fixture` object (without the `s`) at the top level is read as a `commit` fixture named `codebase` for backward compatibility with scenarios generated before the `fixtures` plural form. Prefer the plural form for new scenarios.

## User preferences

Tessl stores user preferences globally to customize your experience. You can view and modify these preferences using the `tessl config` commands.

### Available preferences

* `shareUsageData` - Whether to share telemetry and usage data with Tessl (defaults to `true`)
* `agents` - Which agents to configure on `tessl init` (default to auto-detect when empty); see supported agents in `tessl init --help` .

### Managing preferences

View all current preferences:

```bash
tessl config get
```

View a specific preference:

```bash
tessl config get shareUsageData
```

Set a preference:

```bash
tessl config set shareUsageData false
```

### Opting out of telemetry

To opt out of sharing telemetry and usage data:

```bash
tessl config set shareUsageData false
```

For more information about data collection, see [Sharing Usage Data](/legal/sharing-usage-data).


# Skill schemas

How a launchable skill declares typed input and output JSON Schemas, how \`$ref\`s are resolved, and the structured result a cloud launch returns.

A launchable skill can declare typed **input** and **output** contracts in its `SKILL.md` frontmatter. When you run the skill with `tessl launch skill --cloud`, Tessl validates the launcher-supplied inputs against the declared input schema before the skill runs, and validates the recorded result against the declared output schema when it finishes — so a launch either conforms to the contract or fails fast with a field-level diagnostic.

This page covers authoring the `schemas` block, the `$ref` forms it accepts, how those refs are resolved, and the structured `result` a launch returns.

## Authoring the `schemas` block

Declare schemas under a single top-level `schemas` key in the skill's `SKILL.md` frontmatter. It has two optional slots, `inputs` and `output`:

```yaml
---
name: greet
description: Greet someone by name.
schemas:
  inputs:
    $ref: ./schemas/inputs.schema.json
  output:
    $ref: ./schemas/output.schema.json
---
```

Each slot is either an **inline JSON Schema** or a single **`$ref`** reference. Both slots are optional and independent — declare one, both, or neither:

* **`schemas.inputs`** — validated against the launcher-supplied inputs (the `INPUTS` object, keyed by the skill's own placeholder names) before the skill runs. A missing required input fails the launch during preparation rather than being discovered mid-run.
* **`schemas.output`** — describes the structured payload the skill produces. It is composed into the returned result (see [The returned result](#the-returned-result)).

A slot may be written inline instead of via a `$ref`:

```yaml
schemas:
  output:
    type: object
    properties:
      message: { type: string }
    required: [message]
    additionalProperties: false
```

For a complete, copyable example — a `greet` skill with both slots and a bundled `./schemas/` directory — see the [quickstart-typed-skill](https://github.com/tesslio/monorepo/tree/main/apps/docs/tiles/quickstart-typed-skill/README.md) tile.

## `$ref` forms

A slot's `$ref` must be a non-empty string and the **sole** key of the slot (you cannot mix `$ref` with other keys). Three forms are accepted:

| Form       | Example                                     | Resolved from                                                                    |
| ---------- | ------------------------------------------- | -------------------------------------------------------------------------------- |
| **inline** | `{ type: object, ... }` (no `$ref`)         | Used as-is; nothing is fetched.                                                  |
| **local**  | `{ $ref: ./schemas/output.schema.json }`    | A file read relative to the `SKILL.md` directory. Must start with `./` or `../`. |
| **remote** | `{ $ref: https://example.com/schema.json }` | Fetched over HTTPS at launch preparation time.                                   |

Anything else (a bare name, an `http://` URL, a fragment-only `#/...` pointer) is rejected.

### Local `$ref`s are contained to the skill bundle

A local `$ref` is resolved relative to the directory holding the `SKILL.md`, but it is **contained** to the skill's bundle: a ref may point at a sibling or a shared file elsewhere in the same bundle (`../shared/output.schema.json`), but one that escapes the bundle directory — lexically or through a symlink — is rejected. This lets skills that genuinely share a contract stay DRY by pointing a local `$ref` at one shared file, without a ref reaching outside the bundle.

### Remote `$ref`s are fetched safely

A remote `$ref` is fetched only at launch **preparation** time (never during plain validation), over a guarded HTTPS client:

* **HTTPS only**, with no embedded credentials.
* **No private or internal targets** — `localhost`, private/reserved IP ranges, and link-local / unique-local IPv6 are refused. The host is re-resolved and pinned to the validated address at connection time, so a DNS-rebinding trick cannot swap in an internal address after the check.
* **Bounded** — a 10-second timeout and a 1 MiB body cap; HTTP redirects are refused outright.

The fetched body must be valid JSON describing a JSON Schema object.

## Resolution precedence

When a launch prepares a skill, each declared slot is resolved into a fully inline JSON Schema:

1. **Read** the `schemas` block from the skill's `SKILL.md` frontmatter. A skill with no `schemas` block declares no contract — its inputs are not validated and its output is left unconstrained.
2. **Resolve** each slot by its form: an inline schema is used as-is; a local `$ref` is read from the bundle; a remote `$ref` is fetched.
3. **Inline** the resolved schema. Resolution is **single-level** — a `$ref` inside a resolved schema document is not followed. Author self-contained schema files.

If a slot cannot be resolved (a malformed block, an unreadable local file, an unfetchable or unsafe remote URL), the launch fails during preparation with a diagnostic naming the failing slot, rather than proceeding with a partial contract.

## The returned result

Every cloud launch returns a fixed **envelope**, regardless of whether the skill declared any schemas:

```json
{
  "status": "succeeded",
  "summary": "One sentence on what the skill did.",
  "output": { }
}
```

* **`status`** — `succeeded` when the skill did its work, or `no-action` when it made no change. This is a coarse "did it change anything" flag; it is distinct from the launch run's own status.
* **`summary`** — a short human-readable sentence on what the skill did.
* **`output`** — the skill-governed structured payload.

When the skill declares a `schemas.output`, that resolved schema is **composed into** the envelope's `output` property and `output` becomes **required** — the skill must produce a payload conforming to its declared schema, and the launch validates it. When the skill declares no output schema, `output` is unconstrained and may be omitted. Composition never overrides the envelope: the `{ status, summary, output }` shape is always enforced.

### Consuming the result from the CLI

`tessl launch skill --cloud` renders the returned result when a launch completes, and `--json` emits the whole envelope for a script to consume:

```sh
$ tessl launch skill engteam/greet --cloud --repo engteam/my-repo --json
{
  "launchRunId": "…",
  "status": "completed",
  "result": {
    "status": "succeeded",
    "summary": "Greeted Ada.",
    "output": { "message": "Hello, Ada!", "recipient": "Ada" }
  }
}
```

See [`tessl launch skill`](/reference/cli-commands#tessl-launch-skill) for the full flag reference.


# Custom agent setup

For agent setup, perform the following steps:

1. Run `tessl init` from your project root first. Auto-detected agents (Cursor, Claude, Gemini, Copilot, Codex) need no further configuration. You can skip the rest of these steps and start your agent to [validate it's configured](#validating-configuration).
2. MCP configuration
3. Setup rules
4. Accept running Tessl

## Configuring your agent

### MCP setup

This will allow your agent to access context from installed plugins through the Tessl exposed tools.

Typically most agents have a settings file for MCP, often .mcp.json or support for that file. Refer to your agents documentation for the specific formats and files involved for your agent. The values are the following:\
\
**Name**: "tessl"\
\
**Command**: "tessl"

**Args**: "mcp", start"

**Type**, if asked: "stdio"

#### Examples

```json
{
  "mcpServers": {
    "tessl": {
      "command": "tessl",
      "args": [
        "mcp",
        "start"
      ]
    }
  }
}
```

```toml
[mcp_servers.tessl]
type = "stdio"
command = "tessl"
args = ["mcp", "start"]
```

### Rules setup

Rules setup will load the configuration to help your agent use the Tessl MCP effectively plus any other rules from the plugins you installed.

Determine what file you can indicate to the agent to use Tessl and provide steering rules. If there is capability to use AGENTS.md, use or create an `AGENTS.md` file with the following content:

```
# Agent Rules

@.tessl/RULES.md
```

### Enable Tessl

Most agents will prompt on startup to allow the MCP tool to be used, however some may require you to take an extra step and go into the agent's settings to enable it:

<figure><img src="/files/6QsmDHnwVLmk8nBIcWBR" alt=""><figcaption></figcaption></figure>

## Validating configuration

Review the agent mcp configuration, often "/mcp" in terminal based agents, and determine if Tessl is enabled/review tools are available.\
\
`/mcp`

<figure><img src="/files/liBJvtTEqzP4q88EV2OP" alt=""><figcaption></figcaption></figure>

Prompt your agent:\
`Use tessl to search for code review skills`

You will see calls to tessl **query\_library\_docs**, and/or tessl **search** , and results if configured properly.

<figure><img src="/files/R7HnNl0E8mmWQ5nq56SO" alt=""><figcaption></figcaption></figure>

## Sample configurations for agents not auto-detected

[OpenCode](/reference/custom-agent-setup/opencode)


# OpenCode

## **Tessl Configuration**

Run `tessl init` in your project to create the tessl files and directory structure.

## **MCP Setup**

In your project folder, create a opencode.json with the following content:

```
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "tessl": {
      "type": "local",
      "command": ["tessl", "mcp", "start"],
      "enabled": true
    }
  }
}
```

After opening OpenCode to that project, use **/mcp** and ensure it's enabled and connected

<figure><img src="https://docs.tessl.io/~gitbook/image?url=https%3A%2F%2F1171143958-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FXbWzspFdXV0HNujz6gJ9%252Fuploads%252Fn4qpeASLCLCKjNRKJvkR%252Fimage.png%3Falt%3Dmedia%26token%3Dd430663c-3130-4b07-81bc-ab960e0c6c41&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=e896a393&#x26;sv=2" alt=""><figcaption></figcaption></figure>

## **Rules setup**

If not already present in your project, create an `AGENTS.md` file with the following content, ensuring the .tessl and RULES.md paths are correct:

```
 @.tessl/RULES.md
```


# OpenClaw

### OpenClaw

OpenClaw is an autonomous AI agent framework with its own workspace and skills system. Tessl integrates with OpenClaw by installing skills directly into an agent workspace — no MCP configuration or rules files are used, to keep config clean.

### How skills work with OpenClaw

Tessl installs skills as symlinks into the `skills/` directory of your OpenClaw agent workspace. OpenClaw reads skills from this directory automatically.

Skills installed by Tessl are prefixed with `tessl__` so they can be identified and managed separately from your other skills, if necessary.

### Installing skills

Navigate to your agent workspace directory before running `tessl install`. A workspace is identified by the presence of a `.openclaw/workspace-state.json` file.

```bash
cd ~/.openclaw/workspace   # or whichever workspace you want to install into
tessl install plugin-name
```

If you run `tessl install` from anywhere other than a workspace root, Tessl will exit with an error and suggest the correct directories to navigate to.

### Multiple agents

If you have more than one OpenClaw agent, run `tessl install` separately from each workspace:

```bash
cd ~/.openclaw/workspaces/agent1
tessl install plugin-name

cd ~/.openclaw/workspaces/agent2
tessl install plugin-name
```

### Installing for coding agents at the same time

If your OpenClaw agent uses coding agents (Claude Code, Codex, etc.), use the `--agent` flag to control which agents receive skills:

```bash
# Install for both OpenClaw and a coding agent
tessl install plugin-name --agent openclaw --agent claude-code

# Install for a coding agent only, skip OpenClaw
tessl install plugin-name --agent claude-code
```

With no `--agent` flag, Tessl auto-detects which agents are present in the workspace directory, and installs for all of them.

### Using tessl init

`tessl init` is not supported in OpenClaw workspaces. If you run it from a workspace root, Tessl will exit with an error and prompt you to run tessl install instead.


# Workspaces

Overview of creating and managing Tessl workspaces

Workspaces within Tessl make managing it easy to create, share and manage your team's context.

## Setting up a new workspace

### create

To create a workspace, run `tessl workspace create <name>`

```
tessl workspace create engteam

> ✔ Created workspace engteam (019b324b-...)
```

### list

Verify that your workspace has been created using `tessl workspace list`.

```
tessl workspace list

> ╔════════════╤══════════════════════════════════════╗
  ║ Name       │ ID                                   ║
  ╟────────────┼──────────────────────────────────────╢
  ║ engteam    │ 019952d9-...                         ║
  ╚════════════╧══════════════════════════════════════╝
```

## How workspaces appear in the Registry

When you publish plugins to a workspace, they appear in the Tessl Registry with URLs that follow this pattern:

```
https://tessl.io/registry/<workspace>/<pluginname>/<version>
```

**Example:** If you publish a plugin with:

* Workspace name: `engteam`
* Plugin name: `api-patterns`
* Version: `1.0.0`

Your plugin will be available at:

```
https://tessl.io/registry/engteam/api-patterns/1.0.0
```

{% hint style="info" %}
The workspace name and plugin name are determined by the `"name"` field in your `.tessl-plugin/plugin.json` file:

* `"name": "engteam/api-patterns"` where `engteam` is the workspace and `api-patterns` is the plugin name
* This is independent of your GitHub repository organization or name
  {% endhint %}

The version in the URL is optional - if omitted, the latest version will be displayed.

## Configuring workspace users

### add-member

Add a new member to a workspace using:

`tessl workspace add-member --workspace <workspace-name> --username <username> --role <role>`

```
tessl workspace add-member --workspace engteam --username macebake --role publisher
```

Check out our supported [roles](/administrators/roles) to see which are appropriate for your users.

### list-members

Verify that your users were added correctly using `tessl workspace list-members <workspace-name>`

```
tessl workspace list-members engteam
```

### remove-members

Remove members using `tessl workspace remove-member --workspace <workspace-name> --username <username>`

```
tessl workspace remove-member --workspace engteam --username macebake
```

## Managing your workspace

### archive

Archive a workspace using `tessl workspace archive --reason <text> [workspace-name]`. The `--reason` flag is required. An archived workspace won't be available to publish to or read from, but can be unarchived later.

```
tessl workspace archive --reason "deprecated" engteam
```

### unarchive

To unarchive an archived workspace, making it active again, use `tessl workspace unarchive <workspace-name>`.

```
tessl workspace unarchive engteam
```

### delete

Delete a workspace entirely using `tessl workspace delete <workspace-name>`. Note: this will delete all content in a workspace, and cannot be undone! Use `archive` above as a safer alternative.

```
tessl workspace delete engteam
```


# MCP tools

Overview of Tessl MCP tools for AI coding agents.

The Tessl MCP (Model Context Protocol) server provides tools that AI coding agents can use to search for, install, and work with plugins from the Tessl registry.

## Registry MCP server vs. workspace MCP gateway

Tessl exposes MCP through two distinct entry points — pick the one that matches what you need:

* **Registry MCP server (`tessl mcp start`)** — a local stdio server that gives the agent the tools listed on this page (`login`, `search`, `install`, `uninstall`, `status`). Use it when the agent needs to discover and manage Tessl plugins. This is the server `tessl init` configures for auto-detected agents.
* **Workspace MCP gateway (`tessl mcp proxy <workspace>/<mcp>`)** — a stdio proxy that connects the agent to an external MCP server registered in a Tessl workspace. Use it when several teammates need to share access to an upstream MCP server (such as a third-party integration) without each person re-running its OAuth flow. See [MCP gateway](/reference/mcp-gateway) for how to create and connect to one.

The rest of this page documents the tools exposed by the registry MCP server.

## Server Configuration

The Tessl MCP server can be configured in your AI coding agent's MCP configuration or by running:

```sh
tessl init --agent <agent-name>
```

**Server Details:**

* **Command**: `tessl mcp start`
* **Type**: stdio
* **Name**: Tessl Registry MCP

## Available Tools

### login

Authenticate with Tessl to access registry features.

**Authentication**: Not required (this tool provides authentication)

**Parameters**

None

**Notes**

* Attempts to open authentication URL in your browser automatically
* Authentication happens asynchronously - credentials are saved in the background
* After completing authentication once, authenticated tools work automatically
* Triggers automatic dependency sync after successful login

***

### search

Search for plugins in the Tessl registry by name, package URL (PURL), or HTTP URL.

**Authentication**: Required (automatically handles authentication if needed)

**Parameters**

* `query` (string, required): Search query - can be a plugin name, package URL, or HTTP URL

**Notes**

* Works with partial names and package URLs (PURLs)
* Supports HTTP URLs from package registries (e.g., npm, PyPI)
* Returns plugin name, version, description, and installation command

**Example**

```json
{
  "query": "svelte"
}
```

***

### install

Install plugins into your project. Can install a specific plugin or sync all missing plugins from tessl.json.

**Authentication**: Required (automatically handles authentication if needed)

**Parameters**

* `packageName` (string, optional): plugin name to install (e.g., "workspace/plugin" or "workspace/plugin\@version"). If not provided, installs all missing plugins from tessl.json
* `projectDir` (string, optional): Project directory. Defaults to current working directory

**Notes**

* plugins are installed to `.tessl/plugins/<workspace>/<plugin>/` in your project
* Your project's `tessl.json` is automatically updated with the plugin reference
* If a plugin is already installed and up-to-date, it will be skipped
* If no version is specified, installs the latest version

**Example: Install specific plugin**

```json
{
  "packageName": "tessl/svelte@5.38.0"
}
```

**Example: Sync all missing plugins**

```json
{}
```

***

### uninstall

Uninstall a plugin from your project.

**Authentication**: Not required

**Parameters**

* `packageName` (string, required): plugin name to uninstall (e.g., "workspace/plugin")

**Notes**

* Removes the plugin from `tessl.json` and deletes files from `.tessl/plugins/`
* Does not require authentication (local operation only)
* Only affects your local project - doesn't unpublish from the registry

**Example**

```json
{
  "packageName": "tessl/svelte"
}
```

***

### status

Check authentication status and plugin synchronization status for your project.

**Authentication**: Not required

**Parameters**

None

**Notes**

* Returns JSON with authentication status and plugin sync summary
* Shows plugins that are up-to-date, missing, outdated, or invalid
* Useful for checking if you need to run `tessl install` to sync plugins

**Example**

```json
{                                                                     
       "authentication": {
         "authenticated": true,
         "email": "example@tessl.io"
       },
       "manifest": {
         "summary": {
           "upToDate": 1,
           "missing": 0,
           "outdated": 0,
           "invalid": 0
         },
         "tiles": {
           "upToDate": [
             {
               "workspaceName": "tessl",
               "tileName": "pypi-fastapi",
               "manifestVersion": "0.116.0",
               "installedVersion": "0.116.0"
             }
           ],
           "missing": [],
           "outdated": [],
           "invalidPackages": []
         }
       }
     }

```


# MCP gateway

Create a workspace MCP gateway in Tessl and connect to it from any agent with \`tessl mcp proxy\`.

A **workspace MCP gateway** lets Tessl broker connections to an external [Model Context Protocol](https://modelcontextprotocol.io) server for a workspace. You register the upstream server once in the workspace's settings, authorize it (via OAuth where required), and then any workspace member can connect to it through a single stable address: `tessl mcp proxy <workspace>/<mcp>`.

A gateway is useful when:

* You want a shared, authorized MCP server that every workspace member can use without each person re-running an OAuth flow.
* You want to keep upstream credentials (client secret, tokens) inside Tessl rather than copy them into individual agent configurations.
* You want one identifier (`<workspace>/<mcp>`) to reference the same MCP server from a coding agent, a plugin, or a CI environment.

The gateway sits between the agent's MCP client and the upstream MCP server: the agent talks to `tessl mcp proxy` over stdio, the CLI relays JSON-RPC messages to the gateway over HTTP with Tessl auth headers, and the gateway relays them on to the upstream MCP server using the credentials you stored when you registered it.

## Create a gateway in a workspace

Workspace owners and managers can register MCP servers. Members without `manage_mcp_servers` permission see the page in read-only mode.

1. Open the workspace in the Tessl web app and go to **Settings → Integrations → MCP servers**.
2. Click **Add MCP server**.
3. Fill in the form:
   * **Server name** — used as the slug in the gateway path. Use only alphanumerics, hyphens, and underscores (max 63 characters). Example: `linear`.
   * **Upstream URL** — the URL of the MCP server you are wrapping. Example: `https://mcp.example.com`.
   * **Transport** — `HTTP` or `SSE`, matching how the upstream server exposes itself.
   * **Optional OAuth overrides** — leave blank to use the upstream server's discovery defaults. Fill them in if you need to pin a specific client, scope, resource, or authorization server:
     * **Client ID** and **Client secret** — pre-registered OAuth client for the upstream server. The client secret is encrypted at rest.
     * **Scope** — space-separated OAuth scopes (for example `openid profile email`).
     * **Resource URL** — RFC 8707 resource indicator for the upstream API.
     * **Authorization server URL** — explicit authorization server, used when discovery does not point at the right one.
4. Click **Add MCP server**.

The server appears in the MCP servers list with an **Unauthorized** badge. Click **Authorize** to start the OAuth flow against the upstream provider; once the upstream returns successfully, the badge flips to **Authorized** and the server is ready to use.

If credentials change or expire upstream, the server is flagged as **Needs reauth**. Click **Re-authorize** to refresh; existing proxy sessions are unaffected until they reconnect.

## Connect to the gateway with `tessl mcp proxy`

Once a gateway is authorized, any workspace member can connect to it through the CLI:

```sh
tessl mcp proxy <workspace>/<mcp>
```

* `<workspace>` is the workspace slug (the same one used in registry URLs).
* `<mcp>` is the server name you chose when creating the gateway.

For example, with a workspace named `engteam` and an MCP server named `linear`:

```sh
tessl mcp proxy engteam/linear
```

The command runs in the foreground and speaks the MCP protocol over its own stdin/stdout. It is intended to be launched by an MCP client (your coding agent, or any other tool that supports stdio-transport MCP servers) — running it directly in a terminal is only useful for smoke-testing connectivity.

### Authentication

`tessl mcp proxy` authenticates to the gateway as the calling user:

* **Interactive use** — sign in once with `tessl login`; the proxy reuses the same credentials.
* **CI or other non-interactive contexts** — set the `TESSL_TOKEN` environment variable to a Tessl API key for the workspace. See [`tessl api-key create`](/reference/cli-commands#tessl-api-key-create).

### Use the proxy from a coding agent

`tessl mcp proxy` is a standard stdio MCP server, so any agent that supports stdio-transport MCP servers can launch it. Add it to your agent's MCP configuration in the same way you would any other stdio server — see [Custom agent setup](/reference/custom-agent-setup) for the shape your agent expects.

A typical `.mcp.json`-style entry looks like:

```json
{
  "mcpServers": {
    "engteam-linear": {
      "command": "tessl",
      "args": ["mcp", "proxy", "engteam/linear"]
    }
  }
}
```

You can include several gateways at once — give each one a distinct key so the agent can address them individually.

### Use the proxy from a plugin

Plugins can declare MCP servers in their bundled [`.mcp.json`](/reference/configuration#bundled-mcp-json), and a workspace gateway is just another stdio MCP server from the plugin's perspective. Add an entry that invokes `tessl mcp proxy`:

```json
{
  "mcpServers": {
    "engteam-linear": {
      "command": "tessl",
      "args": ["mcp", "proxy", "engteam/linear"]
    }
  }
}
```

When a project installs the plugin, the gateway is wired into the project's agents automatically.

## Related

* [MCP tools](/reference/mcp-tools) — the registry MCP server (`tessl mcp start`) versus the workspace gateway (`tessl mcp proxy`).
* [Configuration files](/reference/configuration) — how `.mcp.json` is shaped and discovered.
* [Custom agent setup](/reference/custom-agent-setup) — how individual agents read MCP server entries.


# GitHub badges

Using GitHub badges is a great way to share your skill and show a score!

<figure><img src="/files/mdRADl0DGPvTp8oOBv1u" alt=""><figcaption></figcaption></figure>

## Usage

To use a badge, navigate to the registry page of your plugin/skill. If the skill is public, there will be a badge displayed on the right hand side of the page. Use the copy button and place the markdown in your README.MD to display the badge on your GitHub page.

## Improving your score

To improve a low score, run `tessl review fix ./my-skill --workspace engteam` to apply automated improvements. See [Check a skill's quality using review](/improving-your-skills/reviewing-skills).

To gate the score in CI – for example, to fail a pull request when a skill drops below a threshold – use `tessl review run` with `--json` and `--threshold`. See [Gate skill quality in CI](/codifying-and-enforcing-your-skill-standards/gate-skill-quality-in-ci).


# Glossary

Key concepts and terminology used throughout Tessl.

This glossary defines the core concepts you'll encounter when working with Tessl.

## Tessl CLI

Tessl's command line tool for installing, updating and managing context for coding agents.

It enables users to:

* Create, install and manage agent skills and Tessl packages across their coding agents
* Publish skills and Tessl packages to the Tessl Registry
* Locally evaluate skills and Tessl packages

## Tessl Registry

Tessl's online registry for discovering and distributing agent context.

It enables users to:

* Discover agent skills and Tessl packages (plugins) and assess their quality (via evals)
* Connect their repositories to Tessl and automatically generate context for them
* Request new skills and Tessl context

## Skill

Agent Skills are folders of instructions, scripts, and resources that agents can discover and use to do things more accurately and efficiently, giving agents access to procedural knowledge and specific context they can load when the agent determines they're relevant (lazy push).

In Tessl, skills are treated as software with a complete lifecycle: versioned, evaluated, and maintained as dependencies and systems change.

See <https://agentskills.io/home> for more information.

## Tessl package (Plugin)

Tessl packages (or plugins) are versioned bundles of reusable, agent-agnostic context that make coding agents more effective. They can (but do not always) contain:

* Skills
* Rules

Like software packages in npm or pip, Tessl packages are versioned, dependency-managed, and can be safely updated as libraries and systems evolve.

## Tessl project

The stable home for Tessl in a Git repository. A Tessl project identifies that repository and acts as the anchor for the eval runs and other repository-connected data attached to it.

## Repository

A Git repository containing your code and history.

## Codebase

The code inside a repository.

## Working directory

The directory, or subdirectory, where you run the CLI.

## Project link

The link stored in `tessl.json` that connects a repository to a Tessl project.

## Rules

Mandatory steering for the agent to always follow, always pushed to the agent's context (eager push).

## Evaluations (evals)

Structured testing processes to systematically measure AI system performance, accuracy and reliability. Evaluations are typically contextual - they depend on the type of evaluation and the type of AI system or agent.

Tessl uses evaluations to validate that skills and context actually improve agent behavior, catch regressions as systems change, and ensure updates are safe before they reach production workflows.

The evaluations we run at Tessl typically measure the success rate of agents on real world tasks with and without some context, by:

* Generating a representative set of tasks
* Prompting agents to solve the tasks with and without the context
* Scoring the agent's solution to the tasks using grading criteria (we typically use criteria with multiple binary criteria at Tessl)
* Comparing baseline performance against performance with the context over all tasks


# FAQs

Find quick answers to the most common questions about Tessl.

The following lists a set of questions that we have been asked about Tessl in the past. If you have a different question which isn’t answered here, talk to the community on the [Discord Server](https://discord.com/channels/1233374481364418570/1417176126207426760).

## Getting Started

### How can I install a skill with Tessl?

You can install skills using the Tessl CLI. Search for available skills with `tessl search <skill-name>` and install them with `tessl install <skill-name>`. Tessl automatically evaluates skills to ensure they improve agent behavior.

For detailed instructions, see [Improve your first skill](/introduction-to-tessl/improve-your-first-skill).

## Core Concepts

### What is a Plugin?

Plugins are Tessl packages, which are bundles of reusable context that capture knowledge you want to use across your team and projects. Common plugin content includes:

* Agent skills
* Usage documentation for libraries, APIs, tools, etc.
* Common, repeatable workflows
* Styleguides
* Policies
* ...

### What is the difference between a plugin and a skill?

A plugin is a bundle of agent context. A plugin is a container for context - it's what you install and manage via the package manager.

A skill is one type of context that can be included inside a Tessl package (along with docs and rules).

A helpful analogy is:

* Tessl package/plugin = the npm package
* Skills, rules = different types of files inside that package

Just like npm packages, plugins are versioned and can be updated safely as libraries and dependencies evolve.

For detailed definitions, see our [Glossary](/reference/glossary).

### What is a Tessl project?

A Tessl project is the stable home for Tessl in a Git repository.

It identifies that repository and acts as the anchor for the eval runs and other repository-connected data attached to it.

See [Projects overview](/projects/overview).

### What is the difference between a repository and a Tessl project?

A repository is your Git repo.

A Tessl project is the stable home for Tessl in that repository.

## Platform

### What agents does Tessl support?

Skills are agent and model-agnostic, allowing teams to maintain consistent behavior across tools without locking into a single ecosystem.

Tessl installs skills to the appropriate agent-specific directory:

* **Claude Code**: `.claude/skills/`
* **Cursor**: `.cursor/skills/`
* **Codex**: `.codex/skills/`
* **Gemini**: `.gemini/skills/`
* **Copilot CLI**: `.copilot/skills/`
* **Copilot in VSCode**: `.copilot-vscode/skills/`

Docs: full support for Claude Code, Cursor, Gemini, Codex, Copilot CLI, and Copilot in VSCode.

See the [Supported platforms](/support/supported-platforms#agents) reference for the most up-to-date list of supported agents.

### How does Tessl compare to other marketplaces like skills.sh?

[skills.sh](https://skills.sh) is a directory and an easy way to browse and copy individual skills. Tessl is a fully fledged package manager and registry for agent context: you install, version, and update skills as dependencies rather than duplicating them to your codebase.

Comparing the two:

* **skills.sh** – Browse and copy skills from a catalog; no built-in versioning or dependency management. You manually keep skills in sync.
* **Tessl** – Install skills with `tessl install <skill-name>`; skills are versioned, tracked in a manifest, and updates are controlled and repeatable across your team.

Tessl also adds:

* **Evaluation** – Measure whether skills are structured well and if they improve agent behavior
* **Lifecycle managemenet** – Ensure skills stay correct and up to date as systems change

So Tessl treats skills as software with a full lifecycle (build, evaluate, distribute, optimize), which helps teams move from ad‑hoc agent usage to long-lived, production systems where agent behavior can be inspected, measured, and reasoned about.

## Evaluations

### Why do I need a Tessl project to run an eval?

Evals need a Tessl project so Tessl knows which repository the eval belongs to.

Without that link, the run is just a one-off local action. With a Tessl project, Tessl can keep the run attached to the right repository, find it later, and compare it with future runs.

See [Projects for evals](/projects/evals).

### How does Tessl evaluate skills?

Tessl evaluates skills using both task evaluations and conformance reviews:

**Task evaluation:** Measure whether agents can successfully complete real-world coding tasks when using the skill.

* Creates a representative set of coding tasks that require using the skill
* Runs each task with the agent both with and without the skill installed
* Scores each task using task-specific success criteria
* Compares baseline performance against performance with the skill over all tasks
* Reports improvement as a multiplier (e.g., 2× improvement)

**Conformance review:** Assess whether the skill conforms to the Agent Skills specification created by Anthropic.

* Validates that the skill conforms to the official specification at [agentskills.io/specification](https://agentskills.io/specification)
* Checks proper file structure and formatting
* Verifies required frontmatter fields (name, description)
* Ensures the skill follows best practices defined in the specification

## Publishing & Sharing

### How can I publish a skill?

To publish a skill:

* Create an account and workspace on Tessl
* Define visibility (public or private) at the Tessl package level
* Use the Tessl CLI to publish:
  * `tessl skill publish` - If you have a standalone `SKILL.md` file (skill-first workflow)
  * `tessl plugin publish` - If you've created a plugin structure with `.tessl-plugin/plugin.json` that contains a skill (plugin-first workflow)

Published skills are evaluated and versioned, so users can see quality metrics and choose versions that match their dependencies. See [Creating skills](/create/creating-skills) for a complete tutorial.

### Can I share these with my team?

Yes! The Tessl Registry has workspaces which let you share Tessl packages for your own libraries with your team members. Skills and context can be kept private to your workspace or published publicly.

This allows teams to onboard agents the same way they onboard developers: with shared assumptions, behavior, and clear expectations about how internal systems should be used.

## Advanced

### Does Tessl support monorepos?

Yes! Tessl supports monorepo workflows. Run `tessl init` at the monorepo root to create `tessl.json` and configure your coding agent. From there, use `tessl search` to find plugins and `tessl install` to add them. You can run `tessl install` from any subfolder to add plugins relevant to that part of the repo — all installed plugins are tracked in the single `tessl.json` at the root.

**Example:**

```sh
# Initialize Tessl at the monorepo root
tessl init

# Search for and install plugins relevant to a subfolder
cd backend
tessl search fastapi
tessl install tessl/pypi-fastapi
```

## Support & Help

### How can I check if Tessl services are experiencing issues?

Visit the [Tessl Status Page](https://tesslstatus.io/) to check the current status of all Tessl services, view any ongoing incidents, and see historical uptime data.

For other support options, see [Giving feedback](/support/giving-feedback).


# Giving feedback

### Contact us

You can get in touch with us if you need some help via the following methods:

* **Email -** <support@tessl.io>
* **Discord -** [#tessl-product](https://discord.com/channels/1233374481364418570/1417176126207426760), a channel where you can quickly reach the team
* **GitHub Issues -** [tesslio/cli](https://github.com/tesslio/cli/issues)
* **CLI -** run `tessl feedback` in your command line to quickly send notes straight to the team!

We really appreciate all feedback you have to give - brief, detailed, complimentary or critical - it helps us to improve.


# Supported platforms

This page lists the supported version. Even if your favorite platform is not listed, it might still work  as we support many industry standards.

## Agents

Tessl supports multiple coding agents through MCP (Model Context Protocol) integration.

| Agent                 | Skills | Rules | MCP |
| --------------------- | ------ | ----- | --- |
| **Claude Code**       | ✅      | ✅     | ✅   |
| **Cursor**            | ✅      | ✅     | ✅   |
| **Codex**             | ✅      | ✅     | ✅   |
| **Gemini**            | ✅      | ✅     | ✅   |
| **Copilot CLI**       | ✅      | ✅     | ✅   |
| **Copilot in VSCode** | ✅      | ✅     | ✅   |

All agents listed above (**Claude Code**, **Cursor**, **Codex**, **Gemini**, **Copilot CLI**, **Copilot in VSCode**) are automatically configured during `tessl init`.

Other agents that support MCP can also be manually configured to work with Tessl. See [Custom agent setup](/reference/custom-agent-setup) for detailed instructions.

For more details on agent installation, see the [init command](/reference/cli-commands#tessl-init).

## Node runtime

* You need to have a modern version of Node.js installed (we use **v22.17.0 or higher**)

## Operating system

* **Supported**: Mac, Linux, Windows


# Troubleshooting

The Tessl CLI provides diagnostic capabilities through the `tessl doctor` command that outputs information about the environment and the CLI itself. This information can be helpful to support and in diagnosing issues. Additionally the CLI will provide guidance on how to resolve issues that are detected. The CLI output defaults to human readable output and can be configured to output JSON for reporting automation.

#### Usage <a href="#tessl-doctor" id="tessl-doctor"></a>

```
tessl doctor [--json]
```

**Flags**

* `--json` (boolean, optional): Output diagnostics as JSON for programmatic processing

<figure><img src="/files/6A8twIvdpsRavlFBOomQ" alt=""><figcaption></figcaption></figure>

#### **Examples**

```
# Run diagnostics with human-readable output
tessl doctor

# Output diagnostics as JSON
tessl doctor --json
```

## Common Issues

### Authentication Issues

If you're having trouble authenticating:

1. Run `tessl doctor` to check your authentication status
2. Try logging out and back in: `tessl logout` then `tessl login`
3. Check that your browser allows popups for the authentication flow
4. Verify your internet connection

### Installation Issues

If `tessl init` or `tessl install` fails:

1. Ensure you have the required package manager installed (npm, pip, etc.)
2. For installing skills from GitHub, `tessl install <skill> -v` will provide verbose messaging, showing warning details.
3. Run `tessl doctor` to identify configuration issues

### MCP Server Issues

If your agent cannot connect to the Tessl MCP server:

1. Verify the MCP server is configured in your agent's settings
2. Check that `tessl mcp start` runs without errors
3. Restart your agent after configuring MCP
4. Review the MCP configuration in your agent's settings file

### Workspace Access Issues

If you cannot access a workspace or plugin:

1. Verify you're a member: `tessl workspace list-members <workspace-name>`
2. Check your role has appropriate permissions (see [Roles](/administrators/roles))
3. Ensure you're logged in: `tessl whoami`

## Getting Help

If you continue to experience issues:

* Run `tessl doctor --json` to capture diagnostic information
* Visit our [FAQs](/support/faqs) for common questions
* [Give feedback](/support/giving-feedback) or report issues to the Tessl team


# Changelog

Latest version = 0.92.0

## 0.92.0

### New Features

* **Hooks in plugins** - Plugins can now declare cross-agent hooks via `hooks` / `nativeHooks` in `plugin.json`. See the [plugin configuration docs](https://docs.tessl.io/reference/configuration#hooks).

### Improvements

* **Signed release verification** - CLI installation and self-update now verify against a cryptographically signed release manifest before extraction.

## 0.91.0

### New Features

* **Agent-readiness report** - run `/agent-ready` in the `tessl` agent to scan your repository and surface what to improve.
* **`tessl launch resume`** - resume an interrupted or completed cloud launch run.
* **Signed release verification** - the installer verifies the release signature before installing.

### Improvements

* **Agent works without native search tools** - uses `fd` / `rg` when available and falls back to a basic code implementation when they are not installed.
* **Verify cache relocated** - now stored at `~/.tessl/verify-cache`, so cached results are shared across projects instead of living in each checkout.
* **Auto-detect workspace** - `tessl review run` / `review fix` read the workspace from `tessl.json` instead of always prompting.
* **`tessl launch list`** now shows the workspace and the run's creator.
* **`tessl eval list`** consolidates injected context into a single column.
* **Credit errors link to top-up** - an out-of-credits error now points to the upgrade / top-up flow.
* **Explicit, persistent agent setup** - `tessl init` now records selected agents in `tessl.json` for reproducible installs across machines. Re-run `tessl init` on an existing project to update the list.
* **Clearer permission prompts** - prompts are deduped per tool call, bash paths are classified by read/write/delete, external and sensitive-path actions route through the auto classifier, and auto-mode prompt wording is combined.

### Changes

* **Separate `--agent` and `--model` flags** - compound `--agent <agent>:<model>` tuples are now split into `--agent <agent> --model <model>`. The old form still works but is deprecated and warns.

### Bug Fixes

* Installer validates the remote release version before installing.
* Generic hook command/args aligned to the `exec` / `shell` forms.

## 0.90.0

### Breaking Changes

* `tessl review <target>` (without `run`) no longer runs a review - it now shows the `review` command group's help instead. Use `tessl review run <target>` (or `tessl review run quality <target>`).

### New Features

* **`tessl review run quality` / `tessl review run security`** - `tessl review run` is now a subcommand group: `quality` (the default, unchanged behavior) scores a skill against a rubric, and `security` runs a Snyk-powered security scan - replacing the standalone `tessl security-review` command. `tessl review list`, `view`, and `retry` now work across both kinds from a single unified history, with a `--fail-on` flag mirroring `--threshold` for security scans. `tessl review run <target>` continues to work exactly as before - it's shorthand for `tessl review run quality <target>`.
* **Clone skills from GitLab and Bitbucket sources** - Skill installation and inventory scanning now support GitLab and Bitbucket repository sources, not just GitHub.

### Bug Fixes

* Fixed `tessl agent` ignoring a saved default model from `settings.json` on startup.
* `tessl agent` - Fixed session approval matching for external paths when multiple patterns are involved.

## 0.89.0

### New Features

* **`tessl agent` out in Open Beta** - It helps you build and optimize your software factory one workflow at a time.
* **`tessl change` commands to aid with automated code reviews**
  * **`tessl change risk`** - Assess PR/diff risk and decide whether human review is required.
  * **`tessl change verify`** - Verify code against configured verifiers.
  * **`tessl change review`** - Review the current diff with reviewer skills and emit structured review data.
  * Use `tessl agent` to set them up!
* **`tessl launch skill`** - Run skills using your preferred agent in order to automate parts of your workflow with skills.
* **`tessl mcp proxy`** - Connect to MCP servers through an MCP gateway set-up in a workspace’s settings.

### Improvements

* **Clearer error when `--skill` can't apply** - `tessl install --skill <name>` now fails fast with an actionable message when given zero sources or more than one source, instead of silently installing nothing.
* **Friendlier model-lock message on eval runs** - Selecting a non-default model on a Free plan now produces a single, clear message explaining how to proceed, instead of a raw `403 Forbidden`.

### Bug Fixes

* Fixed relative `file:` sources (e.g. `tessl install file:../my-source --global`) failing to resolve; they now resolve against your current working directory as expected.
* Fixed a single unsupported entry in a plugin's `.mcp.json` failing the whole file at publish and install time; unsupported entries are now skipped and the rest of the plugin installs.

## 0.88.2

### Bug Fixes

* **npm package** - fixup README.md file

## 0.88.1

### Bug Fixes

* **Global plugin MCP servers** - `tessl install --global` now writes a plugin's MCP server config to each agent's real user-level config.

## 0.88.0

### New Features

* **Plugin MCP Servers** - Plugins can now declare MCP servers in a bundled `.mcp.json` at the package root.
* **Publish Through Symlinks** - `tessl skill publish` and `tessl plugin publish` accept an opt-in `--resolve-symlinks` flag that copies a symlink target's bytes into the published tarball (within a safe boundary), so authors can reuse files from elsewhere in the repo.

### Improvements

* **Workspace Scoping for Reviews** - `tessl review view` and `tessl review retry` now accept `--workspace` / `-w`, and `--last` resolves the most recent run within that workspace.
* **Publish OIDC Warning** - When publishing from GitHub Actions without an OIDC token permission, the CLI now warns instead of failing opaquely.

### Bug Fixes

* Fixed `tessl skill review --threshold 0` incorrectly emitting a "Skill validation failed" error.

## 0.87.0

### Breaking Changes

* **Skill review now requires a Tessl account.** Both `tessl review` and the older `tessl skill review` now require authentication: sign in with `tessl login`, or set a `TESSL_TOKEN` API key in the environment for CI. Reviews run on Tessl's servers, so anonymous review runs are no longer supported.

### Deprecations

* **`tessl skill review` is deprecated - use `tessl review` instead.** `tessl review` (alias `tessl review run`) is the replacement: an async, server-side review with companion `view`, `list`, `retry`, and `fix` commands. The old command still runs for now but prints a deprecation warning on every run and will be removed in a future release. Replace `tessl skill review <path>` with `tessl review <path>`.

### New Features

* **`tessl review` is now fully launched as an end-to-end workflow** - review runs are first-class in the CLI with `run` as the default subcommand, and companion commands to view, retry, and fix reviews directly from the terminal.
* **Flexible reviewer selection** - you can target a specific reviewer with `--review-plugin` or use your workspace's default reviewer configuration.

### Improvements

* **Richer review output for debugging and automation** - `tessl review view` now renders dynamic judges per run, and review JSON includes reviewer/plugin identity metadata.
* **Clearer `tessl eval view` output** - run labels are shown and scenarios are sorted for easier reading.
* **More informative `tessl eval run` start output** - pre-run context details are surfaced before execution.

### Bug Fixes

* **Review command reliability fixes** - `tessl review list`, `view`, and `retry` now resolve workspace names correctly, and `--json` without `--workspace` now returns a clear error.
* Fixed completed scenario counts in multi-solution eval runs.
* Fixed evaluator failures caused by repeated plugin installation arguments.

## 0.86.0

### New Features

* **Customise the eval-scenarios run when publishing** - added `--eval-scenarios <scenario-search-path>` to `tessl plugin publish` / `tessl skill publish`. The default is `./evals` in the directory of the plugin being published.

### Improvements

* **Default eval model** is now DeepSeek v4 Flash.
* **`tessl eval list --context-type`** - filter eval runs by the type of context injected into scenarios for the "with context" variant.
* **Richer `tessl eval view`** - clearer variant labels, an injected-context block, scenario paths, and repo/plugin provenance.
* `tessl eval run` echoes the scenario search directory and count before starting.
* Commit-fixture uploads are grouped and deduped to remove some cases where redundant context was uploaded.
* Install source policy: git-source allowlist, with denial messages that name the offending source.
* You're prompted to accept pending invites before a personal org is created.

## 0.85.0

### Breaking Changes

* **tessl eval run --agent is now single-valued** - Previously `--agent` was repeatable and each value created a separate eval run. It now accepts a single agent; run the command once per agent to compare.
* **Removed legacy eval-run context flags** - `--variant`, `--context-ref`, and `--context-pattern` have been removed from `tessl eval run` in favour of the new `--context` selection (see below).

### New Features

* **Skill Inventory** - Skill Inventory gives you a living map of every skill in your GitHub org - what exists, where it's used, and where you're duplicating effort. Run the initial import with `tessl inventory import` and it scans your repos, collects your skills and manifests, and gives you a snapshot of your whole inventory. Run it again any time - each scan is diffed, so you get a living view of what's new, unchanged, and removed over time.
* **Context Selection for tessl eval run** - A single `--context <path>` front door now picks the context under test, with `--context-commit` to source it from a commit and `--skill` (repeatable) to narrow a local plugin to specific skills.
* **Control Baseline by Default** - `tessl eval run` now always runs a control variant to compare against, with `--skip-baseline` to opt out.
* **Secrets injection for plugin evals** — `tessl eval run` now accepts `--env-file <path>`. Variables in the file are encrypted client-side and delivered into the eval sandbox, where they are available to `setup.sh` scripts and the agent. See [Passing secrets to your eval](/improving-your-skills/evaluate-skill-quality-using-scenarios#passing-secrets-to-your-eval).
* **--child Flag for Nested Projects** - tessl project create now requires `--child` to create a project nested inside an existing one, and blocks with a clear explanation when a parent project is detected in an ancestor directory.
* **tessl version** - Bump a plugin's version locally without publishing, like `npm version`. Pass `patch`, `minor`, or `major` to increment the current version following semver, or an explicit version (e.g. `tessl version 2.1.0`) to set it directly. Updates the plugin manifest in place; an optional path argument targets a directory other than the current one.

### Improvements

* **Clearer Install Output** - `tessl install` now shows only the dependencies you explicitly requested on the success line; incidental re-installs are summarised as a dim `Synced: N count`.
* **tessl scenario generate workspace resolution** - Workspace is now resolved from your linked Tessl project (`tessl.json`), the `--workspace` flag, or an interactive prompt — instead of being derived from the tile manifest name, which caused confusing 403 errors when the manifest used the `local/ prefix`. The `--workspace` flag is now accepted for tile-based generation.

## 0.84.0

### New Features

* **Bootstrap Project Create** - `tessl project create` now works in directories that don't yet have a `tessl.json`, bootstrapping it as part of the create flow.
* **Personal GitHub Account in Skill Inventory Import** - `tessl skill inventory import` can now authenticate with a personal GitHub account, not just org-level credentials.
* **Plugin Marketplace Discovery** - Tessl now classifies `.claude-plugin/marketplace.json` as a first-party manifest, picking up plugins from that location.

### Improvements

* **Warning for Large-Scale Eval Runs** - `tessl eval run` now prompts a confirmation before launching large eval batches.
* **Plan-Entitlement-Gated Model and Agent Selection** - model and agent selection respects plan entitlements with clearer messages when a selection isn't available.
* **Age-Gated Registry Sources Fallback** - registry sources blocked by release-age policy can now resolve to an older fallback source rather than hard-blocking.

### Bug Fixes

* Fixed `tessl install` to fast-fail on private or missing git repositories instead of silently succeeding with a hidden failure.
* Fixed the judge-results display to show the correct score denominator in both CLI and frontend.

### Windows installer (new distribution channel)

Signed Windows installers are now available for direct download. The Inno installer wraps a signed `tessl.exe` bundled with `TESSL_DISABLE_UPDATE` (winget will manage updates):

* <https://install.tessl.io/installers-windows/0.84.0/TesslSetup-0.84.0-x64.exe>
* <https://install.tessl.io/installers-windows/0.84.0/TesslSetup-0.84.0-arm64.exe>

The signed package will be installable directly via `winget install tessl.tessl` as soon as it will be approved by Microsoft

## 0.83.0

### New Features

* \*\*Jujutsu Repo Support - `tessl project repair` now detects and handles `jj`-managed repositories alongside Git.
* Finer Eval Run Controls - `tessl eval run` adds two independent opt-outs: `--skip-forced-context-activation` and `--skip-scoring`. Use them on their own or together to control whether the run forces context activation and whether the rubric scorer fires.

### Improvements

* Solver and Scorer Flag Deprecation - The `--solver` and `--scorer` flags on tessl eval run are now hidden but still functional, with a one-line deprecation warning; prefer the new `--skip-*` flags.

### Bug Fixes

* \*\*Removed a vendor-native plugin-manifest ingestion path that could pick up stale manifests outside the expected resolution flow.

## 0.82.0

### Improvements

* **Install Policy Enforcement** - `tessl install` now honors org-configured release-age and commit-age policies. For registry sources, the CLI automatically falls back to an older version that satisfies the policy (with a clear reason in the install output) or hard-blocks if no version qualifies. For git sources, it resolves to the most recent commit old enough to satisfy the minimum commit-age policy instead of installing HEAD.
* **Policy-Aware `tessl outdated`** - Versions blocked by a release-age policy are now annotated as `[release age policy]` in the update table, and git sources show the latest age-compliant commit as the recommended update so you can see what will (and won't) be installed before running `tessl update`.

## 0.81.3

### Improvements

* **Eval Failure Reasons** - `eval run` and `eval view` now display the reason when a run fails (e.g. quota exceeded), instead of a bare failure marker
* **Eval Default Model Notice** - A one-time notice informs you that the default eval model is now GLM 5.1, with guidance on selecting a different model
* **Resilient Eval Polling** - `eval run` now rides out transient server errors and network blips while polling, instead of reporting a completed run as failed
* **Clearer Validation Errors** - Manifest schema errors are now rendered in a readable format instead of a raw JSON dump
* **MCP Tool Updates** - The `new_tile` MCP tool is renamed to `new_plugin`, and the `outdated` tool now accepts a `projectDir` parameter to check a specific directory

### Bug Fixes

* Fixed `plugin pack` failing with a missing `tile.json` error for plugins created with `plugin new`; migrated plugins also no longer pack from the stale legacy manifest
* Fixed `eval run` evaluating the stale legacy `tile.json` instead of `.tessl-plugin/plugin.json` when both manifests are present
* Publishing a migrated plugin now errors if `tile.json` declares `private: true` but `plugin.json` omits it, preventing a private plugin from accidentally going public
* Fixed broken documentation links shown after `plugin new` and `skill new`
* Removed misleading advice pointing at `tile.json` from the "no content" validation error

## 0.81.2

### Bug Fixes

* **`scenario generate`: Clearer Error When No Manifest Found** — Running `tessl scenario generate` in a directory with no manifest previously crashed with a confusing `ENOENT: tile.json` error. It now shows a clear message pointing you to add a `.tessl-plugin/plugin.json`.

## 0.81.1

### Bug Fixes

* Fixed `skill publish` incorrectly triggering the import wizard when `plugin.json` already exists
* Fixed `skill publish --bump` not writing the bumped version to `plugin.json`, causing the old version to be published
* Fixed `skill publish` pre-publish version checks reading from `tile.json` instead of `plugin.json`

## 0.81.0

### New Features

* **Tiles are now Plugins** - This release completes the switch from Tiles to Plugins. The CLI now uses "plugin" across every command, help listing, flag description, and message. For more information on how to migrate from Tiles to Plugins, [there is a guide in the documentation](https://github.com/tesslio/monorepo/tree/main/apps/docs/use/tile-to-plugin-migration.md).
* **Full moderation status in `plugin info`** - `plugin info` now shows the complete moderation state for a published version (pass, pending, skipped, fail, or error).

### Improvements

* **`ls` shortcut** - `tessl ls` now works as a shortcut for `tessl list`, mirroring the existing `i` → `install` shortcut.
* **Workspace-scoped uploads** - Eval-related uploads (scenario tarballs, plugin archives, repo archives) are now scoped to the active workspace, so teammates in the same workspace can access uploads created by other members.

### Bug Fixes

* Eval run links now point directly to workspace-scoped URLs, skipping the redirect members previously hit when clicking through.
* `scenario generate` now works in plugin-only directories (a `.tessl-plugin/plugin.json` with no `tile.json`), which previously failed with a "tile.json not found" error.
* The CLI no longer fails to start when its log file can't be written (e.g. in sandboxed or read-only environments) — file logging is now best-effort.

## 0.80.0

### New Features

* **Eval Enablement Checks** - `tessl scenario generate`, `tessl tile publish`, and `tessl skill publish` now pre-flight check whether the target workspace has evals enabled. Scenario generation fails fast with a clear message; publish still succeeds but cleanly skips the eval upload with a single info line.

### Improvements

* **Cleaner Publish Output** - `tessl tile publish` no longer prints validation warnings twice (once from pre-publish validate, once from pack).
* **Clearer Forbidden Errors** - When creating a project fails because the workspace doesn't exist or you lack permission, the CLI now shows an actionable message instead of a generic `403 Forbidden`.
* **Skill Install Paths** - Skills are no longer written under `.gemini/skills`; installation routes through `.agents/skills`, and any legacy `tessl:*` / `tessl__*` entries left in `.gemini/skills` are cleaned up automatically.

### Bug Fixes

* `tessl tile new` now preserves the rule description you provide instead of overwriting it with a `TODO` placeholder.
* Generated `RULES.md` now ends with a trailing newline.

## 0.79.1

### Improvements

* **Clearer Guidance for Missing Project Links** - When a linked Tessl project can't be found or isn't accessible, the CLI now surfaces actionable next steps with specific `tessl project create` and `tessl project repair` commands instead of a raw 404. The `tessl eval run` help text now also explains that eval runs are saved to a Tessl project.

## 0.79.0

### New Features

* **OpenHands agent support (alpha)** — `tessl init`, `tessl install`, and `tessl run` now recognise OpenHands. Auto-detection follows the standard project → home → PATH ladder; OpenHands is excluded from the interactive picker while in alpha but can be selected explicitly via `--agents openhands`.
* **`tessl search --global`** — install search results into `~/.tessl/` without requiring a project to be initialised. Short form `g` available.
* **`tessl eval run --list-agents`** — print the supported `<agent>:<model>` catalogue (with the default marked) without running an eval. Supports `--json` for scripting.
* **`tessl project` -** Tessl now supports workspace-backed projects in the CLI, giving your local work a persistent project identity for evals and other project-based workflows. Use `tessl project create` to create a project, `tessl project link` to connect an existing one, and `tessl project repair` to fix broken project links.
* **`tessl eval run --scorer-agent`** — override the agent and model used for the score step (as `agent:model`), while the solver agent stays unchanged. `tessl eval view` shows the override under a `Scored by:` line.
* **`tessl eval run --quality-check`** — opt-in flag that asks the backend's LLM judge to filter out misleading scenarios (low feasibility, rubric leakage, low value) before solve and score. Excluded scenarios show up under a red `✗ Excluded by quality check` line in `tessl eval view`. `tessl tile publish --with-scenario-quality-check` enables the same filter for the eval that runs as part of publishing.

### Improvements

* **Simpler `tessl skill import` / `skill new`** — no longer prompts for workspace or visibility; defaults to `local` workspace and `private` visibility. Pass flags explicitly to override.
* **Scenario config (`scenario.json`)** — declarative working-directory setup for evals. Declare `fixtures` to install (commit or directory), `include` paths to copy in verbatim, and `setup` scripts to run after install. Conventional defaults (`resources/` auto-included, `setup.sh` auto-run) mean most scenarios need no `scenario.json` at all. `tessl scenario generate` now produces a `scenario.json` for every generated scenario, plus any supporting input state (e.g. `resources/`) when the source commit needs it. Setup scripts are off by default per workspace — contact Tessl to enable.
* **Cleaner install error messages** — local paths missing the `file:` prefix now surface a clear validation error instead of a generic parse failure.
* **Softer security-review copy** — surfaces showing a per-skill security status now display "No security review available." instead of "Security review has not been run yet."
* `tessl skill review` **includes referenced skill content** — skill reviews now include all referenced content and scripts for logged-in users.

### Bug Fixes

* **Install exits non-zero on failure** — `tessl install` and `tessl install --global` now reliably propagate tile install failures as command failures (non-zero exit code).
* **`tessl scenario generate <relative-path>`** — relative paths like `tiles/foo` are now correctly routed to the tile flow when the directory exists locally, instead of misrouting to the repo flow and erroring on missing `-commits`/`-prs`.
* **`tessl tile lint`** — `@decorator` tokens in markdown headings and YAML frontmatter are no longer treated as hard-link references and no longer produce false-positive lint warnings.
* **MCP install bootstrap message** — the "Initialising new tessl project at …" message no longer prints during bulk sync installs that don't actually write `tessl.json`.
* **Experimental agent detection** — explicit project-level usage of experimental agents (e.g. OpenClaw workspace markers) is now respected ahead of the experimental gate, and the default install flow no longer force-enables experimental agents.

## 0.78.0

### New Features

* **Activation Solver for Evals** - `tessl eval run --solver=activation` measures which skills activate for each scenario, and `tessl eval view` renders the results in a per-scenario activation table
* **Set Project Name on Init** - `tessl init` accepts a new `--name` flag to set the project name in `tessl.json` at creation time
* **Target Org on Workspace Create** - `tessl workspace create` now accepts a `--org-id` flag to associate a workspace with a specific organization
* **List Organizations** - New `tessl org list` command displays the organizations you belong to
* **Scenario Quality Checks for Evals** - `tessl eval run --quality-check` will filter out scenarios that would give misleading results, based on a quality assessment that looks for things like “criteria leaking into the task” or “task duplicating information from the skill it is meant to exercise”

### Improvements

* Clearer Eval Run Status - Pending and in-progress eval and generation runs render as yellow "In Progress" with elapsed time, instead of an ambiguous "Pending"
* Better Invalid Manifest Errors - tessl eval run against a directory with a malformed tile.json now reports the manifest error directly with a hint to fix it, instead of falling through to the scenarios flow
* Removed Eval Compare - tessl eval compare has been removed. Use tessl eval view and tessl eval list instead
* Global Install from Search - `tessl search` now supports `--global` so selecting a result installs it to `~/.tessl/` instead of the current project

### Bug Fixes

* Fixed tile rule creation to safely handle prompts containing `/` so they no longer create unintended nested paths in the generated rule files

## 0.77.0

### New Features

* **Experimental Windows Support** - The Tessl CLI is now available on Windows as an experimental release. Install it with PowerShell:

  ```powershell
  irm https://install.tessl.io/scripts/latest.ps1 | iex
  ```
* **Eval Setup Scripts** - Eval scenarios support a new `setup` field in `scenario.json` — an ordered array of script paths that run after fixtures and includes are installed, before the solver agent starts.

### Improvements

* **Cleaner Top-Level Help** - Simplified top-level CLI help.

## 0.76.0

### New Features

* **Eval Progress Bars** — `eval run` and `eval view` now show real-time per-scenario progress bars with colour-coded status (complete, active, queued)
* **Directory Fixtures in Evals** — Scenarios can now declare `include` paths for directory-based fixtures, alongside existing commit-based fixtures.
* **"latest" Dependency Version** — Use `"latest"` as a dependency version in `tessl.json` to always resolve the most recent published version
* **Uninstall Individual Skills** — `tessl uninstall --skill <name>` removes specific skills from a dependency instead of removing the entire tile
* **Verifiers in Tile Packing** — The `verifiers/` directory is now included when packing tiles (when evals are enabled)
* **Failed Security Review Visibility** — Security reviews that failed to run are now shown as "failed" instead of appearing as "pending"

### Improvements

* **Project Name from Directory** — `tessl init` now derives the project name from the directory basename instead of using a generic default
* **Archive Without Version** — `tessl archive` now works without a version suffix, allowing you to archive all versions of a tile at once
* **Eval Agent/Model Display** — `eval view` now shows the agent and model for all eval run types
* **Workspace Commands** — `-user` flag renamed to `-username` , `-user` still works with a deprecation warning
* **Help Text Corrections** — Improved descriptions for `install --skip-init`, `tile pack`, `skill import`, and `config set`

### Bug Fixes

* Fixed eval scenario path resolution when base directory is "."
* Fixed eval git diff ignoring user's custom diff tool configuration
* Fixed object metadata serialization in eval debug output

### Breaking Changes

* **Removed `--project-dependencies`** — The `--project-dependencies` flag has been removed from `tessl install` and `tessl init`. Dependency scanning and automatic tile matching are no longer part of the install flow. Use `tessl search` to find relevant tiles instead.

## 0.75.0

### New Features

* **API Key Management** — New `api-key` command group with `create`, `list`, and `delete` subcommands for managing workspace-scoped API keys. Supports both interactive and non-interactive (scripting) modes
* **Auto-Select Single Workspace** — When you're a member of only one workspace, the CLI now skips the workspace selection prompt and selects it automatically

### Breaking Changes

* **`auth token` Removed** — The `auth token` command has been removed. Use the new `api-key create`, `api-key list`, and `api-key delete` commands instead for workspace-scoped API key management

## 0.74.0

### New Features

* **Machine-Readable Search**: `tessl search --json` flag outputs results in JSON format for scripting and automation
* **Skill Review Threshold**: `tessl skill review` now supports a `--threshold` option: when the score is below this threshold, the command will fail - helpful for CI use cases
* **Scores in Search & Info**: Search results and `tessl tile info` now display quality scores and security review details

### Improvements

* **Piped Token Output**: `tessl auth token` now suppresses the spinner and hints when output is piped, making it easier to use in scripts
* **Better Error Display**: Failed operations now render a red cross indicator for clearer error visibility
* **Search Column Alignment**: Interactive search results now have properly aligned columns
* **Remove Steering to Use `query_library_docs` MCP tool**: It was getting in the way of skill activation from some users. You can manually opt-in to install the rules yourself with `tessl install tessl/cli-setup`

### Bug Fixes

* Fixed skill review API calls failing due to stale authentication tokens
* Fixed eval commands resolving git repo root incorrectly when run from subdirectories

## 0.73.0

### **New Features**

* **Security Reviews on Install** - `tessl install` and `tessl update` now show security review results before installation. CRITICAL/RISKY findings require confirmation to proceed, ADVISORY findings show an advisory after install, and unscanned items display a warning. Use `-dangerously-ignore-security` to bypass prompts in CI/scripted contexts
* **Commit-Pinned Installs** - `tessl install` now accepts `github:<repo>@<sha>` and full GitHub commit URLs, allowing you to install a skill at a specific commit. A post-install hint directs to `tessl update` for future updates
* **Publish `--bump` Flag** - `tessl tile publish` and `tessl skill publish` now accept `--bump patch|minor|major` to auto-increment the version when the current version already exists in the registry
* **`.agents/skills` Directory Support** - Install skills in `.agents/skills` alongside other requested agents since that’s the folder many tools are aligning with

### **Improvements**

* **Grouped Search Results** - `tessl search` now groups results by type (Tiles / Skills) with section headers when both types are present

### **Bug Fixes**

* Fixed `tessl skill new` showing interactive prompts even when all required flags (`-name`, `-description`, `-workspace`) are provided
* Fixed MCP server processes becoming orphaned when the parent process disconnects (stdin closes)

## 0.72.0

### **New Features**

* **Pre-Publish Validation & Dry Run** - Tile and skill publish commands now validate permissions, workspace, and version availability before publishing, with clear pass/fail output. Use `--dry-run` to check without actually publishing.
* **Security Scores in Search** - Search results now display security assessment levels (Passed, Caution, Risky, Critical) alongside tile scores

### **Improvements**

* **Smarter Eval Scenario Generation** - Existing scenarios are now considered when generating new ones, avoiding duplicates
* **Large File Exclusion in Eval Archives** - Files over 10MB are automatically excluded from repo archives during eval runs
* **Eval Commit Ref Validation** - Commit refs are validated before archive creation, with clear error messages for missing refs

## 0.71.0

### New Features

* **Support for Copilot in VSCode** — Skills, rules, and our MCP server can be automatically set-up for vscode
* **Eval Run Labels** — New `--label` / `-l` flag on `tessl eval run` lets you attach a short description to a run. Labels appear in `tessl eval list` and the Tessl web UI, making it easier to identify what you were testing across multiple runs.
* **Eval Variant Selection** — New `--variant` flag on `tessl eval run` lets you run only a specific variant. Pass `--variant without-context` to run the baseline only (useful for iterating on scenario quality without affecting the with-context comparison), or `--variant with-context` to skip the baseline.
* **Local Repo Eval Runs** — Project evals can now run against local git repos without SCM integration; the CLI archives and uploads the repo automatically
* **Smarter Scenario Generation** — `tessl eval generate` now avoids duplicating existing scenarios when generating new ones; `--count` specifies how many new scenarios to add

### Bug Fixes

* Allow installation of skills from unknown dot folders in GitHub repositories (e.g., `.agent-skills/`)

## 0.70.1

### Improvements

* **Non-Interactive Mode for Evals & Scenarios** — `tessl eval run` and `tessl scenario generate` now print the run/generation ID and URL immediately when running non-interactively, instead of polling for completion
* **Clearer Help Text** — `tessl eval run` and `tessl scenario generate` now show which flags are mode-specific, and invalid flag combinations are rejected with helpful messages

### Bug Fixes

* **Fixed install --watch-local exiting prematurely** — the process now stays alive until Ctrl+C and updated output to show relative paths rather than absolute ones
* **Fixed installation from `file:`** **source to exclude .git directories** - It now installs the same files that would be captured by `tessl tile pack` or `tessl tile publish`

## 0.70.0

### New Features

* **Local Tile Watching** — New `--watch-local` flag on `tessl install` watches local file-source tiles for changes and automatically reinstalls tiles, streamlining the tile development workflow
* **Search Score Display** — `tessl search` results now show aggregate quality and impact scores with color-coded badges
* **Scenario Generation from PRs** — New `--prs` flag on tessl scenario generate accepts PR numbers as an alternative to `--commits`
* **Multiple Scenario Downloads** — `tessl scenario download` now accepts multiple space-separated IDs (e.g., `tessl scenario download id1 id2`)
* **Eval Run Repeats** — New `--runs / -n` flag on `tessl eval run` to repeat each agent configuration multiple times
* **Eval Polling for Tile Evals** — Tile evals now poll for completion instead of returning immediately, with Ctrl+C to detach gracefully
* **Eval JSON Output for Tile Evals** — `--json` flag on `tessl eval run` now works for tile evals, outputting run ID, tile name, and scenario count
* **Eval Agent Flag** — New `--agent` flag (format: `agent:model`) replaces `--model` for tile evals, aligning with project eval conventions
* **Eval Cost Metadata** — `tessl eval view` now displays cost, runtime, turns, and token usage below each solution
* **Eval Agent/Model Display** — `tessl eval view` stats now show the agent and model used for each solution
* **`--last` for Eval Debug & Retry** — `tessl eval debug` and `tessl eval retry` now support `--last` for quick access to the most recent eval run
* **Repository Metadata in tile.json** — Tiles now support an optional repository URL field in their manifest

### Improvements

* **Tile Cache Protection** — Tile authoring commands now warn when operating on paths inside `.tessl/tiles/`, preventing accidental edits that would be overwritten on the next install
* **Cleaner Help Text** — Removed meaningless `--no-{flag}` negated boolean flags from all commands, improved flag capitalization, and reordered commands for logical grouping
* **Consistent Scenario Terminology** — "Generation run" renamed to "generation" throughout the CLI for simpler, more natural language
* **Scenario Generate Table Output** — `tessl scenario generate` results now render as a formatted table with Scenario ID and Commit ID columns
* **Smarter Binary Install** — Skips re-downloading binaries that already exist and pass validation; corrupt binaries are automatically cleaned up

### Fixes

* Fixed CLI crashes when output streams disconnect unexpectedly (EPIPE handling)
* Fixed `unpublish` help text to reflect the correct 2-day timeframe (was showing 2 hours)

## 0.69.0

### New Features

* **Scenario Generation Commands** - New `tessl scenario` command suite for generating and managing test scenarios. Generate scenarios from tiles or repository commits (`tessl scenario generate`), download them to disk (`tessl scenario download`), and track generation runs (`tessl scenario list`, `tessl scenario view`)
* **Global Tile Installation** - Install tiles globally with `tessl install --global` to make documentation and skills available across all your projects.
* **Eval Variant Comparison** - `tessl eval run` now supports running evaluations with multiple agent variants and context patterns, with automatic detection of tile vs. project scenario sources

### Improvements

* **Project Directory Hints** - `tessl init` and `tessl install` now display a helpful hint when the target project directory differs from your current working directory

### Bug Fixes

* Fixed a crash when piping CLI output to another command (e.g., `tessl list | head`) by gracefully handling broken pipe signals
* Fixed markdown link validation incorrectly parsing non-markdown files during tile linting

## 0.68.0

### New Features

* **GitHub Copilot CLI Support** — Tessl now recognizes GitHub Copilot CLI as an agent, with automatic detection, rules wiring via `AGENTS.md`, skill installation, and MCP configuration
* **Search Type Filtering** — `tessl search` now accepts a `--type` flag to filter results by content type (skills, docs, or rules)
* **Skill Review Auto-Accept** — `tessl skill review --optimize` now supports a `--yes / -y` flag to skip the confirmation prompt and auto-apply improvements

### Improvements

* Automatic Binary Cleanup — Old CLI binary versions are now automatically cleaned up after updates, keeping only the current version and one rollback
* Short SHAs for Git Tiles — `tessl list` and `tessl doctor` now display short SHAs for git-sourced tiles instead of full commit hashes
* Command Detection Timeout — Command lookups now have a 1-second timeout to prevent indefinite hangs during agent detection

### Breaking Changes

* `tessl skill search` Removed — Use `tessl search` --type skills instead

### Bug Fixes

* Fixed `tessl skill review --optimize` failing with a raw 401 error when not authenticated — now shows a clear login prompt
* Fixed `unpublish` help text to reflect the correct 2-day window (was incorrectly showing 2 hours)

## 0.67.0

### **New Features**

* Skill Optimization - `tessl skill review --optimize` now applies feedback from the review to generate an updated SKILL.md file
* Evaluation Type Support - `tessl eval list` now displays all evaluation types (tile, repo, skill) with a new "Type" column and `--type` flag to filter by evaluation type
* Filter Evaluations by Status - `tessl eval list` now supports a `--status` flag to filter runs by status (pending, in\_progress, completed, failed)

### **Bug Fixes**

* Fixed `tessl skill review` returning exit code 0 on validation failure — it now correctly returns a non-zero exit code, enabling proper CI/CD integration
* Fixed `tessl api --input` - sending incorrect Content-Type when piping JSON via stdin

## 0.66.0

### New Features

* **`outdated` command** — Check installed tiles for newer versions, showing current, safe update, and latest version info
* **`update` command** — Update tiles to newer versions. Use `--yes` for all, and `--force` to include breaking updates

## 0.65.0

### Bug Fixes

* **Windows Compatibility for Generated Files** - Fixes generated file and directory names containing colons (`:`) which are invalid in Windows file paths. Tile files committed to git repositories can now be cloned on Windows without errors. Existing installations are migrated automatically

## 0.64.0

### New Features

* **Local Tile Evaluation** - Run evals against your tiles directly from the CLI with `tessl eval run` and get a fast feedback loop for improving your tiles
* **Eval Results in Terminal** - View eval results with per-scenario breakdowns, variant comparisons, and scoring summaries using `tessl eval view`
* **Eval Run History** - List recent eval runs filtered by workspace, tile, or author with `tessl eval list`
* **Eval Retry** - Re-run failed evals with `tessl eval retry`

## 0.63.4

### Improvements

* **Internal** - Stability improvements

## 0.63.3

### New Features

* **Local Path Support for Tile Info** - `tessl tile info` now accepts a local directory path as an argument and defaults to the current directory when no argument is provided, making it consistent with other tile commands like `publish` and `lint`

### Improvements

* **Better Publish Messages** - After publishing tiles or skills, the CLI now displays the published resource URL and a note about moderation timelines

### Bug Fixes

* Fixed MCP configuration failures when using `npx tessl` by ensuring the tessl binary is accessible via the PATH during `init`

## 0.63.2

### Bug Fixes

* Fixed circular reference issues when `CLAUDE.md` and `AGENTS.md` are symlinked

## 0.63.0

### Improvements

* The CLI is now distributed as a native binary instead of a bundled Node.js package

## 0.62.2

### New Features

* **Optional Authentication** - You can now use `tessl init`, `tessl install`, and `tessl search` without logging in. Public tiles are accessible to everyone, while private tiles will show helpful hints to log in when needed

### Bug Fixes

* Fixed `--skill` flag not working correctly when installing a single skill from a local tile with multiple skills

## 0.62.1

### Improvements

* **Internal** - Stability improvements

## 0.62.0

#### New Features

* Unified Search — `tessl search` now returns both tiles and skills in a single view, with visual badges showing content types (\[docs], \[skills], \[rules]) and skill provenance
* Tile Evaluations — New tessl eval command group for evaluating tiles:
  * `tessl eval run [path]` — Run evaluations on local tiles
    * `--force` flag to re-run all evaluations including previously solved cases
  * `tessl eval list` — View recent eval runs with status
  * `tessl eval view-results <id>` — View detailed results with color-coded scores and assessment tables
    * `--last` flag to quickly view most recent eval results
  * Git metadata (branch, commit, dirty state) automatically attached to eval runs
* Tile Info — New `tessl tile info <name>` command to view tile metadata, verification status, and moderation status
* Skills in MCP Context — The `query_library_docs` MCP tool now includes installed skills when building knowledge context

#### Improvements

* Redesigned Help for `tessl -h` — Commands are now grouped by category with improved formatting and readability
* Publish Workspace Context — Publishing now shows the target workspace name before uploading

#### Bug Fixes

* Fixed `--skill` flag being ignored when installing skills from registry tiles
* Fixed re-installing tiles not updating the manifest with new skill selections
* Fixed tile lint incorrectly flagging files as orphaned when linked via `@path.md` includes

## 0.61.4

### Improvements

* **Install `--yes` Flag Behavior** - The `--yes` flag now auto-selects all skills when installing from GitHub, even in interactive mode. Previously it only worked in non-interactive environments.
* **Non-Interactive tile new** - The tessl tile new command can now run fully non-interactively when all required flags are provided, making it easier for scripts and agents to use.

### Fixes

* **GitHub Skill Installation Bugfixes** - Address various edge cases that prevented some skills being installed from GitHub
* **GitHub Skill Installation Respects Pinned Version** - Fixed an issue that meant we always installed a skill from a repository's trunk rather than the commit sha in `tessl.json` when doing `tessl install`

## 0.61.3

### Improvements

* **Faster git installs** - Git dependencies are no longer re-downloaded on every install when already at the correct version

## 0.61.2

### Improvements

* **Windows Platform Detection** - The CLI now detects Windows and provides a clear error message directing users to use WSL instead
* **Lenient GitHub Skill Installation** - Skills from GitHub with missing referenced files or minor schema issues now install with warnings instead of failing completely
* **Better Warning Display** - Installation warnings are now grouped by tile name with count summaries (e.g., "3 content warnings in github:user/repo")
* **Verbose Install Output** - Added `--verbose` (`-v`) flag to `tessl install` and `tessl skill search` commands to display detailed warning messages during installation

### Bug Fixes

* Fixed skill validation warnings showing absolute temp directory paths instead of relative paths
* Fixed installation failures when GitHub skills have invalid optional frontmatter fields (e.g., `allowed-tools` as array instead of string)

## 0.61.1

### New Features

* **Skill Commands** - Added a complete set of dedicated skill management commands: `tessl skill new`, `tessl skill import`, `tessl skill lint`, `tessl skill publish`, `tessl skill review`, and `tessl skill search`. Skills are now first-class citizens with their own command group for easier discovery and management.
* **GitHub Installation Support** - Install tiles and skills directly from GitHub repositories using `tessl install github:user/repo` or full URLs. Supports branch selection, subdirectories, and interactive skill selection. Git sources are pinned to commit SHAs for version stability.
* **Skill Search** - Discover available skills across the Tessl ecosystem with the new interactive `tessl skill search` command. Search returns both external skills from GitHub and tiles containing skills, with interactive selection and installation.
* **Skill Review** - Evaluate skill quality with `tessl skill review`, which validates [SKILL.md](http://skill.md/) files and provides LLM-based scoring across multiple dimensions with actionable suggestions for improvement. Supports both local paths and GitHub URLs.
* **Non-Interactive Mode** - Commands now auto-detect TTY availability and work in CI/CD pipelines and with AI agents. When required flags are missing in non-interactive environments, commands provide clear error messages pointing to available options.
* **Selective Skill Installation** - Choose specific skills when installing tiles using the new `include.skills` manifest field in tessl.json. Reduces clutter in agent directories by only activating the skills you need.
* **Codex Support** - Full support for Codex as a core agent alongside Claude Code, Cursor, and Gemini. Includes project detection, MCP configuration, steering, and skills synchronization.
* **Gemini Production Ready** - Gemini agent is no longer experimental and fully supported in production workflows.

### Improvements

* **Simplified Skill Naming** - Skill directories now use cleaner names (`tessl:<skill>` instead of `tessl:<workspace>:<tile>:<skill>`) and are symlinked rather than copied for better performance and consistency.
* **Automatic Eval Publishing** - Evals are now published by default when running `tessl tile publish` or `tessl skill publish`. Use `-skip-evals` to opt out. Published evals automatically trigger evaluation runs.
* **Better Skill Discovery** - Improved skill detection uses a three-step process (root check, priority directories, full scan) with optimizations that reduce scan time and exclude build/cache directories.
* **Streamlined Publishing** - The `tessl skill publish` command no longer asks redundant "will you share this?" prompts since publishing inherently means sharing.
* **Improved Help Text** - Updated `tessl init --agent` to list all supported agents (claude-code, codex, cursor, gemini) and clarified that `tessl install` accepts both registry tiles and GitHub URLs. Added `tessl i` as a shortcut alias.
* **Relative Paths in Manifest** - When creating tiles with `--install`, the CLI now stores relative paths in tessl.json instead of absolute paths, making projects portable across machines and directories.
* **Smarter CLI Setup** - The tessl/cli-setup tile is now only installed when your tiles have documentation, reducing overhead for steering-only projects.
* **Flexible Tile Content** - Tiles can now contain any file type, not just markdown files, allowing for configuration files, code examples, and other documentation formats.

### Bug Fixes

* Fixed skill review score display showing `/4` instead of the correct `/3` scale
* Fixed status command handling of non-semver versions for git-based and file-based tiles
* Fixed orphaned file detection for tiles with root-level skills - README.md and other root files are no longer incorrectly flagged as orphaned
* Fixed skill publish command to accept [SKILL.md](http://skill.md/) file paths directly instead of only directory paths
* Fixed file source tiles being incorrectly deleted as orphaned on repeated installs when dependency key differed from tile name
* Fixed skill frontmatter validation warnings during installation from external sources like GitHub
* Fixed `tessl skill new` output messages to reference correct tile directory paths
* Fixed skill selection in GitHub repos to require explicit choices, preventing accidental installation of all skills from large repositories

## 0.60.0

### New Features

* **Project Mode (Managed vs Vendored)** - Choose how tile content is managed in your project:
  * **Managed mode** - Tile contents are gitignored like `node_modules` (default for existing projects)
  * **Vendored mode** - Tile contents are committed to your repository (default for new projects)
  * Switch modes anytime by setting `"mode": "managed"` or `"mode": "vendored"` in `tessl.json`

### Improvements

* **Simplified Local Tile Dependencies** - Local tiles (using `file:` or `link:` sources) no longer require a `version` field in `tessl.json`. The CLI automatically reads versions from installed `tile.json` files. Existing manifests with both `version` and `source` are automatically migrated to the new format.

## 0.59.0

### New Features

* **`.tileignore` Support** - Exclude files from tile validation and packaging using gitignore-style patterns.

## 0.58.1

### Improvements

* **Tile Commands Auto-Detect** - `tessl tile pack`, `tessl tile lint`, and `tessl tile publish` can now be run directly from your tile directory without explicitly specifying the path

### Bug Fixes

* Squashed some bugs that were hiding in the codebase. They know what they did.

## 0.58.0

### New Features

* **Context Cost Analysis (Experimental)** - The `tessl doctor` and `tessl tile lint` commands now display estimated token costs for tile content loaded into agent context windows. This helps you understand which tiles contribute most to context usage and identify oversized content before publishing.
* **HTTP Proxy Support** - The CLI now works in proxied network environments by automatically detecting and using HTTP/HTTPS proxy settings from environment variables (`http_proxy`, `https_proxy`, `HTTP_PROXY`, `HTTPS_PROXY`). The CLI respects `no_proxy`/`NO_PROXY` bypass rules.

### Improvements

* **Enhanced Python Dependency Scanning** - Improved Python dependency detection with support for extras notation (e.g., `openai[aiohttp]>=1.52.2`) across requirements.txt, pyproject.toml, and `uv tree` output. The scanner now also automatically falls back to `pip3` when `pip` is not available, improving compatibility with macOS and Linux distributions.

### Bug Fixes

* Fixed Go package PURL validation to require the `v` prefix in version strings (e.g., `v1.9.3` instead of `1.9.3`), ensuring pkg.go.dev documentation links work correctly.
* Fixed false "broken link" warnings during `tessl tile lint` when markdown files contain URI schemes like `mailto:`, `tel:`, `ftp:`, or `data:`.

## 0.57.0

### New Features

* **Monorepo Subfolder Support** - The `tessl install --project-dependencies` command now scans dependencies from your current working directory, enabling you to run it from monorepo subfolders in an initialized project (e.g., `tessl init && cd backend && tessl install --project-dependencies`)

### Improvements

* **Smarter Documentation Tree** - The context tool now only includes files that are transitively linked from a tile's documentation entrypoint, filtering out orphaned files and making documentation discovery more focused

### Bug Fixes

* Fixed markdown link validation to properly handle anchors (e.g., `./guide.md#section`). The validator now validates both file existence and anchor validity, with clearer error messages for broken links

## 0.56.2

### Improvements

* **Internal** - Stability improvements

## 0.56.1

### Improvements

* **Observability Enhancements** - Improved telemetry infrastructure for better diagnostics and system monitoring

## 0.56.0

### Breaking Changes

* **Node.js 18 No Longer Supported** - The CLI now requires Node.js 20 or later. Node.js 18 reached end-of-life in April 2025 and is no longer supported. The CLI will now fail with a clear error message if you attempt to run it on Node.js 18.

### Improvements

* **Only Auto-Init Outside Existing Projects** - The `install` and `search` commands no longer automatically initialize a project when run in a subdirectory of a Tessl project directory. This prevents accidentally creating unwanted projects when running commands after changing directories. To initialize a project, explicitly run `tessl init` first.

### Bug Fixes

* Fixed an issue where the `init` command's failed to identify and install relevant tiles.

## 0.55.1

### Improvements

* **Faster Auto-Updates** - The CLI now checks for updates every 3 hours (down from 24 hours), ensuring you get critical fixes and improvements more quickly. You can still adjust the interval with `TESSL_AUTO_UPDATE_INTERVAL_MINUTES` or disable it by setting it to `0`.

## 0.55.0

### New Features

* **Updated Workspace Roles** - Workspace member roles have been updated to: `member`, `publisher`, `manager`, and `owner` (the `viewer` role has been removed)

### Bug Fixes

* Fixed authentication issue where API token authentication (`TESSL_TOKEN`) would fail after token refresh attempts, causing authenticated API calls to fail

## 0.54.0

### New Features

* **Tile Manifest Validation** - The `describes` field in tile manifests is now validated to ensure it contains a valid PURL (Package URL) format. Invalid PURLs or unsupported package types will show helpful warnings during `tessl tile lint`, `tessl tile pack`, and `tessl tile publish` operations

### Improvements

* **Project Directory Detection** - Improved project directory discovery logic allows the CLI to better locate your `tessl.json` even when running commands from subdirectories within your project

### Bug Fixes

* Fixed missing newline after `tessl list` output for better terminal formatting

## 0.53.0

### New Features

* **Go Modules Support** - Dependency scanner now detects Go projects and extracts dependencies from `go.mod` files
* **Auto-Init on Search** - When selecting a tile from search results, the CLI now automatically initializes the project if needed (creates `tessl.json`)
* **Dynamic Terminal Sizing** - Interactive prompts now adapt to your terminal height for better readability
* **Escape Key Cancellation** - Press Escape to cancel select/checkbox prompts

### Improvements

* **Smarter Context Tool** - When no documentation is found, the tool now suggests running a search to find relevant tiles
* **CI Environment Detection** - Auto-update and version checks are now automatically disabled in CI environments

### Bug Fixes

* Fixed tile installation failures when system temp directory is on a different filesystem (handles cross-device moves)

## 0.52.2

No changes in this release

## 0.52.1

### Improvements

* Homebrew installation now available for stable releases
* MCP server stability improvements

## 0.52.0

### New Features

* Added `tessl tile lint` command to validate tiles before publishing

### Bug Fixes

* Tile upgrades now properly clean up old files when installing new versions
* Fixed markdown link validation to skip code blocks in tile documentation

## 0.51.0

* MCP Tool Improvements
  * Renamed `get_library_context` tool to `query_library_docs` and updated descriptions for better clarity
  * Updated cli-setup steering tile version to reflect tool rename and improve adoption
* Tile Management
  * Added `tessl list` command to display installed tiles
* CLI UX
  * Improved CLI message spacing and copy for better readability

## 0.50.6

* Added the ability to `archive` and `unarchive` workspaces
  * Archiving a workspace allows you to non-destructively remove workspaces you no longer wish to use or see. Archiving a workspace also archives all tiles in that workspace. This means that users can still install those tiles if defined in their manifest, but will not otherwise see them in search etc.
  * Unarchiving, as you’d expect, shows a workspace once again. However, it does *not* unarchive tiles within the workspace, to avoid potentially unarchiving content that was previously archived before the workspace was.
* Fixed a bug when authenticating in multiple machines that would result in our MCP tool `get_library_context` only working on the last machine you authenticated.

## 0.50.5

We added a new `tessl tile pack` command which validates and builds a tarball for a tile. It can be useful to validate things before doing `tessl tile publish`.

Also fixed a bug where the CLI would fail to run when who signed up without a first or last name.

## 0.50.4

Fix `tessl tile publish` requiring an absolute path

## 0.50.3

This release marks a significant shift in focus. We've rebuilt the CLI from the ground up as an **Agent Enablement Platform**, pausing work on the Tessl Framework to concentrate on our registry functionality and agent integration.

We really appreciate all the feedback we have received so far. Please, keep it coming.

### What's Changed

#### Getting Started is Now Simpler

When you run `tessl init` in your project, it now automatically detects your dependencies and pulls relevant tiles from the registry. For teams already using tessl, new developers only need to install the CLI and grant MCP server permissions—everything else happens automatically when the MCP starts up.

#### Smarter Agent Integration

Instead of agents searching through generated documentation, they now use our new `get_library_context` MCP tool to query tiles directly. This requires logging in to tessl, but makes context retrieval much more efficient. The MCP tools also include `login` (for in-session authentication) and `status` (for checking project state).

Note: `KNOWLEDGE.md` is no longer generated since agents now pull context on-demand.

#### Command Reorganization

We've streamlined the command structure. Changes to existing commands:

* `tessl registry install|search` → `tessl install|search`
* `tessl registry sync` → `tessl install --project-dependencies`
* `tessl registry publish|unpublish|archive` → `tessl tile publish|unpublish|archive`
* `tessl version` → `tessl --version`

#### Release Channels & Auto-Updates

You can now choose between `latest` (default, stable) and `beta` (early access) channels. The CLI checks for updates hourly and auto-updates transparently (max once per 24 hours). Configure the interval with `$TESSL_AUTO_UPDATE_INTERVAL_MINUTES` or set it to 0 to disable.

#### New Commands

* `tessl doctor` - diagnose authentication, manifest status, detected agents, and dependencies (add `-json` for full dependency details)
* `tessl uninstall` - remove tiles from your project

### What's Removed

**The Framework functionality is no longer included.** If you need the full framework features, v0.28.0 remains available (though development is paused).

Currently, automatic setup only supports Claude Code and Cursor. We'll add other agents based on requests—in the meantime, you can manually configure the MCP with any agent.

***

**Note:** This is a major rewrite (v0.30.0 → v0.50.2). Existing workflows will need adjustment.

*(Updated Nov 27, 2025)*

***

## 0.28.0

### New Features

* Invoking `setup agent` via `npx` will now configure mcp to use tessl via `npx`, ensuring smoother setup for users without a global install.
* Added integration with Cursor IDE for automatic generation and application of steering rules from tiles.
* Added `tessl registry uninstall` to easily uninstall tiles.

### Improvements

* Improved error messages for the `add-member` command to enhance clarity.
* Improved `tessl status` output to better reflect post-generation changes.
* Aligned arguments for `tessl registry unpublish` and `tessl registry archive`.

### Bug Fixes

* Fixed detection of direct dependencies in the pip detector.
* Resolved issue where unsupported package managers showed unnecessary user-facing messages.
* Extended display name support to include PyPI and Maven packages.
* Removed outdated compatibility code for `specs.json`.

## 0.27.0

### New Features

* **New `tessl setup project-info` Command**: CLI-only users can use this command to add details that Tessl tools require to `AGENTS.md`.
* **Framework Initialization**: you can choose “full-framework” (closed beta, login required) or “registry only” when running `init`.
* **Steering Rules**: Tiles can now define agent behavior rules via a new `steering` section in their manifests. These rules are automatically aggregated into a `RULES.md` file.
* **Local Usage Spec Installation**: Added support for installing tiles from local directories via a new `source` field in `tessl.json`.

### Improvements

* Simplified usage spec installation paths by removing version info from the directory structure.

### Bug Fixes

* Fixed `config list` to return empty results instead of throwing errors when no config file is present.

## 0.26.0

### New Features

* Selecting Cursor during `tessl init` or via `tessl setup agent` will now automatically install rule files into `.cursor/rules/tessl/framework` as part of project setup, improving Framework adherence.

## 0.25.0

### New Features

* **Improved Tile Installation UX:** Tiles suggested during install/update are now selected by default, making the default path simpler for users.
* **Improved Help for `tessl init`:** The `-help` output for `tessl init` now lists available agents, making it easier to discover options.
* **Non-Interactive Shell Support:** CLI installation no longer blocks in non-interactive shell environments.

### Improvements

* **Better Logging Behavior:** In non-interactive mode, JSON logs are now correctly sent to stderr, preserving standard piping behavior.
* **Help Text Visibility:** Tile help text remains visible even when tiles are deselected, improving clarity during installation.

### Bug Fixes

* **Maven Dependency Detection:** Fixed issues with the Maven dependency detector to ensure accurate detection.
* **Logging Flushing Reliability:** Addressed a flakiness issue by ensuring that stdio is flushed on close, not exit.
* **Ink Render Handling:** Corrected usage of Ink’s rendering logic to prevent hanging or exit-related issues.
* **Security:** Updated `pino` logger to remove a transitive vulnerability.

## 0.24.0

### New Features

* `tessl registry sync` to synchronize tiles from the registry.
* `tessl setup framework` to switch between the full Tessl framework and “registry-only” mode.
* `tessl stamp` to manually sync spec/code hashes after intentional edits so tessl status stops flagging them.
* `tessl registry search` now matches by full tile name (workspace/name), making it easier to find your own tiles.
* `tessl registry list` added to browse available tiles.
* `tessl document` adds tests to spec by default.

### Improvements

* `tessl status` surfaces an explicit error if bootstrap hasn’t been run.
* Tool calls will fail if agent bootstrap process has not been run, with guidance to fix.
* Added --print-project-cache flag for getting the path to the project cache.
* Removed interactive tool picker removed to simplify workflows.
* AGENTS.md now includes clearer “bootstrap” hints and wording tweaks to reduce confusion about when/why bootstrap should run.

### Bug Fixes

* MCP commands now authenticate correctly in all call sites.
* Reduced noisy output during `tessl registry sync`.

### Compatibility

* Minimum Node.js version is now **>= 22.0.0**.

## 0.23.0

### New Features

* Added support for **GitHub Copilot**.
* `tessl edit` now supports code files that have an associated `@describe` spec. Changes are made via the spec.

### Improvements

* `tessl whoami` command now includes your user ID.
* Reduced the chances of "token expired" errors, by proactively refreshing tokens when commands are run.
* Test commands will now time out if no output is received for a set period, preventing hangs.
* Registry commands now prompt for initialization if the workspace isn’t already set up.
* Unused `.tessl/usage-specs` directories are now removed during sync if the corresponding entries are removed from `tessl.json`.
* Test generation is now controlled by a unified `generateTests` param, which always skips locked tests.
* Improved `list` command usability, to make it easier for agents to select the right parameters.
* `tessl registry publish` **s**kips uploading irrelevant `.md` and `.gitignore`d files.

### Bug Fixes

* `tessl status` no longer shows duplicated test paths.
* Resolved issue where interactively selected tools weren’t able to run.
* Fixed Goose setup, so that correct `.gooserules` configuration is used.

### Deprecations

* Removed deprecated annotations like `@describes`, `@generates`, and `@satisfied-by`.

{% hint style="warning" %}
**⚠️ Be sure to check out the changes in** [**0.22.0**](#0.22.0) **if you're coming from an older version**
{% endhint %}

## 0.22.1

### Bug Fixes

* Fixed a project language detection issue that would occasionally cause errors across different commands.

## 0.22.0

{% hint style="warning" %}
**⚠️ Upgrading for users who installed via `npm`**

If you have already installed tessl via npm, you'll need to:

* Run `npm uninstall -g tessl-alpha` (if you have a version earlier than `v0.21.0`)
* Run `npm i -g @tessl/cli` to update to the latest version.

The `update` command will work as expected from `v0.22.0` onwards.
{% endhint %}

{% hint style="info" %}
**Camel case flag support has been removed**

Camel case flag support has now been fully phased out, all command flags should be provided in kebab case.
{% endhint %}

### **New Features**

* `init` now offers the option to set up an agent and MCP integration when initializing a project for the first time.

### **Improvements**

* Support information is now listed in help for logged-out users.
* Tool parameters are now displayed before model parameters in tool-level help.
* Links are now supported in kitty terminal.

### **Bug Fixes**

* Fixed the rules file targeting in Gemini CLI agent setup.
* `feedback` is now gated to authenticated users, unauthenticated users can request support via email (<support@tessl.io>).

## 0.21.2

### **Bug Fixes**

* Fixed MCP server not allowing invocation of install or search tools when not logged in.

## 0.21.1

### **Improvements**

* Running tools with spec-registry-only context will now fail early and remind you to install the Tessl Framework before continuing.
* Added ability to exit `registry search` with the Escape key.
* Search results now link to the **spec registry** page instead of individual package registries.

### **Bug Fixes**

* Fixed **Ctrl+C** handling with the experimental `observe` command.
* Fixed a deprecation warning on `registry install`.

## 0.21.0

{% hint style="warning" %}
**⚠️ Upgrading for users who installed via `npm`**

We have now published to public npm! This means that if you installed Tessl using `npm`, auto update with `tessl update` will not work for you for this version. To update, you’ll need to run:

```markdown
npm uninstall -g tessl-alpha
npm install -g @tessl/cli
```

{% endhint %}

{% hint style="warning" %}
**⚠️ Re-initializing your projects**

With this release, you’ll need to re-initialize any previously-created Tessl projects by running `tessl init` inside those directories.
{% endhint %}

***

### Breaking Changes

* Removed test generation from the `build` tool and introduced a new `build-tests` tool
* The spec format has been updated to allow capabilities to contain requirements that don’t have `[@test]` links:
  * `create` and `edit` specs will only add `[@test]` links if explicitly asked to do so in the `--prompt`

### **New Features**

* Our spec format now supports distinguishing between three types of tests:
  * `locked` tests: capture functional requirements provided
    * Denoted by `{ .locked }` next to the `[@test]` link or in a header containing `[@test]` links.
    * You can manually mark tests as locked or use `tessl test` to do it by passing `--lock-tests`.
  * `impl` tests: cover implementation details that are tested to identify changes in behaviour disconnected from a spec’s functional requirements.
    * Denoted by `{ .impl }`.
    * They are generated by `tessl document --include-impl-details` .
  * `draft` tests: are untagged and could have been added manually or using `edit` or `create`
    * You can use `tessl test --lock-tests` to automatically lock all draft the tests from a spec when all tests pass.
* Added flags to `build-tests` tool to select which kind of tests to generate `--generate-draft-tests`, `--generate-locked-tests`, and `--generate-impl-tests`.

### New Commands & Tools

* Added new `registry install`, `registry search`, and `registry sync` commands for working with Usage Specs.
* Added a new `test` tool, to run all of the tests for a given spec.
* Added `generate-tests` tool to add tests to a given spec.
* Added experimental `observe` tool to observe MCP tool invocations.

### Spec Registry

* Unauthenticated users can now access a subset of Tessl’s features to add Usage Specs to their projects.
  * Running `init` while logged out will set up `AGENTS.md` and framework files relating to the Tessl Spec Registry.

### Global Config

* `config` commands now support the `--global` flag, for updating the global Tessl config.
* The global config now supports a `shareUsageData` key to allow for analytics opt-out.

### **Improvements**

* Cleaner output for `build` and `build-tests` with a final summary listing successful and failed specs.
* Spec discovery for `build` is smarter: only builds specs with @generate links that actually need code updates.
* Diagnostics suggestions now correctly use positional parameters (e.g., `tessl build <spec>`), and `status` accepts \<spec> as positional.
* Registry-only flows link to the Knowledge Index; usage spec manifest split into tessl.json (structured) and `KNOWLEDGE.md` (narrative).
* Tessl MCP tools can now log detailed output to a file to reduce their output and avoid saturating agent context when the agent is instructed to do so.
* Added `--code` and `--tests` filters to `list` command for finer control.
* Made `test` tools `spec` argument positional in CLI commands.
* `status` now splits diagnosed issues into errors and warnings and includes errors regarding spec parsing.
* `config set` now **validates keys** before setting.
* Updated spec syntax information in our system prompts:
  * Added context about our content tags: untagged (draft), `locked` and `impl`.
  * Removed un-used `.dependencies` and `.dependency` tags.
* Updated Tessl framework content with clearer guidance on `tessl test`, `status`, and `fix` behavior.
* `version` output is now cleaner and includes a hint to update if a new version is available.
* The `--spec` argument in `build` is now positional.
* Exposed `modelName` parameter in MCP tools

### **Bug Fixes**

* Spec selection no longer appears to “infinite scroll.”
* `infer-spec` no longer swallows errors.
* Fix loop now receives test results properly.
* Reporter failures print helpful context (e.g., missing file paths) to the terminal.
* Prevent generation of tests when using edit on code files.
* Test-runner name generation validates input and throws on invalid paths.
* Tessl framework files are now filtered from context provided to tools to prevent context poisoning.
* Fixed issue where **login could not be cancelled** while polling.
* Fixed truncated console logs when running in **non-interactive/piped mode**.
* Fixed `edit` tool so context files are properly passed.
* Fixed dependency verification to use correct `@use` path resolution.
* Prevented whitespace-only messages from being sent to models.
* Pass test results through fix loop iterations correctly.
* Fixed an incorrect path in `.tessl/.gitignore` for session data storage.
* Fixed `init` missing from global help.
* Reject invisible characters from LLM interactions.

## 0.19.0

{% hint style="warning" %}

> This release includes breaking changes that require migration for existing projects.\*\*

To migrate your existing projects using `TESSL.md`, run the following steps:

1. Remove old system prompt directory: `rm -rf .tessl/system-prompt`
2. Run `tessl init` to initialize the new framework.
3. Migrate any custom content from `TESSL.md` to `AGENTS.md`
4. Remove the old file: `rm TESSL.md`
5. Re-configure any existing agent integrations: `tessl setup agent`
   {% endhint %}

***

### New Features

* Adopted [`AGENTS.md`](http://agents.md/) standard (replacing `TESSL.md`) for unified AI agent configuration across your development workflow.
* **Improved Dependency Handling**
  * `verify-deps` now runs automatically after code generation in the build process.
  * New `specifyMissingDependencies` flag can auto-update your spec with missing dependencies in `tessl build` and `tessl edit`.
  * New `never` option added to generation mode to skip file generation entirely.
* `tessl status` enhancements:
  * Highlights whether a spec includes `@generate` or `@describe` annotations.
  * Added dirtiness diagnostic to detect out-of-sync code/test files.
  * Added diagnostic for missing `AGENTS.md` entries in `tessl status`.
* **Improved Spec & Test Management**
  * Rewritten `document` tool with more intuitive behavior and support for complex specs.
  * Re-initializing a project now regenerates framework files.

### Improvements

* Removes `setup language` command; tools that require test commands now have a `--test-command` flag.
* Removed description upon tool invocation.
* Increased latest version check timeout in `update` command to reduce false negatives.

### Bug Fixes

* Logging in from an agent now automatically updates the MCP server so you can continue without restarting.
* Fixed tool summaries not showing in CLI output.
* CLI session data no longer prevents process exit after command completion.

## 0.18.1

### **New Features**

* **`build` tool** now has a post-generation fix loop to automatically resolve issues - *we will be tweaking how we decide which test command to run in the coming week*
* New **`status`** checks for orphaned tests, mixed implementation links & missing required files
* Added support for **agent-native planning**: agents now create and maintain **`.plan.md`** files automatically during planning.

### **Improvements**

* **Removed `--recursive` option** from status command for consistency with other commands
* **Replaced** `--rebuild-tests` with `--generate-tests` to `build` to generate only missing, outdated or always (default is now `outdated` rather than `missing`)
* **Added** `--generate-code` to `build` which behaves like `--generate-tests` but for code files (default is `outdated`, but is likely to change)
* **Generated code now includes self-hashing** for integrity checking and better status reporting on modified files
* Removed **timestamps from generated code tags**
* Improved **logging and error messages** across tools
* Improved **exception messages** to include more debugging context
* Better **editor detection and logging** in planning workflows
* Clarified descriptions for several commands & tools
* Tools invoked via MCP now return more information about their run, improving feedback visibility for agents
* The `build` tool now returns a failure exit code when the fix loop fails, ensuring accurate signaling of build status.

### **Bug Fixes**

* Fixed **update** command in Linux when using npm
* Fixed **test generation messages** saying “tests” instead of “test files”

### Deprecations

* Removed ability to edit plan files directly via the `edit` tool; users now receive a clear error if they attempt to do so.
* Made the `plan` tool private to reduce confusion and encourage agent-driven planning workflows

## 0.17.1

### Bug Fixes

* Fixes creation of the Claude subagent instructions directory as part of `setup agent`

## 0.17.0

### New Features

* Enabled tessl status to list all specs by default, providing broader project insights.
* Updated tessl status to include sync checks that detect whether a spec's code and tests are up to date.

### Improvements

* Updated build and document tool descriptions for clarity and accuracy.
* Made the -spec parameter more explicit and consistently required in tessl status help output.
* Renamed build tool's iterations parameter to maxIterations for clarity.
* Renamed @build links to @generate to reflect intended behavior.

### Bug Fixes

* Fixed bash execution in the update command to work reliably across Mac and Linux.
* Corrected error handling for expired keys.
* Made terms and conditions check respect a global directory set via environment variable.
* Fixed a crash in tessl status when a non-existent or empty spec file is provided.
* Resolved incorrect logging of issue counts in single-spec status output.
* Improved handling of file paths in the document tool to normalize inputs like ./path/to/file.


# Sharing Usage Data

Tessl is committed to our users’ privacy, and protecting your data is our top priority.

The nature of Tessl’s product requires it to see and participate in AI exchanges, and that may include sensitive and precious data. We take great care to earn the trust of handling such data, and want to be clear and transparent to our users about this.

#### Opt out of sharing telemetry and usage data

Tessl collects telemetry and usage data from its CLI and cloud service usage, and uses this to improve product quality, guide roadmap priorities and troubleshoot user issues. This may include conversations, code snippets and file contents used to guide Tessl actions.

All data is encrypted at rest and well protected, and you can ask to delete this data at any time.

You can easily opt out of data collection at any time by following the steps [here](/reference/configuration#opting-out-of-telemetry). Doing so will ensure Tessl doesn't see your data for local actions, and doesn't persist it for cloud data. Opting out will not disable or hinder your AI usage, but may make it harder to troubleshoot issues with support.

#### Tessl collaborates with highly trusted cloud LLM providers

Tessl partners with the top AI labs to service our users. We take great care to only use providers with a strong security posture, and while we pass some data to those services as part of our product’s operation, we do not grant those partners any rights to your data.

The most notable partners we work closely with are OpenAI, Anthropic and Google.

#### Tessl uses your data to make our products better for you

The sole purpose of data collection is to understand you, our users, and improve our products for you. We do not sell or monetize your data, and have absolutely no intent to do so.

We reserve the right to train on data collected from our free tier usage, but have never done so to date. Instead, we focus our AI tuning on public data and purposely created synthetic data sets.

If you have any questions or feedback, please email us at <privacy@tessl.io>. We may agree to custom enterprise terms for usage data on a case by case basis - please contact us to discuss this at <legal@tessl.io>. For more information on how we collect, use, disclose and process your personal data, see our full [Privacy & Cookie Policy](https://tessl.io/policies/privacy-cookies)


# Open Source Attribution

The Tessl Registry has been enriched by insights from many open source projects. While no code has been copied, we acknowledge the broader open source community whose work has inspired and informed these specs. All licenses and rights remain with the original project contributors.


