Skip to content

About

A simple starting skeleton of linters and formatters for common web projects.

Topics

Resources

Stars

9 stars

Watchers

2 watching

Forks

Latest commit

 

History

1,150 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

create-project-calavera

skills.sh

Project Calavera is an open-source CLI tool that scaffolds linters, formatters, AI tooling such as agent skills, hooks, and subagents, and other common project infrastructure for web projects. It works standalone for vanilla JavaScript, TypeScript, and library projects, and it works as a complement to framework scaffolding tools like Vite+ and vp create, giving any project a consistent, repeatable setup through a single recipe file.

See docs/vite-plus.md for the litmus test and a full statement of what Calavera adds to a vp create project and what it leaves to Vite+.

MCP-First Agent Flow

Use Calavera after a project already exists, whether it came from vp create, Vite, another scaffold tool, or a manually maintained repository. To start a new Vite+ project and bootstrap it in one command, run npm create project-calavera -- --new from the parent folder instead of steps 1 and 2. Vite+ asks its own questions and writes the scaffold; see --new for details.

After --new or --init, Calavera prints the next steps. The project needs a recipe before Calavera changes anything, so the block offers the agent prompt or the hosted Composer, with the save location and the commands for the project's package manager. After --new, from the parent folder, it reads:

Your project needs a recipe before Calavera changes anything.
  Either: open /home/me/code/my-app in your agent and use the prompt above.
  Or: compose one at https://calavera.schalkneethling.com/ and save
      calavera.config.json into /home/me/code/my-app, then:
        cd /home/me/code/my-app
        npm create project-calavera apply -- --dry-run
        npm create project-calavera apply

--init prints the same block without the cd line; --init --json returns it as a nextSteps array.

If you composed a recipe first, pass it with --config before --new: npm create project-calavera -- --config ~/Downloads/calavera.config.json --new. Calavera validates the recipe before vp create runs, copies it into the scaffolded project as calavera.config.json, and prints the preview and apply commands for it. It does not apply the recipe.

  1. Open the project directory.
  2. Run npm create project-calavera -- --init.
  3. Choose exactly one project-local MCP host when prompted: Claude Code, Codex, Cursor, OpenCode, or skip/manual.
  4. Restart or reload the agent session if your MCP host does not discover new tools dynamically.
  5. Confirm the Calavera MCP tools are exposed: inspect_project, list_profiles, list_integrations, list_ai_artifacts, compose_recipe, validate_recipe, explain_recipe, dry_run_apply, and apply_recipe.
  6. Start the agent from the project root.
  7. Agent prompt: Use Calavera for this project. First verify that the Calavera MCP tools are available. If they are not available, stop and help me configure the MCP server before composing or applying anything. Once the tools are available, inspect the current project for existing tooling and possible config conflicts, list the available profiles, integrations, and AI artifacts, compose a recipe, validate and explain it, show me the dry-run result, and apply it only after I approve.

Find the equivalent commands for your package manager in the agent-first command table.

Agent-First Command Table

Package manager Bootstrap agent guidance Preview apply Apply recipe
npm npm create project-calavera -- --init npm create project-calavera apply -- --dry-run npm create project-calavera apply
pnpm pnpm dlx create-project-calavera --init pnpm dlx create-project-calavera apply --dry-run pnpm dlx create-project-calavera apply
Yarn yarn dlx create-project-calavera --init yarn dlx create-project-calavera apply --dry-run yarn dlx create-project-calavera apply
Bun bunx create-project-calavera --init bunx create-project-calavera apply --dry-run bunx create-project-calavera apply

npm create needs the -- separator before Calavera flags such as --init and --dry-run. Do not use npm create project-calavera --init; npm treats --init as its own option and Calavera falls back to the recipe CLI. Yarn requires Yarn 2+ for dlx; Yarn 1.x users can use npx --package create-project-calavera create-project-calavera --init. Direct binary launchers such as npx --package do not need an extra -- before Calavera flags: use npx --package create-project-calavera create-project-calavera --help, not npx --package create-project-calavera create-project-calavera -- --help. MCP server registrations launch create-project-calavera-mcp directly and should not add --help.

