CodeHerderSearch⌘KRequest access →

Plugin sources

Sync a team's Claude Code plugin skills, agents and commands into the workspace catalog at one pinned commit, and see what the sync imports and refuses.

A plugin source is one plugin of a plugin marketplace, pinned to one commit. A marketplace is a GitHub or GitLab repo that lists plugins. CodeHerder reads the plugin at the commit you name. It copies the plugin’s skills, agents and commands into your catalog. Every session that starts after the sync can use them.

A plugin source is not native plugin loading. CodeHerder does not install the plugin into the harness. It copies instruction content only. For the other route, see Changing a device’s settings and When a task says “Repo config not trusted”.

You need no repo commit and no device setting for a plugin source. A workspace owner or admin decides, the same as for Skills.

Add a plugin source

From the web app: open Set up → Plugin sources and press Add source. Fill in three fields.

  • Repo — the marketplace repo. Use github:owner/repo, gitlab:group/repo, or an https URL.
  • Plugin name — the plugin’s name in the marketplace.
  • Commit — the full 40-character commit SHA. A branch name, a tag name or a short SHA is refused. A pin never moves by itself.

Press Preview before you save. The preview shows each item the commit imports and each item it refuses. It writes nothing. Press Add source to save and sync.

From the CLI:

ch plugin-source create --repo github:acme/plugins --plugin review-kit --commit <full-sha>

ch plugin-source list shows every source. ch plugin-source show <id> shows one source with its last sync. A source id is a full UUID, not a name.

Preview and update a pin

A new release of the plugin does not reach your catalog by itself. You move the pin on purpose.

From the web app: open the source and find Update pin. Enter the new commit and press Preview. The preview lists each item as added, removed, changed or unchanged. A refused item is listed with its reason. CodeHerder clips a long body, so a very large preview can show paths only. Then confirm the pin.

From the CLI:

ch plugin-source preview <id> --commit <full-sha> --files
ch plugin-source pin <id> --commit <full-sha>

--files adds a diff of each changed file. pin shows the item diff and asks you to confirm. In CI, add --yes.

A pin is guarded. If another admin moved the pin after you opened the source, your pin fails with plugin_source_pin_stale and nothing changes. Reload the source and try again.

An update removes an item that the new commit no longer offers. It also removes an item that the new commit now offers in an invalid form.

Remove a plugin source

Open the source and press Remove, or run ch plugin-source delete <id>. The items it synced leave the catalog. A session that starts after the removal does not get them. A session that is already running does not change.

The retained versions of each item stay readable, as Version history and going back describes. The sync history stays too.

Groups

A group can own a plugin source. Every workspace below the group sees the synced items. Managing workspaces explains groups.

In a child workspace, the source shows as inherited. The child can read it. The child cannot preview, pin or remove it. Make those changes in the group.

What a sync imports

Kind Where CodeHerder looks Notes
Skill skills/<name>/SKILL.md and its files Same rules as Skills.
Agent agents/<name>.md Stored as one AGENT.md.
Command commands/**/*.md A nested path joins with hyphens. commands/a/b.md becomes a-b.

The plugin’s own plugin.json can name other paths for these. CodeHerder follows them.

A synced item starts enabled. You added the source to make the items available. Your workspace can still turn one off.

What a sync never imports

A catalog item loads into every agent session of the workspace. Executable configuration needs the trust of a device owner, and a plugin source does not ask for it. So the sync refuses these and lists each one in the sync report:

  • Hooks.
  • MCP servers.
  • LSP servers.
  • Environment variables.
  • Settings.
  • Output styles.
  • An item whose frontmatter has a hooks, mcpServers or lspServers key.
  • A plugin whose marketplace entry points at a different repo. This is an external plugin source. CodeHerder refuses the whole plugin.

A refused entry does not stop the other items. The other items still import.

Warnings and collisions

${CLAUDE_PLUGIN_ROOT}. Some plugin files name a path that starts with ${CLAUDE_PLUGIN_ROOT}. The sync imports the file and adds a warning. In a session, that path does not exist. Only native plugin loading creates it. Read these files before you pin, and fix the plugin if it needs the path.

Slug collisions. A slug is unique for each kind in the whole workspace tree. An admin item, an ancestor group’s item or another source’s item can already hold the slug. Then the sync refuses the new item with slug_taken. The other items still import.

CodeHerder never renames an item for you. Rename or delete the first item, or ask the plugin author to rename.

The catalog budget. All enabled catalog items share one 2 MB budget. This includes skills, agents and commands. Skills has the details.

A synced item starts enabled, so a pin can go over the budget. CodeHerder checks the owner and every workspace below it. If any of them goes over, CodeHerder refuses the whole pin. The old pin and the old items stay. The sync history shows the refusal.

To fix it, disable some items or choose a smaller plugin. Then try again.

When a sync fails

What you see What it means
plugin_source_unreadable The workspace has no git credential for the host, the credential does not cover the repo, or the commit does not exist. See Integrations and Connecting the GitHub App.
plugin_source_rejected CodeHerder cannot import the plugin at all. The marketplace file is missing, the plugin is not listed, or its source is not a path inside the repo.
plugin_source_fetch_failed The git host or the network failed, or the archive is too large. Try again later.

A failed sync keeps the old pin and the old items. The source page shows each attempt under Sync history. Last sync shows what the newest attempt did, item by item.

Who can change what

Any member can read the sources and their history. Adding, previewing, pinning and removing need a workspace owner or admin. The caller must be a signed-in person. An agent’s session cannot do any of them. Preview counts as a change, because it reads the repo with the workspace’s own git credential.

A synced item is read-only. You cannot edit it or delete its definition. The error is catalog_item_synced, and it names the source. Change the plugin at its source and pin the new commit. You can still enable, disable and reset a synced item.

Audit events

Each change writes an event to the activity feed:

  • plugin_source.added
  • plugin_source.pinned
  • plugin_source.removed
  • plugin_source.sync_failed

Each item a sync creates, updates or deletes also writes skill.created, skill.updated or skill.deleted. These events carry the plugin source id.

How items reach a session

A change reaches the next session. A session that is already running keeps what it started with.

Agents and commands reach Claude Code only. CodeHerder writes an agent to .claude/agents and a command to .claude/commands.

Another harness has no folder for them. Its session page shows Unsupported harness for each one. Skills reach every harness. Harnesses lists them.

The device needs a current release. An older device gets skills only. Delivered files stay out of git. If your repo already has a file at the same path, the repo file wins.

Device opt-out

A device owner can turn synced content off for one device. Set CH_SYNCED_CATALOG to off. The default is on. The change applies at the next session. Items an admin wrote in the catalog still reach the device. See Changing a device’s settings.

Reading the session page

Open a session’s page and find the Skills section. It groups the rows. Items that an admin wrote come first. Then one group appears for each plugin source. The group title shows plugin@marketplace and the short commit. Each row shows its kind and one outcome:

  • Loaded — the item is in the session.
  • Skipped — your repo has its own file at that path.
  • Removed — the item is no longer enabled, so CodeHerder removed its old copy.
  • Not found and Turned off — a stage selection named a skill that is missing or off. See Which skills a stage gets.
  • Unsupported harness — the harness cannot take an agent or a command.
  • Opted out — the device owner turned off synced content.
  • Refused — the last sync refused the item. The row names the reason.

Commands can run shell lines

A command can contain a line that starts with !. Claude Code runs that line as a shell command when someone runs the command. CodeHerder does not run it. The harness’s own permission rules decide whether it runs.

This is the same class of risk as a skill script. Read each command body in the preview before you pin.

Last updated

CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close