Skip to content
Back to skills

Add Vendor Adapter

ASecurity

Scaffold a brand-new ynh vendor adapter end-to-end (a new AI CLI harness like GitHub Copilot CLI, Gemini CLI, etc.). Use when onboarding a vendor that has no adapter yet — as opposed to vendor-adapters, which maintains adapters that already exist against evolving vendor specs.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 20, 2026
ai-agentsgoreactdockergitbackenddocumentation

Works with

  • cursor
  • cli
  • mcp

Security analysis

A100/100

Scanned October 20, 2026

npx -y skills add eyelock/ynh --skill add-vendor-adapter --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Vendor Adapter?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Add Vendor Adapter
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/eyelock-add-vendor-adapter/badge)](https://www.skillsdirectory.com/skills/eyelock-add-vendor-adapter)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: add-vendor-adapter
description: Scaffold a brand-new ynh vendor adapter end-to-end (a new AI CLI harness like GitHub Copilot CLI, Gemini CLI, etc.). Use when onboarding a vendor that has no adapter yet — as opposed to vendor-adapters, which maintains adapters that already exist against evolving vendor specs.
---

# Add a New Vendor Adapter

Use this skill when ynh needs to support a **new** AI coding CLI that has no
`internal/vendor/<name>.go` yet — e.g. adding GitHub Copilot CLI, Gemini CLI,
or any future vendor. If the vendor already has an adapter and you're just
reacting to a spec change, use the `vendor-adapters` skill instead — it owns
the per-vendor documentation links and format-mapping tables that this skill
depends on.

## Before writing code: research

1. Research the vendor CLI's actual behavior — install method, config file
   layout (project-level and user-level), plugin/extension system (if any),
   skills/agents/rules/commands support, MCP support, hooks, instructions
   file, and CLI flags for interactive/non-interactive/initial-prompt launch.
   Cite official docs, not blog posts, wherever possible — vendor CLIs change
   fast and secondary sources go stale.
2. Add a new section to `.claude/skills/vendor-adapters/SKILL.md`'s
   documentation-links table and format-mapping tables for the new vendor.
   That skill is the single source of truth for vendor doc links — do not
   duplicate them here.
3. Decide the vendor's **launch strategy** up front — this drives most other
   decisions:
   - **Native plugin loading** (like Claude's `--plugin-dir`): `syscall.Exec`,
     no symlinks, `NeedsSymlinks() == false`.
   - **No native plugin loading** (like Codex, Cursor): symlink install into
     the project's vendor config dir + managed child process with signal
     forwarding, `NeedsSymlinks() == true`.

## Checklist: files to touch

Every one of these was touched when Cursor was added; treat it as the
canonical touch-list. Search the codebase for `cursor` (case-insensitive) at
any point to cross-check completeness — `grep -rli cursor --include="*.go" --include="*.md" .`

### Core adapter

- [ ] `internal/vendor/<name>.go` — new file implementing the full `Adapter`
  interface (`internal/vendor/adapter.go`). Self-register in `init()` via
  `Register(&<Name>{})`. No other wiring needed for the adapter itself to be
  reachable by name.
- [ ] `internal/vendor/<name>_test.go` — table-driven tests for every method,
  matching the depth of `internal/vendor/cursor_test.go`.
- [ ] If the vendor needs symlinks, reuse `installSymlinks`/`cleanSymlinks`
  from `internal/vendor/symlinks.go` — don't reimplement.
- [ ] If the vendor launches as a managed child process, reuse
  `runChildProcess` from `internal/vendor/process.go` for signal forwarding.

### Exporter (vendor-native plugin distribution)

- [ ] `internal/exporter/exporter.go` — add the vendor's export layout
  (skills/agents/rules/commands directory names may differ from runtime
  `ArtifactDirs()` — see Codex's `.agents/skills/` vs runtime `.codex/`).
- [ ] `GeneratePluginManifest` in `internal/vendor/<vendor>.go` — the
  vendor-native plugin manifest. There is **no** `internal/exporter/manifest.go`;
  the exporter calls the adapter (`exporter.go:190` and `:330`), and so does
  marketplace generation (`marketplace.go:305`). One implementation serves both.

### Marketplace

- [ ] `internal/marketplace/marketplace.go` — add the vendor to the default
  vendor list in `Build` (search for `[]string{"claude", "cursor", "codex",
  "copilot"}`).
- [ ] `GenerateMarketplaceIndex` in `internal/vendor/<vendor>.go` — the index
  content itself, called from `internal/marketplace/index.go:41`. Each adapter
  declares its own anonymous structs; `Codex` is the worked example of a schema
  that genuinely differs (`interface.displayName`, `source{source,path}`,
  `policy.installation`).

  Do **not** copy Claude's implementation and rename it. `Cursor` did exactly
  that, and shipped the wrong shape until ynh#301 was fixed: Cursor's documented
  format nests `description` under `metadata`, carries no per-plugin `version`,
  and uses a bare `"plugin-name"` source, none of which the copied
  implementation had. Nothing caught it, because it compiled and produced valid
  JSON — it was just the wrong vendor's JSON.

  Write it from `references/<vendor>.md`, which is hand-tested, and check the
  result against that file rather than against another adapter.

  Note `codexMarketplaceJSON` in `marketplace.go` is a **test** unmarshalling
  helper, not the generator — do not add a sibling struct there expecting it to
  produce output.

### `ynh agent run` backend (if the CLI supports scriptable turn-by-turn sessions)

- [ ] `internal/agent/<name>.go` — implement `WorkerBackend`
  (`internal/agent/worker.go`) if the vendor CLI can run non-interactively
  with session resume (see `internal/agent/cursor.go`, `codex.go`,
  `claude.go` for the three existing resume strategies — they differ
  significantly, don't assume one pattern fits).
- [ ] `internal/agent/loop.go` — register in `selectBackend`.
- [ ] Find the CLI with `lookWorkerCLI(b.Name())`, never a literal: the
  binary's name is the adapter's `CLIName`, the only place it is spelled
  (#524). Run the CLI itself, with no leading subcommand left over from some
  other launcher.
- [ ] `cmd/ynd/llm.go`: add the vendor to `llmVendors` if its CLI can take a
  one-shot prompt on stdin and print the answer as text, so `ynd compress`
  and `ynd inspect` can use it. Arguments only; the binary comes from the
  adapter.
- [ ] This is a **separate surface from `vendor.Adapter`** — a vendor can have
  one without the other, but if the CLI supports non-interactive prompting at
  all, prefer adding both in the same PR since they share research.

### Docker image support

- [ ] `cmd/ynh/image.go` — add `COPY --chown=ynh:ynh` line (no `--link`) for the new vendor's staged
  config, and confirm the default-vendor fallback logic still makes sense.

### Documentation

- [ ] `docs/vendors.md` — vendor capability table.
- [ ] `docs/hooks.md` — hook event mapping table.
- [ ] `docs/mcp.md` — MCP config format table.
- [ ] `docs/marketplace.md` — marketplace format table.
- [ ] `docs/artifacts.md`, `docs/skills-standard.md` — skills/agents/rules/
  commands format notes if the vendor has quirks (e.g. Claude's plugin loader
  demoting certain frontmatter fields).
- [ ] `docs/getting-started.md`, `docs/harness-engineering.md`, `README.md`,
  `AGENTS.md` — mentions of the supported-vendor list.
- [ ] `docs/tutorial/vendors-and-symlinks.md` and any other tutorial that
  enumerates vendors by name.
- [ ] `docs/tutorial/manual-test-plan.md` — add vendor-specific manual test
  steps.
- [ ] `.github/CONTRIBUTING.md` — the format-mapping tables in the "Vendor
  Adapters" section quote every vendor inline; add a column.
- [ ] `.claude/agents/evals.md`: add the vendor's CLI binary to the `STUBS`
  line and the stub table, so no eval can launch the real CLI.
  `make check-vendor-parity` fails until you do.
- [ ] `.claude/CLAUDE.md`, `.claude/agents/ynh-contributor.md`,
  `.claude/agents/evals.md`, `.claude/skills/ynh-dev/references/architecture.md`
  — project-level mentions of the vendor list.

### Tests

- [ ] Unit tests alongside every changed file (errcheck is strict — check all
  returned errors).
- [ ] `test/e2e/` — add the new vendor to the end-to-end matrix once the
  adapter is stable enough to exercise against real fixtures (this is the
  release gate, not a per-PR gate — see `.github/CONTRIBUTING.md` § E2E test
  suite).

## Order of operations

1. Research + update `vendor-adapters` skill docs/tables (this makes the
   adapter code review-able against a written spec, not tribal knowledge).
2. Write the adapter + its test, get `make test FILE=./internal/vendor`
   green in isolation.
3. Wire exporter + marketplace + docker image.
4. Wire `ynh agent run` backend if applicable.
5. Update all documentation touch points.
6. `make check` (full CI: deps, format, lint, test, build).
7. Manual smoke test: `make install`, create a throwaway harness, `ynh run -v
   <name>` against the real vendor CLI, confirm launch, skills/rules/MCP/hooks
   actually take effect.
8. Only then: commit, push, PR into `develop` per the branching model and
   pre-remote gates (`.claude/rules/branching.md`, `.claude/rules/pre-remote.md`).

## Common pitfalls

- **Don't force a lowest-common-denominator design.** Per
  `.github/CONTRIBUTING.md` § Design Stance, "vendor-neutral" means every
  *feature* translates cleanly to every vendor — not that every vendor must
  implement every feature identically. It's fine for `SupportsExportDelegates()`
  or `ExportArtifactDirs()` to return "not supported" for a vendor that
  genuinely lacks the concept; document the gap, don't fake support.
- **Don't assume the CLI's flags are stable.** Vendor CLIs that are under
  active development (weekly releases) explicitly warn that flags change —
  verify against the CLI's own `--help` output at implementation time, not
  just docs pulled during research.
- **Don't invent a new artifact directory shape** unless the vendor genuinely
  requires it — reuse `DefaultArtifactDirs()` (`skills`, `agents`, `rules`,
  `commands`) unless the vendor's own conventions differ enough to justify a
  custom `ArtifactDirs()` override (see Codex's `.agents/skills/` handling).
- **Skills-as-directories vs skills-as-files**: some vendors (Claude, Cursor)
  read `SKILL.md` under vendor-owned directories; some read it under
  cross-vendor directories like `.agents/skills/` or even another vendor's
  directory natively (a vendor recognizing `.claude/skills/` directly, for
  example) — check whether the new vendor's own docs list *other* vendors'
  conventions as inputs it accepts natively before assuming it needs its own
  private copy.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.