Agents should treat dry_run_apply as the approval boundary. They should show the package manager, integrations, dependency packages and their install command, inspection findings, omitted script explanations, ownership notes, file changes, and AI artifact changes before calling apply_recipe. If MCP tools are not exposed, agents should configure or repair MCP setup first; they should not inspect npm cache internals or import Calavera source files from package cache paths as a substitute for MCP setup.

If the agent finds likely conflicts, it should pause and list whether each one is a hard stop or a migration decision the user can still approve. A dry run is the best next step when adoption is still possible and the user wants to see the impact.

Compose the recipe yourself with the interactive CLI:

npm create project-calavera init
npm create project-calavera apply -- --dry-run
npm create project-calavera apply

init composes calavera.config.json; -- --init bootstraps agent guidance.

Use the web UI when you prefer browser composition. Save or download calavera.config.json, then run the displayed package-manager command from the project folder that contains the saved file.

See docs/agent-first-calavera-workflow.md for agent, CLI, web UI, MCP/WebMCP, Vite+, other scaffold, and existing-project examples.

Bun-managed projects and npm devEngines

Some starters declare Bun in devEngines.packageManager. npm 11 fails before Calavera can run when npm create is used from one of those projects:

Invalid devEngines.packageManager
Invalid name "bun" does not match "npm" for "packageManager"

Use the package manager declared by the project instead:

bunx create-project-calavera apply

The same rule applies to manual MCP server registration. Use bunx --package create-project-calavera@<version> create-project-calavera-mcp instead of npx --package create-project-calavera@<version> create-project-calavera-mcp when the agent harness launches Calavera from a Bun-managed project root. The explicit version avoids Bun dropping the non-default create-project-calavera-mcp bin during ad-hoc --package resolution and keeps every persistent MCP registration from floating to a later package release.

If bunx reports error: bun is unable to write files to tempdir: PermissionDenied in a restricted agent or MCP sandbox, configure the MCP host to set TMPDIR to an absolute writable directory. If Bun's package cache is also blocked, set BUN_INSTALL_CACHE_DIR to an absolute writable cache directory for that server registration.

If you intentionally want to launch through npm anyway, npm requires --force to bypass its own devEngines preflight:

npm --force create project-calavera apply

What Calavera Manages

  • Linting and formatting tools
  • Stylelint and CSS quality plugins
  • AI skills, hooks, and agents under .agents/
  • package.json scripts
  • A repeatable calavera.config.json recipe

Editor extensions, global apps, shell setup, and machine-level configuration are out of scope. Install the matching editor integrations for your development environment of choice. Calavera does not scaffold a TypeScript configuration or a type-check script; JavaScript and TypeScript type checking comes from vp check in a vp-managed project.

Profiles

  • Default (default): EditorConfig and Stylelint. In a vp-managed project, JavaScript and TypeScript linting comes from vp lint, formatting from vp fmt, and type checking from vp check; Calavera does not scaffold a linter, formatter, or TypeScript configuration for that language pair.
  • Minimal (minimal): EditorConfig only

The Modern and Classic profiles were removed once their defaults became identical (ADR-0011). A calavera.config.json that names modern or classic fails validation with a message naming default as the replacement.

explain_recipe, compose_recipe, and dry_run_apply report whether the project is managed by Vite+. For a vp-managed project they state that JavaScript and TypeScript linting, formatting, type-checking, and testing are provided by Vite+, not by Calavera.

Integration Catalog

Calavera includes curated integration packs grouped by outcome:

  • React Doctor
  • Unused files, dependencies, and exports
  • HTML validation
  • CSS Baseline
  • CSS property ordering
  • CSS property type validation
  • Environment variable schema and validation with Varlock
  • GitHub repository governance, security settings, and drift checks

React Doctor is a deterministic scanner for React codebases that complements vp lint with security, performance, correctness, accessibility, bundle-size, and architecture diagnostics. The curated JavaScript and TypeScript rule packs that once accompanied it are gone; a Vite+ project enables Oxlint plugins in the lint block of vite.config.ts.

