Skip to main content
Use this page when changing release packaging, agent bundle files, install-time setup, or public repository exposure.

Decision rule

supaschema uses the files allowlist in package.json as the npm package boundary. There is intentionally no root .npmignore.
npm treats files as an allowlist. A root .npmignore is a denylist. This repository has many maintainer-only support files, so allowing known package contents is safer than trying to exclude everything that should not publish.

Four surfaces

SurfaceSource of truthPurpose
npm tarballpackage.json filesFiles downloaded into node_modules/supaschema
Consumer setupsupaschema initFiles written or merged into the installing project
Public npx skills sourceskills/supaschemaPortable Agent Skill context installed by the Skills CLI
Public repositoryGit-tracked public-safe filesSource, docs, examples, tests, CI, and release evidence that can be public
Private maintainer workspacePrivate repository or intentionally untracked local filesPrivate automation, credentials, plans, scratch output, and non-public operator context
The npm tarball and consumer setup are not the same thing. The tarball is what npm downloads. The installer is the script that uses selected tarball files and generated templates to prepare the consuming project.

npm package

The package allowlist includes only runtime and install assets: the built CLI and library, config schema, README/license files, and the explicit supaschema consumer agent bundle. Do not add broad repo directories to the allowlist just because a single file is needed. Add the narrowest file or directory that matches the consumer contract. Public docs, examples, benchmarks, corpus fixtures, source files, tests, services, and maintainer scripts stay out of the npm tarball. They belong in the public repository or hosted docs when they are product evidence, and in a private maintainer workspace when they are not. Generated build caches must not live inside an allowlisted directory: a broad entry like dist ships everything beneath it, so write a tsBuildInfoFile to .tmp/ rather than dist/. tests/package-contents.test.ts fails if any .tsbuildinfo, source file, public-support directory, or maintainer tooling reaches the tarball.

Agent bundle boundary

The exact Claude, Codex, and shared agent surfaces live in Agent bundle. Keep that page as the reader-facing owner for agent bundle contents. Keep this page focused on package mechanics, tarball inclusion, consumer setup, and maintainer-only exclusions.

Public npx skills source

skills/supaschema is a generated mirror of the canonical .claude/skills/supaschema workflow. It exists so users can install portable workflow context without installing the npm package:
npx skills add https://github.com/jmclaughlin724/supaschema/tree/main/skills/supaschema
Do not advertise the repository root as the Skills source. The Skills CLI scans standard agent skill directories, including .agents/skills and .claude/skills; this repository uses those locations for maintainer mirrors while developing supaschema itself. That command does not install hooks or rules. Agent Skills are SKILL.md folders with optional scripts, references, and assets; the supaschema rule and hooks need project files and Claude/Codex hook registration. Those surfaces ship as raw files under node_modules/supaschema/agent-bundle/ and are installed only after the user approves AI-agent enforcement. Package install and default supaschema init do not invoke the Skills CLI and do not copy active .agents, .claude, or .codex surfaces.

Consumer setup

supaschema init owns setup for consuming projects after package install. The install contents list lives in What’s included; keep it there instead of duplicating it across release and packaging references. The supaschema init command performs this setup through bin/scaffold.mjs (a dist-free module that ships in the bin allowlist entry). Run it through the consuming package manager’s local runner from the package directory that owns the schema workflow. The command is idempotent, so it is also the repair path when config needs refresh. The shared scaffold creates supaschema.config.json from the generated config contract when it is absent, rewrites it only for explicit repair, and records unresolved path confirmation in .supaschema/install.json only when detected paths still need human confirmation. Resolved installs do not create .supaschema/; durable project defaults belong in supaschema.config.json. The same scaffold installs no active agent surfaces by default. The raw AI-agent bundle remains available under agent-bundle/ in the package and can be installed on demand with supaschema init --agent-bundle after review. Do not copy maintainer workspace tooling into consumer projects unless the consumer contract explicitly changes and package tests are updated at the same time.

Maintainer workspace

