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

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. The primary public package name is supaschema on npmjs.org. Releases also publish the same consumer contents as the scoped GitHub Packages mirror @jmclaughlin724/supaschema, because GitHub Packages requires scoped npm package names and uses npm.pkg.github.com. 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. The source docs/ tree, examples, benchmarks, corpus fixtures, source files, tests, services, and maintainer scripts stay out of the npm tarball. The narrow documentation exception is the consumer-safe projection under agent-bundle/docs/: the canonical sync writer copies every docs/**/*.mdx file byte-for-byte and generates a sorted URL index, while docs.json, images, and all other non-MDX files remain excluded. The projection stays inside node_modules for offline reference and is never copied by supaschema init. 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. Lower-level helpers that the CLI and tests share internally (in src/database/admin.ts, src/migrations/runners.ts, src/migrations/status.ts, src/pipeline/deploy-safety.ts, and src/pipeline/type-safety.ts) are not part of the public package surface: they are compiled into dist/ for the CLI to use but have no subpath. They may change or be removed in any release. The package has one documented public entry, dist/index.js; no convenience subpaths, shims, or escape-hatch entry points are published.

Agent bundle boundary

The exact Claude, Codex, shared agent, and offline documentation 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. Consumer hook registration is limited to Supaschema’s generated-migration protection and schema-write automation. The repository’s broad Bash, Git, secret, branch, worktree, and deletion guard remains maintainer-only and is excluded from both the tarball’s raw agent bundle and the files registered by supaschema init.

Public npx skills source

skills/supaschema is a generated mirror of the canonical .claude/skills/supaschema workflow, including its references/** guides. One exported ordered list owns that public inventory. Users can install the skill without installing the npm package:
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. The migration and maintenance workflows are references/ guides inside that one skill, not separate installs. The Skills CLI 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 under node_modules/supaschema/agent-bundle/ and become active through the default supaschema init scaffold. Init reads the packaged skills manifest, recursively installs the Agent and Claude skill directories while preserving conflicts, and never creates .codex/skills/**. Package install and default init do not invoke the Skills CLI or write consumer-owned AGENTS.md or CLAUDE.md.

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 as a narrow package file alongside bin/config-contract.mjs). 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 when the merged config contract changes, and records unresolved path confirmation in .supaschema/install.json only when multiple detected paths still need an agent or operator to choose the owning schema and migration directories. Resolved installs do not create .supaschema/; durable project defaults belong in supaschema.config.json. Supabase inventory or _bootstrap projects are resolved installs with manual schema diff and migration sync policy, managed-schema excludes, and _bootstrap source skipping. The same scaffold installs missing package-owned active agent surfaces by default, merges package-manager-specific Claude and Codex hook registration, preserves and reports existing non-identical files, and reports skipped non-mergeable hook config. It does not install or register the maintainer-only Claude-to-Codex surface-sync hook. The packaged agent bundle remains available under agent-bundle/ for audit and repair. 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): 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 prepublish release-facing entry point. It calls the installed-CLI use proof and then the package-manager smoke after the package checks, so use that command for release readiness. After publication, npm run release:registry-smoke proves registry availability and package-manager download behavior that a local tarball cannot prove.
A local registry (Verdaccio) publish-then-install flow remains optional for prepublish rehearsal. Production release uses the real npm registry after publish because dist-tags, registry freshness, and package-manager download behavior cannot be fully proven from a local tarball.

Verification

Run these checks when packaging or installer behavior changes:
The dry-run tarball is the authoritative preview of what npm will publish.
Last modified on July 28, 2026