The optional Knip integration adds unused-file, dependency, and export analysis to the generated quality script. Calavera writes a minimal knip.json that keeps Knip's default project discovery and ignores .agents/**, because Calavera-installed agent files are not imported by project code. When those defaults do not fit a project, add targeted entry, project, or workspaces configuration as described in the Knip configuration guide. Calavera treats those changes as local edits and will refuse to overwrite or remove them automatically on a later apply or clean.

The optional HTML Validate integration adds html-validate, writes .htmlvalidate.json with the html-validate:recommended and html-validate:document presets, and ignores node_modules/, dist/, and coverage/ through .htmlvalidateignore. It also adds lint:html to the generated quality script. The recommended preset already includes HTML Validate's accessibility rules, so Calavera does not add a redundant separate accessibility integration.

lint:html runs node scripts/lint-html.mjs "**/*.html", a Calavera-managed wrapper around html-validate. html-validate exits with an error when no file matches and has no option to allow empty input, so the wrapper passes when no HTML file matches, and otherwise runs html-validate with the same patterns and exit code. With an option, such as --stdin or --ext, it runs html-validate directly. A real validation error still fails lint:html. In the same way, lint:styles and lint:styles:fix pass --allow-empty-input to Stylelint, so quality passes in a project without CSS files.

A project without static HTML files, such as one whose HTML a server or a Worker renders, can leave lint:html out of quality with the quality option. Calavera still generates lint:html, and a later apply keeps the choice, because it lives in the recipe:

{
  "integrations": ["html-validate"],
  "integrationOptions": {
    "html-validate": { "quality": false }
  }
}

When lint:html is the only script quality would run, Calavera does not generate quality. Apply removes a quality script whose value an earlier release wrote, such as npm run lint:html, and keeps any other value as your own. The dry run shows both.

Validate the rendered HTML in your tests instead, with the HtmlValidate class from the HTML Validate API, and assert that the report is valid. validateString does not read .htmlvalidate.json, so pass the configuration to the constructor:

import { readFile } from "node:fs/promises";
import { HtmlValidate } from "html-validate";

const config = JSON.parse(await readFile(".htmlvalidate.json", "utf8"));
const report = await new HtmlValidate(config).validateString(renderedHtml);

HTML Validate follows HTML semantics and Calavera deliberately leaves its doctype and void-element style rules at their honest defaults. Oxfmt, the formatter vp fmt is built on, cannot currently be configured to preserve an uppercase <!DOCTYPE html> or omit the slash it adds to void elements such as <meta />. Calavera does not blanket-exclude HTML from vp fmt or weaken HTML Validate to hide this conflict. Projects selecting both tools should review the formatter/validator interaction until Oxc issue #24645 is resolved. See the HTML Validate preset documentation for the rules included by each preset.

The CSS catalog includes stylelint-plugin-logical-css for logical CSS property, value, and unit checks, plus @schalkneethling/stylelint-plugin-css-property-type-validator as a curated experimental integration.

Adding a new integration should be a catalog-first change. For example, a Stylelint plugin entry can declare its package dependency, parent stylelint integration, plugin name, and default rules in packages/cli/src/catalog.js; the CLI then uses that metadata when generating .stylelintrc.json.

See docs/contributing-calavera-integration-varlock.md for a contributor walkthrough based on Theo Ephraim's Varlock integration.

GitHub repository controls

The optional github-repository-controls integration generates a committed desired-state policy, Dependabot configuration, a portable Node.js administration script, and setup documentation. A recipe must identify the expected repository so the generated script can refuse to operate against the wrong remote. The integration applies at the repository root, because GitHub reads .github/ only there: in a monorepo, a dry run or apply from a workspace member that selects it stops with a hard stop that names the repository root, before any file is planned or written.

{
  "integrations": ["github-repository-controls"],
  "integrationOptions": {
    "github-repository-controls": {
      "repository": "octocat/example",
      "requireCodeqlResults": true,
      "requiredChecks": [],
      "mergeMethods": ["squash"],
      "codeqlLanguages": ["actions", "javascript-typescript"]
    }
  }
}

