---
title: "Plugin improver"
description: "Install the improver and start a reviewed change to an owned plugin."
canonical_url: "https://docs.oz0.ai/build/plugins/verified/plugin-improver"
---
# Plugin improver

> Install the improver and start a reviewed change to an owned plugin.

For: tenant administrators and plugin users.

Use Plugin improver (`ai.oz0/plugin-improver`) to propose changes to plugins your tenant owns and keeps in its repositories. It works on a copy of one plugin repository and produces a changeset with evidence for a person to review.

Only after approval does [GitHub's `push_changes`](https://docs.oz0.ai/build/plugins/github) open a draft pull request. A person must merge it. The improver cannot change Orchestrator Zero, another publisher's plugin or itself.

<table>
<thead>
  <tr>
    <th>
      
    </th>
    
    <th>
      
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Kind
    </td>
    
    <td>
      capability: one job, proposing changes to your plugins, owned by the team that maintains them
    </td>
  </tr>
  
  <tr>
    <td>
      Category
    </td>
    
    <td>
      Improve
    </td>
  </tr>
  
  <tr>
    <td>
      Flows
    </td>
    
    <td>
      <code>
        improve-plugin
      </code>
      
       (propose one change), <code>
        improver-notice
      </code>
      
       (what a routine's fire found), <code>
        improver-after-merge
      </code>
      
       (the result and the update after a pull request closes)
    </td>
  </tr>
  
  <tr>
    <td>
      Agents
    </td>
    
    <td>
      <code>
        improver
      </code>
      
       (Claude Agent SDK), <code>
        improver-opencode
      </code>
      
       and <code>
        improver-goose
      </code>
      
       (OpenCode and goose through harness-acp): one instruction file and one contract, one agent per harness
    </td>
  </tr>
  
  <tr>
    <td>
      Tool
    </td>
    
    <td>
      <code>
        oz0_plugin_improver
      </code>
      
      : the flows' own steps that need no model; local and read-only, reaches nothing
    </td>
  </tr>
  
  <tr>
    <td>
      Built-ins
    </td>
    
    <td>
      <code>
        oz.evidence
      </code>
      
       (where a target is installed from), <code>
        oz.report_outcome
      </code>
      
       and <code>
        oz.propose_update
      </code>
      
       (after a pull request closes), run as flow steps with no model
    </td>
  </tr>
  
  <tr>
    <td>
      Uses
    </td>
    
    <td>
      <a href="https://docs.oz0.ai/build/plugins/github">
        ai.oz0/github
      </a>
      
      : <code>
        resolve_ref
      </code>
      
      , <code>
        download_archive
      </code>
      
      , <code>
        get_pull_request
      </code>
      
       and <code>
        push_changes
      </code>
      
      , nothing else
    </td>
  </tr>
  
  <tr>
    <td>
      Skills
    </td>
    
    <td>
      the <a href="https://docs.oz0.ai/build/plugins/claude-code">
        build kit
      </a>
      
      's skills, as its agents' own
    </td>
  </tr>
  
  <tr>
    <td>
      Reaches
    </td>
    
    <td>
      nothing of its own: every call to GitHub is ai.oz0/github's, with your connection
    </td>
  </tr>
</tbody>
</table>

"Verified" means the project tested, pinned and secured this plugin. It does not mean that GitHub, Anthropic or any
other vendor endorses it.

## Install

```bash [Terminal]
oz0 plugin install hub:ai.oz0/github
oz0 plugin install hub:ai.oz0/harness-claude          # or harness-acp, for OpenCode or goose
oz0 plugin install hub:ai.oz0/plugin-improver --accept-reads results --reads-target notes --reads-target triage
                                                      # refused once with what it asks of ai.oz0/github
oz0 plugin install hub:ai.oz0/plugin-improver --accept-reads results --reads-target notes --reads-target triage \
  --accept-uses sha256:...
oz0 setting set PLUGIN_IMPROVER_TARGETS "notes=acme/notes, triage=acme/plugins:plugins/triage@main"
oz0 setting set PLUGIN_IMPROVER_PUBLISHER acme        # only when your plugins carry a hub listing
```

What it asks for:

<table>
<thead>
  <tr>
    <th>
      Grant
    </th>
    
    <th>
      Why
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        oz0_github.resolve_ref
      </code>
      
       (read)
    </td>
    
    <td>
      The commit a target's branch is at
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        oz0_github.download_archive
      </code>
      
       (read)
    </td>
    
    <td>
      That commit's code, for the target's check and the session's copy
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        oz0_github.get_pull_request
      </code>
      
       (read)
    </td>
    
    <td>
      A merged pull request, after the merge
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        oz0_github.push_changes
      </code>
      
       (write, waits for a person)
    </td>
    
    <td>
      The approved changeset as a draft pull request; the connector keeps to <code>
        GITHUB_ALLOWED_REPOS
      </code>
      
       when it is set
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="https://docs.oz0.ai/improve/evidence-for-agents">
        <code>
          reads: [results]
        </code>
      </a>
      
      , for the target plugins you name (<code>
        --reads-target
      </code>
      
      )
    </td>
    
    <td>
      What those plugins' jobs came to, read with <code>
        oz.evidence
      </code>
      
       with your permissions at every read, and the <code>
        results
      </code>
      
       events the <code>
        findings.yaml
      </code>
      
       routine fires on. Grant the same plugins as <code>
        PLUGIN_IMPROVER_TARGETS
      </code>
      
       names; add or take one back later with <code>
        oz0 plugin reads grant
      </code>
      
       and <code>
        revoke
      </code>
    </td>
  </tr>
</tbody>
</table>

Its settings:

<table>
<thead>
  <tr>
    <th>
      Setting
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        PLUGIN_IMPROVER_TARGETS
      </code>
    </td>
    
    <td>
      none
    </td>
    
    <td>
      The plugins it may propose changes to: <code>
        &lt;plugin>=&lt;owner>/&lt;repository>[:&lt;folder>][@&lt;branch>]
      </code>
      
      , one per line or comma-separated, at most 50. Without it, every job ends with "Nothing to do"
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        PLUGIN_IMPROVER_PUBLISHER
      </code>
    </td>
    
    <td>
      none
    </td>
    
    <td>
      Your publisher name on a hub; a target whose listing names another publisher is refused, and with this empty, any listed target is
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        PLUGIN_IMPROVER_FORGE_HOST
      </code>
    </td>
    
    <td>
      <code>
        github.com
      </code>
    </td>
    
    <td>
      The host your GitHub is on, such as your GitHub Enterprise Server's; a target installed from a repository on another host is refused (one installed from a <code>
        file://
      </code>
      
       mirror, which only an operator who allows file plugins can install, is compared by owner and name alone)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        PLUGIN_IMPROVER_HARNESS
      </code>
    </td>
    
    <td>
      <code>
        claude-agent-sdk
      </code>
    </td>
    
    <td>
      The coding harness: <code>
        claude-agent-sdk
      </code>
      
      , <code>
        opencode
      </code>
      
       or <code>
        goose
      </code>
      
      . Codex and Gemini CLI run some calls without asking, so the job's hooks and approvals could not decide them: they are not offered
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        PLUGIN_IMPROVER_CANARY
      </code>
      
      , <code>
        PLUGIN_IMPROVER_SOAK
      </code>
      
      , <code>
        PLUGIN_IMPROVER_SHADOW_RUNS
      </code>
    </td>
    
    <td>
      1, <code>
        10m
      </code>
      
      , 10
    </td>
    
    <td>
      The rollout the update after a merge proposes
    </td>
  </tr>
</tbody>
</table>

Changing them is a [plugin configuration change](https://docs.oz0.ai/govern/reviewed-changes/plugin-configurations#plugin-configurations), reviewed as your tenant
reviews them. Set the repositories your GitHub connection may write in `GITHUB_ALLOWED_REPOS` too, so that
`push_changes` refuses any other.

Its agents ask for your `smart` alias (the session) and `fast` (the judge), never a vendor's model: map them with
`oz0 model alias set`. The Claude Agent SDK speaks Anthropic's Messages API only, so `improver` needs an alias that
resolves to a provider that takes it; OpenCode and goose speak others.

## Start it

A person runs it from the console or the CLI:

```bash [Terminal]
oz0 run improve-plugin '{"target": "notes", "task": "The date format eval case fails since the last model change"}'
oz0 run improve-plugin '{"target": "notes", "evidence": ["finding:f-2c91"], "harness": "goose"}'
```

`evidence` cites findings, eval runs and comparisons by ID (`finding:<id>`, `eval:<run>`, `comparison:<id>`); the
platform keeps the ones that are your tenant's in the change's record, with what it knows of each. An app starts it the
same way through the [runtime API](https://docs.oz0.ai/build/apps/runtime-api) with its key, such as a CI job of the plugin's repository
whose tests failed:

```yaml [.github/workflows/test.yml]
- name: Ask the improver for a change
        if: failure()
        run: |
          curl -fsS "$OZ0_URL/v1/agents/improve-plugin/jobs?tenant=acme" -H "Authorization: Bearer $OZ0_APP_KEY" \
            -H "Content-Type: application/json" \
            -d '{"target": "notes", "task": "CI test failed on ${{ github.sha }}: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}'
        env:
          OZ0_URL: ${{ vars.OZ0_URL }}
          OZ0_APP_KEY: ${{ secrets.OZ0_APP_KEY }}
```

### Routines

No manifest key installs a routine, so the improver ships its routines as files in its folder,
`plugins/plugin-improver/routines/`, which an admin saves (`oz0 routine save -f <file>`) with an `owner_team` of the
tenant's:

<table>
<thead>
  <tr>
    <th>
      File
    </th>
    
    <th>
      Fires on
    </th>
    
    <th>
      Runs
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        ci-failure.yaml
      </code>
    </td>
    
    <td>
      GitHub's <code>
        workflow_run
      </code>
      
       and <code>
        check_suite
      </code>
      
       events that completed with <code>
        failure
      </code>
      
       or <code>
        timed_out
      </code>
      
       on a target's repository and branch (not a pull request's run)
    </td>
    
    <td>
      <code>
        improver-notice
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        findings.yaml
      </code>
    </td>
    
    <td>
      The platform's <code>
        results
      </code>
      
       events: a finding that opened on a target, a model alias or mapping rule that changed under its agents. They come only for the targets a person granted the improver the results of (<code>
        --reads-target
      </code>
      
      )
    </td>
    
    <td>
      <code>
        improver-notice
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        weekly.yaml
      </code>
    </td>
    
    <td>
      A schedule, once a week, for one target (copy it per target)
    </td>
    
    <td>
      <code>
        improver-notice
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        after-merge.yaml
      </code>
    </td>
    
    <td>
      GitHub's <code>
        pull_request
      </code>
      
       event, closed (merged or not), from an <code>
        oz0/improver-
      </code>
      
       branch
    </td>
    
    <td>
      <code>
        improver-after-merge
      </code>
    </td>
  </tr>
</tbody>
</table>

A routine's fire is a job an outside event starts, and such a job never runs a shell and a write in one run
([routines](https://docs.oz0.ai/build/parts/routines/outputs-and-permissions#what-a-fire-may-do)). The improver's session writes files, and its changeset ends in
a write, so a fire does not run it: `improver-notice` reads only, works out the target and the cause,
and ends with the command that starts `improve-plugin`, for the person who reads the fire's job.

A CI system that should
start the improver itself does it through the runtime API, as above. `improver-after-merge` runs no session: its
routine lists the two platform built-ins its flow calls, `oz.report_outcome` and `oz.propose_update`.

## Related tasks

- [How an improvement runs](https://docs.oz0.ai/build/plugins/verified/plugin-improver/job-lifecycle): Follow evidence collection, candidate checks and the work after a merge.
- [Improver limits and records](https://docs.oz0.ai/build/plugins/verified/plugin-improver/limits-and-records): Look up its boundaries, retained evidence and agent names.

<legacy-sections>

- <span id="after-a-merge">

Section

</span>

: [after a merge](https://docs.oz0.ai/build/plugins/verified/plugin-improver/job-lifecycle#after-a-merge)
- <span id="limits">

Section

</span>

: [limits](https://docs.oz0.ai/build/plugins/verified/plugin-improver/limits-and-records#limits)
- <span id="names">

Section

</span>

: [names](https://docs.oz0.ai/build/plugins/verified/plugin-improver/limits-and-records#names)
- <span id="the-candidate-check">

Section

</span>

: [the candidate check](https://docs.oz0.ai/build/plugins/verified/plugin-improver/job-lifecycle#the-candidate-check)
- <span id="what-a-job-does">

Section

</span>

: [what a job does](https://docs.oz0.ai/build/plugins/verified/plugin-improver/job-lifecycle#what-a-job-does)
- <span id="what-it-leaves-on-record">

Section

</span>

: [what it leaves on record](https://docs.oz0.ai/build/plugins/verified/plugin-improver/limits-and-records#what-it-leaves-on-record)
- <span id="what-it-never-does">

Section

</span>

: [what it never does](https://docs.oz0.ai/build/plugins/verified/plugin-improver/limits-and-records#what-it-never-does)

</legacy-sections>


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
