> ## Documentation Index
> Fetch the complete documentation index at: https://supaschema.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Package Boundary

> How supaschema decides what belongs in the npm package, consumer setup, and maintainer workspace.

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`.

<Note>
  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.
</Note>

## Four surfaces

| Surface                      | Source of truth                                           | Purpose                                                                                 |
| ---------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| npm tarball                  | `package.json` `files`                                    | Files downloaded into `node_modules/supaschema`                                         |
| Consumer setup               | `supaschema init`                                         | Files written or merged into the installing project                                     |
| Public `npx skills` source   | One curated directory under `skills/**`                   | Portable Agent Skill context installed by the Skills CLI                                |
| Public repository            | Git-tracked public-safe files                             | Source, docs, examples, tests, CI, and release evidence that can be public              |
| Private maintainer workspace | Private repository or intentionally untracked local files | Private 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.

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](/docs/coding-agents/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:

```bash theme={null}
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.

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](/docs/whats-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:

<Steps>
  <Step title="Classify">
    Decide whether each surface is public product source/docs/examples, public
    verification evidence, or private maintainer context.
  </Step>

  <Step title="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.
  </Step>

  <Step title="Ignore reintroduction">
    Add `.gitignore` patterns only after the files are untracked, so future
    generated or private-local copies do not get staged again.
  </Step>
</Steps>

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:

* [npm package.json files](https://docs.npmjs.com/cli/v11/configuring-npm/package-json/#files)
* [npm publish package contents](https://docs.npmjs.com/cli/v11/commands/npm-publish/#files-included-in-package)
* [GitHub changelog: upcoming npm v12 changes](https://github.blog/changelog/2026-06-09-upcoming-breaking-changes-for-npm-v12/)
* [npm developer guide](https://docs.npmjs.com/cli/v11/using-npm/developers/#keeping-files-out-of-your-package)
* [Git gitignore manual](https://git-scm.com/docs/gitignore)
* [GitHub repository visibility](https://docs.github.com/en/repositories/creating-and-managing-repositories/about-repositories#about-repository-visibility)
* [GitHub sensitive data removal](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository)

## 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):

| Phase                 | Owner                                | Proves                                                                                                                                                                                                                                               |
| --------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Download              | `tests/package/contents.test.ts`     | The 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.                                         |
| Setup                 | `tests/config/install.test.ts`       | The shared scaffolder creates the consuming project setup (config, schema/migration dirs, agent bundle, install manifest).                                                                                                                           |
| Use                   | `tests/package/consumer.test.ts`     | The 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 smoke | `scripts/release/package-smoke.mjs`  | The packed tarball installs and initializes through the supported consumer package managers and workspace recovery paths using current supported client behavior.                                                                                    |
| Registry smoke        | `scripts/release/registry-smoke.mjs` | Operator proof that npm, pnpm 11 with `minimumReleaseAge` disabled for the install, and Bun can download `supaschema@<version>` from the npm registry and execute the installed binary after publication.                                            |

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.

<Note>
  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.
</Note>

## Verification

Run these checks when packaging or installer behavior changes:

```bash theme={null}
npm run release:verify
npm run test:consumer-lifecycle
npm pack --dry-run --json
npx vitest run tests/cli/editor.test.ts tests/config/install.test.ts tests/package/contents.test.ts tests/package/consumer.test.ts
```

The dry-run tarball is the authoritative preview of what npm will publish.