requireCodeqlResults (default true) requires CodeQL results through the ruleset's code scanning rule, not through a status check name, so you do not enter CodeQL in requiredChecks. Set it to false so that Calavera does not manage the code scanning rule; a rule that already exists stays until you delete it in the repository settings under Rules. requiredChecks (default []) lists additional status check names. A required check is the exact name that a check reports on a pull request, usually the workflow job name, and a name that no check reports blocks every merge. Leave the list empty for a new project and add names after your first CI run, then re-apply the recipe. A check added by hand to the managed ruleset is reported as drift and removed on the next apply; require it in a separate ruleset that Calavera does not manage instead. See GitHub's available rules for rulesets.

calavera apply only writes local files and package scripts. Run npm run repo:controls:check for a read-only GitHub drift report, then run npm run repo:controls:apply separately after reviewing the plan. The apply command requires confirmation unless you pass --yes explicitly, for example npm run repo:controls:apply -- --yes. GitHub features that are unavailable for the repository or plan are reported as unsupported rather than ordinary drift.

Newly generated policies use the extended CodeQL query suite (override with codeqlQuerySuite: "default" in the recipe). Policy languages are required coverage; remote apply preserves additional configured CodeQL languages. The managed default-branch ruleset requires CodeQL results and blocks errors/warnings and medium-or-higher security alerts. The committed policy's mainRuleset.codeScanning object exposes alertsThreshold and securityAlertsThreshold using GitHub's threshold values. Set it to null to leave scanning rules unmanaged; older policies without the field retain that behavior. Regenerating the policy with calavera apply restores the generated thresholds.

The drift check also verifies branch targeting, active enforcement, no exclusions, and an explicitly empty bypass list. Remote apply repairs those shared protections while preserving unrelated rule types and other scanners. Code-scanning merge protection requires GitHub support and scan results for both the commit and target reference; enabling default setup alone does not guarantee a PR can merge.

The drift check reports a policy CodeQL language that GitHub does not detect as blocked, with the reason. While default setup is not configured, it uses the languages GitHub reports for default setup. When a configured setup gains a language, it reads the repository languages API or, for actions, which that API does not report, the .github/workflows directory on the default branch. Remote apply runs the main ruleset first and CodeQL default setup last. A failed or blocked change does not stop the others; only a change that requires a failed change is skipped. An apply that does not fully succeed ends with a summary of the changes applied, failed (with the error), and not attempted, with what to do about each, and exits with a non-zero code. Until CodeQL default setup reports results, the generated ruleset blocks merges.

CLI

The CLI and the MCP server support Node.js ^24.11.0 || >=26.0.0. Vite+ 1.0.0 also supports Node.js 22.18 and later, but Calavera does not. On any other Node.js version, both print the required range and exit with a non-zero code.

Create a recipe:

npm create project-calavera init

The interactive recipe composer lets you choose a profile, package manager, integration packs, and bundled AI artifacts. By default it only writes calavera.config.json.

Run init without selection flags for guided prompts that present the available options. Use selection flags only for scripted or CI flows:

npm create project-calavera init -- --profile default --package-manager pnpm --tool stylelint-order

Wrap labels that contain spaces in quotes, for example --tool "CSS property ordering". Prefer ids such as stylelint-order in scripts and CI so commands stay copy-pastable.

Apply a recipe:

npm create project-calavera apply

Inspect the current project:

npm create project-calavera doctor

Update managed tooling from the recipe:

npm create project-calavera update

Remove stale managed files:

npm create project-calavera clean

Inspect machine-readable output for agent workflows:

npm create project-calavera doctor --json
npm create project-calavera apply -- --dry-run --json

Bootstrap an existing project for agent-first Calavera usage without scaffolding app code:

npm create project-calavera -- --init

npm create needs the -- separator before Calavera flags. Do not use npm create project-calavera --init; npm treats --init as its own option and Calavera falls back to the recipe CLI. With other package managers, use pnpm dlx create-project-calavera --init, yarn dlx create-project-calavera --init, or bunx create-project-calavera --init. The Yarn command requires Yarn 2+ because Yarn 1.x does not support dlx; Yarn 1.x users can use npx --package create-project-calavera create-project-calavera --init or install create-project-calavera globally.

The --init bootstrap installs the base Calavera skill, adds concise project guidance, optionally writes one project-local MCP config, and prints a recommended first prompt for the user to give their agent. It writes MCP setup notes only when the user chooses skip/manual or project-local MCP config cannot be written. When AGENTS.md already exists, interactive runs ask whether to append marked Calavera guidance directly to that file or leave it unchanged and write fallback guidance to AGENTS.calavera.md. Scripted runs keep the fallback-only behavior unless --agents-md=append is passed.

