@vsuite/core
The generation pipeline: loads and migrates vsuite.json, loads packs, resolves the selection, renders agents, skills, instructions, the vsuite MCP server, job-metrics tooling, and native/MCP configs for each target, and writes them atomically. Non-goals: interactive prompts and argument parsing (@krizic/vsuite), catalog contents, and target formats.
This is a private, source-only workspace package (exports → ./src/index.ts). It is bundled into the @krizic/vsuite CLI and is not published to npm. Workspace consumers depend on it with "@vsuite/core": "workspace:*".
Public API
| Export | Kind | Signature | Description |
|---|---|---|---|
loadConfig |
function | (root: string, options: LoadConfigOptions) => Promise<LoadedConfig> |
Reads <root>/vsuite.json, runs migrateConfig to cliVersion, validates with parseConfig, and, only when the migration changed the config and write is true, writes it atomically. Missing file: Cannot find <path>. Run "vsuite init" to create vsuite.json, then run "vsuite generate" again.; invalid JSON: Cannot read <path>: <reason>; non-object: <path> must contain a JSON object. |
LoadConfigOptions |
type | { cliVersion: string; write?: boolean } |
Target vsuite version; write defaults to true (false for dry runs). |
LoadedConfig |
type | { config: VsuiteConfig; migration: MigrationResult; path: string; before: string; after: string } |
Validated config, migration result, file path, and original/migrated text (after === before when unchanged). |
Migration, MigrationResult |
type | re-export from @vsuite/migrations |
See @vsuite/migrations. |
readGenerationConfig |
function | (root: string) => Promise<VsuiteConfig> |
Reads vsuite.json for generation, migrating legacy files in memory without writing them. |
planGeneration |
function | (root, options) => Promise<GenerationPlan> |
Renders every output without writing (used by preview and generate). |
generate |
function | (root: string, options: GenerateOptions) => Promise<RenderedOutput[]> |
Plans, merges legacy .agent-metrics/ records into .vsuite/agent-metrics/, writes all outputs, git-ignores .vsuite/, removes stale skills and pack outputs, and updates vsuite.lock.json. GenerateOptions: cliVersion (required), updatePacks, onWarning, packSources. |
parseEnvFile, readProjectEnvFile, updateProjectEnvFile, ensureVsuiteGitignored, and related |
functions | Read and update the git-ignored .vsuite/.env that holds MCP secrets. |
|
migrateLegacyMetrics, mergeJobLogs |
functions | Move pre-0.7 .agent-metrics/ content into .vsuite/agent-metrics/. |
|
loadProjectSkills |
function | (root: string, directory: string, ids: readonly string[]) => Promise<RenderableSkill[]> |
Loads <directory>/<id>/SKILL.md; rejects paths escaping the root (including via symlinks), and requires YAML frontmatter with name equal to the id and a description containing “use when” or “use for”. |
writePlan |
function | (root: string, outputs: readonly RenderedOutput[]) => Promise<void> |
Validates and writes all outputs via temp files and renames. |
RenderedOutput |
type | re-export from @vsuite/targets |
A file to write. |
Dependencies
- Workspace:
@vsuite/catalog,@vsuite/config,@vsuite/json,@vsuite/migrations,@vsuite/packs,@vsuite/targets,@vsuite/templates. - Third-party:
yaml(frontmatter),jsonc-parser(existing JSONC configs). Dev:@vsuite/test-utils. - Used by:
@vsuite/workflows,@krizic/vsuite.
Diagrams
sequenceDiagram
participant CLI as "vsuite generate / migrate"
participant L as loadConfig
participant M as "@vsuite/migrations"
participant C as "@vsuite/config"
participant G as generate
CLI->>L: loadConfig(root, { cliVersion, write })
L->>L: read and JSON.parse vsuite.json
L->>M: migrateConfig(raw, cliVersion)
M-->>L: { config, from, to, applied, changed }
L->>C: parseConfig(migration.config)
opt changed and write
L->>C: writeJsonAtomically(vsuite.json, migration.config)
end
L-->>CLI: LoadedConfig
opt not a dry run
CLI->>G: generate(root)
end
flowchart TD
A["writePlan(root, outputs)"] --> B["resolve each output path under root"]
B --> C{"absolute, root itself, or escapes root?"}
C -- yes --> X1["throw: unsafe path"]
C -- no --> D{"duplicate path?"}
D -- yes --> X2["throw: Multiple renderers produced path"]
D -- no --> E{"existing ancestor is a symlink?"}
E -- yes --> X3["throw: path beneath symbolic link"]
E -- no --> F["mkdir parent, write each to path.pid.uuid.tmp"]
F --> G["rename every temp file onto its target"]
G --> H["finally: remove leftover temp files"]
Existing native configs are only extended: MCP servers already present in .opencode/opencode.json, .mcp.json, or .vscode/mcp.json are not overwritten. Existing Copilot agent frontmatter tools/agents are read so the adapter can preserve them.
Usage
import { generate } from "@vsuite/core";
const outputs = await generate(process.cwd(), { cliVersion: "0.7.1" });
for (const output of outputs) console.log(output.path);Testing
pnpm vitest run --project @vsuite/core