Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@suaveplan/installer - Plugin host + lifecycle for project boilerplating and asset installation: detect → prompts → plan → apply → postInstall, transactional apply with rollback, conflict policies, manifest discovery.
Summary
Plugin host for project boilerplating and asset installation. Pipelines
plugins through detect → prompts → plan → apply → postInstall with
transactional rollback, conflict resolution, and dry-run support.
Documentation tree
- bin — (no submodules)
- suaveplan-install — (no submodules)
- errors — (no submodules)
- errors — (no submodules)
- disk-fs — Disk-backed implementation of
MutableInstallerFsused by thesuaveplan-installbin and any host-side code that want… - installer-fs — Re-exports the read-only
InstallerFsinterface from the types module and declares its mutating extension `MutableInst… - memory-fs — In-memory implementation of
MutableInstallerFs. Used by the testing harness (runPluginconstructs one if the caller… - host — (no submodules) - conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules) - conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules) - conflict — Resolves the per-op
conflictpolicy on… - conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… - json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… - text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/…
- apply — (no submodules) - conflict — Resolves the per-op
- detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… - host — (no submodules) - conflict — Resolves the per-op
conflictpolicy on… - plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… - post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… - prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe…
- apply — (no submodules) - conflict — Resolves the per-op
- manifest — (no submodules)
- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
createMemoryFs(seed)is a thin… - run-plugin — End-to-end test harness for plugins.
runPlugin(plugin, options)wires up an in-memory filesystem, a scripted CLI, a n… - script-cli — Non-TTY
InstallerClidriven by pre-recorded answers.ScriptCliis the default CLI used byrunPlugin— tests scrip… - error-codes — Defines the canonical error-code registry for
@suaveplan/installerand theInstallerErrorclass that carries those…
- installer-fs — Re-exports the read-only
InstallerFsinterface from the types module and declares its mutating extension `MutableInst… - memory-fs — In-memory implementation of
MutableInstallerFs. Used by the testing harness (runPluginconstructs one if the caller… - host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… - conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… - json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… - text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/…
- apply — (no submodules)- conflict — Resolves the per-op
- detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… - host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… - plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… - post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… - prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe…
- apply — (no submodules)- conflict — Resolves the per-op
- manifest — (no submodules)- discover — Walks the consumer's
node_modulestree and returns every installer plugin matching the naming conventions: first-part…- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
createMemoryFs(seed)is a thin…
- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
- run-plugin — End-to-end test harness for plugins.
runPlugin(plugin, options)wires up an in-memory filesystem, a scripted CLI, a n… - script-cli — Non-TTY
InstallerClidriven by pre-recorded answers.ScriptCliis the default CLI used byrunPlugin— tests scrip… - error-codes — Defines the canonical error-code registry for
@suaveplan/installerand theInstallerErrorclass that carries those… - suaveplan-install — (no submodules)- errors — (no submodules)- errors — (no submodules)- disk-fs — Disk-backed implementation of
MutableInstallerFsused by thesuaveplan-installbin and any host-side code that want… - installer-fs — Re-exports the read-only
InstallerFsinterface from the types module and declares its mutating extension `MutableInst… - memory-fs — In-memory implementation of
MutableInstallerFs. Used by the testing harness (runPluginconstructs one if the caller… - host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… - conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… - json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… - text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/…
- apply — (no submodules)- conflict — Resolves the per-op
- detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… - host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… - plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… - post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… - prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe…
- apply — (no submodules)- conflict — Resolves the per-op
- manifest — (no submodules)- discover — Walks the consumer's
node_modulestree and returns every installer plugin matching the naming conventions: first-part…- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
createMemoryFs(seed)is a thin…
- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
- run-plugin — End-to-end test harness for plugins.
runPlugin(plugin, options)wires up an in-memory filesystem, a scripted CLI, a n… - script-cli — Non-TTY
InstallerClidriven by pre-recorded answers.ScriptCliis the default CLI used byrunPlugin— tests scrip… - error-codes — Defines the canonical error-code registry for
@suaveplan/installerand theInstallerErrorclass that carries those… - suaveplan-install — (no submodules)- errors — (no submodules)- errors — (no submodules)- disk-fs — Disk-backed implementation of
MutableInstallerFsused by thesuaveplan-installbin and any host-side code that want… - installer-fs — Re-exports the read-only
InstallerFsinterface from the types module and declares its mutating extension `MutableInst… - memory-fs — In-memory implementation of
MutableInstallerFs. Used by the testing harness (runPluginconstructs one if the caller… - host — (no submodules)- apply — (no submodules)…
- apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on…- apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… - conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… - json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… - text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/…
- apply — (no submodules)- conflict — Resolves the per-op
- detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… - host — (no submodules)- apply — (no submodules)…
- plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… - post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… - prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe…
- apply — (no submodules)- conflict — Resolves the per-op
- manifest — (no submodules)- discover — Walks the consumer's
node_modulestree and returns every installer plugin matching the naming conventions: first-part…- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
createMemoryFs(seed)is a thin…
- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
- run-plugin — End-to-end test harness for plugins.
runPlugin(plugin, options)wires up an in-memory filesystem, a scripted CLI, a n… - script-cli — Non-TTY
InstallerClidriven by pre-recorded answers.ScriptCliis the default CLI used byrunPlugin— tests scrip… - error-codes — Defines the canonical error-code registry for
@suaveplan/installerand theInstallerErrorclass that carries those… - suaveplan-install — (no submodules)- errors — (no submodules) - errors — (no submodules)- disk-fs — Disk-backed implementation of
MutableInstallerFsused by thesuaveplan-installbin and any host-side code that want… - installer-fs — Re-exports the read-only
InstallerFsinterface from the types module and declares its mutating extension `MutableInst… - memory-fs — In-memory implementation of
MutableInstallerFs. Used by the testing harness (runPluginconstructs one if the caller… - host — (no submodules) - apply — (no submodules) - apply — (no submodules) - conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP…- json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… - text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/… - detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… - host — (no submodules) - plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… - post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… - prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe…
- json-merge — Implements the deep-merge semantics used by
- manifest — (no submodules) - discover — Walks the consumer's
node_modulestree and returns every installer plugin matching the naming conventions: first-part…- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
createMemoryFs(seed)is a thin…
- manifest — (no submodules)- installer-fs.test-helpers — Convenience helpers for assertions against the in-memory installer fs in plugin tests.
- run-plugin — End-to-end test harness for plugins.
runPlugin(plugin, options)wires up an in-memory filesystem, a scripted CLI, a n… - script-cli — Non-TTY
InstallerClidriven by pre-recorded answers.ScriptCliis the default CLI used byrunPlugin— tests scrip… - error-codes — Defines the canonical error-code registry for
@suaveplan/installerand theInstallerErrorclass that carries those…
Quickstart
# Add a plugin to your project as a dev dep, then run the installer
bun add -D @suaveplan/install-agent-skills
npx @suaveplan/installer add agent-skills
Programmatic use
import {
Host,
DiskFs,
type InstallerContext,
} from "@suaveplan/installer";
const fs = new DiskFs({ cwd: process.cwd() });
const host = new Host(ctx, fs);
const result = await host.run(myPlugin, {
dryRun: false,
force: false,
noInteractive: true,
});
console.log(result.summary);
Testing harness
import { runPlugin, ScriptCli } from "@suaveplan/installer";
const result = await runPlugin(myPlugin, {
answers: { name: "agent-skills" },
});
expect(result.summary.written).toBeGreaterThan(0);
Subpath exports
@suaveplan/installer— main barrel.@suaveplan/installer/types— types-only.@suaveplan/installer/errors—INSTALLER_CODES,InstallerError.@suaveplan/installer/host—Host, stage runners, apply/conflict helpers.@suaveplan/installer/fs—DiskFs,MemoryFs,MutableInstallerFs.@suaveplan/installer/manifest—discoverPlugins,findPlugin,loadManifest,validateManifest.@suaveplan/installer/testing—runPlugin,ScriptCli,assertWrote,createMemoryFs.
Module documentation
Every implementation file ships with a sibling .md covering Purpose,
Features, Usage examples, API Reference, and Implementation Notes. See
src/host/host.md, src/host/apply/apply.md, src/manifest/discover.md
for the load-bearing modules.
License
MIT