MCP Server

Calavera also ships a standard MCP server for agent-native recipe composition:

npx --package create-project-calavera@<version> create-project-calavera-mcp

During --init, Calavera can write one project-local MCP config for Claude Code, Codex, Cursor, or OpenCode. It never writes global/user MCP config. It writes .agents/calavera/mcp.md only when you choose skip or the selected local config cannot be written.

Project-local config targets:

  • Claude Code: .mcp.json
  • Codex: .codex/config.toml
  • Cursor: .cursor/mcp.json
  • OpenCode: opencode.json

Use the package manager declared by the target project's package.json. When configuring MCP manually, choose the matching command and put the first word in the MCP command field and the remaining words in args:

  • npm: npx --package create-project-calavera@<version> create-project-calavera-mcp
  • pnpm: pnpm dlx --package create-project-calavera@<version> create-project-calavera-mcp
  • Yarn: yarn dlx --package create-project-calavera@<version> create-project-calavera-mcp
  • Bun: bunx --package create-project-calavera@<version> create-project-calavera-mcp

JSON-based MCP hosts use this shape:

{
  "mcpServers": {
    "calavera": {
      "command": "npx",
      "args": ["--package", "create-project-calavera@<version>", "create-project-calavera-mcp"]
    }
  }
}

Codex uses TOML:

[mcp_servers.calavera]
command = "npx"
args = ["--package", "create-project-calavera@<version>", "create-project-calavera-mcp"]

OpenCode stores local MCP servers under mcp:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "calavera": {
      "type": "local",
      "command": [
        "npx",
        "--package",
        "create-project-calavera@<version>",
        "create-project-calavera-mcp"
      ],
      "enabled": true
    }
  }
}

Project-local MCP servers run from the project root. Matching the project package manager prevents package-manager preflight failures before Calavera can start, such as npm 11 rejecting a Bun-managed project through devEngines.packageManager.

When a restricted MCP host launches the Bun command, Bun may fail before Calavera starts with error: bun is unable to write files to tempdir: PermissionDenied. Configure that MCP server environment with TMPDIR set to an absolute writable directory, such as an absolute path to a project-local .calavera/tmp directory. If the package cache is also restricted, set BUN_INSTALL_CACHE_DIR to an absolute writable directory such as an absolute path to .calavera/bun-install-cache. Keep these as Bun-only recovery settings rather than default MCP config.

Agent guidance should tell the harness to use Calavera when a user wants to inspect available project tooling, compose calavera.config.json, preview a Calavera apply run, or apply an approved recipe. An MCP client can use the tools in this order:

  1. inspect_project
  2. list_profiles
  3. list_integrations
  4. describe_integration
  5. list_ai_artifacts
  6. compose_recipe
  7. validate_recipe
  8. explain_recipe
  9. dry_run_apply
  10. apply_recipe

dry_run_apply returns structured JSON with the package manager, integrations, dependency packages, the command that installs them, the Vite+ detection report, project inspection findings, omitted script explanations, file ownership/action notes, and AI artifact changes that would be made. On a project where the recipe was already applied and nothing has changed since, every change has type: "unchanged". Agents should present that dry-run summary to the user first. apply_recipe is intentionally the approval boundary: call it only after the user explicitly approves the proposed recipe and dry-run result.

Common Flags

  • --config calavera.config.json
  • --profile default|minimal
  • --package-manager npm|pnpm|yarn|bun; in a Vite+-managed project it does not change the dev dependency install command, vp add -D
  • --integration <id-or-label> or --tool <id-or-label> for scripted composition; quote labels with spaces, or use ids/slugs in scripts and CI
  • --ai-artifact <id-or-label-or-source>; use <artifact>@<target> for hook and agent targets, or omit this flag to select from the interactive option list
  • --agents-md append|fallback with --init to script how existing AGENTS.md files are handled
  • --mcp-harness claude-code|codex|cursor|opencode|skip with --init to script project-local MCP auto-config
  • --apply with init to preview and then confirm applying the composed recipe
  • --dry-run
  • --no-install
  • --yes
  • --json

