# `plugin` _(no submodules)_ ## Purpose Composes the agent-skills installer plugin from its constituent stages (`detect`, `prompts`, `plan`, `apply`, `postInstall`). Exposes both the default `agentSkillsPlugin` (no-options instance using the bundled manifest) and a `buildAgentSkillsPlugin(options)` factory for tests and embedders that want to override the bundle root or capture deterministic timestamps. ## Features - Default export is `agentSkillsPlugin` so `import "@suaveplan/install-agent-skills"` returns a ready-to-mount plugin via `mod.default`. - Factory `buildAgentSkillsPlugin(options)` accepts `bundleRoot`, `manifestPath`, and `nowIso` for full test control. - The `apply` lambda derives `targetDir` from the planned `index.json` op so `postInstall` always sees the resolved path, even when answers used a relative path. - Stable plugin metadata: `id: "agent-skills"`, `version: "0.1.0"`. ## Basic Example ```ts import { agentSkillsPlugin, Host, DiskFs, } from "@suaveplan/installer"; import "@suaveplan/install-agent-skills"; // ensures default export is loaded const fs = new DiskFs({ cwd: process.cwd() }); const host = new Host(ctx, fs); const result = await host.run(agentSkillsPlugin, { answers: { targetDir: ".suaveplan/skills" }, }); ``` ## Advanced Example ```ts import { buildAgentSkillsPlugin } from "@suaveplan/install-agent-skills"; import { runPlugin } from "@suaveplan/installer/testing"; const plugin = buildAgentSkillsPlugin({ bundleRoot: "/tmp/test-bundle", manifestPath: "/tmp/test-bundle/manifest.json", nowIso: "2026-04-28T00:00:00.000Z", }); const result = await runPlugin(plugin, { answers: { targetDir: "/x", only: ["crypto"], }, }); expect(result.handle?.installed).toBe(2); ``` ## API Reference - `agentSkillsPlugin: InstallerPlugin` — default-options instance. - `buildAgentSkillsPlugin(options?): InstallerPlugin` — factory. - `interface AgentSkillsPluginOptions` — `{ bundleRoot?, manifestPath?, nowIso? }`. ## Implementation Notes The default `agentSkillsPlugin` is created via `buildAgentSkillsPlugin()` so the no-options path stays test-coverage-friendly (one factory, two callers). The `apply` lambda's `readTargetFromOps` helper reads the trailing `/index.json` op to derive the resolved target — this is more robust than threading answers through closures because it survives the host's `only`/`exclude` filtering, which can drop earlier ops but never the index patch. The factory's options are forwarded to `plan` via spread conditionals so omitting any option produces a runtime that uses the default (the bundled manifest path, the bundled assets root, and a fresh `Date.now()` timestamp respectively). Tests use `nowIso` to fix the timestamp for snapshot assertions; production runs let it default so each install carries its own ISO 8601 marker in the index.