Repo-local editor, language-server, Python, MCP, Code Atlas, FastMCP, lint, test, guard, and release tooling is for developing supaschema itself. The private Python/FastMCP workflow, when present locally as .github/workflows/python.yml, stays untracked with the private FastMCP service. Public GitHub Actions workflows must not require ignored maintainer-only service files that are absent from a clean checkout. These files stay out of the package allowlist unless they become runtime product assets or consumer install outputs. If any of them are not public-safe, they must be moved to a private repository or intentionally untracked local path before the public repository is pushed.

Public repository boundary

The public repository may include public-safe product source, public docs, public examples, tests, CI, and release evidence. It must not include credentials, customer data, private plans, private operator context, or maintainer-only automation that is not intended for public review. .gitignore is the prevention layer for generated and local-only files, not an access-control layer. Git’s own manual says ignore rules apply to intentionally untracked files and do not affect files already tracked by Git; tracked files must first be removed from the index before ignore rules prevent reintroduction. That means the correct public-repo sequence is:
1

Classify

Decide whether each surface is public product source/docs/examples, public verification evidence, or private maintainer context.
2

Move or untrack private files

Move private surfaces to a private repository or remove them from the public index with git rm --cached after verifying the public build and release no longer depend on them.
3

Ignore reintroduction

Add .gitignore patterns only after the files are untracked, so future generated or private-local copies do not get staged again.
Do not solve GitHub exposure by adding broad ignore rules over files that release, package, docs, or CI still require. That creates a public repository that cannot reproduce the package and still does not remove already committed content from GitHub history.

Why not .npmignore?

npm supports .npmignore, but it is a blocklist. Blocklists are fragile in a repo that has many development surfaces and only a small, deliberate consumer surface. npm also falls back to .gitignore when .npmignore is missing and no files allowlist is present. Because supaschema does have a files allowlist, the root package boundary should stay in package.json. Sources:

Consumer lifecycle verification

The test owners and release smoke script prove the package surfaces, and they move together with this page and the guards (no single test should grow to cover another’s surface):
PhaseOwnerProves
Downloadtests/package-contents.test.tsThe shipped file list, package-size budget, and broad-directory denylist so docs, examples, benchmarks, corpus fixtures, source, tests, services, and maintainer scripts cannot silently bloat the download.
Setuptests/database-url.test.tsThe shared scaffolder creates the consuming project setup (config, schema/migration dirs, agent bundle, install manifest).
Usetests/consumer-lifecycle.test.tsThe full chain end to end: pack, npm install the tarball into a throwaway project, edit a schema in the scaffolded tree, then run the installed supaschema binary and confirm an accurate, replay-safe migration and accurate generated types.
Package-manager smokescripts/release/package-smoke.mjsThe packed tarball installs and initializes through the supported consumer package managers and workspace recovery paths.
The “use” proof installs the real tarball rather than extracting it, because a bare extract cannot run the CLI — dist/cli.js needs its runtime dependencies. This is the npm-documented “install the tarball, run the installed bin” pattern. The published package must not define preinstall, install, postinstall, or prepare scripts. Consumer setup runs through explicit supaschema init, so pnpm, Bun, Yarn, and npm installs do not require build-script approval to download the CLI. npm run release:verify is the release-facing entry point. It calls the package-manager smoke after the package checks, so use that command for release readiness.
A local registry (Verdaccio) publish-then-install flow is the optional high-fidelity tier for exercising registry resolution, dist-tags, and package manager download behavior. It is intentionally not used by default: this is a single-package CLI whose bin is a small launcher of dist, so a tarball install is hermetic, offline, and cross-platform without the extra service.

Verification

Run these checks when packaging or installer behavior changes:
npm run release:verify
npm pack --dry-run --json
npx vitest run tests/editor-surfaces.test.ts tests/database-url.test.ts tests/package-contents.test.ts tests/consumer-lifecycle.test.ts
The dry-run tarball is the authoritative preview of what npm will publish.
Last modified on June 19, 2026