Vite+ And Delta Workflows

Calavera keeps generated package scripts as ordinary tool commands. It can add tooling, configuration, dependencies, and package scripts, but delta execution belongs to tool-native options, project-specific scripts, Vite+/vp, or CI workflow logic rather than a Calavera changed-file wrapper.

In a project Vite+ manages, apply installs the recipe's development dependencies with vp add -D <packages>, using the project's own vite-plus, so Vite+ runs the package manager version the project pins. There, --package-manager and the MCP packageManager input do not change the install command. Other projects keep their package manager's command, such as pnpm add --save-dev. apply --dry-run names the command and how apply runs it. See docs/vite-plus.md and ADR-0012.

In a project Vite+ manages, the generated quality script runs vp check and vp test --passWithNoTests before Calavera's own scripts, for example vp check && vp test --passWithNoTests && pnpm lint:styles && pnpm knip. At a workspace root, the test step is vp run -r test, which runs each member's test script, and leaves the step out when no package defines test. Other projects keep a quality script without vp. Calavera writes no script that repeats a vp command on its own, and does not add Playwright or other test suites to quality. The Stylelint scripts are lint:styles and lint:styles:fix. In a project that has .calavera/state.json from an earlier apply, a later apply renames a lint or lint:fix script whose value is exactly one Calavera wrote with Stylelint; it keeps any other value as your own, and never overwrites a lint:styles of your own. Without that state file, lint and lint:fix are not renamed. See ADR-0013.

See docs/vite-plus-and-delta-mode.md for the Vite+ design boundary and delta workflow guidance.

Template And Agent Composition

A future @schalkneethling/create package may collapse Vite+ scaffolding, Calavera recipe composition, Calavera apply, and project startup into a single creation path. It should remain separate from Calavera's tooling-composition responsibilities.

Calavera exposes agent-native recipe composition through the standard MCP server and browser-safe recipe composition through WebMCP, so coding agents can compose recipes directly instead of driving the human web UI.

See docs/create-template-and-agent-composition.md for the current boundary, research questions, and phase-two handoff plan.

Recipe Schema

Generated recipes reference the public draft 2020-12 schema at https://calavera.schalkneethling.com/calavera.config.schema.json. The maintained schema lives at apps/composer/public/calavera.config.schema.json so it is published with the web composer.

AI Artifacts

Calavera can install bundled AI skills, hooks, and agents from the optional ai section in calavera.config.json. The ai key is a composed list of AI artifacts, whether it was written by hand or generated by the CLI, Web UI, or an agent workflow.

Define the exact artifact items to include:

{
  "ai": [
    { "type": "skill", "src": "skills/frontend-engineering" },
    {
      "type": "hook",
      "src": "hooks/block-dangerous-commands",
      "target": "claude-code"
    }
  ]
}

Skills install into .agents/skills/. Hook and agent items can set target to choose their .agents/hooks/<target>/ or .agents/agents/<target>/ directory. The current bundled hooks and agents come from claude-toolkit and default to claude-code.

