@krizic/vsuite
v0.7.5
Published
Configure and generate project-specific AI agents and skills.
Readme
@krizic/vsuite
The vsuite command-line interface. It configures and generates project-local AI agents, skills, and MCP configuration for OpenCode, Claude Code, and GitHub Copilot from one validated vsuite.json. This page is the reference for the CLI and the configuration file; the desktop app (@vsuite/ui) runs the same workflows.
The package publishes only the vsuite binary and the JSON Schema @krizic/vsuite/schema/vsuite.schema.json. There is no JavaScript API: exports contains only ./schema/vsuite.schema.json and ./package.json. The internal @vsuite/* workspace packages are bundled into dist/main.js and are not published.
Install
Requires Node.js 24 or later. Run commands from the root of the project that receives the generated files.
The npm registry currently carries an older release (0.3.1) that predates most of this reference; the current version will be published together with the source code. Until then, contributors run the CLI from source (see Development).
pnpm dlx @krizic/vsuite init # run once without installing
pnpm add -D @krizic/vsuite # or install as a dev dependency (enables editor schema validation)
pnpm add --global @krizic/vsuite # or install globallyCommands
| Command | Description |
|---|---|
| vsuite init [dir] | Detects frontend technologies, runs an interactive wizard, writes vsuite.json, and generates artifacts. dir defaults to the current directory and is created if missing. Fails if vsuite.json already exists. |
| vsuite init [dir] --no-generate | Writes vsuite.json without generating artifacts. |
| vsuite generate | Regenerates artifacts from vsuite.json, migrating an outdated config in memory without rewriting it, and prints each written path. |
| vsuite generate --update-packs | Accepts changed npm:/git: pack content and relocks it instead of failing with PACK_INTEGRITY. |
| vsuite generate --strict | Treats MD_LINT warnings as errors; nothing is written. |
| vsuite generate --quiet | Prints only the written paths, with no spinner or summary. |
| vsuite generate --json | Prints a single { "outputs": string[] } JSON envelope and nothing else. |
| vsuite migrate | Upgrades vsuite.json to this vsuite version, prints what changed, and regenerates. |
| vsuite migrate --dry-run | Prints the pending migrations and a diff of vsuite.json; writes nothing and does not generate. |
| vsuite graph [--format json\|mermaid] [-o <path>] | Prints the agent graph from vsuite.json (--format defaults to json); -o/--output writes to a file, inferring the format from .json, .mmd, or .md. |
| vsuite stack set <category> <id...\|none> | Sets a stack category and regenerates the artifacts. |
| vsuite pack add <source> [--name <name>] | Fetches and validates a pack (path:<dir>, npm:<spec>, git:<url>#<ref>), writes vsuite.json and vsuite.lock.json, and reports the agents and skills it adds or overrides. |
| vsuite pack remove <name> [--reset-to-catalog] | Removes a pack. Refuses while agents or skills use it unless --reset-to-catalog resets them (entries not in the catalog are removed). |
| vsuite pack list [--json] | Sources, locked versions, integrity status, and contributions. |
| vsuite pack update [name] | Refetches and relocks one or all packs. |
| vsuite pack validate <dir> [--json] [--strict] | Checks a pack directory without a project. |
| vsuite agent use <id> --from <pack\|catalog> | Chooses where an agent comes from; a new pack agent is added as a specialist. |
| vsuite skill use <id> --from <pack\|catalog> | Chooses where a skill comes from. |
| vsuite, vsuite --help, vsuite -h | Prints usage. Unknown commands print usage and exit 1. |
| vsuite <command> --help, vsuite <command> -h | Prints that command's usage and options. |
| vsuite --version, vsuite -v | Prints the installed vsuite version. |
Commands route through cac. On an interactive terminal init, generate, and migrate also render guided @clack/prompts output: init is bracketed by an intro/outro and shows a note summarizing the selected agents; generate (by default) and a non-dry-run migrate show a spinner and then a boxed summary titled Generated artifacts that groups the written paths by target directory with a per-group file count and a Total N files line, followed by a next-steps line suggesting vsuite graph. This decoration is suppressed when stdout is not a TTY (piped/scripted output) and by generate --quiet/--json; artifact paths always go to stdout, one per line.
All commands exit 1 and print the error message on failure.
The init wizard
vsuite init detects technologies from package.json, requirements.txt, pyproject.toml, go.mod, pom.xml, build.gradle, build.gradle.kts, and *.csproj, and prefills the stack. It then asks for targets, stack, agents, skills, capabilities, the preferences the selected agents need, MCP connection settings, and one default model (with optional effort and reasoning) applied to every agent. Edit modelProfiles afterwards to override individual agents.
When the agent-memory capability is selected, init also checks that npx is available, that @agentmemory/mcp is reachable in the npm registry, and whether the local agentmemory engine is running, then prints the remaining manual steps.
Configuration
vsuite.json is validated against a strict schema. For editor validation and completion, reference the published schema; this requires a local dev install, because pnpm dlx and global installs do not create the node_modules path.
This example selects every target, wires Context7, and defines a coordinator with one specialist:
{
"$schema": "./node_modules/@krizic/vsuite/schema/vsuite.schema.json",
"version": "0.7.3",
"targets": ["opencode", "claude-code", "github-copilot"],
"mcpServers": { "context7": { "source": "catalog" } },
"agents": {
"orchestrator": {
"role": "coordinator",
"canCall": ["backend-engineer"],
"skills": ["agent-efficiency-protocol"],
"tools": ["read", "search", "todo", "agent"],
"mcps": { "context7": ["*"] }
},
"backend-engineer": {
"role": "specialist",
"skills": ["agent-efficiency-protocol"],
"tools": ["read", "edit", "search", "execute", "todo", "web"],
"mcps": { "context7": ["*"] }
}
},
"modelProfiles": {
"default": {
"agents": {
"orchestrator": { "model": "provider/model" },
"backend-engineer": { "model": "provider/model" }
}
}
},
"activeModelProfile": "default"
}Top-level fields: version, targets, stack, capabilities, mcpServers, packs, agents, skillSources, projectSkills, projectSkillsDirectory, preferences, modelProfiles, and activeModelProfile. Every configured agent needs model settings in every model profile.
Agents and the agent graph
agents is the only source of agent behavior. Each entry has:
role:coordinatororspecialist. At most one agent is the coordinator. Only the coordinator may declarecanCalland hold theagenttool. Specialists finish with a handoff back to the coordinator, which decides who runs next.skills: built-in skill ids, or ids listed inprojectSkills.tools: the neutral vocabularyread,edit,search,execute,web,browser,todo, andagent.mcps:{ "<server>": ["*"] }or specific tool names, such as"prisma": ["migrate-dev"]. Every server must be declared inmcpServers.stack(optional): stack categories whose conventions the agent's prompt includes.metrics(optional, defaultfalse): adds the detailed job-metrics contract and a per-target report script.source(optional):catalogorpack:<name>.
Each target enforces the graph in its own way:
| Field | OpenCode | Claude Code | GitHub Copilot |
|---|---|---|---|
| canCall | permission.task | Agent(...) in tools, enforced when started with claude --agent <coordinator> | agents: allow-list |
| skills | permission.skill | skills: preload (not enforced; warns) | skill paths in the prompt |
| tools | tools map | tools: | tools: |
| mcps | mcp in .opencode/opencode.json with per-agent tool gates | .mcp.json and mcp__<server>__<tool> | .vscode/mcp.json and <server>/<tool> |
When a target cannot express a field, vsuite generate prints a named warning, such as warning [claude-code] skills-not-enforced: …. Nothing is dropped silently.
The catalog has 19 agents. The default set includes the orchestrator, backend and frontend engineers, software architect, project manager, UI/UX designer, design reviewer, docs steward, market requirements analyst, project onboarding agent, code reviewer, and QA evidence tester. Optional agents cover DevOps, Git workflow, database optimization, security auditing, performance engineering, tech debt analysis, and agent optimization.
GitHub Copilot agents use the custom agent frontmatter: review-only agents (code-reviewer, design-reviewer, qa-evidence-tester) get user-invocable: false, agent-optimizer gets disable-model-invocation: true, and planning and implementation roles get handoffs buttons to their next step.
Agent graph output
vsuite graph # JSON on stdout
vsuite graph --format mermaid # Mermaid on stdout
vsuite graph -o docs/agent-graph.mdWith -o/--output, the extension picks the format unless --format is given: .json writes JSON, .mmd writes Mermaid, and .md writes Mermaid in a fenced block. The file is replaced atomically.
Stack
stack records the selected technologies. frontend takes one framework plus optional companion shells (such as electron), database takes a list, and backend, orm, and designLibrary take one id or null.
| Category | Ids |
|---|---|
| frontend | nextjs, nuxt, angular, svelte, react, vue, and the companion electron |
| backend | nestjs, express, fastify, fastapi, django, go, spring-boot, aspnet-core |
| orm | prisma, drizzle, typeorm, sqlalchemy, django-orm, ef-core |
| database | postgresql, mysql, sqlite, mongodb, redis |
| designLibrary | daisyui, mui, antd, chakra-ui, radix-ui, tailwind |
Each technology except design libraries adds a <id>-conventions skill. The owning agents (the frontend engineer for frontend; the backend engineer for backend; the database optimizer and backend engineer for ORM and database) also get the technology's MCP server where one exists. Reviewers and other readers get the skill and Context7.
vsuite stack set orm drizzle
vsuite stack set database postgresql redis
vsuite stack set frontend react electron
vsuite stack set frontend nonestack set removes what the catalog added for the old choice and adds what it adds for the new one. Entries you edited by hand are kept and reported as warning stack: ….
MCP servers and secrets
mcpServers declares the servers agents may use. Catalog servers: agent-memory, context7, playwright, prisma, prisma-remote, next-devtools, angular-cli, angular-cli-readonly, svelte, nuxt, microsoft-learn, gopls, mongodb, redis, postgres-mcp-pro, electron, github, gitlab, and obsidian.
Secret settings are stored as ${VAR} references in vsuite.json, never as values. The values live in the git-ignored .vsuite/.env; generate adds .vsuite/ to .gitignore.
"mcpServers": { "mongodb": { "source": "catalog", "env": { "MDB_MCP_CONNECTION_STRING": "${MONGODB_URI}" } } }Self-managed GitLab
The gitlab server targets gitlab.com by default. For a self-managed instance, set the non-secret GITLAB_INSTANCE_URL setting to the instance base URL; generate renders <instance>/api/v4/mcp into every target's native config. Leaving it unset keeps https://gitlab.com/api/v4/mcp.
This is a vsuite setting, not an environment variable GitLab's server reads. Because it is not a secret, it is stored as a literal value in vsuite.json (secret settings are ${VAR} references whose values live in .vsuite/.env):
"mcpServers": {
"gitlab": {
"source": "catalog",
"env": { "GITLAB_INSTANCE_URL": "https://gitlab.example.com" }
}
}The init wizard asks for it when the gitlab server is selected or tracking.provider is GitLab (which implies gitlab); the desktop app edits it on the MCP & capabilities tab. To change it later, edit the value in vsuite.json and run vsuite generate, or save it in the app (which regenerates). There is no dedicated CLI subcommand for MCP settings.
Validation: http or https only, a single-line literal with no query string, fragment, or embedded credentials; sub-path installs are allowed and trailing slashes are stripped; a ${VAR} reference is rejected. The setting's help warns that http: sends the URL in cleartext. Self-managed needs GitLab 18.6 or later with the MCP server enabled, and OAuth consent on first connect.
Refresh caveat: generate rewrites a target's native URL only while it still equals the gitlab.com default; a custom URL in the file is left untouched, because the previous setting value is not persisted and a hand-edited endpoint cannot be proven vsuite-generated. To switch from one custom instance to another, edit or remove the generated entry (.opencode/opencode.json mcp.gitlab.url, .mcp.json mcpServers.gitlab.url, .vscode/mcp.json servers.gitlab.url) and regenerate. If the OAuth consent screen still opens against gitlab.com, that entry still holds the default endpoint: check the URL it holds and edit or remove it as above.
vsuite also generates its own MCP server, vsuite (.vsuite/vsuite-mcp.mjs), and grants it to every agent. Its tools are current_time and log_job.
Capabilities
The top-level capabilities list holds declarable capabilities that are not MCP servers; currently only brainstorming. MCP-backed capabilities (agent-memory, context7, playwright, prisma) come from their mcpServers entry.
brainstormingwrites thebrainstormingandwriting-plansskills to every target and adds a Brainstorming And Planning section to the orchestrator. The skill text is vendored from superpowers v5.1.0 (MIT, © 2025 Jesse Vincent); see@vsuite/templates.agent-memorywires the agentmemory MCP server (npx -y @agentmemory/mcp) and adds a Persistent Memory section to the granted agents. Project-local data lives under.vsuite/agentmemory.initprints the command that starts the local engine (REST API on port 3111, viewer on port 3113).
Preferences
Agents that need a tracking system or documentation location read it from preferences. Both accept any non-empty string; the wizard and the desktop app offer these values:
| Preference | Offered values |
|---|---|
| tracking.provider | None, GitHub, GitLab, Gitea |
| documentation.location | None, Obsidian, Local |
Known values match case-insensitively; unknown values render with generic wording.
Per-target models
Targets use incompatible model ids, so model accepts either a string (for every target) or an object keyed by target with an optional default:
"code-reviewer": {
"model": { "opencode": "github-copilot/claude-opus-5.5", "claude-code": "opus", "default": "claude-opus-5.5" }
}| Target | model format | Validated |
|---|---|---|
| opencode | provider/model-id | Yes |
| claude-code | alias (such as sonnet or opus), inherit, or a full model id | No |
| github-copilot | free string | No |
Each target resolves to its own key, then default. A selected target with neither fails validation with no model for target "<target>" (add "<target>" or "default").
Project skills
projectSkillsDirectory names a source-controlled directory of your own skills, such as .vsuite/skills. List each skill id in projectSkills and in the skills of the agents that use it. Each <directory>/<id>/SKILL.md needs frontmatter whose name equals the id and whose description says when to use the skill:
---
name: tenancy-rls-verification
description: Use when verifying tenant isolation and row-level security.
---Generated files
| Target | Agents | Skills | MCP and native config |
|---|---|---|---|
| opencode | .opencode/agents/<id>.md | .opencode/skills/<id>/SKILL.md | .opencode/opencode.json |
| claude-code | .claude/agents/<id>.md | .claude/skills/<id>/SKILL.md | .mcp.json |
| github-copilot | .github/agents/<id>.agent.md | .github/skills/<id>/SKILL.md | .vscode/mcp.json |
Every run also writes .vsuite/vsuite-mcp.mjs (the vsuite MCP server) and the job-metrics tooling in .vsuite/agent-metrics/ (merge-telemetry.mjs, plus the jobs.jsonl log that the vsuite MCP server appends to). When any agent sets metrics: true, each target also gets <target dir>/scripts/agent-metrics.mjs. .vsuite/mcp-env.mjs is written when a stdio server needs .vsuite/.env.
Existing native config is extended, not replaced: unrelated .opencode/opencode.json settings, MCP servers, and custom agents are preserved. JSONC comments in .opencode/opencode.json are not preserved, and a malformed file stops generation before anything is written.
generate removes catalog skills that are no longer selected and pack agents, skills, and instructions that are no longer generated. It does not remove catalog agents you deselect or files of targets you deselect; delete those deliberately.
sequenceDiagram
actor U as User
participant R as "cac router (runCommand)"
participant I as "init()"
participant D as "@vsuite/detection"
participant W as "wizard (@clack/prompts)"
participant P as "@vsuite/workflows createProject"
participant G as "@vsuite/core generate"
participant M as "agentmemory check"
U->>R: vsuite init [dir] [--no-generate]
R->>I: init(argv)
I->>I: fail if vsuite.json exists; create dir if missing
I->>D: detectTechnologies(cwd)
I->>W: targets, agents, skills, capabilities
I->>W: preferences required by selected agents
I->>W: model profile name, model, effort, reasoning
I->>P: createProject(answers) writes vsuite.json and .vsuite/.env
P-->>I: config, warnings
I->>G: generate(cwd) unless --no-generate
opt agent-memory capability selected
I->>M: verifyAgentMemorySetup(targets): npx, npm registry, local engine
M-->>W: note with results and next steps
end
I-->>R: outputs
R-->>U: written paths; Clack intro/outro on a TTYflowchart LR
R["cac router (runCommand)"] --> A["vsuite generate"]
R --> MM["vsuite migrate [--dry-run]"]
A --> L["loadConfig(cwd, { cliVersion, write: false })<br/>migrate in memory; does not rewrite vsuite.json"]
L -- changed --> W["print vsuite.json is <version>; run vsuite migrate (unless --json)"]
W --> B
L -- ok --> B["generate(cwd)"]
B -- ok --> O["print each output path (or one { outputs } JSON with --json), exit 0"]
O --> V["Clack spinner + boxed target-grouped summary + next-steps line on a TTY<br/>(suppressed by --quiet/--json and non-TTY)"]
L -- error --> D["print error message, exit 1"]
B -- error --> D
MM --> ML["loadConfig(cwd, { cliVersion, write: !dryRun })"]
ML -- dry run --> MD["print pending migrations + diff, exit 0"]
ML -- otherwise --> MP["print migration or up-to-date line"]
MP --> B
ML -- error --> DJob metrics
Every agent logs its own completed job through the vsuite MCP server: current_time supplies timestamps and log_job validates each record against the built-in v2 metrics schema (exact fields, metrics_version 2, the tier/outcome/verdict enums, and real ISO timestamps), keeps ts non-decreasing, and appends one line to .vsuite/agent-metrics/jobs.jsonl. Records from the pre-0.7 .agent-metrics/ directory are merged into the new location on the next generate, and the directory also holds merge-telemetry.mjs, which backfills tool_calls and the start/finish timestamps from normalized external telemetry matched by session_id. The desktop app's Metrics tab reads this log.
Packs
Packs add or override agents, skills, and instructions with Liquid templates. A typical session:
$ vsuite pack add path:./packs/acme
Added pack acme: Acme Engineering Standards 1.2.0
agents added: secure-reviewer
agents overriding the catalog: code-reviewer
skills added: acme-threat-model
skills overriding the catalog: -
instructions added: development-standards
Select entries with `vsuite agent use <id> --from acme`, then run `vsuite generate`.
$ vsuite agent use secure-reviewer --from acme
agent secure-reviewer now uses pack:acme
added agent secure-reviewer as a specialist
Run `vsuite generate` to update generated files.Pack errors print their code (PACK_*, TPL_*, MD_LINT), the file and line, and a hint. See the pack author guide (including the error table) and the enterprise pack guide.
Config versions and migration
version in vsuite.json is the vsuite release the config conforms to (the root package.json version of this repository). vsuite init writes the running CLI version; the legacy integer "version": 1 is treated as 0.0.0.
vsuite generatemigrates in memory before generating and never rewritesvsuite.json. When the config is outdated it prints one line and still generates:vsuite.json is 0.0.0; run `vsuite migrate` to upgrade the filevsuite migraterewritesvsuite.jsonatomically, prints one line per applied migration then the version change, and regenerates. If nothing changed it printsvsuite.json is up to date (<version>)and still regenerates:migrated vsuite.json 0.2.0: Record the vsuite version in vsuite.json vsuite.json version 0.0.0 → 0.2.0vsuite migrate --dry-runwrites nothing and does not generate. It printsvsuite.json <from> → <to> (dry run, nothing written), one<version>: <description>line per pending migration, and a unified diff ofvsuite.json; or the up-to-date line.Upgrading the CLI restamps
versionto the new CLI version on the nextmigrate, even when no format change applies.A config newer than the CLI fails with
vsuite.json was written by vsuite <version>; upgrade @krizic/vsuite to <version> or later.
The registered format changes are listed in @vsuite/migrations:
| Version | Description | Effect |
|---|---|---|
| 0.2.0 | Record the vsuite version in vsuite.json | Stamps version; no other format change. |
| 0.2.1 | Move plain-string agent models to { "default": … } | Each modelProfiles agent string model becomes { "default": <string> }; other keys and key order are kept. |
| 0.3.0 | Replace the 0.2.x selection with an explicit agent graph | Writes agents, mcpServers, stack, projectSkills, and metrics; removes skills, capabilities, skillWiring, toolWiring, and preferences.frontend. (capabilities returns in 0.5.0 for declarable, non-MCP capabilities only.) |
| 0.4.0 | Add packs and record each agent/skill source | Adds an empty packs object, source: "catalog" on catalog agents, and skillSources entries. |
| 0.5.0 | Rename gitea-reconciliation-run to reconciliation-run | Rewrites the skill id in every agent's skills and in skillSources. |
Dependencies
- Workspace (bundled by tsup):
@vsuite/catalog,@vsuite/config,@vsuite/core,@vsuite/detection, and@vsuite/workflows, plus the packages those depend on (@vsuite/json,@vsuite/migrations,@vsuite/packs,@vsuite/targets, and@vsuite/templates). - Third-party (runtime, external):
@clack/prompts(prompts and guided terminal output),cac(command routing),diff(dry-run output),jsonc-parser,liquidjs(restricted Liquid templates),yaml, andzod. - Used by: end users.
Development
From the repository root:
pnpm vsuite <command> # run the CLI from source (tsx)
pnpm run build # bundle packages/cli/dist/main.js
pnpm run schema # regenerate schema/vsuite.schema.json
pnpm vitest run --project @krizic/vsuite # this package's testsTo try a local build in another project, pack it and install the tarball; it is self-contained:
pnpm --filter @krizic/vsuite pack --pack-destination /tmp # prepack runs build and schema
pnpm add -g /tmp/krizic-vsuite-<version>.tgzA globally installed vsuite is a separate copy. If it lacks a command listed above, it is out of date.
The version comes from the root package.json; pnpm run version:sync copies it into this package (a test enforces they match). See architecture for bundling and the release flow.