When a recipe installs a skill, Calavera also creates or updates .coderabbit.yaml so CodeRabbit excludes .claude/skills/**, .agents/skills/**, and pnpm-lock.yaml. This avoids spending downstream review tokens on vendored skill documentation whose findings belong upstream. Existing CodeRabbit settings and path filters are preserved. The file remains project-owned rather than Calavera-managed, so clean does not remove these review preferences.

Set an agent item's target to codex when you want Calavera to generate a Codex custom-agent TOML file under .codex/agents/ instead of preserving the source Markdown under .agents/agents/<target>/.

Calavera owns the managed AI files it writes, including canonical .agents/ artifacts and Codex-adapted .codex/agents/ files. Other vendor tools may need their own settings, symlinks, or import step before they consume those files. See docs/ai-adapter-guidance.md for Claude Code, Codex, and other agent-tool guidance.

skills.sh Discovery

Calavera's bundled skills are grouped for discovery on skills.sh. Use the directory page, badge, or skills CLI listing flow to inspect available skills before choosing what belongs in a project.

For Calavera-managed projects, prefer selecting bundled skills through calavera.config.json, the interactive AI artifact prompt, or scripted --ai-artifact flags. That keeps installed skills tracked in .calavera/state.json, covered by dry runs, and protected by Calavera's overwrite checks.

Direct installs with npx skills add schalkneethling/create-project-calavera can be useful for one-off discovery or non-Calavera workflows, but those files are managed by the skills CLI rather than Calavera. Do not mix direct installs and Calavera-managed installs for the same destination unless you intentionally want Calavera to treat the existing files as local, unmanaged content.

The skills of the Claude Code plugins below are not listed there, because they work only inside their plugin.

Claude Code Plugins

This repository is also a Claude Code plugin marketplace named calavera. The plugins are in plugins/. Add the marketplace once, then install a plugin from it:

claude plugin marketplace add schalkneethling/create-project-calavera
claude plugin install dependency-review@calavera
Plugin What it does
dependency-review Reviews Dependabot updates for what matters to the current project, with a dependency usage map and a WORKAROUND marker convention for workarounds.

Calavera does not version the plugins. Claude Code uses the latest commit of this repository as the version of every plugin, so any commit to the repository counts as an update, even one that does not change the plugin. Claude Code turns auto-update off by default for this marketplace. To take an update, run claude plugin marketplace update calavera, then claude plugin update <plugin>@calavera, and restart Claude Code. You can also turn on auto-update for the calavera marketplace under /plugin, Marketplaces. Adding the marketplace clones this whole repository into Claude Code's plugin folder.

Calavera writes nothing into your project for plugins. calavera apply does not install or enable them.

Web Composer

The recipe composer runs as a small Vite app:

The hosted Composer reads the version currently published under the npm latest tag and only offers integrations supported by that CLI release. New integrations can therefore land and deploy without producing recipes that the published CLI cannot apply. If the npm registry is unavailable, the Composer falls back to the last known-safe v2.2 integration catalog.

npm run web:dev

Note: You can also access the UI via https://calavera.schalkneethling.com

Open the printed local URL, choose your packs, then either:

  • save calavera.config.json directly with the browser file picker, or
  • download calavera.config.json.

Both options are shown by default so users can choose the flow they are most comfortable with. After saving the file, run the displayed next commands from the project folder that contains calavera.config.json. The optional bootstrap command prepares agent guidance; the dry-run command previews local changes; the apply command writes approved changes.

When the browser exposes WebMCP, the composer registers a browser parity surface for the MCP recipe composition workflow:

  1. list_profiles
  2. list_integrations
  3. describe_integration
  4. list_ai_artifacts
  5. list_baseline_targets
  6. describe_baseline_target
  7. search_baseline_features
  8. recommend_baseline_target
  9. compose_recipe
  10. validate_recipe
  11. explain_recipe
  12. download_recipe

WebMCP uses the same shared recipe composition model as the standard MCP server, but it cannot inspect, dry-run, or apply files in a local project workspace from the browser. Use download_recipe to save calavera.config.json, then apply it with the CLI or standard MCP server from the project root.

Build the composer with:

npm run web:build

Baseline targets

The independently deployable Baseline Target Explorer explains Widely, Newly, and fixed-year targets, shows the matching Chrome, Edge, Firefox, and Safari versions, and recommends the earliest fixed target for selected CSS features.

Recipes keep integrations as string IDs and carry optional integration-specific settings separately:

{
  "integrations": ["stylelint-baseline"],
  "integrationOptions": {
    "stylelint-baseline": {
      "available": 2025,
      "severity": "warning"
    }
  }
}

available accepts "widely", "newly", or a supported fixed year. severity accepts "warning" or "error". Options are rejected unless their integration is selected, and existing recipes without integrationOptions retain their previous Stylelint behavior.

Build the Explorer independently with:

pnpm --filter @calavera/baseline-explorer build

Versioned artifacts

New recipes select package-backed skills, hooks, and agents by stable ID:

{
  "ai": [
    { "id": "skill-project-goal" },
    { "id": "agent-technical-devils-advocate", "target": "codex" }
  ]
}

Legacy { "type", "src", "target" } entries remain readable during the compatibility window. Migrate and manage exact versions with:

create-project-calavera artifacts migrate
create-project-calavera artifacts install
create-project-calavera artifacts status
create-project-calavera artifacts status --check-updates
create-project-calavera artifacts doctor
create-project-calavera artifacts update skill-project-goal
create-project-calavera artifacts update --all --tag next

Installation resolves npm packages into .calavera/packages and a verified npm cache without changing consumer package.json or node_modules. The independently versioned artifact packages are not runtime dependencies of the CLI or artifact core, so they do not enter a consumer dependency graph or lockfile through Calavera itself. .calavera/artifacts.lock.json records exact versions, integrity, destinations, and payload hashes; apply and apply_recipe reuse those exact locked versions. When the recipe selects an artifact that has no lock entry, apply installs it first, as artifacts install would: apply --dry-run and dry_run_apply report each artifact they would resolve and lock, with its version, and change nothing; apply and apply_recipe lock and install only those artifacts, then apply the rest of the recipe. Before that install commits, apply checks every selected artifact against the project. If an artifact output would overwrite a local edit or a file Calavera does not manage, or the install fails for any other reason, apply stops with an error that names artifacts install. When the install stops before its transaction commits, or a partly committed transaction rolls back, the artifact lock, artifact outputs, and Calavera state stay as they were. If the rollback itself fails, the error reports both failures, the project may be partly changed, and the next apply, apply_recipe, or artifacts command retries the rollback; a dry run refuses to run until it has. Registry cache entries can remain in an existing .calavera/cache/npm. Only artifacts update advances a version. Status is offline unless --check-updates is explicit. Run artifacts doctor to verify installed outputs, managed state, and local edits without checking the registry. The existing managed-state hashes continue to block overwriting local edits.

macOS update companion

The optional Calavera menu-bar app monitors only project directories that you explicitly register. It reads recipes, artifact locks, and state without changing them; checks npm and GitHub on launch, every six hours, or when you select Check now; and deduplicates notifications by component and target version.

For project updates, the app always copies the exact command and never executes it. Opening a terminal is opt-in: save your preferred terminal application's macOS name in the app to open it at the registered directory, or leave the preference blank for copy-only behavior. App updates open a stable GitHub release, and self-updating is intentionally outside v1.

Local development requires Node.js, pnpm, Rust through rustup, and Xcode:

pnpm --filter @calavera/menu-bar dev

Tags matching menu-bar-v* run the independent macOS release workflow, which builds a universal signed, notarized, and stapled DMG through the protected publish environment.

Publishing

Calavera publishes to npm from GitHub releases with npm trusted publishing. The repository workflow is .github/workflows/publish.yml, and npm should be configured with that workflow as a trusted publisher for create-project-calavera and each public workspace package, including @schalkneethling/calavera-baseline-core.

The complete independent-package, static-app, artifact-channel, recovery, and macOS rehearsal is documented in docs/release-and-update-journey.md. For the concrete, step-by-step commands to run once a Changesets version PR is open and ready to release, see docs/release-runbook.md.

Before the first trusted publish:

  • enable 2FA on npm and GitHub;
  • remove any NPM_TOKEN repository secret;
  • create a GitHub environment named publish and restrict it to main;
  • configure npm trusted publishing for this repository, workflow, and environment.

To validate the package locally, first install uv. It provisions the locked Python environment used by SkillSpector and the workflow audit. pnpm workflow:check runs uvx zizmor@1.25.2 --offline, so prime that exact version in uv's cache once while online before using the offline check. The pnpm check quality gate includes the repository's own Knip analysis.

uv sync --frozen
uvx zizmor@1.25.2 --version
pnpm browsers:install
pnpm check
pnpm web:build
pnpm publish:check
pnpm pack --dry-run
pnpm workflow:check

For the 2.0.0 release, create tag v2.0.0 from main, draft a GitHub release for that tag, and use CHANGELOG.md as the starting release notes. Publishing the GitHub release triggers the trusted-publishing workflow.

The publish workflow checks the project, builds the web composer, packs the package, audits the workflow with zizmor, then publishes the packed tarball with npm provenance.

About

A simple starting skeleton of linters and formatters for common web projects.

Topics

Resources

Stars

9 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages